Semantica delle interazioni basata su commitment in ...web4.cs.ucl.ac.uk/staff/E.Rondini/Elisa...

133
Alma Mater Studiorum Università degli Studi di Bologna Facoltà di Ingegneria C.d.L. in Ingegneria Informatica Tesi di Laurea in Sistemi Operativi L-A Semantica delle interazioni basata su commitment in applicazioni ad agenti Candidato Relatore Elisa Rondini Prof. Ing. Anna Ciampolini Correlatore Ing. Paolo Torroni Anno Accademico 2002-2003 Sessione Autunnale

Transcript of Semantica delle interazioni basata su commitment in ...web4.cs.ucl.ac.uk/staff/E.Rondini/Elisa...

Alma Mater Studiorum

Università degli Studi di Bologna Facoltà di Ingegneria

C.d.L. in Ingegneria Informatica

Tesi di Laurea in

Sistemi Operativi L-A

Semantica delle interazioni basata su commitment in applicazioni ad

agenti

Candidato Relatore

Elisa Rondini Prof. Ing. Anna Ciampolini

Correlatore

Ing. Paolo Torroni

Anno Accademico 2002-2003 Sessione Autunnale

1

INDICE

INTRODUZIONE pag. 4 1. SVILUPPO DEI PARADIGMI DI PROGRAMMAZIONE pag. 5 1.1 Il Linguaggio Macchina pag. 6 1.2 I Linguaggi Imperativi e la metodologia Top-Down pag. 7 1.3 Il paradigma di programmazione

Orientato agli Oggetti pag. 7 1.4 Il passaggio dagli Oggetti agli Oggetti Attivi pag. 8 1.5 Il paradigma di programmazione basato

sugli Agenti pag. 9 1.6 I Sistemi Multiagente pag. 11 1.7 Alcuni esempi di utilizzi industriali di

Agenti Software pag. 12 1.7.1 Cos’è WINA e quali sono i più comuni utilizzi industriali di Agenti Software pag. 12

1.7.2 Pianificazione industriale pag. 13 1.7.3 Controllo industriale pag. 14 1.7.4 Collaborazione aziendale pag. 14 1.7.5 Simulazione aziendale pag. 15 1.8 Obiettivi di questo lavoro pag. 15 2. GLI AGENTI E LA LORO INTERAZIONE pag. 17 2.1 Il Paradigma ad Agenti pag. 17 2.2 L’Intelligenza pag. 19 2.3 L’Ambiente pag. 19 2.4 Descrizione astratta di un Agente pag. 22 2.5 L’architettura BDI (belief – desire - intentions) pag. 24 2.6 Da un approccio di tipo BDI verso un approccio

basato su Commitment pag. 27 2.7 L’insieme è più della somma delle parti pag. 27 2.8 ACL e atti linguistici pag. 29 2.9 FIPA ACL pag. 31

2

2.10 Dieci peculiarità di un Agente e differenza degli stessi dagli oggetti pag. 32

3. UN LINGUAGGIO DI COMUNICAZIONE PER AGENTI BASATO SUL CONCETTO DI OBBLIGO SOCIALE pag. 36

3.1 Concetti principali pag. 36 3.1 .1 L’Obbligo Sociale (The Social Commitment) pag. 38 3.1 .2 Proposizioni Temporali (Temporal Proposition) pag. 40

3.2 Specifiche Tecniche pag. 41 3.2.1 Classe Commitment pag. 43 3.2.2 Classe Temporal Proposition pag. 46 3.2.3 Azioni pag. 47 3.2.4 Le regole di aggiornamento della macchina a stati

(Update rules) pag. 48 3.3 Definizione dei principali atti comunicativi

(Speech Acts) pag. 49 3.3.1 Asserzioni (Assertives) pag. 50 3.3.2 Richieste (Directives) pag. 51 3.3.3 Promesse (Commissives) pag. 53 3.3.4 Dichiarazioni (Declarations) pag. 55 3.3.5 Proposte (Proposals) pag. 56 3.4 Usi significativi della semantica descritta pag. 57 3.5 Dalla fase di analisi alla fase di progettazione pag. 58 3.5.1 Diagrammi UML pag. 59 3.5.2 Diagramma UML – Analisi delle responsabilità pag. 64 3.6 Struttura dei packages utilizzati pag. 70 4. UN ESEMPIO DI PROTOCOLLO DI INTERAZIONE FRA AGENTI: “L’ASTA INGLESE” pag. 72 4.1 Definizione di protocolli di interazione pag. 72 4.1.1 La società pag. 73

3

4.1.2 I Diagrammi di Interazione pag. 74 4.2 Condizioni di correttezza per un Protocollo di

Interazione pag. 77 4.3 Protocollo dell’Asta Inglese pag. 79 4.3.1 La società pag. 79 4.3.2 Schema degli oggetti Temporal Proposition

relativi all’asta pag. 81 4.3.3 Atti comunicativi caratterizzanti l’asta

e Condizioni pag. 82 4.3.4 Diagramma di Interazione pag. 84 4.4 Dalla fase di analisi alla fase di progettazione pag. 85 4.4.1 Diagramma UML pag. 85 4.4.2 Diagramma UML – Analisi delle responsabilità pag. 95 5. PRESENTAZIONE DI ALCUNI ESPERIMENTI CONDOTTI SULL’ACLFramework pag. 103 5.1 Descrizione degli esperimenti pag. 103 5.1.1 TestAuction_1 pag. 103 5.1.2 TestAuction_2 pag. 108 5.1.3 TestAuction_3 pag. 111 5.1.4 TestAuction_4 pag. 114

5.2 Prestazioni del sistema pag. 117 5.3 Problematiche generali pag. 121

6. CONCLUSIONI pag. 123 7. Appendice pag. 129 8. Bibliografia pag. 131

4

INTRODUZIONE Questa tesi ha lo scopo di fornire la realizzazione di un protocollo di interazione fra agenti, basato sul concetto di “social commitment”, con l’obiettivo di verificarne la semantica. Lo sviluppo di questo progetto nasce dalla collaborazione congiunta della sottoscritta E. Rondini e di G. A. Ingenito che ha steso la tesi riportata in [10]. La prima parte è dedicata ad un’introduzione al concetto di agente e alle applicazioni dei sistemi ad agenti in alcuni ambiti industriali. Segue una descrizione del framework sociale basato su commitment, esposto in [3]. Verrà, quindi, presentato un esempio di interpretazione dei requisiti al fine di creare un protocollo di interazione per un’asta inglese. Nella fase di progettazione del sistema, si seguirà una metodologia tipica dell’Ingegneria del Software presentando vari Diagrammi UML. Si utilizzerà, come framework di basso livello, quello esposto nel dettaglio in [10]. Si presenteranno un insieme di test condotti sull’applicazione creata. Si esporranno i vantaggi e gli svantaggi dell’approccio seguito, esponendo il personale punto di vista relativamente a eventuali futuri miglioramenti da apportare al framework di basso livello su cui si appoggia la concreta applicazione dell’asta. La piattaforma, usata per l’implementazione del protocollo, è Microsoft .NET Framework 1.1; il linguaggio di programmazione utilizzato è C#.

5

1. SVILUPPO DEI PARADIGMI DI

PROGRAMMAZIONE

Negli ultimi anni è cresciuto esponenzialmente l’impiego di supporti informatici per aiutare l’uomo nelle più disparate attività. L’entità dell’aiuto è tanto maggiore quanto più tale supporto è capace di lavorare e inferire indipendentemente da noi. Si possono immaginare molti domini applicativi concreti in cui diventa necessario il fatto di poter risolvere un problema, semplicemente istruendo l’elaboratore sulle specifiche e sui dati iniziali, lasciando che si organizzi e si gestisca in modo indipendente per produrre autonomamente una soluzione. Purtroppo ciò non è sempre facilmente attuabile, soprattutto quando si tratta di problemi complessi che richiedono decisioni basate su conoscenze che è difficile dare a componenti software, e rimane centrale il ruolo dell’uomo come razionale risolutore. Ciononostante l’elaboratore rimane un mezzo indispensabile per delegare parti importanti di questo processo decisionale, soprattutto quelle che sono facilmente automatizzabili, e diventa fondamentale, di conseguenza, la comunicazione fra l’uomo e la macchina.

Quando si affronta un problema con l’ausilio di un supporto informatico, si attraversano principalmente due fasi: 1) L’analisi a livello astratto del problema, e lo sviluppo di una metodologia

capace di risolverlo; è, ovviamente, la fase fondamentale, in quanto rappresenta, in potenza, la soluzione stessa.

2) Il trasferimento della conoscenza acquisita sul dominio del problema e delle metodologie risolutive sviluppate mentalmente al sistema informatico, che diventa così capace di eseguirle concretamente.

L’evoluzione dei paradigmi di programmazione, in senso lato, mira a dare

sempre più autonomia all’elaboratore.

6

Programmazione

monolitica

Programmazione

modulare

Programmazione

orientata agli

oggetti

Programmazione

ad agenti

Struttura del

componente

NON

MODULARE

MODULARE

MODULARE

MODULARE

Stato

del

componente

ESTERNO

ESTERNO

INTERNO

INTERNO

Invocazione

del

componente

ESTERNA

ESTERNA

call

ESTERNA

messaggio

INTERNA

regole+obiettivi

Figura 1.1. L’evoluzione dei paradigmi di programmazione[2].

Lo schema mette in evidenza proprio come, nel tempo, i sistemi sono stati organizzati in componenti sempre più intrinsecamente coerenti, indipendenti, capaci di prendere decisioni in modo autonomo. 1.1 Il Linguaggio Macchina

Agli albori, la difficoltà principale per un programmatore risiedeva nel colloquiare con il sistema, per “istruirlo” sui passi da seguire per raggiungere una soluzione. Una difficoltà che avrebbe dovuto essere marginale diveniva, quindi, determinante; per scrivere un programma in linguaggio macchina era necessario conoscere l’architettura del processore e i dettagli di ogni istruzione vale a dire il codice, il formato e la rappresentazione della stessa, nonché manipolarne direttamente la memoria . La linearità tipica della mente umana, si frastagliava tra registri e branches. Il componente software era costituito dall’intero programma, controllato totalmente dal programmatore, che doveva, inoltre, incaricarsi di gestirne lo stato e l’invocazione. Era assente, ovviamente, l’idea di modularità e di riutilizzo del codice.

L’evoluzione tecnologica si è mossa nella direzione di ridurre la distanza semantica tra uomo ed elaboratore, permettendo una comunicazione sempre più astratta ed automatizzando la traduzione dal linguaggio macchina verso nuovi linguaggi ad alto livello.

7

1.2 I Linguaggi Imperativi e la metodologia Top-Down I linguaggi imperativi, prima grande evoluzione dell’approccio alla

programmazione, permettono di organizzare il codice in moduli, più o meno indipendenti e, quindi, riusabili. L’approccio imperativo riflette la caratteristica umana di decomporre ricorsivamente il problema in “sotto-problemi” sempre più semplici, fino ad arrivare a casi “banali” per cui si conosce già un buon algoritmo risolutivo: questa è la caratteristica peculiare della metodologia top-down. Le subroutines, moduli fondamentali di un linguaggio imperativo, permettono di incapsulare il codice relativo a un sottoproblema, ovvero l’algoritmo, ma non gestiscono il proprio stato, che viene loro passato dall’esterno all’atto dell’invocazione. La logica di un linguaggio imperativo è ancora molto lontana da quella umana, soprattutto quando si devono affrontare problematiche complesse, fondamentalmente perché non c’è modo per trasportarvi e rappresentarvi entità e concetti: i dati e il codice sono nettamente separati. La decomposizione del problema aiuta ad intaccarne la complessità, ma non riflette il modo in cui l’uomo tende a suddividere concettualmente le varie parti in gioco. 1.3 Il paradigma di programmazione Orientato agli Oggetti

La rivoluzione, in questo senso, è arrivata con la programmazione orientata agli oggetti dove un oggetto viene visto come la trasposizione informatica del concetto di entità.

Figura 1.2. Schema rappresentativo di un oggetto [1].

8

Un oggetto incapsula non solo il proprio comportamento ovvero le proprie operazioni, ora chiamate metodi, ma anche le variabili manipolate dai metodi stessi, ovvero il proprio stato; ogni oggetto nasce dalla necessità di “istanziare” la classe a cui esso stesso appartiene.

Pur essendo, dal punto di vista implementativo, una semplice modifica incrementale della struttura, il concetto di classe ha delle enormi ripercussioni a livello progettuale, perché stravolge l’approccio alla programmazione rendendola molto più vicina alle modalità con cui la mente procede nel risolvere problematiche complesse. La classe non è altro che la rappresentazione informatica di un’idea platonica, che ci permette di astrarre le caratteristiche comuni e immutabili delle entità fisiche, ovvero le istanze, dando loro un “nome”, quello della classe da cui vengono generate, utile per identificarle e per sottolinearne similitudini e differenze. Se, ad esempio, da un punto di vista “imperativo”, (5+4) è un’operazione di somma avente come operandi 5 e 4, dal punto di vista “object oriented” l’operazione potrebbe essere considerata come un metodo che l’entità “5” di tipo “Intero” mette a disposizione nei confronti di un’altra entità dello stesso tipo. La programmazione ruota finalmente attorno al concetto di entità. 1.4 Il passaggio dagli Oggetti agli Oggetti Attivi

Si è detto che un oggetto è la trasposizione informatica di entità; è altrettanto vero, però, che dal punto di vista comportamentale, esso rimane totalmente privo di iniziativa e lontano dalle idee di autonomia e dinamicità, che sono proprie dell’entità che esso potrebbe rappresentare. Riprendendo l’esempio del paragrafo precedente, l’oggetto “5” della classe “Intero” non potrà mai decidere autonomamente quando gli conviene sommarsi a “4” e questo perché i metodi di un oggetto possono essere invocati solo da un’entità esterna, tramite la spedizione di un messaggio. Allo stesso modo, supponendo che la classe “Intero” metta a disposizione un metodo pubblico di somma, l’oggetto “5” non potrà mai rifiutare di eseguire quel metodo quando riceve un messaggio che glielo indica.

9

Figura 1.3. Schema rappresentativo di un oggetto attivo.

Gli oggetti attivi ovviano al secondo problema. Un oggetto attivo dispone, infatti, di una parte di esecuzione parallela che ha il compito di accodare i messaggi in arrivo esterno. Queste richieste possono essere a questo punto vagliate, per decidere quali e quando accettarle. Nel caso degli oggetti attivi, dunque, l’esecuzione del processo è vincolata a rimanere all’interno dell’oggetto che, di conseguenza, comincia a controllare la propria esecuzione diventando responsabile di sé stesso. 1.5 Il paradigma di programmazione basato sugli Agenti

Rimane ancora da risolvere il primo problema, vale a dire che non si è ancora riusciti a dare agli oggetti la capacità di prendere iniziative. Un oggetto attivo può decidere se e quando rispondere a una richiesta, ma questo meccanismo è attivato sempre e solo dall’esterno; non può, cioè, manifestare una forma di “volontà” relativamente al soddisfacimento del compito per cui è stato progettato, e riguardo al coordinamento con le altre entità per trarne mutuo beneficio. Questo può non sempre essere un vantaggio, ma vedremo più avanti alcune applicazioni in cui ciò risulta addirittura necessario. Gli agenti colmano queste limitazioni, e aprono la strada a un nuovo modo di progettare sistemi complessi, ancora più astratto, potente e versatile. Costituiscono, per riassumere, la

10

prossima inevitabile tappa nell’approccio alla programmazione, soprattutto quando si ha a che fare con sistemi aperti e distribuiti.

Figura 1.4. Schema rappresentativo di un agente [1].

Di seguito viene proposta una figura che espone quali sono le caratteristiche peculiari degli agenti mettendo in evidenza il perché di una loro così rapida diffusione, come paradigma di programmazione, soprattutto nell’ambito industriale. Parleremo di alcuni esempi di applicazioni concrete in questo settore nei prossimi paragrafi.

11

Figura 1.5. Caratteristiche incapsulate dai vari Paradigmi di Programmazione.

Oggetto Oggetto Attivo

Oggetto mobile

Agente

Who (la propria identità)

X X X X

What (il proprio stato)

X X X X

How (il proprio comportamento)

X X X X

When (il proprio thread di controllo)

X X X

Where (il luogo della propria esecuzione)

X X

Why (la motivazione delle proprie azioni)

X

1.6 I Sistemi Multiagente

Se è vero che il paradigma di programmazione basato su Agenti risulta molto più espressivo del paradigma di programmazione orientato agli Oggetti, è vero anche che, così come un oggetto, un agente non è sempre in grado di assolvere il proprio compito da solo. In particolare, ogni agente ha una visione solamente parziale dell’ambiente in cui vive e degli altri agenti che fanno parte della comunità. Trattandosi di sistemi dinamici, non è detto che un agente possegga, in ogni istante, tutte le risorse e le capacità necessarie per raggiungere da solo gli obiettivi prefissati. Nascono, per questo motivo, sistemi in cui esistono più agenti in grado di interagire, e tali sistemi sono chiamati, appunto, sistemi multiagente.

Così come gli oggetti si scambiano messaggi per richiedere servizi l’uno all’altro, gli agenti comunicano per aiutarsi reciprocamente nel conseguimento dei propri compiti, cercando di sopperire alla limitatezza dell’agire in solitudine, o per competere, tentando di accaparrarsi risorse .

12

Quando la comunicazione fra agenti assume i tratti di un vero e proprio discorso continuato nel tempo e con una precisa finalità si parla di cooperazione. 1.7 Alcuni esempi di utilizzi industriali di Agenti Software

A valle delle considerazioni fatte sull’evoluzione dei paradigmi di programmazione, è nostra intenzione fornire una breve panoramica sull’uso dei paradigmi di programmazione basati su agenti nell’ambito degli applicativi industriali reali. Chiaramente questa sezione non ha la pretesa di trattare in maniera esauriente questo argomento, sarebbe pressoché improponibile, in questa sede, in quanto l’oggetto di studio di questa tesi va ben oltre l’analisi dettagliata degli applicativi attualmente in uso.

Nella sottosezione vengono descritti gli utilizzi più comuni di agenti software in ambito industriale. 1.7.1 Cos’è WINA e quali sono i più comuni utilizzi industriali

di Agenti Software Il “Centro del Commercio Elettronico”(CEC, Centre for Electronic

Commerce) di ERIM ha promosso, nel 1998, una serie di seminari relativamente agli “agenti utilizzati per le applicazioni industriali”(WINA, Workshop on Industrial Agents). L’obiettivo primario di WINA è stato quello di riunire i professionisti di tecnologie multiagente tentando di accrescere la conoscenza e la collaborazione nello sviluppo comparato delle tecniche e degli applicativi correntemente in uso nelle industrie. WINA ha contrastato, per molti aspetti, le tradizionali conferenze nate per la ricerca per vari motivi:

Una conferenza tradizionale per la ricerca presuppone una totale

apertura in relazione ai dettagli tecnici. Nell’ambito WINA è possibile che alcune parti delle esposizioni siano soggette a segreto industriale, per questo tutti i partecipanti sono, in prima persona, responsabili del contenuto delle loro presentazioni.

Una conferenza tradizionale basa il suo successo sulla novità. WINA focalizza il proprio successo sull’abilità di coloro che partecipano.

13

Una conferenza tradizionale ha una tendenza a specializzarsi sulla tecnologia. WINA tende a discutere dei problemi, enfatizzando il problema fornito di purezza nell’approccio tecnico.

In una conferenza per la ricerca, raramente si trova una forma di “promozione del prodotto”. WINA incoraggia, al contrario, tutti i partecipanti a parlare dei prodotti che essi offrono.

I progetti basati su agenti software coprono quattro aree applicative: la pianificazione nell’ambito manifatturiero, il controllo, la collaborazione aziendale e la simulazione in ambito industriale. 1.7.2 Pianificazione industriale

Il problema della pianificazione è quello di determinare cosa succede, dove, come e quando accade un certo evento sul piano industriale. Nella sua forma tradizionale, si sfrutta il fatto che gli eventi spesso sono predicibili; il problema è che spesso, in parecchie industrie, un evento repentino ed inaspettato può invalidare tutto il processo di pianificazione nell’arco di un paio d’ore causando grossi problemi di ripristino. I moderni sistemi di scheduling aziendale tentano di mantenere valido il processo di pianificazione anche a fronte di problemi e di interruzioni che avvengono in tempo reale attraverso l’uso di un processo conosciuto come “pianificazione reattiva” la quale forza la pianificazione in tempi reali. I progetti discussi da coloro che hanno partecipato a WINA tentano di riunire sia gli aspetti predicibili sia gli aspetti reattivi, forzando sia la fase esecutiva sia la fase di pianificazione.

L’approccio CEC propone un esempio di ecosistama popolato da differenti specie di agenti interagenti dove un agente viene visto proprio come un oggetto software attivo dotato di iniziativa, vale a dire un oggetto, con il proprio processo di controllo, che ha la possibilità di essere mandato in esecuzione senza essere invocato esternamente. Questa semplice definizione consente di avere a disposizione degli agenti reattivi molto semplici con una limitata intelligenza locale, dalla cui interazione nascono, però, dei comportamenti molto più complessi e dove questi stessi agenti rappresentano cose piuttosto che funzioni all’interno del dominio del problema. Ciascun agente agisce sulla base di limitate risorse locali, ma la sua influenza si propaga

14

attraverso l’intero ecosistema determinando comportamenti osservabili globalmente, che però sono configurati e assemblati in una maniera puntuale.

Vari progetti sono nati, si possono citare solo a titolo di esempio i seguenti:

ANTS (Agent Network for Task Scheduling) sviluppato da Deneb Robotics;

AEMSI (Agent-Enhanced Manufacturing System Initiative) diretto da ObjectSpace;

Fakos, KoWest, HMS (Holonic Manufacturing Systems), MASCADA (Manufacturing Control Systems capable of managing production Changes and Disturbances – an application of autonomous and cooperative Agents) sviluppati da DaimlerChrysler.

Per i dettagli di sviluppo di ciascuno di questi progetti, e di quelli che verranno citati nel seguito, si rimanda a [4] dove si pone in evidenza l’importanza di ciascun progetto stesso relativamente all’uso di agenti software.

1.7.3 Controllo industriale

Il problema del controllo a livello industriale rappresenta oggi un’ampia problematica su cui discutere e copre vari ambiti, dalla pianificazione strategica della struttura aziendale alla pianificazione dei cicli degli attuatori di sensori. Anche per questo si sono evoluti molti progetti che hanno fatto uso di agenti software e le attività proposte da WINA si occupano principalmente del bilanciamento dei carichi di lavoro attraverso le varie aree di sviluppo lavorative. Tra i vari progetti citiamo:

Vision for Control di DaimlerChrysler; MAS (Maufacturing Agility Server) diretto da Flavors Technology.

1.7.4 Collaborazione aziendale

Oltre al problema della pianificazione aziendale, spesso nelle industrie gli agenti software vengono utilizzati come supporto collaborativo agli esseri umani. L’idea di un supporto di collaborazione è importante nel processo di

15

pianificazione nelle attività di design, dove innumerevoli esperti tecnici devono riuscire a convergere ad un piano di risoluzione comune e coerente per un determinato prodotto o un definito processo. Tra i vari progetti citiamo:

HRL ovvero Hughes Research Laboratories che hanno promosso un insieme di vari progetti per il controllo aziendale;

RAPPID (Responsible Agents for Product-Process Integrated Design) promosso da ERIM CEC e Ward Synthesis.

1.7.5 Simulazione aziendale

La simulazione e un modello specifico basato su agenti software è in grado di offrire innumerevoli e significativi vantaggi rispetto al modello di gestione tradizionale basato sulle equazioni e sui calcoli all’interno di innumerevoli applicazioni. Tra i vari progetti citiamo:

DASCh (Dynamical Analysis of Supply Chains) progetto promosso dall’associazione ERIM CEC;

Simulation of Induction Heating promosso dal NCMS ovvero National Centre for Manufacturing Sciences.

1.8 Obiettivi di questo lavoro

Nelle precedenti sezioni abbiamo citato solo alcuni esempi di progetti nati per scopi industriali, allo scopo di mostrare la recente ascesa dell’interesse nello sviluppo di sistemi ad agenti software anche al di fuori degli ambienti accademici.

L’obiettivo di questa tesi è quello di implementare un framework per la comunicazione tra agenti, rispettando le specifiche riportate in [3] di cui parleremo in dettaglio nei prossimi capitoli. Parleremo delle scelte progettuali effettuate per lo sviluppo del framework e dell’applicazione che vi sta sopra, discutendo i risultati di vari esperimenti fatti e valutandone la scalabilità. L’applicazione scelta è quella di un’asta inglese, un meccanismo utile per l’allocazione di risorse nei sistemi che studiamo.

Prima di arrivare a tutto ciò, riprenderemo alcuni concetti relativi ai sistemi ad agenti che in questo capitolo introduttivo abbiamo volutamente lasciato da parte, ma che sono necessari allo sviluppo tecnico di questa tesi.

16

Di seguito sono sinteticamente riassunti i contenuti principali di ciascun capitolo.

Il Capitolo 2 cercherà di inquadrare il concetto di agente e di capire il ruolo dell’interazione nei sistemi multiagente. Si cercherà, inoltre, di mettere in evidenza le differenze tra “agenti” e “oggetti”, ma anche la continuità che li lega.

Il Capitolo 3 avrà la responsabilità di esporre le specifiche contenute nell’articolo di [3] che costituiranno i requisiti base dell’implementazione del framework di basso livello progettato. Verranno, inoltre, presentati i diagrammi UML di progetto, creati a fronte dell’implementazione e verranno esposte le principali scelte progettuali effettuate.

Il Capitolo 4 esporrà i requisiti dell’applicazione di più alto livello che utilizzerà il framework, ovvero le specifiche dell’asta inglese. Verranno presentati i diagrammi UML di progetto e saranno esposte le principali scelte progettuali effettuate a fronte dell’implementazione.

Il Capitolo 5 parlerà delle varie prove sperimentali fatte per testare il framework, riportando alcuni esempi significativi e mettendo alla prova la scalabilità dello stesso. Si cercherà di osservare il comportamento del framework all’aumentare del numero dei partecipanti all’asta inglese e si esaminerà fino a che punto il framework sarà in grado di fornire “risposte utili”, ovvero in tempi ragionevoli.

Il Capitolo 6 metterà in evidenza le lezioni imparate e discuterà della possibilità di impiego di questo framework in sistemi reali. Si faranno, inoltre, delle riflessioni conclusive su ciò che è stato fatto e su ciò che ancora rimane da fare esaminando i limiti del framework e riflettendo su come questo potrebbe essere modificato per essere migliorato.

17

2. GLI AGENTI E LA LORO INTERAZIONE

Nell’introduzione, abbiamo evidenziato i limiti dei paradigmi di programmazione: ci piacerebbe poter contare su entità capaci di iniziativa e di autonomia nel conseguimento degli obiettivi per cui le abbiamo progettate . Tali entità sono chiamate comunemente “Agenti”. Abbiamo inoltre visto, sempre nel capitolo precedente, come nel tempo, le applicazioni industriali hanno sempre di più utilizzato il paradigma ad agenti, citando alcuni esempi pratici di applicazioni in ambito web o industriale. Questo capitolo vuole essere una controparte teorica ai concetti introdotti, ed esporre alcune problematiche relative alla realizzazione di sistemi multiagente. 2.1 Il Paradigma ad Agenti

Il termine “agente” è stato nel passato impiegato in ambito informatico ad esempio con l’accezione generica di “entità che si coordina con altri agenti, per svolgere un servizio richiesto da qualcuno”.

Figura 2.1. Coordinazione di agenti per consegnare le e-mail.

Quando un utente vuole mandare una e-mail, consegna il messaggio al proprio User Agent, il quale a sua volta lo inoltra, corredato delle informazioni necessarie, al relativo Mail Transfer Agent; gli MTA, si coordinano con gli MTA di cui hanno visibilità, per mandare avanti il messaggio, fino a quando un MTA non si accorge che il destinatario è un UA di sua competenza. Siamo ancora molto lontani dalla complessità di un agente e di un sistema multiagente come lo intendiamo oggi.

18

Non esiste una definizione che sia universalmente accettata, fondamentalmente per la molteplicità dei domini in cui gli agenti possono essere impiegati, domini che richiedono agenti con caratteristiche differenti, a volte contrastanti. In maniera molto generale, un agente può essere definito come:

un sistema computazionale immerso in un certo ambiente, capace di intraprendere autonomamente azioni atte al raggiungimento dell’obiettivo per cui è stato progettato.

Questa definizione, proposta da Wooldridge in [5], nasconde alcuni concetti, che è bene evidenziare.

È applicabile anche ad agenti non “intelligenti”. Specifica quanto sia stretto il legame agente-ambiente: un agente

esiste solo in relazione ad un ambiente, e ogni sua azione influenza l’ambiente modificandolo. Ovviamente, un agente non controlla totalmente il proprio ambiente, ma va a “perturbarlo”; l’intensità della perturbazione, ovvero l’insieme delle possibili azioni che può eseguire, viene detta capacità d’azione.

Non dice nulla riguardo la natura dell’ambiente in cui l’agente agisce; questo perché esiste un’enorme varietà di ambienti, all’interno dei quali possono operare agenti.

Non definisce con quale accezione utilizza il concetto di “autonomia”; possiamo, in prima approssimazione, considerarla come la capacità dell’agente di operare senza stimoli esterni né di natura umana, né di natura computazionale: un agente controlla sia il proprio stato che il proprio comportamento, ed è capace di agire per lunghi periodi senza necessità di stimoli esterni.

Considera un agente come entità singola, non tratta, cioè, le capacità interattive che legano un agente alle altre entità di un sistema, espandendone le potenzialità.

19

2.2 L’Intelligenza Esiste un vasto insieme di agenti, anche molto sofisticati, che non sono

stati concepiti per funzionare come sistemi “intelligenti”. Un termostato potrebbe essere considerato come un rudimentale agente che percepisce la temperatura di una stanza e agisce sull’ambiente attivando o disattivando l’impianto di riscaldamento, senza dubbio però nessuno scommetterebbe sulla sua intelligenza. Parlare dell’intelligenza di un agente esula, comunque, dal contesto specifico degli agenti come li abbiamo definiti. In realtà il problema della classificazione dei sistemi in base all’intelligenza tocca tutto il mondo dell’Intelligenza Artificiale. Possiamo per ora accontentarci di definire “intelligente” un agente che manifesta autonomia, ma anche flessibilità di comportamento. Per “flessibilità”, si intende:

reattività, la capacità di reagire agli stimoli provenienti dall’ambiente;

intraprendenza, la capacità di agire nell’ottica di raggiungere il proprio obiettivo;

abilità sociale, la capacità di interagire con altre entità. Un agente deve saper bilanciare reattività e intraprendenza, ovvero non deve perdere di vista il proprio obiettivo, che è lo scopo finale del suo agire, ma nemmeno disinteressarsi dei cambiamenti ambientali poiché l’azione migliore da fare per avvicinarsi al proprio obiettivo dipende dalle circostanze. L’abilità sociale di un agente, infine, è più del mero scambio di informazioni: per poter raggiungere i propri obiettivi, gli agenti devono negoziare e cooperare con altri agenti, conoscerne obiettivi e potenzialità per guadagnare risorse e capacità. 2.3 L’Ambiente L’ambiente costituisce l’infrastruttura che permette all’agente di esistere, operare e comunicare. Gli eventi a cui è interessato un agente vengono recepiti nell’ambiente, e i risultati delle sue azioni si propagano in esso. L’interazione tra l’agente e l’ambiente è continua; l’agente percepisce il proprio ambiente tramite sensori, e opera nell’ambiente tramite attuatori.

20

Figura 2.2. Rapporto tra l’agente e il proprio ambiente.

Ogni azione ha, quindi, un impatto sull’ambiente, che viene, in conseguenza di essa, parzialmente modificato (nessun agente ha un controllo totale del proprio ambiente). Da questo fatto, ricordandoci anche che nell’ambiente coesistono più agenti, si deduce che:

la stessa azione, eseguita in istanti diversi, porterà a risultati diversi, e potrà, quindi, anche fallire (si parla in questo caso di ambienti non deterministici);

possono presentarsi particolari stati ambientali che rendono impossibile l’esecuzione di un’azione; ogni azione è, quindi, associata a una serie di precondizioni, che indicano quando l’agente può tentare di eseguirla;

l’ambiente costituisce il mezzo attraverso cui gli agenti interagiscono comunicando, ma è anche il mezzo che li mette in relazione indirettamente, proprio in virtù del fatto che l’ambiente stesso viene modificato dalle azioni degli agenti.

In definitiva, il punto cruciale per l’agente è riuscire a determinare, fissato un istante, quale sia l’azione più conveniente per perseguire i propri scopi. Esistono tipologie differenti di ambienti, che influenzano l’architettura e la complessità degli agenti che dovranno operare in esso.

21

In [6] viene presentato un elenco di caratteristiche che identificano un ambiente; questo elenco è proposto di seguito.

Accessibile. Un ambiente è accessibile quando l’agente può ottenere informazioni complete e dettagliate sul suo stato; ovviamente, la maggior parte degli ambienti non sono completamente accessibili.

Deterministico. In un ambiente deterministico, fissata un’azione, essa produrrà sempre lo stesso risultato; la maggior parte degli ambienti non forniscono questa certezza, sono infatti non deterministici.

Statico. Un ambiente statico varia solo rispetto all’impatto delle azioni degli agenti; questa caratteristica è difficilmente riscontrabile in un ambiente, che modifica il proprio stato in seguito a una lunga serie di fattori trasparenti all’agente (in questo caso, si parla di ambiente dinamico).

Discreto. E’ un ambiente in cui vi è un numero finito di percezioni e azioni; si contrappone ai più diffusi ambienti continui.

Altro aspetto fondamentale nell’analisi di un ambiente è il suo dominio temporale (ovvero l’insieme di regole che ne controllano l’evoluzione nel tempo); ogni dominio temporale soddisfa la regola per cui il tempo non può tornare indietro. Si differenziano due tipologie fondamentali di domini temporali, riportate di seguito.

Continuo. E’ un dominio temporale in cui il tempo è un insieme “denso”: fissati due istanti qualsiasi, il loro valore temporale sarà sempre e comunque diverso. E’ il modo in cui l’uomo percepisce il tempo, ma è in pratica difficilmente realizzabile.

Discreto. E’ un dominio che partiziona lo scorrere del tempo in intervalli (che definiscono la sua granularità): l’intervallo è, quindi, il più piccolo valore che determina una variazione temporale percepibile; ogni evento che si verifica nell’intervallo, è come se si verificasse alla sua fine. Un dominio discreto può rappresentare approssimativamente un dominio continuo; il grado di approssimazione dipende, ovviamente, dalla granularità.

22

Un ambiente è caratterizzato nel suo complesso da un insieme di stati ambientali S={s1,s2,…}; fissato un istante, l’ambiente si deve trovare in uno di questi stati. La capacità d’azione di un agente è rappresentata dall’insieme di tutte le possibili azioni che può compiere A={a1,a2,…}. 2.4 Descrizione astratta di un Agente

A livello astratto, quindi, il comportamento di un agente può essere rappresentato come una funzione che mappa sequenze ambientali in azioni:

action: S*→A dove il simbolo S* indica l’insieme di tutte le sequenze possibili. Ciò riflette il fatto che un agente non è, nella maggior parte dei casi, puramente reattivo: la decisione di eseguire un’azione dipende non solo dallo stato attuale, ma anche da un certo numero di stati passati. Un ambiente, invece, può essere visto come una funzione che mappa uno stato ambientale e un’azione in un insieme di nuovi stati ambientali, che derivano dall’impatto dell’azione sull’ambiente stesso:

env: S x A→℘(S) La storia dell’agente è determinata dalla sequenza di stati ambientali che si verificano e si sviluppano in seguito ad ogni sua azione. L’approccio con cui si progetta un agente, è tipicamente quello di scomporlo in sottosistemi con compiti precisi e separati. La prima naturale decomposizione riguarda percezione e azione, ovvero capacità sensoriale e capacità decisionale/attuativa. Se chiamiamo P l’insieme di percezioni possibili dell’agente, la funzione di percezione mapperà uno stato ambientale in una di queste percezioni:

see: S→P L’agente agisce, quindi, in corrispondenza di una serie di percezioni, non più direttamente rispetto a sequenze ambientali:

action: P*→A Questo fatto porta a prendere in considerazione la possibilità che l’agente non riesca a distinguere tutti gli stati ambientali (in questo caso, sarebbe

23

onniscente), ovvero ciò implica che stati differenti portino in realtà alla stessa percezione (ciò è quello che succede anche per l’uomo). Si pensi, ad esempio, ad un agente software che agisce in un file system; l’agente avrebbe la stessa percezione dell’ambiente se si aggiungesse un file in una directory differente da quella in cui si trova. In realtà, possiamo immaginare che l’agente possieda una struttura dati interna adibita alla memorizzazione della propria storia (o almeno del suo passato più recente) in forma di percezioni. In questo modo egli potrebbe ragionare sugli eventi passati per decidere cosa fare. Si introduce così il concetto di stato interno; se I è l’insieme degli stati interni attualmente memorizzati dall’agente, una nuova percezione comporterà l’aggiornamento di questo insieme. Tale funzione di aggiornamento degli stati interni, next, è del tipo:

next: I x P→I A questo punto, l’agente agisce sulla base dei propri stati interni:

action: I→A

Figura 2.3. La scomposizione astratta di un agente in sottosistemi.

2.5 L’architettura BDI (belief – desire - intentions)

24

Il passaggio dall’architettura astratta a una concreta porta a diverse implementazioni di un agente, le quali si differenziano principalmente per come realizzano la funzione action, che rappresenta il processo decisionale dell’agente. Si evidenziano, così, due architetture contrapposte, una che realizza il processo decisionale tramite la manipolazione di formule logiche (architettura simbolica, la quale presuppone che l’agente abbia una rappresentazione astratta dell’ambiente in forma logica, e deduca da questa cosa gli conviene fare), e una che evita questo modo di procedere, in quanto troppo dispendioso dal punto di vista computazionale e, quindi, irrealizzabile negli ambienti real-time (architetture reattive, le quali considerano il legame agente-ambiente fondamentale, e tentano quindi di mappare direttamente le percezioni in azioni). Ovviamente, tra questi due estremi, sta tutta una serie di architetture ibride che attingono da entrambi gli approcci. Tra queste ultime, si desidera mettere in evidenza l’architettura Belief-Desire-Intention. L’architettura BDI poggia sulla concezione filosofica del ragionamento pratico, che studia come raggiungere i propri obiettivi ragionando in termini di azioni da compiere. Per rispondere a questi interrogativi, la teoria del ragionamento pratico individua in questo processo mentale il ruolo fondamentale delle credenze, dei desideri e delle intenzioni. E’ l’interazione fra queste componenti, secondo la teoria, che porta a decidere quale azione compiere effettivamente. Questa decisione deriva da due processi fondamentali:

decidere quale obiettivo si vuole raggiungere; decidere con quali mezzi lo si vuole raggiungere.

Per questo motivo, un agente BDI è descritto in termini di stati mentali, che si compongono appunto di credenze (Beliefs), desideri (Desires) e intenzioni (Intentions) che l’agente ha, istante per istante. Le intenzioni di un agente diventano, in base a quest’ottica, fondamentali:

25

persistono; di conseguenza, se i mezzi scelti per raggiungere un’intenzione falliscono, si tenta una strada alternativa. Un’intenzione viene abbandonata se è stata raggiunta, se ci si accorge che è irraggiungibile o se le motivazioni che la sostenevano non sono più presenti.

vincolano le opzioni da considerare ad essere consistenti con esse (se si decide di diventare un musicista di strada, non si può coltivare il desiderio di diventare miliardario).

influenzano le credenze su cui si basa il futuro ragionamento pratico, poiché quando si ha un’intenzione si agisce nell’ottica che essa verrà, prima o poi, raggiunta.

Un agente deve essere capace di bilanciare la perseveranza, nel tentare di soddisfare le intenzioni, con la riconsiderazione di esse; in particolare, un agente che non riconsidera abbastanza spesso le proprie intenzioni rischia di intestardirsi inutilmente nel tentare di soddisfare intenzioni ormai irraggiungibili o immotivate. Ciò risulta particolarmente dannoso nel caso di ambienti dinamici, in cui accadono con elevata frequenza nuovi eventi, i quali potrebbero favorire nuove intenzioni. Dall’altra parte, un agente che riconsidera troppo spesso le proprie intenzioni rischia di non raggiungerne mai nemmeno una. In ambienti statici, ad esempio, in cui i cambiamenti ambientali avvengono con frequenza bassa, un agente potrebbe mantenere le proprie intenzioni per periodi di tempo più lunghi. Come al solito, la strategia vincente è una via di mezzo. La Figura 2.4 mette in evidenza la decomposizione dell’architettura di un agente nelle tre componenti dei suoi stati mentali e nelle relative funzioni di aggiornamento.

26

Figura 2.4. Architettura di un agente BDI [1].

In particolare:

la funzione di revisione delle credenze aggiorna le credenze che l’agente ha, in base alle nuove percezioni dell’ambiente, e alle credenze attuali;

l’insieme delle credenze rappresentano le considerazioni dell’agente sull’ambiente istante per istante;

la funzione di generazione delle opzioni determina i desideri dell’agente sulla base delle sue attuali credenze, e nel rispetto delle sue intenzioni; questa funzione deve, quindi, essere coerente con l’attuale stato mentale dell’agente, ed essere opportunistica, ovvero accorgersi di eventuali cambiamenti ambientali favorevoli per le intenzioni dell’agente stesso;

l’insieme dei desideri rappresenta l’insieme delle possibili opzioni per un agente, ovvero le sue potenziali intenzioni;

il filtro decide cosa l’agente deve fare, ovvero quali intenzioni deve considerare, sulla base del suo attuale stato mentale;

l’insieme delle intenzioni rappresenta lo scopo attuale dell’agente, ovvero determina le azioni da eseguire; l’insieme può essere

27

strutturato come uno stack, che ordina le intenzioni sulla base della loro importanza, di quanto facilmente si stima di poterle soddisfare e di quanta motivazione spinge verso di esse;

la funzione di azione determina come l’agente deve andare a perturbare l’ambiente per avvicinarsi al perseguimento di una delle sue intenzioni.

In definitiva, l’architettura BDI permette di suddividere la struttura dell’agente in sottosistemi intuitivi, chiari ed indipendenti; gli agenti si muovono in quanto spinti dai loro desideri, dalle loro credenze e dalle loro intenzioni. Questo comporta una serie di problematiche da affrontare; fra di esse il modo di rappresentare gli agenti in maniera indipendente dal contesto sociale in cui essi stessi vivono: questo approccio non predilige di certo l’interazione fra ambienti ed agenti eterogenei. 2.6 Da un approccio di tipo BDI verso un approccio basato su Commitment L’ approccio, che verrà da noi trattato nei prossimi capitoli, non sarà di tipo BDI in quanto, quest’ultimo, non contempla l’idea di “aspetto sociale” di un sistema. Pone, inoltre, degli evidenti problemi di verifica alla semantica di comunicazione.

L’approccio che introdurremo e che, in pratica, arriveremo ad utilizzare fornendo un’implementazione concreta, sarà un approccio basato sul concetto di “Commitment” ovvero di impegno, di obbligo sociale che si viene ad instaurare all’interno della società di agenti quando un agente decide di interagire con essa attraverso degli atti comunicativi. La logica e il vantaggio di un approccio basato su “commitment” sta nel tentativo di alleggerire il concetto di agente, in accordo con una semantica che appesantisce il sistema nei termini di obblighi che tutti gli agenti hanno verso la comunità virtuale in cui essi vivono, ma che tenta di fornire una descrizione molto più semplificata degli stessi. 2.7 L’insieme è più della somma delle parti

Abbiamo più volte messo in evidenza il fatto che un agente, da solo, abbia scarsa capacità di perseguire gli obiettivi per cui è stato progettato, a

28

causa delle parziali informazioni che può ottenere dall’ambiente di cui non ha una percezione totale e della carenza di capacità e risorse che spesso si trova ad avere. Per sopperire a queste mancanze, l’agente può aggregarsi con le altre entità (agenti, oggetti, uomo e così via) con cui condivide l’ambiente dando così origine ad una società di agenti in cui l’interazione diventa parte integrante del processo di raggiungimento degli obiettivi. L’ambiente è, ovviamente, il mezzo attraverso cui si propaga la comunicazione e, quindi, anche il supporto ai protocolli di interazione. L’interazione tramite scambio di messaggi, per un agente (che può essere condotta peer-to-peer, in multicast e in broadcast), consta di due processi separati: la spedizione e la ricezione di messaggi. Un sistema multiagente, grazie all’interazione, è molto più che un semplice contenitore di agenti, e diventa particolarmente adatto per risolvere problemi distribuiti (poiché gli agenti comunicano, ma contemporaneamente mantengono la propria autonomia e i propri obiettivi). Per poter trarre guadagno dalla comunicazione con gli altri, a un agente non basta scambiare singoli messaggi scorrelati, bensì serve condurre un discorso articolato e con una finalità precisa: si parla in questo caso di protocollo di interazione. Analizzando un sistema multiagente, si possono individuare due situazioni distinte:

gli agenti sono in competizione; in questo caso, l’obiettivo del protocollo è quello di massimizzare il guadagno che le parti traggono dall’interazione. E’ il tipico caso in cui l’ambiente mette a disposizione risorse limitate, e gli agenti devono contendersele cercando di ottimizzarne l’uso e di evitare deadlock;

gli agenti si coordinano; in questo caso, l’obiettivo del protocollo è quello di rendere coerente l’insieme delle azioni dei vari agenti rispetto all’obiettivo per cui stanno cooperando. Diventa importante, in questa situazione, la buona ripartizione del compito globale in sotto-task.

Quando in un ambiente sono immersi molti agenti, diventa impossibile mantenere la coerenza del sistema ragionando sulla singola entità.

29

Si può limitare la complessità analizzando gli agenti non più a livello individuale, ma a livello di agglomerati di essi, ovvero di società. Una società permette di astrarre il monitoraggio di un sistema dalla struttura interna dei singoli agenti, considerando invece il gruppo di agenti che la costituiscono e le loro interazioni. Gli obiettivi di un agente sono in generale differenti da quelli della società: è il comportamento che emerge dall’insieme delle azioni dei vari membri a tendere verso lo scopo sociale. Una società definisce i ruoli che la costituiscono, le norme di comportamento all’interno di essa e le regole per entrarvi e uscirvi. Un agente, che entra in una società, assume uno o più ruoli e si accolla i relativi compiti; una volta diventato parte della società, ha obblighi e diritti nei confronti di essa. E’ proprio in relazione a queste idee di base che noi andremo ad approfondire, nei prossimi capitoli, l’approccio che abbiamo seguito e sviluppato andando a esaminare nel dettaglio l’articolo : “Defining Interaction Protocols using a Commitment-based Agent Communication Language” di Nicoletta Fornara e Marco Colombetti riportato in [3]. E’ questa idea di obbligo sociale, che si instaura all’interno della società di agenti, che tanto differenzia l’approcci BDI dall’approccio basato su “commitment”. 2.8 ACL e atti linguistici

Abbiamo parlato di comunicazione e interazione fra agenti, senza però entrare nel merito di come avvenga effettivamente lo scambio di messaggi. Il linguaggio usato dagli agenti per comunicare è detto Agent Communication Language (ACL). Un ACL si sviluppa su vari livelli di astrazione [7]:

strato di interconnessione, che provvede al trasferimento effettivo dei messaggi (ad esempio su Internet, questo strato potrebbe essere rappresentato dal TCP/IP);

strato del formato, che definisce la sintassi dei messaggi; strato della semantica, che descrive il significato dei messaggi che

si possono scambiare.

30

In molti approcci, come ad esempio le raccomandazioni FIPA ACL e le specifiche KQML, la semantica dei messaggi di un ACL si ispira alla teoria degli atti linguistici. La teoria degli atti linguistici, sviluppata per analizzare la comunicazione umana, presuppone che lo scopo di un messaggio sia sempre legato, direttamente o indirettamente, all’esecuzione di un’azione. Il linguaggio umano si compone di determinati atti [8]:

atti locutori (la reale emissione di parole); atti proposizionali (il riferimento a entità o a proprietà di entità); atti illocutori (constatazioni, ordini, consigli, …); atti perlocutori (il tentativo di ottenere una certa reazione da parte

dell’interlocutore). A differenza della comunicazione umana, spesso ambigua, nella comunicazione fra agenti è sempre chiaro lo scopo del messaggio; la classe di atti linguistici che soddisfano questa caratteristica è quella dei performativi, che sono legati per definizione all’esecuzione di un’azione, e hanno, quindi, una forte componente illocuzionaria.

Fondamentalmente, nell’interazione, si evidenziano due tipi fondamentali di messaggio:

asserzioni; interrogazioni.

Per prendere parte passiva all’interazione, un agente deve essere disposto a ricevere messaggi e capace di rispondere alle interrogazioni che gli vengono poste con asserzioni. Ovviamente, nella comunicazione, gli agenti si riferiscono a concetti e entità che fanno parte della loro conoscenza; non è detto che due agenti condividano questa conoscenza, e quindi, riescano a capirsi. Per sopperire a questo problema, i concetti, le entità e le relazioni che li legano vengono raggruppate in una tassonomia speciale detta ontologia, che può essere immaginata come una sorta di vocabolario strutturato.

31

Agenti che accedono alla stessa ontologia, e che condividono la sintassi di comunicazione, possono capirsi. 2.9 FIPA ACL

Abbiamo detto che due agenti, per capirsi, devono condividere la stessa sintassi di comunicazione. FIPA ovvero Foundation of Intelligent Physical Agents è una fondazione nata con lo scopo di fornire uno standard per l’interazione fra agenti. Lo sforzo di standardizzazione del FIPA riguarda tutto ciò che è coinvolto nella comunicazione fra agenti. Anche per gli atti linguistici, ribattezzati atti comunicativi (CA), il FIPA ha proposto un linguaggio standard. Il linguaggio assomiglia a KQML, pietra miliare nel mondo degli ACL, ma differisce da esso soprattutto per quanto riguarda la semantica dei messaggi. FIPA-ACL (come del resto anche KQML) è pensato soprattutto per agenti BDI; ogni messaggio è, infatti, associato ad una pragmatica, che definisce l’effetto atteso sullo stato mentale dell’agente ricevente. Si compone, quindi, di due parti: un linguaggio esterno, che definisce il tipo di atto comunicativo, e un linguaggio interno, che tratta credenze, desideri e intenzioni dell’interlocutore. La semantica di un atto comunicativo viene definita in termini di:

precondizioni, che devono valere per il mittente quando spedisce il messaggio;

effetto razionale, ovvero l’effetto che il mittente si aspetta di innescare sul proprio interlocutore.

Il limite fondamentale del linguaggio sviluppato dal FIPA è, però, quello di impostare la semantica sulla struttura interna (BDI) degli agenti e quindi, di conseguenza, di non supportare appieno l’eterogeneità. L’architettura BDI e il FIPA-ACL presuppongono che l’agente riesca ad avere una rappresentazione degli stati mentali degli altri agenti; solo così può ragionare sui propri interlocutori decidendo con quale atto comunicativo stimolare credenze, desideri e intenzioni di essi.

32

Si ipotizza così che gli agenti possano accedere agli stati mentali degli altri, ma nel caso generale non è possibile, a priori, fare tale assunzione. Questo problema si fa sentire soprattutto nel caso di ambienti aperti, nei quali non è possibile, per un agente, verificare che lo stato mentale degli altri rispetti la definizione degli atti comunicativi, a meno di non vincolare, a monte, la stessa implementazione degli agenti (e perdere, quindi, in eterogeneità). 2.10 Dieci peculiarità di un Agente e differenza degli stessi dagli oggetti

Di seguito, viene presentato un elenco che riassume le caratteristiche che connotano un agente, nell’ottica di evidenziare la linea evolutiva che lo lega al concetto di oggetto.

L’elenco segue la struttura proposta da Odell in [2]. 1) Autonomia

Abbiamo più volte messo in evidenza il concetto di autonomia come caratteristica fondamentale di un agente. In particolare, si differenziano due tipi di autonomia: dinamica e non deterministica.

La prima mette in evidenza il fatto che un agente ha la capacità di decidere quando intraprendere una certa azione; l’esecuzione di un’azione è il risultato di un processo interno, che tiene conto degli eventi che si verificano e a cui l’agente è interessato. Un agente, quindi, a differenza di un oggetto, non reagisce unicamente all’invocazione di un metodo, ma a tutto ciò che accade nell’ambiente. Simmetricamente, un agente può decidere quando cominciare l’interazione con altre entità, e può essere coinvolto in più conversazioni contemporaneamente: da qui l’architettura parallela nella realizzazione degli agenti, non contemplata nei sistemi object-oriented.

La seconda tipologia di autonomia ci indica che il comportamento di un agente è, in linea generale, impredicibile. Alla ricezione di un messaggio, un oggetto invoca sicuramente il proprio metodo relativo, mentre un agente risponde liberamente ad esso (ovvero, non è considerato un caso strano se

33

rifiuta di collaborare). L’impredicibilità degli agenti nasce anche dal forte incapsulamento che li caratterizza:

lo stato interno di un agente, ovvero la sua conoscenza, difficilmente è mappabile negli attributi membro di un oggetto, ed è difficile da interpretare dall’esterno;

ciò che all’esterno si vede di un oggetto è la sua interfaccia, mentre nei sistemi multiagente ci sono svariati meccanismi per mostrare all’esterno diversi lati di un agente;

la comunicazione nei sistemi multiagente è tipicamente asincrona, e qualsiasi agente agisce anche indipendentemente da stimoli esterni, di conseguenza è difficile individuare il flusso di comunicazione.

In definitiva, come già abbiamo evidenziato nel capitolo precedente, un oggetto controlla autonomamente il proprio stato, ma non il proprio comportamento (ovvero deve eseguire un proprio metodo pubblico ogni volta che qualcuno dall’esterno lo vuole); per gli agenti, spesso il messaggio assume la forma di richiesta, ma è sempre e comunque l’agente, che riceve la richiesta, a decidere se eseguire l’azione o meno. Il motto “objects do it for free, agent do it for money” riassume bene questo discorso, evidenziando che il centro decisionale è diverso nei due casi: nel caso degli oggetti, sta nell’entità che invoca il metodo, nel caso degli agenti, nell’entità che riceve la richiesta.

2) Interazione La forma più semplice di interazione è quella dei messaggi tra gli oggetti. Gli agenti possono contare su forme di interazione più complesse, per comunicare col proprio ambiente e con gli altri agenti. Un agente può interagire secondo i canoni di un sistema ad oggetti, ma ha contemporaneamente a disposizione un ACL. Tramite il linguaggio, un agente ha la possibilità di instaurare vere e proprie conversazioni costituite da messaggi non rigidamente ridefiniti come quelli degli oggetti. Le interazioni possono durare a lungo nel tempo, e coesistere mantenendo un’identità separata. Per evitare che, in un ambiente aperto, coesistano più linguaggi comunicativi e che, quindi, gli agenti non riescano a parlarsi, si sente la necessità di portare avanti degli standard (come il già citato FIPA-ACL).

34

Un esempio, citato da Odell nell’articolo, di situazione difficilmente realizzabile in un sistema object-oriented è quello di un’entità che accetta un compito, e ne delega la realizzazione a un’altra entità, selezionandola non in base all’interfaccia, ma secondo un algoritmo interno che deve minimizzare una variabile (che può essere, ad esempio, il costo).

3) Decentralizzazione Nei sistemi ad oggetti è presente un univoco flusso di esecuzione, di conseguenza l’organizzazione del sistema è centralizzata. I sistemi multiagente possono comportarsi allo stesso modo, ma sono per loro natura distribuiti. Ogni agente controlla la propria esecuzione, decentralizzando il controllo.

4) Classi e Ruoli Un oggetto nasce come istanziazione della classe a cui appartiene, e può cambiare classe solo se sta in relazione gerarchica con la precedente. Come vedremo in seguito, per gli agenti l’idea di classe diventa quella di ruolo, ma il legame tra l’agente e i ruoli è molto più flessibile: un agente può giocare contemporaneamente più ruoli e ha la possibilità di cambiare uno dei propri ruoli senza le limitazioni gerarchiche degli oggetti.

5) Possibilità a livello di Istanza Mentre le capacità di un oggetto sono rigidamente definite dall’interfaccia della sua classe, quelle di un agente vanno analizzate a livello individuale, poiché può modificarle o acquisirne di nuove.

6) Limitazione nel tempo La morte di individui è il modo con cui i sistemi naturali si organizzano per liberare risorse e riallocarle; questo approccio può essere comparato sia con quello dei sistemi object oriented, sia con quello dei sistemi multiagente, ma nel secondo caso è un approccio esplicitamente adottato.

7) Limitazione nell’impatto L’impatto che un agente ha rispetto al proprio sistema è inferiore di quello di un oggetto. Questa non è una verità assoluta, è vero che molte considerazioni devono essere fatte in base al progetto specifico esaminato, ma nella maggior parte dei casi si nota che se un agente “muore”, il sistema ne risente limitatamente e prosegue la propria esecuzione in maniera stabile,

35

mentre nel caso degli oggetti viene sollevata un’eccezione oppure, a seconda appunto del progetto, si verifica un comportamento anomalo da parte dell’oggetto stesso.

8) Limitazione nella percezione Gli oggetti agiscono e interagiscono “localmente”, ovvero solo con altri oggetti di cui possiedono un riferimento. Questo concetto si estremizza nei sistemi multiagente, nei quali gli agenti, pur avendo la possibilità di interagire non solo in ambito locale, non sono certamente onniscenti: possono percepire e agire solo nelle proprie vicinanze e non ovviamente in ogni punto del sistema.

9) Comportamento emergente La decentralizzazione dei sistemi multiagente rende possibile che la sovrapposizione dei comportamenti dei singoli agenti (ognuno con le proprie regole e i propri obiettivi), ovvero l’analisi del sistema a livello del sistema stesso, evidenzi un comportamento emergente anche molto complicato. La complessità si può incrementare aggiungendo nuovi agenti, il cui progetto impatta sul comportamento unitario del sistema. Risulta, da questo, che l’obiettivo di una società non coincide, in generale, con quello degli agenti che la costituiscono concretamente, ma è piuttosto il risultato del comportamento emergente a livello della società stessa.

10) Analogie con la natura Da alcuni dei punti precedenti è emerso il parallelismo tra i sistemi naturali e i sistemi multiagente. Questi ultimi tentano solamente di emulare i sistemi naturali, senza la pretesa di riprodurne il reale funzionamento, riprendendone l’idea di organizzazione sociale.

36

3. UN LINGUAGGIO DI COMUNICAZIONE PER AGENTI BASATO SUL CONCETTO DI OBBLIGO

SOCIALE

In questo capitolo si vuole andare a spiegare nel dettaglio l’approccio che è stato utilizzato per la fase di progettazione della Finite States Machine e che segue le specifiche esposte in [3]. Tale approccio si basa sulla definizione di protocolli di interazione usati nei sistemi aperti multiagente ed eterogenei. Assumendo che il linguaggio è il componente fondamentale per ogni interazione, viene proposta una semantica per i linguaggi di comunicazione fra agenti, gli Agent Communication Languages (ACL), basata sulla nozione di social commitment. Questa semantica viene da loro usata per definire il significato di un set di atti comunicativi di base. Si propone, inoltre, un metodo, per la definizione dei protocolli di interazione, che è possibile verificare e che è assolutamente indipendente dall’applicazione che lo può utilizzare ad alto livello e il cui componente di base fornisce le specifiche per un diagramma di interazione in cui sono elencate tutte le azioni che possono essere compiute dagli agenti sotto certe condizioni. Tutti i protocolli di interazione fanno affidamento sull’idea di avere delle primitive di comunicazione di base che possano essere usate in maniera assolutamente indipendente dal tipo di applicazione sovrastante che le utilizza. 3.1 Concetti principali

I “Protocolli di Interazione” (Interaction Protocols) rappresentano dei modelli di comportamento che gli agenti, che fanno parte di un sistema, devono seguire per poter interagire con altri agenti all’interno dello stesso sistema aperto multiagente (MAS). In [3] viene evidenziato quanto sia cruciale creare delle buone specifiche per descrivere un protocollo di interazione in quanto l’avvento di Internet ha reso molto urgente lo sviluppo di metodi generali e indipendenti dall’applicazione che li utilizza.

Il framework risultante deve essere in grado di descrivere un gran numero di sistemi aperti, dinamici, eterogenei e distribuiti cercando di fornire

37

una descrizione ad alto livello che, solo da un punto di vista implementativo, verrà adattato nel rispetto delle sue specifiche.

Un protocollo di interazione ben fatto dovrebbe essere capace di rispettare i seguenti requisiti di base:

Specificare una sequenza di atti comunicativi che costruiscono

un’interazione completa all’interno del sistema. Ciascuna primitiva deve mantenere il suo significato così come accadrebbe se si creasse un Linguaggio di Comunicazione fra Agenti standard, per questo del tutto generale e indipendente dall’applicazione.

Consentire l’interazione fra “agenti puramente reattivi” che, per

definizione, non fanno altro che seguire ciecamente il protocollo e “agenti deliberanti” che, invece, sono in grado di ragionare sulle conseguenze di certe azioni e, di conseguenza, decidere autonomamente se prendere parte all’interazione o meno.

Permettere di verificare se un agente del sistema si sta

comportando bene o male in accordo con le specifiche del protocollo. In fase progettuale si è pensato di andare a catalogare gli agenti come “Trustworthy Agents” e “Untrustworthy Agents” in relazione alla condotta degli stessi nel sistema.

D’altronde un metodo assolutamente generale per lo sviluppo di un protocollo d’interazione dovrebbe consentire al progettista di verificare continuamente se un protocollo è robusto in relazione a particolari criteri di solidità. Nel tempo sono stati proposti innumerevoli approcci per la definizione di protocolli di interazione. Alcuni autori hanno creato protocolli di interazione plasmati sull’idea di macchina a stati finiti descritta attraverso i diagrammi di Petri, ma non si sono soffermati sui messaggi effettivamente scambiati durante l’interazione. L’approccio Fornara – Colombetti ritiene assolutamente predominante il prendere in esame il valore dei messaggi scambiati.

38

Altri approcci prendono in esame il significato dei messaggio scambiati, ma non forniscono uno ACL standard con una semantica indipendente dall’applicazione.

Un esempio di specifica per un protocollo di interazione fra agenti è quello proposto da Yolum e Singh in [9], i quali hanno introdotto un metodo basato sul calcolo degli eventi per la definizione di protocolli che possono essere usati dagli agenti artificiali per determinare dei percorsi flessibili di interazione conformi alle specifiche. La principale differenza fra l’approccio proposto da Yolum e Singh in [9] e quello proposto da Fornara e Colombetti è che, in quest’ultimo, tutti i metodi descritti, le precondizioni e gli effetti derivanti dalla performance degli atti comunicativi sullo stato complessivo dell’interazione sono completamente gestiti attraverso le specifiche di protocollo; l’approccio dell’articolo è quello di proporre un metodo tramite cui i progettisti possono, in ogni istante, verificare e monitorare se il protocollo è robusto rispetto a particolari criteri di solidità, indipendente dall’applicazione che lo sta utilizzando e strettamente correlato alla semantica dei messaggi scambiati. Inoltre l’approccio descritto utilizza uno standard ACL con una semantica non ambigua e le definizioni introdotte settano le regole per l’esecuzione di primitive di comunicazione che vengono esaminate come azioni che semplicemente manipolano degli oggetti chiamati “commitment”. 3.1 .1 L’Obbligo Sociale (The Social Commitment)

Uno dei punti chiave dell’approccio che ci apprestiamo a descrivere riguarda la scelta di come andare a descrivere gli effetti di un atto comunicativo all’interno di una società di agenti utilizzando delle entità che siano il più possibile oggettive, non ambigue e osservabili sia da ogni agente comune sia da una qualunque entità superiore. Queste entità sono i social commitments. La nozione di social commitment è molto differente dalla nozione di internal commitment; questi ultimi sono utilizzati dagli agenti per descrivere le loro intenzioni, i loro desideri così come si descrive all’interno dell’approccio BDI (Belief-Desire-Intention) di cui si è parlato nel Capitolo 2. L’idea di base è questa: gli agenti che comunicano fra loro all’interno della società si scambiano dei messaggi attraverso un set di oggetti social commitments che rappresentano

39

una sorta di oggetti istituzionali. D’ora in poi, per indicare il concetto di social commitment, utilizzeremo il termine “commitment”.Un commitment viene creato e manipolato dagli agenti tramite un set di regole approvate tramite un comune accordo interno alla società stessa di agenti. Parlando di commitment si vuole sottolineare l’idea del forte aspetto sociale. La responsabilità di questi oggetti è quella di rendere stabili i rapporti sociali fra gli agenti facendo in modo che il comportamento di altri agenti sia predicibile entro certi limiti. La comunicazione fra agenti non avverrà in modo deterministico, ma in ogni istante il set delle possibili azioni che gli agenti potranno compiere dipenderà fortemente dai precedenti messaggi che gli agenti stessi si saranno scambiati. Intuitivamente un oggetto social commitment rappresenta un impegno preso da un agente (il debtor) verso un altro agente (il creditor) in relazione a un azione che verrà fatta o a un messaggio che i due si scambieranno (il content). Il tutto è stato formalizzato introducendo un tipo di dato astratto: la classe commitment con tutte le sue caratteristiche interne, la sua struttura, la sua evoluzione dinamica nel tempo e i metodi disponibili per manipolare la stessa. Un’istanza di questa classe sarà chiamata: oggetto commitment. In particolare il content di un commitment è rappresentato da una proposizione formale che sarà in grado di assumere differenti valori di verità nell’arco di un certo intervallo temporale entro cui l’azione dovrà essere portata a compimento. Questa proposizione sarà chiamata temporal proposition. Si può tenere traccia dell’evoluzione dinamica nel tempo di un social commitment memorizzando i differenti stati attraverso cui passa lo stesso. Esaminiamo i differenti states: un commitment si dice active quando non ha ancora raggiunto uno stato fulfilled o violated, ciò accade quando il valore di verità del content di un commitment è ancora indefinito (undefined). Un active commitment aspira a diventare fulfilled, se il content del commitment diventa vero (true), o violated, se il content del commitment diventa falso (false). Infine un commitment potrebbe entrare nello stato cancelled, ciò significa che, non essendo soddisfatto, questo sarà eliminato. E’ stato, inoltre, necessario introdurre ulteriori stati alla macchina per far fronte ad alcuni problemi concreti. Esaminiamo un problema concreto: nelle applicazioni reali, come ad esempio nel commercio elettronico, gli agenti spesso hanno la necessità di fare dei commitments non in senso assoluto, ma sotto determinate

40

condizioni. Ad esempio un agente potrebbe decidere di fare un’azione solo a patto che si verifichi un requisito che ne sta alla base. Nell’approccio che stiamo tentando di spiegare, l’idea di un conditional commitment, ovvero di un commitment che si instaura solo a patto che si verifichino certe condizioni, diventa, dunque, un requisito di base mentre la nozione di commitment senza condizioni può essere considerato un caso speciale. Per riuscire ad esprimere ciò, è necessario introdurre nel formalismo dell’oggetto commitment un nuovo campo che rappresenti la condition. Lo stato di un commitment, con una condizione che deve diventare vera affinché il commitment entri nello stato active, è detto stato pending. Un ultimo dettaglio su cui è opportuno soffermarsi: utilizzando l’oggetto commitment come è stato definito è possibile esprimere il significato di vari atti comunicativi come asserzioni (assertives) e promesse (promises), non è invece possibile esprimere il significato di atti di comunicazione diretti come le richieste (requests e questions). Ciò perché quando un agente richiede a un altro agente di fare qualcosa, il suo obiettivo è quello di indurre il secondo agente a fare un commitment. Di solito quando il contesto di interazione non definisce una relazione di autorità fra gli agenti che interagiscono, risulta impossibile per un agente creare un commitment di cui qualsiasi altro agent sia il debtor: un agente non può direttamente obbligarne un altro. Per far fronte al problema si deve notare come, nell’impostare una richiesta, un agente instaura una situazione in cui chi ascolta può creare un commitment solo accettando (accept request) la richiesta stessa. Per risolvere il problema di un commitment che ha un debtor, un creditor, un content, una condition, ma che è stato proposto dal debtor e che il creditor potrebbe accettare o meno, è stato introdotto un nuovo possibile stato: unset. Per visualizzare e prendere atto di tutti i concetti sopra esposti si può fare riferimento alla Figura 3.1.

3.1 .2 Proposizioni Temporali (Temporal Proposition)

Un altro punto chiave dell’approccio ACL, per cui è stato necessario fornire un formalismo, riguarda il content e le conditions di un social commitment. Di norma non è complesso esprimere delle specifiche temporali per contents e conditions separatamente, ma ancora non si è riusciti a capire come esprimere dei vincoli fra loro. Per quanto riguarda gli aspetti temporali,

41

per parlare di contents e conditions viene introdotto un nuovo tipo di dato astratto: una classe temporal proposition. Un oggetto temporal proposition comprende un campo statement che potrebbe trovarsi in uno dei tre possibili stati: vero (true), falso (false), indefinito (undefined). Affinché possa essere usato come content o condition di un commitment, uno statement tipicamente fa riferimento ad un intervallo di tempo e potrebbe accadere che questo periodo di tempo sia nel futuro. In tal caso, nel presente, sarebbe impossibile dire se lo statement è vero o falso; proprio per questo si è introdotto un nuovo stato: indefinito. L’intervallo di tempo è delimitato da due istanti di tempo, gli estremi stessi dell’intervallo, ovvero quello iniziale e quello finale. Gli statements possono legarsi all’intervallo temporale corrispondente attraverso due differenti modi:

gli statements potrebbero doversi mantenere veri per l’intero intervallo temporale (ad esempio “Il prezzo di questa automobile si manterrà a 10.000€ per un mese intero a partire da oggi”);

gli statements potrebbero diventare veri in un qualsiasi momento all’interno dell’intervallo temporale (ad esempio “Ieri è nevicato”).

Utilizzando delle temporal proposition fatte in questo modo si è in grado di coprire un vasto spettro di proposizioni usate comunemente. 3.2 Specifiche Tecniche

Nell’articolo troviamo anche una serie di note tecniche per arrivare a implementare concretamente le nozioni teoriche esposte in prima battuta. Nel mondo in cui interagiscono gli agenti, un sistema aperto, troviamo:

Un insieme variabile di agenti registrati {a,b ...}; l’idea è quella di creare un metodo che consenta ad un nuovo agente di registrarsi e di entrare a far parte del gruppo.

Un set variabile di oggetti commitment {C1,C2 .. }; ciascun oggetto commitment rappresenta un’istanza della classe commitment stessa.

Un set variabile di oggetti temporal proposition {P, Q ... }; ciascun oggetto temporal proposition rappresenta un’istanza della corrispondente classe. Queste proposizioni servono per rappresentare il content e le conditions di un commitment andando ad influenzare l’evoluzione dinamica dello stesso. Attraverso la verità della lista di

42

conditions si va a testare che il commitment possa o meno diventare active (se le conditions sono tutte vere); attraverso la verità del content si va a testare che il commitment possa diventare o meno fulfilled o violated.

Un set fissato di routines di aggiornamento che sono in grado di aggiornare automaticamente lo stato di un oggetto commitment in funzione del valore di verità del content e delle conditions. Queste regole saranno spiegate nel dettaglio nella sezione 3.2.4.

Un set di oggetti specifici di dominio {O1, O2 ... } che rappresentano le entità del mondo dell’applicazione. Tali entità potrebbero possedere sia attributi “naturali”, sia attributi “istituzionali”; ad esempio il colore di un prodotto è una caratteristica naturale mentre il prezzo di un prodotto è una caratteristica istituzionale. Gli “attributi naturali” riflettono le proprietà fisiche delle corrispondenti entità del mondo reale e di norma non possono essere modificati durante l’interazione; al contrario gli “attributi istituzionali” sono legati alle performance di un atto comunicativo e per questo motivo possono essere modificati, ciò accade con proposizioni dichiarative. L’articolo specifica chiaramente che ogni oggetto del dominio deve avere un set di metodi che siano in grado di settare il valore delle proprietà istituzionali.

Un set fissato di ruoli {role1, role2 ... }. Il concetto di ruolo è importante per rendere concrete le azioni che ciascun agente può compiere. Un agente, visto come entità astratta, si concretizza se ad esso viene associato un ruolo specifico a cui sono correlate un set di azioni e di autorizzazioni.

Un set fissato di autorizzazioni (authorizations) associate ai ruoli che specificano quale agente, sulla base del ruolo ad esso attribuito, è autorizzato a compiere una determinata azione.

Lo stato globale St di un sistema al tempo t viene valutato basandosi sulla presenza di un insieme di agenti registrati, di proposizioni temporali, di oggetti commitments e di oggetti specifici del dominio. Di conseguenza quando un agente fa un’azione, il sistema evolve da quello stato a un altro stato globale St+1 dove lo stato interno del commitment, degli oggetti

43

proposizione temporale e degli oggetti specifici di dominio sono cambiati in accordo sia con gli effetti comportati dall’azione eseguita sia in accordo con le regole di aggiornamento del sistema.

3.2.1 Classe Commitment

L’articolo fornisce una descrizione del tipo di dato astratto commitment e, attraverso il paradigma object oriented, questo viene formalizzato come classe definendo sia i campi privati che caratterizzano un oggetto commitment sia i metodi pubblici usati per manipolare lo stesso. Campi Privati Un oggetto commitment contiene i seguenti campi privati:

Identifier: rappresenta l’identificatore univoco dell’oggetto nel sistema. Debtor: è il nome dell’agente registrato che effettua il commitment. Creditor: è il nome dell’agente registrato in relazione a cui il

commitment viene fatto. State: viene utilizzato per tenere traccia dell’evoluzione dinamica

dell’oggetto commitment. Questo campo può assumere uno dei seguenti valori:

unset (u): significa che il commitment è stato proposto (dal suo debtor, o creditor o una terza parte), ma non è ancora stato né accettato né rifiutato;

cancelled (c): significa che il commitment è stato bloccato, chiuso da parte del creditor o rifiutato da parte del debtor, oppure significa che la condizione non è diventata vera;

pending (p): significa che il commitment è stato accettato, ma la condition o la lista di conditions non è ancora diventata vera;

active (a): significa che la condition o la lista di conditions è diventata vera;

fulfilled (f): significa che il content di un commitment attivo è diventato vero;

44

violated (v): significa che il content di un commitment attivo è diventato falso.

L’intero ciclo di vita di un commitment è mostrato in Figura 3.1. Lo stato di un commitment può cambiare per effetto dell’invocazione dei suoi metodi di base (le linee continue in Figura 3.1 ) o per effetto di “cambiamenti ambientali” (la linee tratteggiate in Figura 3.1) ovvero eventi che modificano il valore di verità delle conditions o del content di un commitment. Content: è una temporal proposition che rappresenta lo stato degli

eventi o il corso dell’azione verso cui il debtor si è impegnato. Condition/s: è una lista di temporal proposition che devono essere

soddisfatte all’interno dell’intervallo di tempo indicato affinché il commitment diventi active.

Time-out: è rilevante solo nel caso di unset commitments di conseguenza deve essere trattato come un parametro opzionale. Esprime la durata temporale della vita di un unset commitment.

Un oggetto commitment viene rappresentato con la seguente notazione:

Cid (state, debtor, creditor, content | condition {, time-out}). Esaminiamo ora le caratteristiche relative agli oggetti temporal proposition usati per rappresentare il content e le conditions di un commitment. Le conditions sono una lista di temporal proposition [P,Q, ...] che devono essere soddisfatte affinché il commitment diventi active. Il valore di verità della lista di temporal proposition viene definito seguendo queste regole:

una lista vuota di oggetti temporal proposition è sempre vera; una temporal proposition vera viene rimossa dalla lista; una lista che contiene anche solo una temporal proposition falsa, è falsa.

45

Figura 3.1. Ciclo di vita di un commitment – Macchina a stati finiti.

Metodi di Base Tutti gli oggetti commitment sono creati e manipolati attraverso dei metodi di base. Si assume, infatti, che quando un oggetto commitment viene dichiarato, il costruttore della classe deve allocare un blocco di memoria e creare un oggetto commitment vuoto. I metodi di base sono:

Make commitment: sia il debtor, sia il creditor sono autorizzati ad invocare l’operazione mc(a,b,P,Q) con un arbitrario creditor a, debtor b, content P e condition Q. Gli effetti dell’invocazione di questo metodo sono la creazione di un nuovo unset commitment.

Ci().mc(a,b,P,Q) Ci(unset,a,b,P|Q)

Set commitment: consente, attraverso la sintassi sc(s), di cambiare lo

stato di un commitment esistente settandone lo stato a s. Ci sono due differenti condizioni per chi voglia invocare questo metodo e queste

46

sono relative al valore dello stato corrente e al valore dello stato futuro del commitment.

Se lo stato corrente è unset, il debtor ha l’autorizzazione a settare o lo stato cancelled o lo stato pending.

Se lo stato è pending o active il creditor è autorizzato a settare lo stato a cancelled.

Ci(-, a, b, P|Q).sc(s) Ci(s, a, b, P|Q)

Add condition: consente di aggiungere, tramite il metodo ac(R), un nuovo oggetto temporal proposition R alla lista di conditions di un commitment

Ci(s, a, b, P|Q).ac(R) Ci(s, a, b, P|R • Q) dove il simbolo • sta ad indicare l’inserimento di un nuovo elemento nella lista. Questi metodi di base non sono visti come azioni che vengono compiute direttamente dagli agenti, sono piuttosto delle primitive di basso livello usate per implementare delle operazioni sull’oggetto commitment stesso: gli agenti manipolano, invece, i commitment tramite una serie di atti comunicativi che verranno elencati in seguito. Una nota va posta al fatto che, nell’uso degli ACL, vengono definite delle conditions che stanno alla base affinché un commitment entri in uno stato fulfilled o violated, nonostante ciò, in questa sede, non ci si occupa delle “violazioni” di un atto nei termini di sanzioni. Questo è un aspetto che va oltre l’uso della semantica ACL. 3.2.2 Classe Temporal Proposition

Si introduce la classe temporal proposition con la responsabilità di esprimere tutti i possibili valori dei campi content e condition. Nella classe troviamo elencati i seguenti campi privati; si suppone che siano definiti i metodi Get e Set per accedere in lettura o scrittura a ciascuna di tali proprietà.

Statement: rappresenta una proposizione. Il valore di verità (truth-

value) di uno statement può essere vero (1), falso (0) o indefinito (⊥).

47

Time Interval: rappresenta il periodo di tempo a cui la proposizione,

espressa nel campo statement, si riferisce.

Mode: esprime la qualifica temporale del campo statement. Si può

richiedere allo statement di rimanere vero per l’intero intervallo di

tempo (∀), o si può pensare che lo statement diventi vero durante

l’intervallo di tempo definito (∃).

State: può essere vero (1), falso (0) o indefinito (⊥). Si assume che il

valore di verità di una temporal proposition venga continuamente

aggiornato da uno specifico “notifier” secondo le seguenti regole:

Se il valore di mode è “∃”, il notifier setta il valore di verità a

vero se il valore dello statement diventa vero in un qualsiasi

momento del time interval, altrimenti setta il valore a falso

quando l’intervallo di tempo scade.

Se il valore di mode è “∀”, il notifier setta il valore di verità a

falso se il valore dello statement diventa falso in un qualsiasi

momento del time interval, altrimenti setta il valore a vero

quando l’intervallo di tempo scade.

E’ importante notare che quando il valore di verità di una temporal proposition cambia, diventando, da indefinita, vera o falsa, non può poi più cambiare il suo valore. Si denota col simbolo TRUE una temporal proposition costante con uno statement vuoto e uno state che è vero. 3.2.3 Azioni

Un agente può eseguire parecchie azioni nell’ambiente in cui si trova a vivere. Il set di azioni che l’agente può eseguire comprende:

tutte le azioni presenti nella libreria degli atti comunicativi (communicative acts library), dove ciascun azione viene definita utilizzando le operazioni di base che vengono compiute sull’oggetto commitment o altre azioni già definite;

48

tutte le azioni presenti in un set di application domain actions. Ciò

accade nei sistemi di interazione utilizzati per negoziare alcuni prodotti (ad esempio “paga x$ a b” oppure “consegna x quantità di merce ad a”).

3.2.4 Le regole di aggiornamento della macchina a stati (Update rules)

Quando una temporal proposition, content o lista di condition che sia associata a un commitment, cambia il suo stato da indefinito a vero o falso, è necessario aggiornare lo stato dell’oggetto commitment. La formalizzazione di tutto ciò avviene attraverso una serie di routines invocate in automatico utilizzando le regole di aggiornamento descritte nella Tabella 3.1. La prima colonna contiene l’evento che fa scattare la regola, mentre la transizione di stato associata è descritta nella seconda colonna. Il metodo state() serve per andare a reperire, dalla classe temporal proposition, lo stato stesso associato alla temporal proposition.

Di seguito andiamo a spiegare nel dettaglio cosa fanno le varie regole:

Rule 1 Quando il commitment è active e il suo content diventa “true”, il commitment cambia il suo stato entrando in fulfilled.

Rule 2 Quando il commitment è active e il suo content diventa

“false”, il commitment cambia il suo stato entrando in violated.

Rule 3 Quando la condition di un commitment che è in stato pending diventa “true”, il commitment cambia il suo stato diventando active.

Rule 4 Quando la condition di un commitment che è in stato pending

diventa “false”, il commitment cambia il suo stato diventando cancelled.

49

Rule 5 Questa regola serve per gestire la situazione in cui un agente esegue un’azione di richiesta senza accettare la richiesta esplicitamente. E’importante che l’azione descritta dalla temporal proposition P sia un’azione compiuta dal debtor di un commitment. In questo caso il commitment è unset, ma l’esecuzione dall’azione descritta tramite P dal debtor b del commitment, fa cambiare lo stato dello stesso in active e, subito dopo, la Rule 1 lo cambia in fulfilled. Una possibile soluzione per rendere esplicita la connessione fra l’azione effettuata e la richiesta di fare quell’azione viene risolta attraverso un riferimento esplicito fatto dall’attore della richiesta associata.

Rule 6 Quando il content di un commitment diventa “true”, anche se

la condition o la lista di condition è ancora “undefined”, il commitment cambia comunque il suo stato diventando fulfilled.

Rule 7 Quando il valore del time-out di un unset commitment scade,

il commitment cambia il suo stato diventando cancelled.

Tabella 3.1. Macchina a stati finiti – Regole di aggiornamento degli stati.

3.3 Definizione dei principali atti comunicativi (Speech Acts)

In questa sezione si esamina come le operazioni di base, utilizzate sugli oggetti commitment, possono essere utilizzate anche per esprimere il significato di alcuni importanti atti comunicativi specialmente quelli comunemente usati nel processo si interazione dei sistemi aperti multiagente. Il set di atti comunicativi costituisce una Libreria di Atti Comunicativi. La tassonomia che si segue, quella di Searle, consente di suddividere gli atti di comunicazione in

50

cinque grandi categorie: assertives (atti di asserzione), commissives (atti di promessa), directives (atti di richiesta), declarations (atti dichiarativi) e expressives (atti espressivi). In questa sede, l’approccio che stiamo discutendo decide di non soffermarsi sugli atti espressivi, in quanto ritenuti poco significativi per la comunicazione di base fra agenti. Mentre si parlerà delle proposals (atti di proposta) per la loro importanza all’interno delle applicazioni di commercio elettronico. Gli atti di proposta non appartengono a una delle cinque categorie sopra elencate, ma si costruiscono a partire dagli atti di promessa e di richiesta. Nella definizione di ogni primitiva compare un mittente, un destinatario, il contenuto del messaggio, in alcuni casi una condizione. Sono elencati qui, di seguito, i simboli usati nella definizione degli atti comunicativi:

“=def”: indica che l’espressione alla destra e alla sinistra del simbolo di

uguaglianza sono assolutamente equivalenti;

“:=”: indica che la primitiva citata alla sinistra del simbolo si comporta

come viene indicato alla destra del simbolo. La primitiva invocata

deriverebbe dalla sequenziale esecuzione di tutta una serie di metodi che

sono elencati dalla parte destra rispetto al simbolo;

{op1; … ; opn}: indica che le operazioni di base elencate, op1, … , opn,

sono eseguite in sequenza;

{op1 ∧ … ∧ opn}: indica che le operazioni di base elencate, op1, … , opn,

sono eseguite in parallelo;

∨ : il simbolo viene usato come or logico; ciò significa che l’azione, alla

sinistra del simbolo, si esegue quando anche una sola delle condizioni

alla destra del simbolo è realizzata;

•: il simbolo denota l’operazione di inserimento di un nuovo elemento

all’interno di una lista.

3.3.1 Asserzioni (Assertives)

In accordo con la Teoria degli Atti Comunicativi, l’obiettivo di un’asserzione, fatta da chi parla, è quello di andare a convincere chi ascolta della verità di ciò che viene comunicato. Si considererà l’inform come atto comunicativo di base o archetipo utilizzato proprio con il ruolo di asserzione.

51

Inform. Questo primitiva viene utilizzata quando un agente a vuole

informare un agente b della verità di una certa proposizione P. Un esempio per P potrebbe essere: “Il mio nome è ...”, “Adesso sta piovendo ...” etc. In un approccio basato su commitment, l’atto di informare viene descritto attraverso la seguente sintassi:

inform(a, b ,P) := {Ci().mc(a,b,P,TRUE);Ci(unset, a, b, P|TRUE).sc(pending)} Il risultato finale, grazie all’intervento della Regola di Aggiornamento 3, è la creazione di un commitment in stato active.

3.3.2 Richieste (Directives)

La caratteristica principale di un atto di richiesta è quella di indurre chi ascolta a compiere una certa azione entro un intervallo di tempo. Si deve puntualizzare, però, che un agente non può obbligare un altro a fare qualcosa, ma può solamente chiedere a quest’ ultimo se accettare o meno di impegnarsi in relazione a un certo commitment.

Request. Come directive di base è stata scelta la request. Ci sono delle richieste che tentano di indurre chi ascolta ad accettare un commitment senza l’imposizione di nuove condizioni come ad esempio “Ti va di prestarmi il tuo libro?”. Ce ne sono altre che, al contrario, inducono chi ascolta ad accettare il commitment con una condizione imposta ad esempio “Se piove, mi puoi prestare un ombrello per tornare a casa?”. Si deve puntualizzare che la realizzazione di una condizione non è in potere di chi parla. La richesta fatta da un agente a ad un agente b relativamente a P entro un certo intervallo di tempo se la condizione Q è soddisfatta, viene definita come segue:

request(a, b, P, Q) := { Ci().mc(b, a, P, Q) }

52

Ovviamente, quando la condizione non è presente, è sufficiente effettuare la richiesta ponendo come simbolo TRUE al posto della condizione Q. Alcune richieste possono essere soddisfatte immediatamente, per questo una risposta alla richiesta stessa potrebbe rappresentare l’esecuzione subitanea dell’atto comunicativo, oppure possono essere rifiutate. Nell’esempio “Chiudi la finestra per favore”, se il debtor di un commitment in stato unset esegue immediatamente l’azione richiesta, la Regola di Aggiornamento 5 viene attivata e lo stato dell’oggetto passa da unset ad active. Al contrario, se la richiesta viene rifiutata, il commitment da unset diventa cancelled. In ogni caso, comunque, grazie alla Regola di Aggiornamento 7, un commitment in stato unset viene in automatico settato a cancelled dopo lo scadere di un certo time-out predefinito. Ci sono, inoltre, richieste che non possono essere soddisfatte nell’immediato come ad esempio “Per favore, mi dai una copia del tuo manoscritto?”. In questo caso colui che ascolta, ovvero il debtor di un commitment in stato unset, può reagire accettando o rifiutando la richiesta. Se accetta si impegna a eseguire la richiesta, altrimenti no. Riassumendo fra le differenti possibilità: chi è il destinatario di una richiesta può reagire in tre differenti modi: può eseguire immediatamente l’azione richiesta (perform), accettare la richiesta (accept), ma eseguirla successivamente, oppure rifiutare la richiesta stessa (reject). Se comunque il time-out scade, il commitment in automatico viene posto in uno stato cancelled.

Question. Una domanda è un particolare atto di richiesta tramite cui, chi parla, tenta di obbligare chi ascolta a credere alla verità di una certa proposizione che viene comunicata. Una domanda può essere vista come “una richiesta fatta per informare” qualcuno su qualcosa. Nell’articolo vengono trattate solamente wh-Question, e non yes-no-Questions, dove l’atto di richiesta, fatto con lo scopo di informare, non

53

può essere completamente descritto da chi fa la richiesta stessa. In questo caso chi effettua la domanda ha a disposizione una sorta di “template” per la risposta che è una temporal proposition S(x) che contiene una meta variabile x che il ricevente deve andare a sostituire con un valore costante c. La sintassi risultante si presenta sotto questa forma:

request(a, b, P) where P. statement() = inform(b, a, S(x)) inform (b, a, S(x)) =def inform(b, a, S(c))

per qualche valore costante c.

Questa definizione implica che la performance di un atto di richiesta, fatto per informare, con una temporal proposition S(c) come parametro rende la temporal proposition P vera.

D’altronde, come ha approfondito Searle (citato nell’articolo stesso), il concetto di “question” è un concetto molto generale in quanto, tramite una domanda, un agente potrebbe richiedere l’esecuzione di un atto comunicativo non di asserzione, ma ad esempio potrebbe rispondere con un’ altra domanda o con una promessa. L’approccio che è stato proposto dall’articolo prevede la massima generalizzazione possibile e, a riguardo, si può trovare un’applicazione concreta di quanto detto nell’esempio dell’asta inglese.

3.3.3 Promesse (Commissives)

L’obiettivo di una promessa è quello di porre in obbligo il debtor, relativamente al creditor, riguardo lo svolgimento di una particolare azione entro un certo intervallo temporale. Di seguito vengono presentate tutte le principali primitive che sono coinvolte in un atto di promessa.

Promise. L’idea di base è che un agente a può promettere a un agente b che a è disposto ad impegnarsi in relazione a ciò che viene espresso all’interno della proposizione P entro un certo intervallo di tempo nel futuro. Possono essere apportati innumerevoli esempi quali: “Prometto che domani ti verrò a portare il libro che mi hai prestato”. Come di

54

norma, l’agente a può promettere qualcosa all’agente b, ma solo a patto che si avveri una condizione Q (il suo valore di verità deve diventare vero entro un intervallo prefissato che precede l’intervallo in cui deve diventare vero il valore di verità della temporal proposition P). Inoltre si deve puntualizzare che l’agente b potrebbe essere o meno responsabile del fatto che la temporal proposition Q diventi vera. Un esempio in cui il valore di verità della condition non dipende da chi ascolta potrebbe essere “Se domani piove, io ti pagherò 10€ dopodomani”. Un esempio invece in cui il valore di verità della condition dipende da chi ascolta potrebbe essere “Se tu mi paghi entro in tempo t1, io prometto che ti porterò al cinema entro un tempo t2” dove t1<t2. Una possibile sintassi per esprimere questa primitiva può essere: promise(a, b, P, Q) :=

{ Ci().mc(a, b, P, Q); Ci(unset, a, b, P|Q).sc(pending) } Quando la condition non è presente, è sufficiente ancora una volta andare a considerare il valore dalla Q come TRUE (è come se avessimo a che fare con una lista di condizioni tutte vere). Il risultato finale generato dall’intervento della Regola di Aggiornamento 3 è la creazione di un commitment in stato active.

Accept, Reject, Conditional Accept. Sono le tre primitive di comunicazione che si possono compiere solo in risposta a un commitment in stato unset. Come risposta ad un commitment che si trova in stato unset, l’atto di “accept” va a trasformare il commitment in pending o in active a seconda che ci sia o meno una condizione che debba essere soddisfatta, mentre con l’azione del “reject” un commitment, dallo stato di unset, entra in uno stato di cancelled. La precondizione: ∃ Ci(unset,b,a,P|Q)

Una possibile sintassi per esprimere queste primitive può essere:

55

accept(b, a, Ci(unset, b, a, P|Q)) := { Ci(unset, b, a, P|Q).sc(pending) }

reject(b, a, Ci(unset, b, a, P|Q)) := { Ci(unset,b,a,P|Q).sc(cancelled) }

Massiccio uso si fa anche di un’altra primitiva che è presente soprattutto negli esempi di commercio elettronico e che viene utilizzata in particolare dagli agenti per negoziare la condizione di un unset commitment: la “conditional accept”. Nel protocollo dell’English Auction, ogni volta che viene iterato il processo di offerta, il banditore dell’asta accetta l’offerta correntemente più alta a patto che nelle iterazioni successive non vengano effettuate offerte più alte. In generale il debtor di un unset commitment può accettare che venga introdotta una nuova condizione, rappresentata da un oggetto temporal proposition. La “Conditional Accept” introduce una nuova condizione alla lista attuale di condizioni relative all’unset commitment e trasforma quest’ultimo in un pending commitment. La precondizione: ∃ Ci(unset,b,a,P|Q)

Una possibile sintassi per esprimere questa primitiva può essere:

condAccept(b, a, Ci(unset, b, a, P|Q), R) :=

{ Ci(unset, b, a, P|Q).ac(R);

Ci(unset, b, a, P|R • Q).sc(pending); }

3.3.4 Dichiarazioni (Declarations) Le dichiarazioni sono delle particolari primitive di comunicazione

utilizzate frequentemente in tutti gli esempi relativi all’asta. A questo proposito una dichiarazione potrebbe essere “Dichiaro l’asta aperta” o “Dichiaro l’asta chiusa”.

Il punto chiave di una dichiarativa è che questa ha come obiettivo quello di andare a cambiare il mondo, non nel senso di apportare cambiamenti fisici o ambientali nello stesso, ma nel mondo inteso in senso istituzionale come

56

insieme di vincoli e di regole che tutti gli agenti che appartengono a quel mondo devono comunque, in un qualche modo, rispettare. Nel framework, che questo articolo punta a costruire passo passo, le dichiarative diventano responsabili dell’introduzione di oggetti che posseggono delle “proprietà istituzionali” nate dal comune accordo e dalla comune intesa di tutti i membri della società. Queste proprietà possono essere espresse tramite le dichiarazioni.

Diventa, quindi, fondamentale e assolutamente necessario andare a identificare quali agenti sono effettivamente “autorizzati” a fare una dichiarazione nel sistema in esame. Tipicamente le autorizzazioni sono assegnate agli agenti in virtù del “ruolo” che essi stessi giocano nell’interazione all’interno del sistema. Si instaura, dunque, una corrispondenza biunivoca stretta fra le autorizzazioni associate ai ruoli e i ruoli stessi. E’ necessario, per questo motivo, introdurre un costrutto che possa esprimere come un agente, che possiede un determinato ruolo all’interno della società, sia autorizzato a portare avanti un cambiamento istituzionale di un certo tipo nel sistema di interazione fra agenti.

Nell’articolo, la sintassi utilizzata per parlare delle dichiarative è così presentata:

preconditions: empowered(rolei, Ok. setPropj()) ∧ a.role() = rolei)

declare(a, Ok.propj = x) := { Ok. setPropj(x) }

3.3.5 Proposte (Proposals) Queste primitive non appartengono a una delle cinque categorie di base

sopra citate e introdotte dalla Speech Act Theory. Nonostante tutto, proprio perché queste sono particolarmente usate all’interno del commercio elettronico, l’approccio che stiamo spiegando ha pensato di inserirle all’interno della propria Libreria degli Atti Comunicativi come primitive che uniscono, per essere definite, vari atti comunicativi di base. Una proposta è vista come la congiunzione di una richiesta con condizione e di una promessa con condizione. Un esempio che potrebbe essere fatto da un agente a ad un agente b si presenterebbe in questo modo: “Mi presti il libro entro il termine di tempo t2 se ti prometto che entro un tempo t1 te lo pago?” dove t1<t2. Per questo motivo, una proposta è molto simile a una

57

richiesta ma con una condizione non vuota. La differenza sostanziale, a livello concettuale e pratico, sta nella condizione: nella proposta la realizzazione della condizione dipende da chi parla. Una possibile sintassi per esprimere questa primitiva può essere:

propose(a, b, P, Q) :=

{ request(a, b, P, Q) ∧ promise(a, b, Q, S)

where S. statement() = Ci(pending, b, a, P|Q) }

E’ importante rilevare che la promessa si lega alla richiesta attraverso il comune oggetto temporal proposition Q. 3.4 Usi significativi della semantica descritta

La definizione di uno standard e di una semantica oggettiva per gli ACL sono due dei problemi più significativi incontrati nell’ambito della comunicazione artificiale. Quali possono essere i “pregi e i vantaggi” di una semantica basata su commitments? Di seguito sono elencate varie funzionalità realizzate da tale semantica:

La definizione di messaggi disponibili in vari sistemi di interazione, o di quelli che, più in dettaglio, sono utilizzati nei protocolli di interazione stessa, che sono oggettivi e non ambigui. Ciò consente il loro utilizzo sia in ambito umano sia in ambito artificiale. Ad esempio si può definire un set di atti comunicativi disponibili specificatamente per l’asta.

La semantica proposta per gli ACL non effettua nessuna sorta di assunzione a priori relativamente alla struttura interna di un agente artificiale che può utilizzare la semantica stessa. Gli agenti possono essere, infatti, sia reattivi sia deliberanti. Gli agenti deliberanti potrebbero usare la semantica per riflettere sulle loro azioni e su quelle degli altri partecipanti per poter così pianificare i propri atti comunicativi. In altre situazioni, in cui per esempio il tempo disponibile fra due interazioni successive risulta molto corto, un agente che reagisce

58

immediatamente si comporterebbe sicuramente in maniera più efficiente.

Mantenere traccia dell’evoluzione dinamica della società in base alle azioni fatte dagli agenti. E’ possibile per ogni agente, o per qualsiasi entità istituzionale, verificare se un agente si sta comportando in maniera corretta in accordo coi suoi commitment (impegni sociali).

Rendere stabile la comunicazione fra gli agenti. Ciò è possibile in quanto i commitment creati hanno implicita la prospettiva che un altro agente si dovrà comportare in un certo modo.

Progettare dei sistemi di interazione che non forzino le azioni degli agenti che partecipano. Una sequenza arbitraria di messaggi in genere non corrisponde a un’interazione sensata. Perché lo sia, il protocollo di interazione deve soddisfare certe “condizioni di robustezza” che forniscono delle garanzie per alcune importanti proprietà nel processo di interazione o nel protocollo stesso.

Testare se un agente si sta comportando bene o male in accordo con le regole adottate nel protocollo. Questa verifica è detta “test di conformità”.

Dato che la semantica proposta parte dalla formalizzazione di studi fatti sulla comunicazione umana, l’uso di questa semantica diventa cruciale quando si vuole ottenere un pool di interazioni fra esseri umani e agenti software.

La nozione di “commitment”, definita in questa sede insieme alla definizione del significato degli atti comunicativi di base, forma ciò che viene chiamato come “Core Institution” (nucleo del sistema) che può essere utilizzato per definire alcuni atti istituzionali come conversazioni, autorità, obblighi e permessi.

3.5 Dalla fase di analisi alla fase di progettazione

L’obiettivo principale di questa tesi è la realizzazione di un framework che implementi la macchina a stati finiti basata sul concetto di commitment con lo scopo di appoggiare, su di essa, l’applicazione concreta di un’asta inglese. In questa sezione si vanno a descrivere i diagrammi UML, che abbiamo progettato e che ci hanno consentito di mappare l’approccio implementativo che abbiamo

59

seguito per realizzare il framework. Vogliamo presentare la tipologia di implementazione scelta, ed esporre il tipo di approccio progettuale utilizzato per analizzare le specifiche. Questi stessi requisiti, inizialmente solo concetti puramente teorici, sono stati tradotti in classi progettuali concrete, ciascuna legata da relazioni particolari alle altre e soprattutto ciascuna dotata di ben definite responsabilità. Si parlerà delle classi, create per descrivere i concetti, solo in modo superficiale in quanto, per ulteriori approfondimenti, si rimanda alla tesi in [10]. 3.5.1 Diagrammi UML 1) Prima evoluzione del diagramma - Diagramma UML concettuale In Figura 3.2 riportiamo un primo approccio approssimativo di mappatura dei concetti base di cui si è parlato nelle sezioni precedenti. E’ solo un’ idea delle classi che potrebbero essere create; queste, però, non sono ancora riempite, non compaiono né campi privati, né metodi e le varie responsabilità delle stesse classi appaiono, all’inizio, piuttosto nebulose.

Figura 3.2. Diagramma UML Concettuale – Primo step.

TimeInterval

1

0..*

1..* 1

1..*

1

1..2

0..*

1

1..*

Agent

Commitment

Role

Statement

TemporalProposition

60

Come si vede dalla figura, ci sono delle entità basilari, in questo approccio, che non possono essere descritte se non tramite classi che riflettono fedelmente i nomi e le responsabilità presentati nei requisiti. Queste sono le classi rappresentative dell’agente, dell’oggetto commitment e dell’oggetto temporal proposition. 2) Seconda evoluzione del diagramma – Diagramma UML concettuale

Figura 3.3. Diagramma UML Concettuale – Secondo step.

Commitment

AuthorityManager

CommitmentManager

TemporalProposition

Role

Statement

«interface»

IAgentActions

1

0..*

1..* 1

1..*

1

1..2 0..*

1

1..*

0..*

0..1

0..*

0..1

0..* 1

Agent

TimeInterval

Workgroup

WorkgroupManager

0..*

0..*

0..*

1

1

0..*

61

In Figura 3.3 notiamo come il diagramma si sia ampliato, pur presentando ancora le caratteristiche di grafico concettuale. Sono state, qui, introdotte delle nuove classi, nate da necessità implementative, capaci di descrivere meglio le specifiche contenute nei requisiti. Queste sono le classi Workgroup e WorkgroupManager, delle cui responsabilità parleremo nella prossima sezione, che servono per gestire ad alto livello gli agenti che sono presenti nella società. E’ stata introdotta la classe AuthorityManager con il compito di monitorare i comportamenti degli agenti dichiarando “trustworthy” quelli che stanno rispettando i propri commitment, ovvero gli obblighi presi nei confronti della società, e dichiarando “untrustworthy” quelli che, invece, hanno perso la loro credibilità agli occhi della comunità stessa in cui vivono. E’ stata, inoltre, introdotta la classe CommitmentManager con lo scopo di gestire tutti gli oggetti commitment presenti nel sistema. 3) Terza evoluzione del diagramma – Diagramma UML progettuale

In Figura 3.4 ed in Figura 3.5 vengono presentati i due pezzi in cui è stato scomposto il grafico definitivo progettuale. Per una visione totale del diagramma si rimanda all’Appendice. Questo è il diagramma UML di fondamentale importanza per la comprensione del framework creato, in quanto è quello che più si avvicina alla reale implementazione che è stata data al framework stesso. Qui sono presenti le definizioni degli attributi e dei principali metodi di ogni classe. Non sono stati riportati tutti gli handler, metodi utili non solo per descrivere il reale funzionamento degli atti di comunicazione a livello di implementazione ma anche utili come metodi di appoggio da eseguire ogni volta che veniva scatenato un evento dal sistema, in quanto sono davvero innumerevoli e come al solito essi, servendo per il funzionamento della macchina a basso livello, rischierebbero di farci perdere la percezione di quelle che sono le reali responsabilità delle classi. Parlaremo, ora, proprio di queste responsabilità di base delle classi. Rimandiamo a [10] per un esame dettagliato della macchina a stati finiti.

62

Figura 3.4. Diagramma UML Progettuale - prima parte.

63

Figura 3.5. Diagramma UML Progettuale - seconda parte.

64

3.5.2 Diagramma UML – Analisi delle responsabilità

IAgentActions

Tale interfaccia rappresenta le azioni che ogni agente, in base al contesto applicativo in cui si trova ad operare, può compiere. E’ in associazione con la classe Role proprio per indicare che ogni ruolo ha il suo specifico set d’azioni.

Role e ConcreteRole

Role è la classe rappresentativa di un ruolo; è definita “astratta” in modo da essere quanto più indipendente dall’applicazione. Ogni utilizzatore potrà derivare le proprie classi “concrete” da questa, in modo da implementare diverse politiche di attribuzione delle azioni agli agenti dei differenti domini applicativi che sta sviluppando. La classe ConcreteRole è un esempio concreto di specializzazione della classe e, da essa, saranno derivate le classi concrete relative ai ruoli all’interno dell’esempio dell’asta inglese di cui si parlerà nel prossimo capitolo. Particolare importanza riveste il metodo

«interface»

IAgentActions

+RoleName() : string

+ConcreteRole()

+ConcreteRole(in roleName : string)

-_concreteActions : ConcreteAgentActions

ConcreteRole

+MakeEmpowerable(in _agentActions : ConcreteAgentActions)

-_obj : object

-_actions : IAgentActions

«abstract»Role

65

MakeEmpowerable() attraverso cui si possono associare le azioni al ruolo specifico attribuito.

Agent

Agent è la classe che rappresenta l’agente che fa parte del sistema. E’ definita “abstract” per poter permettere all’utilizzatore del framework di poter derivare i propri agenti a seconda del dominio applicativo d’interesse. Un esempio concreto è quello dell’asta inglese che descriveremo in seguito. Nella rappresentazione della classe manca l’elenco di tutti quegli handler, metodi che ciascun agente specifico deve implementare o meglio ridefinire per attuare le politiche di gestione delle proprie primitive: OnRequestClientHandler(), PerformRequestClientHandler(), AcceptRequestClientHandler(), OnPromiseClientHandler(), AcceptPromiseClientHandler(), ConditionalAcceptPromiseClientHandler(), OnProposeClientHandler(). Da notare che sono presenti in questa classe tutti i metodi per identificare gli atti primitivi di comunicazione di un agente; un agente può informare un altro di qualche cosa attraverso un’Inform(), può fare una richiesta attraverso una Request(), può fare una promessa tramite una Promise(), può fare una proposta con una Propose() e può dichiarare una sua verità attraverso una Declare().

+Inform(in creditor : Agent, in content : TemporalProposition)

+Request(in debtor : Agent, in content : TemporalProposition, in conditions[0..n] : TemporalProposition)

+Promise(in creditor : Agent, in content : TemporalProposition, in conditions[0..n] : TemporalProposition)

+Propose(in debtor : Agent, in content : TemporalProposition, in conditions[0..n] : TemporalProposition)+Declare(in content : TemporalProposition)

-_idAgent : int = 0-_name : string

-_role : Role

-_commitments[0..n] : Commitment

-_workgroupOwner : Workgroup

-_proposing : bool = false

«abstract»

Agent

66

AuthorityManager

La classe AuthorityManager rappresenta l’autorità che tiene traccia della credibilità degli agenti, inoltre autentica le varie azioni che ogni agente può intraprendere. E’ un “singleton” poichè è concettualmente unica all’interno del sistema e può essere adoperata tramite la sua singola istanza , staticamente, tramite il metodo GetInstance().

Workgroup

La classe Workgroup formalizza il concetto di “gruppo di lavoro” per gli agenti presenti in un sistema. Sono possibili diversi Workgroup, vale a dire che è data la possibilità di istanziare più gruppi con l’unico vincolo di un nome univoco. La gestione dei diversi gruppi che, tra l’altro, hanno come responsabilità quella di assegnare gli identificatori agli agenti, avviene tramite la classe WorkgroupManager. Un’altra restrizione è rappresentata dal fatto che due agenti, che appartengono a gruppi differenti, non possono comunicare fra loro. In tutti gli esempi che esamineremo, noi lavoreremo con un solo gruppo di lavoro. Ogni agente può entrare a far parte del gruppo (Join()), può abbandonarlo (Leave()) o può essere espulso dallo stesso (Remove()).

+Empower(in role : Role, in agentActions : IAgentActions)+AddTrustfulAgent(in a : Agent)

+AddUntrustfulAgent(in a : Agent)

+GetInstance() : AuthorityManager

-_instance : AuthorityManager

-_empoweredRoles[0..n]-_trustfulAgents[0..n] : Agent

-_untrustfulAgents[0..n] : Agent

«singleton»

AuthorityManager

+Join(in a : Agent)+Leave(in a : Agent)

+Remove(in a : Agent)

+GetNextAgentId() : int

+UpdateDeclarations(in c : Commitment)

-_name : string-_agents[0..n] : Agent

-_nextAgentId : int = 1

Workgroup

67

WorkgroupManager

La classe WorkgroupManager amministra i diversi Workgroup presenti nel sistema, controllando l’univocità dei loro identificatori, vale a dire il nome dei differenti gruppi. E’ un “singleton”, per questo motivo è presente una sola istanza di questa classe in tutto il sistema ed, ad essa, si può accedere solo attraverso il metodo GetInstance().

Commitment

La classe Commitment è il cardine del sistema progettato. Come descritto in precedenza, ogni agente può creare un numero indeterminato di istanze di tale classe, purché mantenga fede agli obblighi vincolanti che gli oggetti commitment creano ogni volta che essi stessi vengono creati. Non rispettare gli obblighi significa non essere considerati credibili agli occhi della comunità e ciò implica, nella nostra implementazione, l’essere dichiarati agenti “untrustworthy”.

+AddWorkgroup(in wg : Workgroup)

+RemoveWorkgroup(in wg : Workgroup)

+GetInstance() : WorkgroupManager

-_instance : WorkgroupManager

-_workgroups[0..n] : Workgroup

«singleton»WorkgroupManager

+MakeCommitment(in creditor : Agent, in debtor : Agent, in content : TemporalProposition, in conditions[1..n] : TemporalProposition)

+SetCommitment(in newState : States)

+AddCondition(in cond : TemporalProposition)

+RemoveCondition(in cond : TemporalProposition)

+EnableTimeOut(in interval : int)

-_idCommitment : int

-_creditor : Agent

-_debtor : Agent

-_timeOut

-_state : States = unset

-_content : TemporalProposition

-_conditions[1..n] : TemporalProposition

Commitment

68

CommitmentManager

CommitmentManager è una classe “singleton”: possiede un’unica istanza creata sempre una sola volta e riutilizzata tutte le volte successive. Tale classe tiene traccia dei commitment generati dagli agenti presenti nel sistema, regola i cambiamenti di stato, si occupa della registrazione degli agenti, a livello di eventi del sistema, presso l’AuthorityManager ed, infine, gestisce l’attribuzione, ai commitment ed alle temporal proposition, del proprio identificativo numerico unico nel sistema.

TemporalProposition

La classe TemporalProposition nasce per essere parte integrante di un oggetto commitment in quanto rappresenta la logica comunicativa ed espressiva, nonché semantica, delle istanze della classe Commitment stessa. Una considerazione va fatta in merito al metodo SetTruthValue() il quale è responsabile del cambiamento del valore di verità di una proposizione. Questo

+AddCommitment(in c : Commitment)

+AddDeclaration(in c : Commitment)+RemoveCommitment(in c : Commitment)

+CheckCommitmentConditions(in id : int) : bool

+GetInstance() : CommitmentManager

+GetNextCommitmentId() : int

+GetNextTemporalPropositionId() : int+GetAgentCommitments(in idAgent : Agent)

+GetTemporalProposition(in idTemporalProposition : TemporalProposition) : TemporalProposition

+GetCommitmentId(in idTemporalProposition) : int

-_instance : CommitmentManager

-_commitments[0..n] : Commitment

-_declarations[0..n] : Commitment-_nextCommitmentId : int

-_nextTemporalPropositionId : int

«singleton»CommitmentManager

+SetTruthValue(in thruthValue)

-_idTemporalProposition : int-_mode : Modes

-_truthValue : TruthValueModes

-_statement : Statement

-_timeInterval : TimeInterval

TemporalProposition

69

cambiamento determina l’aggiornamento e la modifica degli stati all’interno della macchina a stati finiti.

TimeInterval

La classe TimeInterval indica l’intervallo di tempo a cui l’oggetto TemporalProposition si riferisce. Essa è caratterizzata da due estremi, uno minimo e uno massimo ed, inoltre, ogni istanza di questa classe tiene traccia della proposizione temporale a cui si riferisce.

Statement

Statement è la classe che si lega all’oggetto TemporalProposition e rappresenta il contenuto reale della frase che deve essere comunicata. E’ definita “abstract” per poter permettere, all’utilizzatore del framework, di poter derivare i propri ConcreteStatement a seconda del dominio applicativo di interesse. Ha, al suo interno, il riferimento alla proposizione temporale a cui si riferisce.

-_minExtreme : int

-_currentValue : int

-_maxExtreme : int-_tpOwner : TemporalProposition

TimeInterval

-_innerStatement : object

-_tpOwner : TemporalProposition

«abstract»Statement

+ConcreteStatement()

+ConcreteStatement(in phrase : string)

+ConcreteStatement(in phrase : string, in tpOwner : TemporalProposition)

-_phrase : string = String.Empty

ConcreteStatement

70

Concludiamo qui il riepilogo delle responsabilità delle classi principali,

rimandando a [10] per l’analisi delle relazioni fra le classi stesse attraverso la chiarificazione delle molteplicità che le legano. 3.6 Struttura dei packages utilizzati L’ultimo argomento, affrontato in questa sezione, riguarda la struttura dei “packages”, ovvero dei pacchetti strutturali, che sono stati creati per l’organizzazione progettuale della parte implementativa. Per cominciare, si deve puntualizzare che tutti i diagrammi UML, di cui abbiamo parlato fino ad ora, fanno parte di un unico package di progetto chiamato ACLFramework Package. Tutti i diagrammi che, invece, presenteremo nel Capitolo 4 faranno parte di un EnglishAuction Package. Questi due pacchetti sono fortemente connessi in quanto, molte classi che vengono presentate nel secondo package, derivano o discendono direttamente dalle classi che fanno parte del primo. Dal punto di vista più strettamente implementativo, la struttura presentata è, invece, quella esposta in Figura 3.5 dove si mostra come, partendo da una logica di basso livello, si riesce a risalire pure all’uso che l’applicazione reale fa del framework che sta sotto. Si vede, infatti, come si passa attraverso una doppia indirezione e l’applicazione dell’asta inglese, che verrà esposta nel prossimo capitolo, non usa direttamente il framework di basso livello bensì un ConcreteACLFramewok intermedio.

71

Figura 3.6. Packages.

ACL Framework Monitor::ConcreteACLFramework

«topLevelPackage»

Static Model::ACLFramework

«uses»

EnglishAuction

«uses»

72

4. UN ESEMPIO DI PROTOCOLLO DI INTERAZIONE FRA AGENTI: “L’ASTA INGLESE”

In questo capitolo viene proposto un metodo verificabile e indipendente

dall’applicazione che lo utilizza, indispensabile per la definizione di protocolli di interazione fra agenti usati nei sistemi aperti multiagente, e che soddisfa un insieme di condizioni di base. L’esempio che presentiamo è stato preso da [3]. 4.1 Definizione di protocolli di interazione

L’obiettivo principale di questo capitolo è di andare a definire un metodo, indipendente dall’applicativo di alto livello che lo utilizza, attraverso il quale si possano andare a testare e verificare tutta la serie di proprietà caratterizzanti per un protocollo di interazione che sono state listate nel Capitolo 3. Come è appena stato detto, tale metodo è verificabile il che significa che, fornita una specifica di protocollo, è possibile andare a controllare se un agente sta seguendo il protocollo in base alle proprietà che lo caratterizzano. Il metodo, che l’approccio in esame ha deciso di seguire, si basa sull’assunzione che il componente fondamentale, per ogni interazione, è “l’istituzione di un linguaggio di comunicazione” e sul fatto che la specifica per i protocolli di interazione si riferisce ampiamente alla definizione di atti comunicativi indipendenti dall’applicazione che sta sopra. Il metodo proposto si articola nei seguenti passi:

1. dare una definizione del significato di ogni singola primitiva di comunicazione presente nel protocollo e conforme all’approccio a commitment descritto nel Capitolo 3. Ciò è possibile sfruttando l’idea che l’approccio a commitment è estendibile. E’ importante ribadire che tutte le primitive di comunicazione, in quanto parte di uno standard di comunicazione, mantengono la loro semantica e la loro sintassi ogni volta che sono utilizzate all’interno di un protocollo di interazione;

2. dare una definizione dell’ “ambiente” (environment) in cui l’interazione prende parte e di tutti gli elementi contenuti al suo interno che verranno descritti in seguito;

73

3. fornire una specifica di “diagramma di interazione” del protocollo, utile per descrivere tutte le azioni che possono essere eseguite dagli agenti in ogni stadio dell’interazione;

4. identificare una serie di “specifiche condizioni” (guards) che devono essere soddisfatte affinché gli effetti degli atti comunicativi usati nel protocollo siano rilevanti. Ovviamente anche le precondizioni, definite nella libreria degli atti comunicativi, devono essere soddisfatte affinché l’atto comunicativo abbia successo.

4.1.1 La società L’ambiente del protocollo definisce:

Un set non vuoto di “ruoli” (roles) che gli agenti possono giocare all’interno dell’interazione. A ciascun ruolo viene associato un set di specifiche autorizzazioni legate al ruolo stesso.

Un set non vuoto di “partecipanti” (participants) che sono gli agenti che effettivamente interagiscono utilizzando il protocollo. Ogni agente che partecipa gioca un ruolo ben definito nel sistema dei partecipanti che interagiscono. Il set di agenti nel sistema potrebbe variare durante l’esecuzione del protocollo, ma il numero complessivo deve, in ogni caso, essere un numero finito.

Un possibile set vuoto di “costanti globali” (global constants) e “variabili” (variables) che possono essere sottoposti a “vincoli globali” (global constraints).

Oltre al set di atti comunicativi che appartengono alla libreria degli atti di comunicazione di base, sono presenti una serie di azioni specifiche di dominio che ogni agente può compiere.

Una collezione di oggetti commitment, di oggetti temporal proposition e di oggetti specifici di dominio usati per rappresentare tutte le entità coinvolte nell’interazione.

Un set di “autorizzazioni” (authorizations), associate ai ruoli, che sono utili per essere legittimati a compiere certe azioni istituzionali come ad esempio le primitive di tipo dichiarativo.

74

4.1.2 I Diagrammi di Interazione Il diagramma, per un protocollo, definisce quali azioni possono essere fatte

dagli agenti in ogni momento dell’interazione. Più precisamente, un diagramma di interazione è rappresentato attraverso un grafico finito (vedi la Figura 4.1) in cui:

Ogni nodo rappresenta uno stato dell’interazione. Ad ogni stato si può associare un contenuto rappresentativo che è un set di tutte le azioni che conducono a quello stato espresso in termini di valore delle variabili di protocollo, di oggetti commitment, di oggetti temporal proposition e di oggetti specifici di dominio.

E’ presente un singolo nodo iniziale che non ha cammini entranti e un

set di nodi finali che non hanno cammini uscenti e che sono marcati da un doppio bordo. Il processo di interazione inizia da un nodo iniziale e termina quando si raggiunge un nodo finale.

Ogni percorso o cammino descrive una transizione da uno stato ad un

altro. Una transizione può corrispondere sia all’esecuzione di un atto comunicativo o può corrispondere al verificarsi di un evento ambientale. Quando si verifica una transizione come conseguenza di un atto comunicativo, il contenuto dello stato preso in esame può essere completamente stimato in base al contenuto dello stato sorgente e in base alla semantica della primitiva di comunicazione presa in esame; mentre quando si verifica una transizione come conseguenza di un evento ambientale, il contenuto dello stato preso in esame può essere completamente stimato a partire dal contenuto del nodo sorgente e dall’uso di rilevanti regole di aggiornamento scatenate in seguito all’evento stesso.

Quando più di un cammino, che rappresenta un atto comunicativo, esce

da un certo nodo, è possibile specificare le condizioni, (definite come espressioni booleane arbitrarie), sotto le quali ciascun atto può essere

75

eseguito. Alla fine, una sola delle azioni deve essere eseguita, ma l’agente specificato come “attore” dell’azione è libero di scegliere quale azione effettuare fra tutte quelle per le quali la condizione è diventata vera. Se tutte le condizioni si rivelano mutuamente esclusive, è come se si avesse a che fare con una sequenza di proposizioni del tipo if – then.

E’, inoltre, possibile associare una cardinalità ai cammini che esprimono

il verificarsi di atti comunicativi. In particolare la cardinalità “1 a n” significa che lo stesso messaggio viene inviato da un agente a n agenti, mentre la cardinalità “1 a 1” significa che il messaggio è stato mandato da un agente ad un altro agente. Le dichiarazioni sono quelle particolari primitive senza uno specifico ascoltatore, o meglio, chi ascolta è l’intero sistema che sta interagendo, infatti le dichiarazioni hanno come effetto quello di andare a modificare la realtà istituzionale che deriva dal comune accordo fra tutti gli agenti o meglio fra tutti i loro progettisti. Per questo motivo, quando si utilizzano le dichiarazioni, non viene specificata nessuna cardinalità.

76

Figura 4.1. Diagramma di Interazione di un “English Auction Protocol”.

77

4.2 Condizioni di correttezza per un Protocollo di Interazione Per poter parlare con certezza di un modello robusto che descriva in

maniera appropriata l’interazione concorrenziale fra agenti interagenti all’interno di un sistema aperto, l’approccio Fornara – Colombetti puntualizza, nel dettaglio, una serie di vincoli, di condizioni che è fondamentale siano rispettati affinché il protocollo possa risultare solido a fronte di cambiamenti, il più generale possibile e, per questo, il più possibile indipendente dall’applicazione.

Un primo set di condizioni riguarda la struttura topologica del diagramma di interazione:

Ciascun nodo del digramma di interazione deve essere raggiungibile a partire dal nodo iniziale.

Nel diagramma di interazione ci deve essere almeno un nodo finale. Un secondo set di condizioni di correttezza da esaminare riguarda il

contenuto degli stati. Tali condizioni esprimono dei vincoli in relazione al significato dei messaggi scambiati.

Tutti gli atti comunicativi che sono consentiti da un protocollo allo

stato s, devono avere le loro precondizioni soddisfatte dal contenuto associato ad s quando la loro condizione diventa vera. Questo vincolo garantisce che tutti gli atti comunicativi, supportati da un protocollo, possano realmente essere eseguiti.

Tutti i commitment inclusi nel contenuto di uno stato finale devono necessariamente avere come stato cancelled o fufilled o violated. Questo vincolo garantisce che l’interazione sia stata completata.

Un problema interessante, sorto durante l’esecuzione di un protocollo,

riguarda il fatto che uno stesso stato può essere raggiunto, a partire dallo stato iniziale, seguendo differenti percorsi (per esempio intraprendendo catene differenti di azioni). Se riusciamo ad astrarre dai differenti percorsi, intuitivamente possiamo capire che l’interazione ha raggiunto lo stesso stato anche se, valutando il contenuto di uno stato, abbiamo ottenuto differenti

78

risultati. Il punto chiave è che questi risultati, benché differenti, sono equivalenti dal punto di vista dell’interazione in quanto hanno lo stesso “peso” a livello di società di agenti (commissive import). Noi diciamo che uno stato s è equivalente a uno stato s’ se e solo se il contenuto di s e di s’ sono identici, con la sola eccezione dei commitment che possono essere in stato cancelled o fulfilled o violated. Per questo un altro vincolo di correttezza può essere così di seguito presentato:

Se lo stato di un’interazione può essere raggiunto attraverso

percorsi differenti, i contenuti dello stato, esaminato lungo i differenti percorsi, devono essere necessariamente equivalenti.

La situazione si complica ulteriormente se, all’interno di un protocollo

di interazione, ci sono dei loop ovvero dei cicli nel diagramma di interazione stesso. I loop di interazione appaiono come una sequenza di azioni che possono essere ripetute innumerevoli volte. Questo è ciò che accade proprio all’interno del “Protocollo dell’Asta Inglese”. L’esistenza di loop fa sì che sia possibile raggiungere lo stesso stato seguendo differenti percorsi, ma la condizione di solidità appena esposta, pur risultando ancora necessaria, non è più di certo sufficiente. Questo problema, noto nell’ambito di computer – programming, può essere risolto introducendo il concetto di “invariante di ciclo” (loop invariant). Consideriamo ancora l’esempio dell’asta, che verrà trattato approfonditamente nei paragrafi successivi: durante una generica iterazione, il banditore si impegna a vendere il prodotto, attualmente puntato da un certo offerente che ha proposto un ben definito prezzo, a patto che non ci siano offerte più alte di quella attuale. D’altronde, l’agente specifico che ha fatto l’offerta più alta, e di conseguenza anche il prezzo di offerta stesso, potrebbero cambiare passando dall’una all’altra iterazione. Il problema si risolve descrivendo la situazione nei termini di un ciclo invariante dicendo che il banditore si è impegnato a vendere il prodotto in asta all’agente che ha fatto l’offerta più alta, al prezzo definito dall’offerta stessa, a patto che non ci siano state offerte più alte.

79

Il vincolo di solidità corrispondente può essere così riformulato:

Se lo stato di un’interazione può essere raggiunto attraverso differenti percorsi, i contenuti dello stato esaminato lungo i vari cammini, espressi nei termini di “invarianti adatti”, devono necessariamente essere equivalenti.

4.3 Protocollo dell’Asta Inglese

Utilizzando il framewok di basso livello descritto in dettaglio nel Capitolo 3 e basato sul concetto di social commitment, andiamo adesso ad indagare il comportamento di un protocollo di interazione, utilizzato in molteplici applicazioni di commercio elettronico su web. Ne è un esempio la Trading Agent Competition (TAC) ovvero un benchmark nell’ambito del commercio elettronico basato su agenti, in cui ciascun agente che entra a far parte della competizione, svolge il ruolo di “agenzia turistica” e ha il compito di mettere insieme dei pacchetti viaggio; ogni agente agisce per il profitto di otto clienti che esprimono le loro preferenze relativamente a vari aspetti del viaggio stesso. L’obiettivo di ciascuna agenzia è quello di massimizzare la soddisfazione complessiva dei suoi clienti.

Il protocollo dall’asta inglese viene utilizzato per vendere un singolo prodotto o (nella TAC si tratta delle camere di albergo), il processo di vendita può, comunque, essere ripetuto per vendere innumerevoli prodotti. 4.3.1 La società L’ambiente dell’asta inglese comprende i seguenti elementi:

Ruoli. Il Banditore (Auctioneer) e l’Offerente (Client). Partecipanti. Un solo agente a col ruolo di Auctioneer e n agenti, {p1,

… , pn} , col ruolo di Client. Costanti e Vincoli.

• tmax : la massima durata dell’asta; • t1: termine ultimo per il pagamento; • t2: termine ultimo per la consegna del prodotto; • tmax< t1< t2.

80

Oggetti specifici di dominio e Azioni. • Oggetto o: rappresenta il prodotto da vendere con un campo

resPrice indicante il prezzo di riserva ovvero il prezzo iniziale con cui viene presentato il prodotto all’asta.

• L’azione è quella che consente di trasferire la proprietà di un oggetto o di una somma di denaro da un agente a un altro. Questa è un’azione istituzionale che coinvolge la nozione istituzionale della proprietà e della moneta. Per ragioni di semplicità, questa viene considerata come una primitiva di dominio. Il fatto che l’agente a trasferisce all’agente b la proprietà su x (un oggetto o una somma di denaro), viene rappresentato con la primitiva give(a, b, x);

• Oggetto A: rappresenta l’oggetto asta. Ha come variabili i seguenti campi inizializzati come viene indicato:

state: identifica lo stato dell’asta e viene inizializzato con state = “closed”;

askPrice: prezzo che viene attribuito al prodotto in asta ad ogni iterazione del ciclo di offerta;

tend: è un istante automaticamente settato a tsystem quando lo stato dell’asta viene settato a “closed”;

tinactivity: è il tempo di inattività che scorre fra due offerte successive.

Variabili. La società dell’asta possiede anche le seguenti variabili inizializzate come indicato:

• newAskPrice: prezzo che ogni Client propone ad ogni ciclo (nuovo prezzo di domanda), viene inizializzato in questo modo newAskPrice = o. resPrice();

• valuewin: valore o prezzo vincente dell’asta. E’ l’ultimo prezzo con cui il prodotto viene definitivamente venduto;

• tsystem: tempo del sistema è una sorta di “clock globale” che assumiamo, in prima approssimazione, accessibile a tutti i partecipanti dell’asta;

• tbid: è l’istante in cui viene accettata l’ultima offerta. Inizialmente è settato con tbid = 0;

81

• i: un contatore che automaticamente viene incrementato ogni volta che il processo di offerta viene iterato.

Autorizzazioni. Solo il banditore è autorizzato ad aprire l’asta, a dichiararne la chiusura e a settare il valore del prezzo del prodotto (askPrice) nelle fasi successive dell’asta stessa, ogni volta che il cliente fa un’offerta :

• empowered(Auctioneer, A. setState()); • empowered(Auctioneer, A. setAskPrice()).

4.3.2 Schema degli oggetti Temporal Proposition relativi all’asta

Nel framework di interazione proposto, la comunicazione dei contenuti e delle condizioni avviene tramite degli oggetti temporal proposition. Di seguito sono proposti alcuni esempi di schemi di temporal proposition espressi in forma parametrica in modo tale da limitare e semplificare un esempio, come quello dell’asta, in sé sufficientemente complesso. I parametri saranno poi riempiti con i valori concreti reali quando l’interazione effettivamente si svolgerà e le istanze degli oggetti temporal proposition saranno effettivamente create (i valori di verità sono tutti inizializzati di default ad undefined). Negli schemi, che ci accingiamo ad esporre, il parametro now è inizializzato a tsystem quando l’oggetto temporal proposition viene creato; i parametri v e v’ sono, invece, utilizzati per indicare la somma di denaro.

Il simbolo “∃”, già incontrato più volte nel Capitolo 3, sta a indicare che il notifier setta il valore di verità di una temporal proposition a vero se il valore dello statement diventa vero in un qualsiasi momento del time interval, altrimenti setta il valore a falso quando l’intervallo di tempo scade. Elenchiamo di seguito gli schemi proposti:

Lo schema Pj rappresenta la proposizione “Il banditore a consegna il prodotto o al cliente pj nell’intervallo di tempo che va dalla fine dell’asta all’istante t2”:

Pj(give(a, pj, o), tend ... t2, ∃);

82

Lo schema Qj,v rappresenta la proposizione “Il cliente pj consegna la somma di denaro v al banditore a dell’asta nell’intervallo di tempo che va dalla fine dell’asta all’istante t1 ”:

Qj,v (give(pj, a, v), tend ... t1, ∃);

Lo schema Sj,i rappresenta la proposizione “Il cliente pj fa un’offerta durante l’iterazione del processo di offerta i”:

Sj,i (propose(pj, a, Pj, Qj(x)), now ... now + tinactivity ,

∃);

Lo schema Uj,v rappresenta la proposizione “Il banditore a si impegna, relativamente al cliente pj, alla proposizione Pj e sotto la condizione Qj,v , nell’intervallo di tempo che va da ora fino alla fine dell’asta”:

Uj,v (Cid2j(pending, a, pj, Pj|Qj,v), now ... tend, ∃);

Lo schema Wv’ rappresenta la proposizione “Il banditore a non

accetta qualsiasi altra proposta che abbia un valore più grande di v’ nell’intervallo di tempo che va da ora fino alla fine dell’asta”:

Wv’ (¬ ∃ j (condAccept(a, pj,Cid2j(unset, a, pj,

Pj|Qj,v),Wv) ∧ v > v’), now ... tend, ∃);

4.3.3 Atti comunicativi caratterizzanti l’asta e Condizioni

Si desidera, ora, evidenziare quali sono gli atti comunicativi, che sono stati effettivamente proposti dal protocollo per lo sviluppo dell’asta e che noi progettisti abbiamo effettivamente implementato, e le condizioni affinché tali primitive di comunicazione possano essere usate. Ovviamente devono anche essere ampiamente soddisfatte tutte le precondizioni definite nella Libreria degli Atti Comunicativi. Alcune di queste primitive vengono ripetute più e più volte

83

durante tutto il processo di offerta. A fronte della performance di particolari atti di comunicazione, si riportano anche gli effetti sortiti su tutto il sistema. Di seguito, sono definite nel dettaglio tutte le primitive usate nell’ambito dell’asta inglese, insieme alle loro precondizioni di base e agli effetti che queste provocano in tutto il sistema.

Il banditore dichiara l’apertura dell’asta (stato s0 in Figura 4.1).

precondizioni: A.state() = “closed” declare(a, A.state() = “open”)

Il banditore dichiara il corrente ask-Price dell’asta in corso (stati

s1, s6, s11 in Figura 4.1).

precondizioni: A. askPrice() < newAskPrice declare(a, A. askPrice() = newAskPrice)

Il banditore effettua la richiesta di nuove offerte, rivolta a tutti i

partecipanti dell’asta (stati s2, s5, s7, s10 in Figura 4.1).

request(a, pj, Sj,i) conseguenze / effetti: Cid1j(unset, pj, a, Sj,i)

Un partecipante fa la sua offerta (stati s3, s8 in Figura 4.1).

precondizioni: {(tsystem < tmax), (tsystem – tbid < tinactivity)}

propose(pj, a, Pj, Qj,v) conseguenze / effetti: {Cid2j(unset, a, pj, Pj|Qj,v), Cid3j(pending, pj, a, Qj,v|Uj,v),

Sj,v.truth_value() = 1 }

Se il valore di un’ offerta è più grande del corrente ask-Price, il

banditore deve accettare l’offerta di quel cliente (stati s4, s9 in Figura 4.1).

84

precondizioni: v > A. askPrice();

condAccept(a, pj, Cid2j(unset, a, pj, Pj|Qj,v), Wv) conseguenze / effetti: {Cid2j(pending, a, pj, Pj|[Qj,v, Wv]) ∀ v’ < v

Wv’.truth_value()=0 }

variabili aggiornate: {newAskPrice = v, tbid = tsystem }

Se il valore di una proposta è minore o uguale al corrente ask-Price, il banditore deve rifiutare l’offerta (stati s4, s9 in Figura 4.1).

precondizioni: v <= A. askPrice();

reject(a, pj, Cid2j(unset, a, pj, Pj|Qj,v)) conseguenze / effetti:{Cid2j(cancelled, a, pj, Pj|[Qj,v, Wv]), Uj,v.truth_value()=0}

Il banditore può dichiarare la chiusura dell’asta solo se il tempo

di inattività diventa uguale alla costante inizializzata all’inizio dell’asta o solo se si è raggiunto il valore del tempo finale dell’asta (stati s3, s8 in Figura 4.1).

precondizioni: {(tsystem >= tmax) ∨ (tsystem – tbid > tinactivity), A. state() = “open”}

declare(a, A.state() = “closed”) conseguenze / effetti: {Wvalue win. truth_value() = 1, Uj,value win. truth_value = 1}

variabili aggiornate: { tend = tsystem, valuewin = newAskPrice }

4.3.4 Diagramma di Interazione Il diagramma di interazione che specifica il protocollo dell’asta inglese è

riportato nella Figura 4.1, mostrata in precedenza. Prendendo nota del contenuto di ogni stato, si nota la correttezza del protocollo in relazione alle specifiche di cui si è parlato nel paragrafo 4.2. Inoltre, il contenuto di ogni stato, accessibile attraverso percorsi differenti, risulta equivalente.

Per gli stati s9, s10, s11, che sono nel loop del protocollo, è possibile identificare un ciclo invariante descrivendo pj come il cliente che ha fatto

85

l’offerta più alta. Questo determina il fatto che, in tali stati, gli oggetti commitment, ad ogni iterazione del processo di offerta, cambiano solamente il valore del campo che si riferisce al partecipante che ha fatto l’offerta più alta.

4.4 Dalla fase di analisi alla fase di progettazione Fino ad ora ci siamo preoccupati di descrivere e di analizzare in

dettaglio tutte le specifiche imposte dal protocollo. Il passo successivo è, ora, quello di creare dei diagrammi UML, come abbiamo fatto per il framework che descrive la macchina commitment del capitolo precedente, in grado di descrivere la tipologia di implementazione, il tipo di approccio progettuale seguito per analizzare le specifiche. Queste specifiche, inizialmente solo concetti puramente teorici, sono stati tradotte in classi progettuali concrete, ciascuna legata da relazioni particolari alle altre e soprattutto ciascuna dotata di ben definite responsabilità. L’obiettivo di questo paragrafo, e di tutti i paragrafi successivi del capitolo, è quello di analizzare le principali scelte progettuali sorte nell’affrontare il problema di creare un’asta inglese. Ricordiamo che gli attori software che interagiranno saranno: il banditore dell’asta, ovvero l’Auctioneer e innumerevoli offerenti, ovvero i vari Bidder. I diagrammi sono stati tutti raggruppati all’interno di un EnglishAuction Package il quale è strettamente connesso con l’ACLFramework Package di cui si è parlato nel capitolo precedente. 4.4.1 Diagramma UML Parliamo, in questa sezione, dei problemi incontrati in fase di progetto, di come sono stati risolti e principalmente delle responsabilità delle classi create.

86

Il primo problema che affrontiamo riguarda come si è deciso di mappare la relazione che lega ogni agente concreto al set di azioni che lo stesso può compiere all’interno del sistema. Dalla Figura 4.2 si nota come non c’è un legame diretto fra ogni agente e il set di azioni che lo stesso può compiere, ma si passa attraverso il ruolo. Ogni ruolo concreto, vale a dire AuctioneerRole e BidderRole che sono una specializzazione della classe ConcreteRole presente nel Package ACLFramework, viene associato a un insieme di azioni. Come si vede dal grafico l’associazione è 1 nel senso che un AuctioneerRole ha associato a sé un solo set di azioni specifiche per quel ruolo, in realtà uno stesso set di azioni potrebbe essere utilizzato da (0..*) AuctioneerRole (il simbolo (0..*) indica una molteplicità che va da zero ad infinito). Lo stesso ragionamento vale anche per il legame fra BidderRole e il suo insieme di azioni. Parlando delle azioni si nota come anche le classi AuctioneerActions e BidderActions nascano come implementazione di interfacce. Per definizione un’interfaccia contiene puramente la signature di un metodo ovvero il suo nome, il suo tipo di ritorno, la sua visibilità, l’insieme dei parametri passati in ingresso con il loro tipo senza, però, contenere codice. Quest’ultimo sarà contenuto nelle sottoclassi concrete che erediteranno la signature di base andando a implementare concretamente i metodi. Ecco perché BidderActions eredita dei metodi sia da un’interfaccia contenente le azioni specifiche che un offerente deve compiere nel sistema ovvero eredita da IBidderActions, sia le azioni generiche relative a un agente contenute nell’interfaccia IAgentActions .

87

Figura 4.2. Diagramma UML: agenti, azioni e ruoli.

88

Un discorso analogo può essere fatto per le classi relative al banditore. Il modo, per associare a un ruolo un set di azioni, avviene proprio tramite il metodo MakeEmpowerable() che ha il compito di assegnare ad ogni ruolo creato un set di azioni specifiche. Ciò viene mostrato in Figura 4.3.

Figura 4.3. Come associare a un ruolo il suo set di azioni.

Per riuscire, quindi, ad associare un agente al suo set di azioni è necessario passare per il ruolo. E’ proprio il ruolo che si lega anche agli agenti concreti del sistema. Ogni Auctioneer può interpretare uno e un solo ruolo, ovvero AuctioneerRole, mentre il ruolo di banditore dell’asta può essere interpretato da più agenti che vogliano incaricarsi di quella determinata responsabilità. Lo stesso legame si instaura fra la classe Bidder e la classe BidderRole. Anche per gli agenti troviamo una grande elasticità rappresentativa. Nel sistema dell’asta inglese ci sono sostanzialmente due attori che interagiscono, vale a dire un banditore e più offerenti; ciò non toglie che se in futuro fosse necessario introdurre altre tipologie differenti di agenti nel sistema, basterebbe ampliare la gerarchia esistente. Tutti i metodi presenti nella classe ConcreteAgent vengono ridefiniti nelle classi ereditate che forniscono un’implementazione specifica rispetto a quella di default offerta dalla classe base. Si può vedere il tutto dalla Figura 4.4.

89

Figura 4.4. Relazione di ereditarietà fra la classe ConcreteAgent e le due classi concrete

Bidder e Auctioneer.

Il secondo problema che affrontiamo riguarda la modellazione del sistema della comunità che partecipa all’asta. Ogni offerente, che propone un prezzo per l’acquisto di un prodotto in asta, fa parte di una società di agenti che si è deciso di modellare tramite la classe AuctionWorkgroup. Questa classe è una specializzazione della classe Workgroup intendendo con essa il gruppo o la comunità a cui gli agenti possono aderire, che possono decidere di lasciare o da cui un agente può essere rimosso. Nella classe AuctionWorkgroup si ha il riferimento ad una sola istanza di banditore alla volta (istanza della classe Auctioneer), infatti un solo auctioneer alla volta può regolamentare l’asta, mentre si ha il riferimento ad una molteplicità di offerenti (istanze della classe Bidder) che fanno proposte relativamente ad un prodotto messo all’asta. La relazione che lega le due classi è una sorta di aggregazione dove, con essa, indichiamo una relazione di contenimento non stretta. Se si dovesse eliminare la classe AuctionWorkgroup, comunque le istanze di Auctioneer e di Bidder

90

continuerebbero ad esistere in quanto dotate di una propria autonomia. La relazione è caratterizzata da un rombo bianco non riempito, come si può vedere in Figura 4.5.

Figura 4.5. Relazione di aggregazione.

91

Ogni asta presenta un solo prodotto alla volta; si spiega, in questo modo, l’associazione a molteplicità 1 che determina la presenza del riferimento, all’interno della classe AuctionWorkgroup, di un’istanza della classe ProductToSell. Tale classe mette in evidenza tutte le caratteristiche principali di interesse comune del prodotto che deve essere venduto; lo stesso prodotto potrebbe, infatti, risultare l’oggetto di contesa di più aste, per esempio ciò si potrebbe verificare in caso di fallimento dell’asta stessa (frequente è il caso in cui il banditore è costretto a dichiarare l’asta chiusa anche solo perché magari tutti gli offerenti non propongono un prezzo superiore al prezzo base del prodotto). Da ciò si spiega la molteplicità (0..*) per mappare l’associazione che lega la classe ProductToSell alla classe AuctionWorkgroup nel senso che lo stesso prodotto può essere proposto in più aste successive. Si deve notare come anche ProductToSell è una classe che può essere specializzata. Potrei avere innumerevoli prodotti tutti diversi messi all’asta, in realtà è proprio questo che accade la maggior parte delle volte, per questo motivo posso creare delle sottoclassi specializzate per ogni tipo di prodotto e, in fase di implementazione, andare a creare solamente delle istanze concrete delle sottoclassi specializzate. Un’ulteriore considerazione da fare sulla classe ProductToSell riguarda il suo legame con la classe ProductToSellManager. Quest’ ultima classe viene utilizzata dalla classe ProductToSell per assegnare dinamicamente ad ogni prodotto, presentato ed in essa contenuto, il proprio identificativo. La classe ProductToSellManager è stata pensata come singleton, infatti questa viene utilizzata solamente quando è necessario assegnare dinamicamente ad un prodotto il proprio identificativo. Per questo motivo non avrebbe senso che venisse istanziata staticamente ogni volta; tramite l’uso del pattern Singleton non solo gestiamo run–time la creazione dell’istanza (che è un attributo statico e privato della classe stessa), ma solo quando la si utilizza la prima volta questa viene istanziata dopodiché, nelle volte successive, si continuerà a usare l’unica istanza creata, sola porta di accesso alla classe. E’ questo il grande vantaggio del pattern Singleton. Il diagramma in Figura 4.6 mostra le relazioni di cui si è appena parlato. Da notare l’associazione che lega la classe Bid con la classe ProductToSell. E’ evidente che ogni offerta viene fatta per acquistare un prodotto, così come ogni prodotto, in quanto parte del sistema dell’asta, può essere l’oggetto di una

92

molteplicità di offerte fatte dai bidder. In realtà non è scontato che qualcuno proponga un prezzo per il prodotto in asta; in questo caso il prodotto verrebbe presentato, ma subito ritirato dall’asta in quanto “non venduto”. Da questa considerazione si deduce e si spiega la molteplicità (0..*).

Figura 4.6. Diagramma UML del prodotto offerto all’asta.

La classe AuctionWorkgroup è vista, inoltre, come un contenitore di oggetti di tipo offerta ovvero Bid. La relazione che lega le due classi non rappresenta un’associazione generica bensì una composizione. Questa relazione viene visualizzata da un rombo annerito. In una composizione si vuole evidenziare

93

come le istanze contenute non abbiano vita propria in caso di eliminazione fisica reale della classe contenitore; in altre parole se si dovesse verificare la morte dell’istanza della classe AuctionWorkgroup, anche tutte le istanze della classe Bid morirebbero non essendo dotate di una propria autonomia. La classe AuctionWorkgroup ha, al suo interno, una sorta di “log” contenente tutte le offerte fatte nel sistema; se morisse l’istanza di questa classe, perderemmo la traccia di tutti questi log con le offerte dell’asta. Un’ultima considerazione va fatta relativamente allo stato del sistema. In ogni momento l’asta cambia il proprio stato, di default l’asta è chiusa, ma grazie al monitoraggio del banditore, l’asta può essere dichiarata aperta e può essere nuovamente chiusa. Si è deciso di mappare i differenti stati attraverso un enumerativo AuctionState. Quanto detto è riassunto dal diagramma UML in Figura 4.7.

Figura 4.7. Relazione di composizione.

94

In Figura 4.8 vediamo, nell’insieme, tutte le associazioni che partono dalla classe AuctionWorkgroup che è, sostanzialmente la classe che identifica, ad alto livello, tutto il nostro sistema. Va notato che sia la classe Auctioneer, sia la classe Bidder si associano alla classe Bid; l’offerente in quanto è colui che effettua realmente l’offerta nel sistema, il banditore in quanto è come una sorta di contenitore che tiene traccia di tutte le offerte che vengono effettuate nel sistema. La relazione non è, però, di contenimento stretto, bensì rappresenta molto più un’aggregazione lasca.

Figura 4.8. Diagramma UML delle associazioni legate alla classe AuctionWorkgroup.

95

In ultima battuta parliamo della classe AuctionStatement, che deriva direttamente da Concrete Statement, la quale non è associata a nulla, ma rappresenta una ponte di connessione con la classe Statement contenuta nel framework. Questo ponte è necessario per far capire come, in ogni società di comunicazione, si possono specificare statement differenti caratterizzanti l’ambiente di interazione stesso. Il legame è meglio visibile in Figura 4.9.

Figura 4.9. Diagramma UML: come si specializzano le proposizioni in differenti ambienti di

interazione.

4.4.2 Diagramma UML – Analisi delle responsabilità In questa sezione esaminiamo le responsabilità associate alle classi principali del diagramma UML.

96

AuctioneerActions e BidderActions

Queste due classi hanno la responsabilità di mettere in luce le azioni che possono essere compiute rispettivamente dal banditore dell’asta (AuctioneerActions) e dagli offerenti (BidderActions). Il banditore può dichiarare l’apertura o la chiusura dell’asta attraverso i metodi DeclareAuctionOpen() e DeclareAuctionClosed(), può dichiarare il prezzo iniziale del prodotto o dichiarare i nuovi prezzi intermedi del prodotto a fronte delle varie offerte tramite DeclareProductToSell(), infine può chiedere a tutti i membri della comunità di fare delle offerte attraverso il metodo RequestForNewBid(). Gli offerenti possono solamente fare delle nuove proposte di acquisto attraverso il metodo ProposeNewBid().

ConcreteAgent, Bidder e Auctioneer

+DeclareAuctionOpen()

+DeclareAuctionClosed()+DeclareProductToSell()

+RequestForNewBids()

AuctioneerActions

+ProposeNewBid(in bidder, in bidPrice : float)

BidderActions

-TimeChangedHandler(in time : int)-ContractPaymentHandler(in time : int)

-ContractDeliveryHandler(in time : int)

-FindBidderOffer(in c : Commitment) : float

+Auctioneer()

-_delivery : bool

-_currentBids[0..n] : Bid

Auctioneer

#OnPromiseClientHandler(in actionToDo : OnPromiseActions, in c : Commitment)

#OnProposeClientHandler(in content : TemporalProposition)#OnRequestClientHandler(in actionToDo : OnRequestActions, in c : Commitment)

#AcceptPromiseClientHandler(in c : Commitment)

#ConditionalAcceptPromiseClientHandler(in c : Commitment, in conditions[1..n] : TemporalProposition)

#AcceptRequestClientHandler(in c : Commitment)

#PerformRequestClientHandler(in c : Commitment)+Trustful() : bool

+ConcreteAgent()

ACLFramework Package::ConcreteAgent

+Bidder()

-_requestActions : OnRequestActions = OnRequestActions.reject

-_payment : bool = true

-_bidValue : float = 0

-_sleep : int = 0

Bidder

97

La classe ConcreteAgent ha una proprietà di base Trustful che identifica un valore booleano utile per classificare gli agenti come affidabili o meno. Abbiamo deciso di esprimere il concetto di trustworthy e di untrustworthy, come metro di classificazione degli agenti in affidabili o meno, in quanto questo è da sempre stato un problema particolarmente discusso all’interno della letteratura. Ci riserviamo di riprendere questi concetti nel Capitolo 5, dove parleremo dei test sperimentali condotti sull’applicazione, esaminando nel dettaglio cosa significa “dichiarare che un agente è trustworthy o che un agente è diventato untrustworthy a causa di particolari comportamenti o azioni compiute”. Nella classe ConcreteAgent è fornita, inoltre, l’implementazione di default di tutti quegli handler, associati agli eventi generati dagli atti comunicativi, i quali saranno ridefiniti all’interno delle classi specializzate. Nella classe Auctioneer particolare attenzione va posta sui metodi ContractPaymentHandler() e ContractDeliveryHandler(), utilizzati dopo la chiusura effettiva dell’asta, utili per determinare se un agente, banditore o offerente che, comunque, abbia preso un impegno definitivo nei confronti della società di agenti, si sta comportando bene o male: l’offerente deve pagare il prodotto entro un tempo t1, il banditore deve consegnare il prodotto entro un tempo t2 (con t1< t2). Altro metodo di rilievo è FindBidderOffer() il quale, preso in ingresso l’istanza di un oggetto commitment, è in grado di estrarre, da esso, il valore effettivo dell’offerta fatta dal cliente.

98

AuctionWorkgroup Responsabilità di questa classe AuctionWorkgroup è quella di monitorare tutto il sistema tenendo traccia del numero dei partecipanti (_bidders[1..n], _auctioneer), del prodotto (_product) che, ad ogni processo di asta, viene offerto, del numero delle offerte per quel prodotto (_numberBids) e dei valori stessi proposti (_askPrice), dello stato dell’asta (_auctionState) in ogni istante e di una miriade di tempi di sistema (descritti ampiamente nei requisiti) utili per regolare le scadenze.

Bid

Questa classe Bid ha il compito di tenere traccia dell’offerta fatta da un agente relativamente ad un prodotto per acquistare il quale lui stesso ha proposto una certa somma di denaro in un certo istante. Nel fare tutto ciò l’offerente si è posto in obbligo nei confronti della società di agenti di cui fa parte .

-OnTimeChanged(in time : int)

-TimeSystemHandler(in newTime : int)+AuctionWorkgroup()

-_auctionId : int = 0

-_bids[1..n] : Bid

-_product : ProductToSell

-_timeEnd : int-_timeInactivity : int

-_timeSystem : int = 0

-_timeBid : int = 0

-_timeMax : int

-_timePayment : int-_timeDelivery : int

-_numberBids : int

-_askPrice : float = 0

-_winPrice : float = 0

-_auctionState : AuctionState = AuctionState.closed

-_auctioneer : Auctioneer-_bidders[1..n]

AuctionWorkgroup

+Bid(in auctionOwner : AuctionWorkgroup, in bidder, in bidPrice : float, in product : ProductToSell, in systemTimeBid : int, in commitmentId : int)

-_auctionOwner : AuctionWorkgroup

-_bidder

-_bidPrice : float = 0

-_product : ProductToSell

-_systemTimeBid : int

-_commitmentId : int = 0

Bid

99

ProductToSell

La classe ProductToSell ha il compito di descrivere il prodotto messo all’asta fornendone il nome (_name), la descrizione (_description) e il prezzo iniziale (_resPrice) di presentazione all’asta.

ProductToSellManager

Responsabilità di questa classe “singleton” ProductToSellManager è quella di assegnare staticamente l’identificativo a ciascun prodotto che viene messo all’asta. Tramite il metodo GetInstance() viene restituita l’unica istanza della classe, creata una sola volta e poi sempre riutilizzata. Il metodo NextProductId() si occupa di creare gli identificativi e di assegnarli.

ConcreteRole, AuctioneerRole e BidderRole

+ProductToSell(in productId : int, in name : string, in description : string, in resPrice : float)

+ToString() : string

-_productId : int

-_name : string

-_description : string

-_resPrice : float

ProductToSell

#ProductToSellManager()

+GetInstance() : ProductToSellManager

+NextProductId() : int

-instance : ProductToSellManager

-_nextProductId : int = 1

«singleton»ProductToSellManager

+AuctioneerRole(in roleName : string)

AuctioneerRole

+BidderRole(in roleName : string)

BidderRole

+RoleName() : string

+ConcreteRole()

+ConcreteRole(in roleName : string)

-_concreteActions : ConcreteAgentActions

ACLFramework Package::ConcreteRole

100

Attraverso queste classi AuctioneerRole e BidderRole (la classe ConcreteRole discende direttamente dalla classe Role del framework), un agente che fa parte del sistema viene legittimato ad interpretare un determinato ruolo, all’interno della comunità. A tale ruolo sono associate un set di azioni definite, quelle presenti nelle classi AuctioneerActions e BidderActions, della cui signature viene tenuta traccia nelle interfacce riportate di seguito. L’interfaccia IAgentActions al momento risulta priva di metodi, in realtà essa può contenere la signature di funzioni non legate in maniera specifica al ruolo giocato dall’agente nel sistema, ma a funzioni del tutto generiche che possono essere utilizzate da tutti gli agenti.

Concludiamo qui la panoramica sulle responsabilità associate alle principali classi del sistema in esame. In Figura 4.10 e in Figura 4.11 riportiamo il Diagramma Progettuale UML complessivo, spezzato ovviamente nelle due figure. Sarà possibile consultare il diagramma, riportato come figura unica, anche nell’Appendice. L’analisi, che è stata riportata con cura in questo capitolo, mette in luce il processo incrementale-iterativo che è stato seguito durante tutta la fase di progettazione e di implementazione. Molti metodi accessori, non essenziali ai fini della comprensione della tesi, non sono stati riportati nel diagramma. L’obiettivo di questo capitolo è stato quello di utilizzare l’applicazione concreta di un’asta per testare il funzionamento della macchina a stati finiti in conformità con le specifiche riportate in [3]. E’ stato sostanzialmente instanziato l’ACLFramework per usarlo su un’applicazione concreta. Nel prossimo capitolo parleremo dei test concretamente effettuati sul framework attraverso

+DeclareAuctionOpen()

+DeclareAuctionClosed()+DeclareProductToSell()

+RequestForNewBids()

«interface»

IAuctioneerActions«interface»

IAgentActions

+ProposeNewBid(in bidder, in bidPrice : float)

«interface»

IBidderActions

101

l’applicazione dell’asta, esaminando cosa si può intendere per “scalabilità del sistema” e traendo qualche considerazione dai risultati sperimentali.

Figura 4.10. Diagramma Progettuale UML complessivo dell’English Auction – prima parte.

102

Figura 4.11. Diagramma Progettuale UML complessivo dell’English Auction – seconda parte.

103

5. PRESENTAZIONE DI ALCUNI ESPERIMENTI CONDOTTI SULL’ACLFramework

In questo capitolo sono presentati un insieme di test, condotti sul

framework nel tentativo di verificarne sperimentalmente la correttezza, che utilizzano l’esempio dell’asta inglese discusso nel Capitolo 4. Parleremo dettagliatamente di alcuni significativi risultati ottenuti, alcuni dei quali si riconducono a grossi problemi in cui si incorre spesso nella letteratura. Esamineremo la scalabilità del sistema dove, con essa, andremo ad indicare quanti agenti offerenti, bidder, il sistema è in grado di supportare al fine di fornire delle risposte accettabili a livello di “tempi di risposta del sistema”. 5.1 Descrizione degli esperimenti

Di seguito sono analizzati i test più significativi portati a termine sul sistema progettato, prendendone in esame le più stringenti problematiche.

5.1.1 TestAuction_1 In questo primo test gli attori sono: un solo banditore e cinque offerenti. Ci sono una serie di passi logici che devono essere compiuti, per ciascun test effettuato, che si pensa di elencare di seguito per comodità.

1. Si crea un’istanza della classe AuctionWorkgroup; risulta, infatti, essenziale creare una società in cui posizionare gli agenti che acquisiscono un’identità propria.

2. Vengono inizializzate le temporizzazioni, ovvero viene fissata una durata massima per l’asta, viene stabilita sia la scadenza per il pagamento del prodotto, una volta che questo è stato venduto, sia la scadenza per la consegna del prodotto stesso all’offerente da parte del banditore. Infine, per poter decretare la chiusura dell’asta, è indispensabile fissare un tempo di inattività oltre cui, se non ci sono più offerte utili, viene decretata l’offerta vincente.

3. A questo punto vengono creati gli oggetti rappresentati dagli agenti, a ciascuno di essi si assegna il proprio ruolo e, di conseguenza, il set di azioni che l’agente può compiere in relazione allo stesso.

104

4. Viene settato il valore che ciascun agente decide di offrire durante l’asta e soprattutto viene settato il valore RequestActions che è un attributo privato della classe Bidder. In questo modo si decide quello che sarà il comportamento dell’agente: quando il banditore fa una richiesta di offerta, l’offerente può accettarla (perform/accept) o rifiutarla (reject) e, solamente se l’ha accettata, va a fissare il valore del prezzo che lui stesso offre.

5. Viene inoltre settato, per ogni agente offerente, il valore booleano “Payment” che indica se, lo stesso, ha intenzione di impegnarsi o meno a pagare la cifra di denaro offerta durante l’asta. In caso di vincita proprio di quell’agente, è fondamentale che lo stesso si impegni, altrimenti l’intero processo di vendita non può andare a buon fine e il commitment entra in uno stato “violated”. Lo stato viene violato anche nel caso in cui sia il banditore a non tenere fede alla parola data: questo è il caso in cui il valore booleano “Delivery” associato all’auctioneer viene settato a false il che equivale a dire che il banditore non si impegna a consegnare il prodotto nonostante l’offerente ne abbia già pagato il prezzo. Se tutto va a buon fine il commitment entra in uno stato “fulfilled”.

6. Dopo il settaggio dei parametri, ogni agente fa un join nel workgroup, ovvero entra a far parte della comunità di agenti.

7. A questo punto inizia l’asta: a. il banditore dichiara l’asta aperta (DeclareAuctionOpen()); b. presenta il nuovo prodotto in vendita con il corrispondente

prezzo (DeclareProductToSell()); c. chiede agli offerenti di proporre, uno alla volta, un nuovo prezzo

per il prodotto, ovviamente superiore a quello iniziale(RequestForNewBids());

d. ciascun agente, se vuole, offre un prezzo per il prodotto in vendita (ProposeNewBid());

e. il banditore dichiara ciclicamente i prezzi intermedi vincenti; il ciclo si ripete fino a quando non scade il tempo massimo per la durata dell’asta, fissato all’inizio;

105

f. solamente quando nessuno dei presenti fa più offerte all’interno di un certo intervallo di tempo, il banditore dichiara prima il vincitore e poi decreta la chiusura dell’asta (DeclareAuctionClosed()).

8. Solo in questo momento sia il banditore che gli offerenti possono, se vogliono, uscire dalla comunità virtuale.

Queste sono le tappe base seguite nell’implementazione. Nell’esempio in questione ci sono cinque offerenti: bidder1 offre 500; bidder2 offre 3000; bidder3 offre 1500; bidder4 offre 5000; bidder5 offre 4000.

Tutti accettano di fare un’offerta per il prodotto in vendita, un quadro di Monet, che vale all’inizio 1000. A livello di codice, mandando in esecuzione il programma, il primo ad offrire è il bidder5, la sua offerta viene accettata, il secondo ad offrire è il bidder4 e la sua offerta viene accettata invalidando quella del concorrente. Il processo di vendita procede di conseguenza e le offerte successive vengono tutte rifiutate in quanto troppo basse. Il vincitore è naturalmente il bidder4. Quest’ultimo si era, inoltre, precedentemente impegnato, in caso di vincita, a pagare tutto il prezzo pattuito durante l’asta; anche il banditore decide di rispettare l’impegno di consegna del prodotto.

Dal punto di vista dei commitment e di come evolve la macchina a stati finiti sia a fronte degli impegni presi dagli attori del sistema sia a fronte del cambiamento del valore di verità delle proposizioni, si può notare come il commitment di proposta del bidder4 entri in uno stato “fulfilled”: tutte le condizioni sono andate a buon fine, il prodotto è stato venduto ed è stato consegnato. Tutti i commitment che falliscono, ovvero quelli che si riferiscono a offerte superate da altre più cospicue, entrano progressivamente, passando attraverso i vari stati della macchina, in uno stato “cancelled”. Anche le offerte che, già dall’inizio, hanno un valore più basso dell’ultima offerta valida generano dei commitment che variano i loro stati fino a raggiungere lo stato “cancelled”. Abbiamo gestito, inoltre, il caso in cui più agenti contemporaneamente propongano lo stesso prezzo vincente: in tale evenienza

106

vince chi offre per primo il prezzo più alto dell’asta. Questo discorso vale, ovviamente, anche per le offerte intermedie: se ci sono più agenti che fanno la medesima proposta, viene attribuito il prezzo di offerta valido a chi offre temporalmente prima; i commitment generati dagli altri agenti, che propongono lo stesso prezzo, entrano tutti progressivamente in uno stato “cancelled”.

Si nota, in Figura 5.1, che l’identificativo dell’offerente vincente è 5 anche se colui che vince è il bidder4, questo perché gli identificativi vengono assegnati staticamente nel sistema composto da agenti ed il primo a cui viene assegnato il numero è il banditore. In realtà, quindi, parlare del bidder1 significa parlare dell’agente che, nel sistema, ha come numero identificativo il 2; parlare del bidder2 significa parlare dell’agente che per identificativo ha il numero 3 e così di seguito; di conseguenza, il bidder4 e l’agente contrassegnato dal numero 5 sono esattamente la stessa entità.

Figura 5.1. TestAuction_1: panoramica sui commitment del sistema.

In Figura 5.2 vediamo nel dettaglio qual è la temporal proposition relativa al

commitment vincente. Della temporal proposition si riescono a vedere, nel dettaglio, sia le proposizioni relative alle conditions, sia il content; entrambe, partendo da un valore di verità falso, diventano vere e, di conseguenza, fanno cambiare gli stati della macchina commitment da pending ad active a fulfilled: questa catena di stati si ottiene, in particolare, in questo caso in cui tutto va a buon fine.

La Figura 5.3 mostra gli agenti del sistema e l’assegnamento degli identificativi. Sono visibili anche i ruoli interpretati dagli agenti stessi. Ad ogni

107

ruolo è associato il set corrispondente di azioni che possono essere compiute: questo è visibile sia nella Figura 5.4 sia nella Figura 5.5 in cui si presentano nel dettaglio le azioni compiute rispettivamente dal banditore e dagli offerenti.

Figura 5.2. TestAuction_1: visione della temporal proposition vincente.

Figura 5.3. TestAuction_1: agenti del workgroup, concetto di “trustworthy” e

“untrustworthy”.

Figura 5.4. TestAuction_1: set di azioni associate al ruolo di Auctioneer.

108

Figura 5.5. TestAuction_1: set di azioni associate al ruolo diBidder.

E’ importante chiarire il concetto di “trustworthy” ed “untrustworthy”. Quando un agente prende parte attiva in un sistema, esso viene inserito nel Workgroup. Per monitorare le entità presenti nel sistema si era creato, in fase progettuale, un componente denominato WorkgroupManager proprio con lo scopo di tenere traccia degli agenti che entravano a far parte del sistema stesso. Esiste un’ulteriore componente, di cui non abbiamo ancora parlato nel dettaglio, che tiene traccia dei cambiamenti di affidabilità di un agente nel sistema: questo è l’AuthorityManager. Siccome in questo primo esempio che stiamo esaminando tutto va a buon fine, si riesce a vedere come anche gli agenti si stiano effettivamente comportando bene, il che significa che stanno adempiendo agli obblighi sociali per i quali essi stessi si sono impegnati. Per questo motivo, come si nota dalla Figura 5.3, tutti sono classificati “trustworthy” ovvero affidabili agli occhi della società.

5.1.2 TestAuction_2 Nell’esempio in questione sono presenti, ancora una volta, cinque

offerenti: bidder1 offre 500; bidder2 offre 1500; bidder3 offre 3000; bidder4 offre 4000; bidder5 offre 5000.

109

Inizialmente sembra che tutti abbiano intenzione di fare un’offerta per il prodotto in vendita, un quadro di Monet, che viene presentato a 1000. Per tutti i bidder viene settato il parametro _bidValue che identifica il prezzo che ciascuno vorrebbe offrire all’asta; il fatto è che fra i parametri che vengono settati inizialmente c’è anche quello relativo a RequestActions che, come è stato detto nella sezione 5.1.1, può essere inizializzato ad accept o perform o reject . E’ evidente che quel parametro ha la priorità sul settaggio del valore dell’offerta nel senso che, se RequestActions è settato a reject, questo implica che il bidder si rifiuta di fare un’offerta per il prodotto, nonostante il valore _bidValue sia stato inizializzato. In questo caso è il bidder4 che, alla fine, si rifiuta di offrire e il commitment, relativo alla richiesta di offerta del banditore, dinamicamente entra in uno stato “cancelled”. A livello di codice, mandando in esecuzione il programma, il primo ad offrire è il bidder5, la sua offerta viene accettata; tutte le offerte successive verranno rifiutate in quanto il prezzo proposto attraverso di esse risulta troppo basso. Il vincitore è naturalmente il bidder5. Il problema è che, a questo punto, deve essere esaminato il parametro “Payment”: esso è settato a falso il che significa che, pur avendo offerto un prezzo per il prodotto ed avendo, con esso, vinto l’asta, alla fine però il bidder5 decide di venire meno agli impegni presi, di conseguenza, all’atto del pagamento, si rifiuta di pagare il prezzo precedentemente pattutito. E’ questo il caso in cui il commitment, vincitore dell’asta, entra in uno stato “violated” e l’agente offerente con il numero identificativo 6, ovvero il bidder5, viene classificato “untrustworthy”. In Figura 5.6 viene presentata una panoramica dei commitment del sistama. Si nota come il commitment vincente evolve da uno stato pending ad active fino a violated a causa del mancato pagamento del prodotto da parte del bidder5. Tutto il processo dell’asta fallisce e, in Figura 5.8, si nota come gli agenti del sistema vengono ora classificati: il bidder5, ovvero l’agente con l’identificativo di sistema 6, è stato considerato inaffidabile agli occhi della società e, per questo, viene catalogato “untrustworthy”.

110

Figura 5.6. TestAuction_2: panoramica sui commitment del sistema.

Figura 5.7. TestAuction_2: visione della temporal proposition vincente.

Figura 5.8. TestAuction_2: agenti del workgroup, sia quelli “trustworthy”, sia quelli

“untrustworthy”.

111

5.1.3 TestAuction_3 Questo test si differenzia di poco rispetto a quello precedente. L’ambiente di esecuzione è lo stesso, vale a dire ci sono sempre cinque offerenti:

bidder1 offre 500; bidder2 offre 1500; bidder3 offre 3000; bidder4 offre 4000; bidder5 offre 5000.

Tutti gli offerenti accettano di fare una proposta, ad eccezione del bidder4 che ha impostato il parametro RequestActions a reject, questa volta però, al contrario del test precedentemente effettuato, i parametri “Payment” dei bidder sono tutti settati a vero il che significa che qualsiasi offerente dovesse essere il vincitore dell’asta, questo si impegnerebbe, comunque, a pagare il prezzo pattuito durante la fase di contrattazione. L’unica sostanziale differenza è che il parametro “Delivery” del banditore viene, per la prima volta, settato a falso vale a dire che, dopo che l’asta è terminata e dopo che il vincitore ha pagato il prezzo offerto stabilito, il banditore, comunque, viene meno ai suoi doveri e non consegna il prodotto al cliente vincitore. Anche in questo caso si verifica una violazione del sistema: il bidder5 fa un’offerta, il banditore lo dichiara vincitore, l’agente paga il quantitativo dell’offerta, ma il banditore non consegna il prodotto. La macchina a stati evolve e il commiment passa da uno stato pending a uno stato active ad uno violated. Questo si vede chiaramente dai vari cambiamenti che sono riportati nella Figura 5.9, nella Figura 5.10 e nella Figura 5.11.

112

Figura 5.9. TestAuction_3: evoluzione del commitment – primo step pending.

Credo sia utile chiarire il perché il commitment numero 4 entra in uno stato violated mentre il commitment numero 5 entra in uno stato fulfilled. Sappiamo, infatti, che il bidder, per fare un’offerta, utilizza la primitiva di comunicazione propose() che è una primitiva composta da una request() e da una promise(). Il commitment 4 nasce dalla richiesta di acquisto (request()) del prodotto che il bidder fa all’auctioneer, a patto che, quest’ultimo, si impegni alla consegna dello stesso prodotto entro la scadenza t2. Il problema è che, nel momento in cui il parametro booleano “Delivery” viene settato a falso, anche il content della proposizione temporale, relativa al commitment 4, diventa falso: ciò implica che la macchina a stati, che ha fatto diventare il commitment active a fronte di conditions vere, fa evolvere lo stato del commitment 4 a violated. Il commitment 5 nasce, invece, dalla promessa (promise()) di pagamento del prodotto all’asta (il bidder nei confronti dell’auctioneer) entro un tempo t1 ( dove t1<t2), nel caso in cui il bidder si riveli il vincitore, ovvero sia colui che ha fatto l’offerta maggiore. Il content della temporal proposition, associata al commitment 5, cambia il suo valore di verità da undefined a true. Ciò causa un cambiamento di stato, all’interno della macchina a stati finiti: il valore del commitment 5 passa da active a fulfilled. A questo punto, come si vede in Figura 5.12, è utile mostare come il bidder5, che ha mantenuto fede alla parola data, viene inserito fra gli agenti credibili che fanno parte del sistema; al contrario il banditore, che non ha tenuto fede alla scadenza di consegna del prodotto, viene catalogato come agente non credibile ovvero “untrustworthy agent”.

113

Figura 5.10. TestAuction_ 3: evoluzione del commitment – secondo step active.

Figura 5.11. TestAuction_3: evoluzione del commitment – terzo step violated.

Figura 5.12. TestAuction_3: agenti del workgroup, sia quelli “trustworthy”, sia quelli

“untrustworthy”.

114

5.1.4 TestAuction_4 I test che, fino ad ora, abbiamo esaminato ci hanno dimostrato come, effettivamente, il sistema funzioni; la macchina a stati finiti cambia realmente il proprio stato vale a dire che, a fronte dei cambiamenti dei valori di verità delle temporal proposition, essa transita da una posizione ad un’altra alla ricerca di una stabilità. Essere stabile significa solamente che i commitment devono aver raggiunto, come stato utile, quello cancelled o fulfilled o violated. Il test, che stiamo per descrivere, è nato con scopi differenti da quelli precedenti. Fino ad ora, ci siamo soffermati solo sulla verifica del buon funzionamento del framework; adesso l’obiettivo è quello di vedere quanto l’applicazione creata può risultare “scalabile” dove, con questo termine, andiamo ad indicare quanto l’applicazione risulta efficiente nel fornire dei tempi di risposta brevi in conformità con i requisiti che gli vengono richiesti. L’ambiente di esecuzione prevede, questa volta, la presenza di quindici agenti che entrano a far parte della comunità:

bidder1 offre 500; bidder2 offre 1500; bidder3 offre 3000; bidder4 offre 4000; bidder5 offre 5000; bidder6 offre 6000; bidder7 offre 7000; bidder8 offre 8000; bidder9 offre 9000; bidder10 offre 10000; bidder11 offre 11000; bidder12 offre 12000; bidder13 offre 20000; bidder14 offre 14000; bidder15 offre 15000.

Tutti gli offerenti accettano di fare una proposta, ad eccezione del bidder4 e del bidder13 che hanno impostato il parametro RequestActions a reject; i parametri “Payment” dei bidder sono tutti settati a vero, il che significa che qualsiasi

115

offerente dovesse essere il vincitore dell’asta, questo si impegnerebbe, comunque, a pagare il prezzo pattuito durante la fase di contrattazione; anche il parametro “Delivery” del banditore è settato a vero, il che significa che l’auctioneer si impegna a consegnare il prodotto dopo che l’offerente ne ha pagato il prezzo. Risulta evidente che il vincitore dell’asta è il bidder15, ovvero l’agente che ha come identificativo il numero 16, la cui offerta risulta la più alta. Dalla Figura 5.13 risulta evidente come, questa volta, tutti gli agenti del sistema, banditore ed offerenti, siano tutti “trustworthy”: nessuno viola le regole del sistema. La Figura 5.14 evidenzia il commitment vincente, ovvero quello relativo all’offerta del bidder15. Mandando in esecuzione il sistema, ci si rende conto che i tempi di esecuzione sono molto elevati; il sistema fatica ad elaborare i dati e questo si può giustificare in quanto, ad ogni step di aggiornamento, l’applicazione deve intervenire su un numero molto elevato di oggetti di tipo commitment. Come si può notare dalla Figura 5.15, il numero di commitment, con cui si ha a che fare, sfiora il centinaio, per questo è comprensibile la difficoltà sia in fase di creazione, sia in fase di aggiornamento. Già con quindici agenti il sistema comincia a vacillare. Si può fissare il limite di portabilità intorno ai 15–20 agenti massimo. D’altronde è necessario pensare che i passi logici, che devono essere compiuti per la simulazione dell’asta, sono moltissimi. Gli agenti, infatti, sono software, ovvero istanze di classi implementate mentre, nella realtà dei fatti, anche in un’asta virtuale su web tipo E-Bay, gli agenti che fanno parte della comunità sono esseri umani. Siamo noi che entriamo a far parte della società e proponiamo un prezzo per l’acquisto del prodotto: in questo caso, infatti, l’unico agente software è il banditore dell’asta, che noi non vediamo, ma che funge da giudice supremo e che, in tempo reale, ha il compito di dichiarare in ogni istante il prezzo vincente fra tutti quelli proposti. Parlare di “ritardo” in questa sede significa, dunque, parlare di un tempo di “delay” dovuto all’elaborazione. E’proprio per questo che abbiamo deciso di affrontare il concetto di “scalabilità” riferendoci, in particolare, alla capacità di risposta del sistema a fronte di forzature estreme compiute sullo stesso.

116

Figura 5.13. TestAuction_4: agenti del workgroup, sia quelli trustworthy”, sia quelli

“untrustworthy”.

Figura 5.14. TestAuction_4: visualizzazione del commitment vincente del sistema.

117

Figura 5.15. TestAuction_4: identificativi di alcuni commitment. Si mette in evidenza

l’enorme numero di commitment creati dal sistema.

5.2 Prestazioni del sistema Vogliamo ora mostrare graficamente il forte legame che esiste fra il ritardo che subisce l’applicazione fino ad ora descritta, all’aumentare del numero degli agenti che prendono parte al processo dell’asta. Abbiamo fatto innumerevoli test sperimentali sull’applicazione, questa volta con lo scopo di vedere il tempo di risposta della stessa. Di seguito non sono descritti i test in dettaglio come è stato fatto nei paragrafi precedenti. Il nostro obiettivo è ora quello di riprodurre, attraverso dei grafici, la relazione forte che lega il tempo di risposta del sistema con il numero degli agenti che fanno parte dello stesso. Abbiamo rilevato sperimentalmente, cronometrandoli, i tempi di risposta dell’applicazione che sono riportati in Tabella 5.1. Nella tabella troviamo il numero di agenti usati nei vari test ed i ritardi, espressi in secondi, dell’applicazione durante la prima iterazione e la seconda iterazione del processo di vendita del prodotto. Per “prima iterazione” intendiamo la prima fase di offerte di prezzi utili per l’acquisto del prodotto in asta con la

118

conseguente creazione di un certo numero di oggetti commitment; per “seconda iterazione” si intende il secondo ciclo di proposte di prezzi, fatte sul prodotto in asta, con la conseguente creazione di nuovi commitment e l’aggiornamento degli stati dei commitment creati durante la prima iterazione. Durante la “seconda iterazione” se un agente incrementa la precedente offerta con una nuova, più alta, non fa che invalidare il commitment precedente e crearne uno nuovo nel sistema. Il commitment precedente entrerà in uno stato cancelled, quello nuovo dovrà essere sottoposto a tutta la fase di confronto dei prezzi di offerta passando, dunque, attraverso gli stati pending, active e fulfilled, in caso di vincita dell’asta e di buona riuscita del processo, o violated in caso di errori causati dal mancato pagamento del bidder o dalla mancata consegna del prodotto da parte dell’auctioneer, o cancelled nel caso in cui l’offerta di quel bidder non sia quella vincente fra tutte quelle coinvolte nel processo. E’ evidente che siamo stati noi a decidere di effettuare due soli cicli di proposta; nei vari test potrebbero essere impostati innumerevoli cicli di offerta prima dello scadere del tempo massimo (tmax) usato per indicare la fine del processo stesso dell’asta.

N° agenti del test in esame.

Ritardo dell’applicazione: “prima” iterazione di offerte (in secondi).

Ritardo dell’applicazione: “seconda” iterazione di offerte (in secondi).

5 3 11 7 8 21 9 13 45

10 22 55 12 31 80 14 36 100 15 43 120

Tabella 5.1. Dati sperimentali raccolti: come varia il tempo di risposta dell’applicazione

all’aumentare del numero di agenti che fanno parte del sistema.

119

Queste rilevazioni sperimentali non sono sicuramente “precise”, se con precisione intendiamo tutta una serie di fattori, fra cui l’errore sulla misura, la precisione dello strumento etc., che volutamente in questa sede non abbiamo voluto tenere in considerazione. I dati riportati vogliono solo testimoniare approssimativamente come si comporta il sistema dal punto di vista del tempo di risposta all’aumento del numero di agenti che partecipano al test. Tutti i tempi di reazione del sistema, con un numero di agenti inferiore a 5, non sono stati riportati poiché dell’ordine dei millisecondi: il sistema reagisce, infatti, ottimamente con un numero di agenti inferiore a tale numero. Dalla tabella si nota come i primi significativi ritardi si ritrovano intorno alla decina di partecipanti; tempi di risposta del sistema eccessivamente lunghi si verificano con un numero di agenti che va dai 10 ai 15. La cosa interessante da notare è che, durante la seconda iterazione, i tempi di reazione si allungano ancor più a causa non solo del processo di creazione di nuovi oggetti commitment, ma anche a causa del processo di aggiornamento degli stati dei commitment creati durante la precedente fase di iterazione. Non c’è, quindi, solo una mera creazione di oggetti, ma anche la necessità di passare in rassegna tutti i commitment precedentemente creati al fine di aggiornarne lo stato. Questi dati non fanno che confermare tutte le considerazioni fatte nel paragrafo 5.1.4 di questo capitolo relativamente al concetto di “scalabilità” dell’applicazione. In Figura 5.16 si mostra come varia il tempo di risposta durante la prima iterazione all’aumento del numero di agenti. Non c’è una relazione di diretta proporzionalità, abbiamo infatti solamente interpolato dei punti nel grafico i cui valori sono stati rilevati sperimentalmente; nonostante ciò l’incremento del ritardo risulta praticamente costante.

120

Figura 5.16. Grafico che riporta il ritardo dell’applicazione al crescere del numero degli

agenti del sistema – prima iterazione processo di offerta.

In Figura 5.17 si mostra come varia il tempo di risposta dell’applicazione durante la seconda iterazione del processo di offerta ed infine, in Figura 5.18, troviamo il ritardo complessivo dell’applicazione: se noi non conoscessimo il reale funzionamento del sistema, avvertiremmo solamente il ritardo totale di risposta dello stesso.

Figura 5.17. Grafico che riporta il ritardo dell’applicazione al crescere del numero degli

agenti del sistema – seconda iterazione processo di offerta.

Ritardo di risposta dell'applicazione -

Prima iterazione ciclo di offerta

0

10

20

30

40

50

0 5 10 15 20

n°agenti

rita

rdo

ap

pli

ca

zio

ne

(sec.)

Ritardo di risposta dell'applicazione -

Seconda iterazione ciclo offerta

0

20

40

60

80

100

120

140

0 5 10 15 20

n°agenti

ritr

do

ap

pli

ca

zio

ne

(s

ec

.)

121

Figura 5.18. Grafico che riporta il ritardo complessivo dell’applicazione al crescere del

numero degli agenti del sistema nei vari test sperimentali.

5.3 Problematiche generali

Per lo sviluppo di questa applicazione è stato fondamentale l’utilizzo di un processo “thread” capace di scandire il tempo e, di conseguenza, di regolare tutte le azioni dei partecipanti all’asta. Nella Figura 5.19 è mostrata la finestra di gestione del tempo, rappresentazione ad alto livello del funzionamento del processo “thread”, che viene descritta nel dettaglio in [10].

Figura 5.19. Form che utilizza il processo thread gestore del tempo di sistema.

Ritardo complessivo dell'applicazione

0, 01, 65, 14

7, 29

9, 58

10, 77

12, 111

14, 136

15, 163

0

20

40

60

80

100

120

140

160

180

0 5 10 15 20

n°agenti

rita

rdo

ap

pli

ca

zio

ne

(s

ec

.)

122

Si vede dalla figura come il tempo può essere incrementato manualmente cliccando sul bottone chiamato “Increment”; si nota come il tempo che scorre può essere visualizzato e come si può ricevere notifica della registrazione agli eventi. Il nostro sistema, infatti, viene fortemente gestito attraverso “eventi e delegati”. Questo significa che, quando un evento viene scatenato, si invoca un handler, ovvero un metodo gestore dell’evento, che serve per far evolvere le azioni del sistema.

E’ proprio questa modalità di gestione ad eventi che causa dei ritardi in materia di aggiornamento di alcuni dei parametri del sistema. Ad esempio l’attributo askPrice, che ciclicamente viene aggiornato coi prezzi offerti dai clienti, subisce dei ritardi di aggiornamento. In pratica tutto il sistema funziona, ovvero utilizza il valore corretto di askPrice, ma quando viene riempita la form TestOutputForm, presentata in Figura 5.20, i valori dell’askPrice vengono aggiornati in ritardo. Nell’esempio mostrato, ciò non accade; il verificarsi di questa anomalia dipende, infatti, non solo da chi offre prima nel sistema, ma anche da qual è l’ordine con cui si succedono le offerte.

Figura 5.20. Form che mostra l’output del test TestAuction_2 come esempio.

123

6. CONCLUSIONI Il presente capitolo, di discussione sul lavoro svolto, nasce con lo scopo di enfatizzare i problemi rilevati nell’approccio seguito, i difetti della corrente implementazione, sia del framework sia dell’applicazione concreta dell’asta che lo utilizza, ed i possibili punti d’espansione futuri.

Il framework che è stato implementato, fornendo una personale interpretazione alle specifiche esposte in [3], presenta notevoli caratteristiche delle quali alcune indubbiamente positive, altre meritevoli di riflessioni.

E’ da attribuire, favorevolmente, a questo approccio il merito di aver

fornito una definizione operativa al concetto di “commitment”, anche se l’ampio utilizzo di una semantica basata su commitment richiede l’integrazione forte di una logica innovativa basata sul concetto di “obbligo sociale” all’interno di una società: aspetto che ancora è in fase di sviluppo.

Un’altra caratteristica, della proposta che è stata esaminata per la

creazione del framework, riguarda la sua modularità e la possibilità di riutilizzo dei vari componenti che lo costituiscono. Partendo, infatti, da un ridotto set di operazioni di base sull’oggetto commitment, è possibile definire il significato di semplici atti comunicativi che possono essere usati per costruire un livello di più alta complessità per gli stessi. La definizione della primitiva di comunicazione “propose”, intesa come combinazione di una primitiva “request” e di una primitiva “promise”, può rappresentare un significativo esempio di atto comunicativo di alto livello costruito a partire da più semplici atti di comunicazione di base. Questa primitiva risulta, inoltre, utilissima a livello di applicazioni web per il commercio elettronico. Potrebbe rivelarsi utile, in futuro, estendere il pacchetto degli atti di comunicazione di base introducendo, ad esempio gli ordini e i comandi. La cosa, assolutamente innovativa, riguarda il fatto che tutti gli ACL sono standard, vale a dire che le definizioni delle primitive di comunicazione, utilizzate per focalizzare l’interazione, rimangono assolutamente inalterate ed indipendenti dall’applicazione che le utilizza.

124

Per aumentare, inoltre, l’espressività del protocollo potrebbe essere utile accrescere il numero di operazioni e di metodi, contenuti all’interno della classe commitment, in modo tale da consentire agli agenti di poter completamente negoziare, fra loro, il valore del “content” e delle “conditions” di un oggetto commitment stesso. Ci siamo resi conto, infatti, che un limite del protocollo esaminato è quello di non tenere traccia, all’interno di ciascun oggetto commitment, del tipo della primitiva di comunicazione che lo ha generato, ma solo del debtor e del creditor ovvero dei protagonisti del commitment stesso.

Un altro pregio dell’approccio in questione, legato strettamente alla

semantica basata su commitment e non alla semantica basata sugli stati mentali degli agenti (approccio BDI), che si riflette anche sul protocollo esaminato riguarda l’utilizzo di agenti, all’interno della società, che sono sostanzialmente “agenti semplici”: non è richiesto un alto livello di sofisticatezza né sugli agenti, né sui concetti da loro esposti. Questa caratteristica è significativa in quanto implica che non si è costretti a dover implementare applicazioni eccessivamente complesse al fine di testare il framework. Si deve notare, infatti, che se questa tipologia di approccio basata su commitment, presente all’interno del sistema che è stato implementato, può diventare costosa quando gli agenti presenti nel sistema sono sull’ordine delle decine, si può facilmente immaginare come una verifica basata sugli stati mentali degli agenti, supposto che questi siano accessibili, sia destinata ad essere ancora più onerosa e, quindi, difficilmente gestibile.

Si presenta qui un’altra considerazione relativamente all’entità Agent

che, pur essendo facilmente estendibile, risulta priva di alcuni meccanismi. In questo primo approccio implementativo non è possibile che due agenti, appartenenti a gruppi di lavoro differenti, possano cooperare; in futuro si potrà risolvere il problema andando a modificare l’attribuzione degli identificatori degli agents, e del relativo attributo privato di classe _workgroupOwner in modo tale che, quest’ultimo, venga gestito come una collezione che tiene traccia, per ogni agente, del gruppo di cui lo stesso fa parte. La stessa entità Agent ha, però, un notevole pregio: non possiede, nel suo stato interno, nessuna struttura che sia necessaria alla gestione dei commitment sociali: tutto è

125

delegato alla piattaforma. La decentralizzazione dello stato è demandato ad un “suitable notifier” così come viene descritto in [3]: la classe CommitmentManager per come è stata progettata. L’esistenza di questa entità snellisce la struttura dell’agente che risulta essere più flessibile in termini d’estendibilità. Il CommitmentManager, d’altro canto, è un punto cruciale per il sistema: senza di esso non ha più senso parlare del concetto di “obbligo sociale” in quanto non sarebbe più possibile, da parte degli agenti, intraprendere alcuna azione a livello sociale.

Anche per quanto riguarda il protocollo di interazione relativo

all’English Auction si possono effettuare alcune considerazioni di carattere pratico. A nostro parere, il framework, creato per essere utilizzato da applicazioni esterne tipo quella dell’asta inglese, risulta essere, per alcuni aspetti, inefficiente. Là dove è necessario avere molti partecipanti al sistema, il framework fornisce tempi di risposta molto lunghi. Basta pensare a come abbiamo fissato il limite di scalabilità, relativamente all’applicazione dell’asta, intorno ai 15, massimo 20 agenti. E’ vero che il sistema che abbiamo creato è monoprocessore e non può essere valutato nel distribuito, nonostante ciò riteniamo che soli 20 agenti che possono fare offerte sia un numero abbastanza limitato per un sistema come quello di un’asta. Basta pensare, poi, che l’applicazione impiega tempi davvero eccessivamente lunghi con 15-20 agenti in quanto si trova a dover elaborare e a dover aggiornare, ogni volta, un numero di commitment che risulta essere, negli esempi studiati, di un ordine di grandezza superiore rispetto al numero degli agenti. Quando parliamo di “delay” del sistema, infatti, facciamo riferimento al ritardo dovuto all’elaborazione. Nei sistemi reali, spesso sviluppati in ambito distribuito, sono molti e differenti i ritardi che si possono accumulare in un sistema. Ad esempio ci sono ritardi dovuti all’implementazione di una piattaforma in maniera distribuita o sfruttando la potenza di calcolo di più processori; ci sono altri ritardi dovuti alla comunicazione, all’intervento umano in ambito distribuito. Il concetto di ritardo, esaminato da noi, è unicamente connesso all’elaborazione, determinato cioè dalla difficoltà di creare ed aggiornare un gran numero di oggetti commitment nel sistema.

126

Un altro punto che deve essere precisato riguarda le “dichiarazioni”, ovvero quelle primitive di comunicazione utilizzate in particolare nel processo di apertura e di chiusura dell’asta. Dalle specifiche esposte in [3] emege che le dichiarazioni non creano dei commitment, ma in generale il loro effetto, a nostro parere, è molto più ampio del semplice “cambiare lo stato delle cose” a livello di attributi. In un futuro processo di revisione del framework si potrà ovviare a tale problema modificando la primitiva “declare()” di basso livello contenuta nel framework. Tale primitiva dovrà, a quel punto, limitarsi a cambiare lo stato degli oggetti relativi al dominio. In questo caso, ad esempio, lo stato di “asta aperta” e di “asta chiusa” potrà essere inserito all’interno dell’oggetto AuctionWorkgroup e di conseguenza, in quanto stato del sistema, potrà essere modificato solo da quegli agenti che, come l’Auctioneer, sono investiti dal potere e dalla responsabilità di compiere tali modifiche.

Un'altra considerazione nasce dal confronto fra due sistemi molto

differenti che utilizzano, entrambi, agenti software. Il primo scenario rispecchia quello di un’asta elettronica, molto simile, ad alto livello, al funzionamento dell’asta inglese di cui a lungo abbiamo parlato nelle precedenti sezioni, tipo E-Bay; il secondo scenario rispecchia un sistema di allocazione di risorse in una catena di produzione, tipo quello proposto in [4], in cui gli agenti rappresentano, ad esempio, dei moduli di una catena di produzione e dove questo sistema può essere utilizzato per verificare quali componenti sono realmente “reliable”, ovvero affidabili, o meno. Nel primo scenario, sicuramente, risulta a nostro parere molto più complesso andare a verificare effettivamente sia se gli agenti si comportano bene sia se comunicano correttamente. Sarebbe, infatti, necessario avere una conoscenza completa sul mondo che non è possibile avere in generale. E’ di conseguenza molto più complesso poter classificare gli agenti come “trustworthy agents” e “untrustworthy agents”. Nel secondo scenario, quello che utilizza gli agenti come parte di una catena di produzione, risulta, invece, già più verosimile pensare di avere un’infrastruttura che riferisce le azioni reali degli agenti in quanto il sistema ad agenti è proprietario e non è un sistema aperto. Probabilmente sarebbe necessario, per ogni ambiente, stabilire un set di temporal proposition specifiche di dominio in modo da creare una sorta di

127

ambiente chiuso in cui si potrebbe sapere con certezza quali sono gli agenti che interagiscono e quali sono le primitive standard per l’interazione. In questo caso ci sarebbero, indubbiamente, meno ambiguità nel classificare gli agenti come affidabili o meno all’interno del sistema in quanto, per ognuno, si potrebbe sapere subito quale proposizione temporale ha utilizzato fra quelle proposte dal sistema proprietario andando a decidere con tempestività e senza ambiguità se l’agente si sta comportando correttamente o meno.

Un’ulteriore considerazione va fatta relativamente al codice. In tutta

questa tesi non si è mai parlato dell’implementazione concreta del sistema se non, ad alto livello, attraverso l’utilizzo di Diagrammi UML fondamentali per la modellazione dell’ambiente di lavoro. E’ importante notare, però, come tutto il framework non sia “Thread Safe”. Questo significa che il sistema creato non gestisce la concorrenza negli accessi a risorsa condivisa. Sarebbe utile per questo fare, in un futuro, un attento studio ed un’accurata analisi delle parti critiche del sistema, proprio a livello di implementazione, al fine di identificare quei metodi o quei punti critici dal punto di vista degli accessi, in modo tale da inserire dei “lock” con lo scopo di evitare dei “deadlock” ovvero delle “corse critiche” causate da accessi contemporanei alla stessa risorsa. C’era stato, durante la fase implementativa, un tentativo di porre dei “lock” sul codice, ma questo, si è sperimentato praticamente, provocava come conseguenza immediata, un notevole appesantimento dell’elaborazione e dell’ interazione tra le classi coinvolte nei casi di test dell’asta. Sicuramente questo è un fattore di così tale importanza che non può essere sottovalutato e che, in futuri sviluppi, dovrà essere sicuramente ripreso in mano.

Un’ultima considerazione viene riportata per precisare come il progetto,

che si è realizzato, è sostanzialmente solo un prototipo di simulazione, sulla stessa macchina, nato per verificare il processo di semantica della comunicazione: si è voluto offrire solo uno studio di fattibilità su un approccio di comunicazione basato sul concetto di obbligo sociale. Lavorare con agenti in ambito distribuito comporterebbe la necessità di affrontare una nuova serie di problematiche molto complesse ed estese, di cui non si è deciso di parlare in

128

questa sede, ma che potrebbe costituire un interessante punto di espansione del progetto stesso in revisioni e sviluppi futuri.

129

7. Appendice

Diagramma UML progettuale ACLFramework.

130

Diagramma UML progettuale English Auction.

131

8. Bibliografia [1] Bauer, B., UML Class Diagrams Revisited in the Context of Agent-Based

Systems. In Proceeedings of the Second International Workshop on Agent-Oriented Software Engineering (AOSE-2001), G. Weiss e P. Ciancarini eds., Springer, 2002, pp. 101-118.

[2] Odell, J., Objects and Agents: How do they differ?. 1999. [3] N. Fornara, M. Colombetti, Defining Interaction Protocols using a

Commitment-based Agent Communication Language. AAMAS 2003, 14-18 Luglio, Melbourne, Australia, 2003, ACM Press.

[4] H. Van Dyke Parunak, A Practitioners’Review of Industrial Agent

Applications. In Autonomuos Agents and Multi-Agent Systems. 2000, pp.389-407, 2000, Kluwer Academic Publishers.

[5] AA.VV., Multiagent Systems – A Modern Approach to Distributed

Artificial Intelligence. MIT Press, 2000. [6] Norvig, P. e Russel, S.J., Intelligenza artificiale – Un approccio moderno.

UTET, 1998. [7] Finin, T., Labrou, Y. e Peng, Y., Intelligent agents. In IEEE Intelligent

Systems, marzo/aprile 1999, pp. 45-52. [8] Graffi, G. e Scalise, S., Le lingue e il linguaggio – Introduzione alla

linguistica. Il Mulino, 2002. [9] P.Yolum, M. P. Sing, Flexible protocol specification and execution:

Applying event calculus planning using commitments. AAMAS 2002, pp. 527-534, New York, 2002, ACM Press.

132

[10] G. A. Ingenito, Implementazione di una macchina a commitment per la semantica delle interazioni nei sistemi ad agenti. Bologna 2003.