SlideShare ist ein Scribd-Unternehmen logo
1 von 87
Downloaden Sie, um offline zu lesen
UNIVERSITÀ DEGLI STUDI DI TRIESTE




                FACOLTÀ DI INGEGNERIA
     CORSO DI LAUREA SPECIALISTICA IN INGEGNERIA
                    INFORMATICA




IMPLEMENTAZIONE IN .NET DI UN FRAMEWORK PER
  L'ANALISI DI SISTEMI BIOLOGICI BASATO SULLA
PROGRAMMAZIONE CONCORRENTE CON VINCOLI.




Laureando                          Relatore
Diego Banovaz                      prof. Luca Bortolussi




            ANNO ACCADEMICO 2009 - 2010
Banovaz Diego - Tesi
Ringraziamenti
Scrivere i ringraziamenti di questa tesi è un passo importante, nel fare il
quale spero di non dimenticare nessuno.
In primis vorrei ringraziare il mio relatore, Luca Bortolussi, per avermi ac-
compagnato in questo viaggio verso la follia della durata di sei mesi. In molte
occasioni ha saputo spronarmi o fustigarmi per spingermi ad andare avanti
con il lavoro. In particolar modo è a lui che si deve la stesura corretta dell'e-
laborato; senza il suo intervento infatti non sempre avrei trovato la forza di
riordinare quella che era una matassa intricata di idee `gettate su un foglio'.
Voglio ringraziare poi la mia famiglia:     mia madre Silvia, in arte Iena, la
quale ha saputo insegnarmi con dolcezza e pugno di ferro che cosa signichi
prendersi un impegno; mio padre Loris, meglio noto come Bao, che non ha
mai lesinato un gesto aettuoso o un incoraggiamento. Spero possano trarre
da questa occasione almeno una parte dell'entusiasmo e della graticazione
che loro hanno sempre saputo darmi.
Ringrazio poi mio fratello Daniele, o Menion, per avermi trasmesso innume-
revoli passioni e ben pochi sani principi. Devo sicuramente a questa `guerra
dei venticinque anni' buona parte della mia formazione caratteriale. Azzar-
dando che almeno un lettore su due abbia pensato `purtroppo', non posso
fare altro che far ricadere sul fratello malvagio la colpa.
Il mio pensiero va poi ai miei Nonni, Alda, Cornelio, Danira e Giordano per
gli insegnamenti che hanno saputo darmi nel corso degli anni e per quanto
di buono mi hanno trasmesso.
Un grande grazie va a Giordana, per avermi reso (e rendermi) ogni giorno
più felice. Un grazie per essere sempre al mio anco, nei momenti belli e in
quelli brutti.


Fine della pseudo-serietà.
Un grazie di proporzioni bibliche va al Sig. Federico Morsut (quel de Gra-
do!), per avermi accompagnato in tutto questo percorso di studi e non solo;
per esser stato sempre ad ascoltare e sempre disponibile. Unico!
Al Dott. Mr.P per l'amicizia di mille mila anni, dalla sabbionaia agli stiva-




                                        i
letti di spritz!
A m3kka, per aver implementato una List in Java e per le mille altre stupi-
daggini che ci hanno portato a sghignazzare insieme.
Al buon lelìn per le mille avventure arontate insieme (quando torniamo a
Novalia?)
A PoL, perchè i motivi da elencare sarebbero troppi.
A ZaK, per essere una delle persone migliori che conosco.
Grazie a tutti i fenomeni del DMI: dal furlanissimo Ghise, al karate-kid-
spartano Alex, alla New Entry Luka, al buon vecchio Peo, al PortaNOT tr3,
ad Alice e a tutti quelli che mi odieranno per essermeli dimenticati!
Un grazie va anche a tutti i compagni di LAN della Tana:         a kapa per il
falsetto potente, a Spruss per le cene di Bio, a Spino per essere un camper,
a Conza per la risata suina, a Defy per i rosik trascendentali, a Max per
la fede nel Dark Cocumber, a Iccio per la perdita dell'olfatto, a Jack per i
tormentoni immancabili, a 0rka per l'Arroganza, a minivap per l'arroganza,
a jockey per nominarmi tra le due e le trecento volte a LAN, a Diu per l'uso
scorretto di qualunque Zombie a Left, a Kane per essersi beccato con gioia
i miei Commando in CnC, a Baz per avermi fornito una scena alla Porky's
che dicilmente dimenticherò, a Turbo per lo Strip CnC con la corriera di
svedesi, a Tora per le sponte in ET, a Fil per la corretta fede nel sacro UT
serale, a Sick perchè tutto è un GdR, a Pislner Urquel per l'UT in esecuzione
automatica, a Angel per i quintali di gamberetti in salsa rosa, a Gandalf per
l'utilizzo corretto della parole Bollione, a Pietro per aver involontariamente
assaggiato, a Toom per la risata contagiosa e letale, a Gibo per il wood rivela
scritte idiote, a bubez per esser sempre più sfalcià, al Wolf per le Storie del
Lupo e alla sk0d3 per essere la prova vivente che una donna non può essere
forte ad UT, per quanto ci provi.
Ai miei cuginetti condividi-pasto/cartoni-inutili del pranzo dalla nonna, An-
gelica e Davide (e ovviamente anche a Fede e Roby). A tutta la musica, in
particolar modo agli Opeth.
Grazie anche agli Insanity Fair (Jo, Tati, Alf, Mauro) e agli Overtures (Meek,
Dani, Luka, Cum, Guitty) per le tournè/viaggi e per le incredibili serate vis-
sute insieme.
Al Gippo (alias el Bomber) per le innumerevoli volte che mi ha lasciato vince-
re a PES adducendo innumerevoli scuse improbabili, alla pazientissima Sara
e al suo acerrimo nemico Rudy.
A Niha, Maru, m3kka e Diu per la GdR experience in montagna.
A butra, per i racconti dei Mig Russi e del cemento per el controllo climatico.
A Nebbia, el Folpo, el Guru, Patachini e a tutti i compagni di carretto della
Sagra.
Un grazie anche ai Bodri per tutte le Bodrate insieme: Hale, Ophy, Sara,


                                      ii
Vale, Xander, Biz, Ushti, la ragazza di Ushti, Scano, Jessica, Marta, Mono,
i ba di Mono.
Come da consuetudine i ringraziamenti son stati scritti 10 minuti prima di
mandare in stampa la tesi, quindi saranno sicuramente carichi di mancanze
e lacune.




                                    iii
Indice

Ringraziamenti                                                                       i
Introduzione                                                                       vii
1 Nozioni Teoriche                                                                  1
  1.1   Algebre di Processo . . . . . . . . . . . . . . . . . . . . . . . .         1
        1.1.1   Operazioni dei processi . . . . . . . . . . . . . . . . . .         1
        1.1.2   CCP: Concurrent Constraint Programming . . . . . . .                4
  1.2   Algebre di Processo Stocastiche        . . . . . . . . . . . . . . . . .    8
  1.3   sCCP: Stocastic Concurrent Constraint Programming . . . . .                 8
        1.3.1   Rate . . . . . . . . . . . . . . . . . . . . . . . . . . . .        8
        1.3.2   Constraint Store    . . . . . . . . . . . . . . . . . . . . .       9
        1.3.3   Grammatica . . . . . . . . . . . . . . . . . . . . . . . .         10
        1.3.4   Le potenzialità del sCCP         . . . . . . . . . . . . . . . .   11
  1.4   ITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      13
        1.4.1   Limitazioni del linguaggio       . . . . . . . . . . . . . . . .   13
        1.4.2   Modello ITS . . . . . . . . . . . . . . . . . . . . . . . .        14
        1.4.3   Le Variabili di Stato    . . . . . . . . . . . . . . . . . . .     14
        1.4.4   Transizioni . . . . . . . . . . . . . . . . . . . . . . . . .      15
  1.5   ODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .        16
        1.5.1   Deterministicità del Linguaggio        . . . . . . . . . . . . .   16
        1.5.2   La denizione di ODE         . . . . . . . . . . . . . . . . . .   16


2 Analisi e Progettazione                                                          18
  2.1   Analisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      18
        2.1.1   Analisi dei Requisiti    . . . . . . . . . . . . . . . . . . .     18
        2.1.2   Studio dei Casi d'Uso . . . . . . . . . . . . . . . . . . .        19
  2.2   Progettazione   . . . . . . . . . . . . . . . . . . . . . . . . . . .      20
        2.2.1   Standardizzazione di Input ed Output           . . . . . . . . .   21
        2.2.2   I Macro Moduli . . . . . . . . . . . . . . . . . . . . . .         22
        2.2.3   Il Compilatore . . . . . . . . . . . . . . . . . . . . . . .       23



                                        iv
2.2.4   Runtime Manager . . . . . . . . . . . . . . . . . . . . .          24
         2.2.5   Constraint Store       . . . . . . . . . . . . . . . . . . . . .   25
         2.2.6   Denition Store . . . . . . . . . . . . . . . . . . . . . .        25
         2.2.7   Interfaccia Graca       . . . . . . . . . . . . . . . . . . . .   26


3 Interfaccia                                                                       29
  3.1    Installazione . . . . . . . . . . . . . . . . . . . . . . . . . . . .      29
  3.2    Il Codice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      29
         3.2.1   Il Codice SourceAM         . . . . . . . . . . . . . . . . . . .   30
         3.2.2   Il Codice SourceCS . . . . . . . . . . . . . . . . . . . .         32
  3.3    La Simulazione     . . . . . . . . . . . . . . . . . . . . . . . . . .     33
         3.3.1   Graphic Simulator        . . . . . . . . . . . . . . . . . . . .   33
         3.3.2   Batch Simulator . . . . . . . . . . . . . . . . . . . . . .        35


4 Implementazione                                                                   37
  4.1    Dettagli dell'Interfaccia Graca       . . . . . . . . . . . . . . . . .   37
  4.2    SCCP    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      38
         4.2.1   Il Constraint Store      . . . . . . . . . . . . . . . . . . . .   38
         4.2.2   Denition Store . . . . . . . . . . . . . . . . . . . . . .        47
         4.2.3   Runtime Manager . . . . . . . . . . . . . . . . . . . . .          50
         4.2.4   ParserCS     . . . . . . . . . . . . . . . . . . . . . . . . .     51
         4.2.5   ParserAM . . . . . . . . . . . . . . . . . . . . . . . . .         53
  4.3    ITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      55
         4.3.1   Constraint Store e Denition Store         . . . . . . . . . . .   55
         4.3.2   Runtime Manager . . . . . . . . . . . . . . . . . . . . .          56
         4.3.3   ParserCS e ParserAM          . . . . . . . . . . . . . . . . . .   59
  4.4    ODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .        60
         4.4.1   ParserAM e ParserCS          . . . . . . . . . . . . . . . . . .   60
         4.4.2   Transition System . . . . . . . . . . . . . . . . . . . . .        60


5 Test                                                                              63
  5.1    Esempio #1:    client server     . . . . . . . . . . . . . . . . . . . .   63
         5.1.1   Analisi del problema       . . . . . . . . . . . . . . . . . . .   63
         5.1.2   Modello sCCP . . . . . . . . . . . . . . . . . . . . . . .         65
         5.1.3   Analisi delle prestazioni      . . . . . . . . . . . . . . . . .   66
  5.2    Esempio #2: Lotka-Volterra . . . . . . . . . . . . . . . . . . .           67
         5.2.1   Analisi del Sistema . . . . . . . . . . . . . . . . . . . .        67
         5.2.2   Modello sCCP . . . . . . . . . . . . . . . . . . . . . . .         68
         5.2.3   Analisi delle Prestazioni      . . . . . . . . . . . . . . . . .   69
  5.3    Esempio #3: Sintesi di Glucosio da Lattosio in E-Coli . . . . .            70
         5.3.1   Analisi del Sistema . . . . . . . . . . . . . . . . . . . .        70



                                          v
5.3.2   Modello sCCP . . . . . . . . . . . . . . . . . . . . . . .      71
        5.3.3   Analisi delle Prestazioni   . . . . . . . . . . . . . . . . .   73
  5.4   Esempio 4: Numero elevato di Agenti . . . . . . . . . . . . . .         73


6 Conclusioni                                                                   75
Bibliograa                                                                     76




                                     vi
Introduzione
La costruzione di modelli di alcuni aspetti della realtà è sempre stata un
tassello fondamentale del metodo di indagine scientico.
Le tecniche di modellizzazione dei giorni nostri permettono di descrivere e ra-
gionare su aspetti sempre più complessi del mondo. In questo la matematica
e l'informatica hanno un ruolo fondamentale: la prima fornisce una cornice
formale entro cui costruire dei modelli, la seconda mette a disposizione po-
tenti strumenti computazionali per l'analisi.
L'aumento della potenza computazionale e il miglioramento delle tecniche di
analisi non sono tuttavia sucienti a rendere la modellizzazione matematica
pervasiva anche nelle discipline scientiche storicamente più descrittive (a
causa della loro complessità), come la biologia.
Costruire modelli formali e analizzarli a calcolatore sono attività complicate
che richiedono nozioni approfondite di matematica ed informatica, oltre che
nell'ambito specico del modello.
Per queste ragioni oggigiorno c'è la tendenza a creare degli ambienti di svi-
luppo integrato per la creazione ed analisi di modelli, che rendano questa
attività accessibile anche a non specialisti.   Sull'onda di questa evoluzione
si è deciso di arontare l'argomento di questa tesi: creare un ambiente di
sviluppo per SCCP, un linguaggio per la creazione di modelli ad agenti con-
correnti ad evoluzione stocastica.
Nel corso del progetto sono stati svolte le fasi di analisi, progettazione e
realizzazione dello stesso e sono state portate tutte a termine: il framework
adesso esiste e rispetta tutte le speciche preventivate.
Lo stesso è composto da un'interfaccia graca che si interfaccia tramite XML
e CSV e tre compilatori diversi che sono stati scritti appositamente per ri-
spondere a tre diverse esigenze.
Nel primo capitolo tratteremo le nozioni teoriche che sono le fondamenta ne-
cessarie per arontare il problema: si parlerà infatti di Algebre di Processo,
Algebre di Processo Stocastiche e si daranno alcuni tratti sul lavoro svolto
dai tre compilatori che sono stati creati.
Nel secondo capitolo si aronteranno l'Analisi e la Progettazione del fra-




                                      vii
mework: si partirà dalle basi teoriche esposte nel primo capitolo per proget-
tare la visione funzionale dei moduli del progetto.
Nel terzo capitolo si darà una visione esterna del progetto, si tratterà l'in-
stallazione e l'utilizzo delle diverse componenti che formano il progetto.
Nel quarto capitolo si guarderà più da vicino al progetto: si analizzeranno le
classi più importanti, si vedranno i punti di forza e di debolezza delle scelte
operate, e si vedranno a livello pratico la dierenza tra i diversi compilatori.
Il quinto capitolo sarà un'analisi prestazionale e funzionale del framework:
si studieranno le prestazioni rispetto a diversi programmi SCCP, si confron-
teranno le tempistiche e le performance dei diversi compilatori cercando di
trovare dei punti nei quali approfondire gli sforzi per migliorare il framework
stesso.
Inne, nel sesto capitolo, si trarranno le conclusioni su quanto è stato fatto.
L'intero codice è stato scritto dal tesista, eccezzion fatta per alcuni mo-
duli di supporto esterno che verranno segnalati per la corretta valutazione
dell'operato.




                                      viii
1




    1
Capitolo 1
Nozioni Teoriche
In questo capitolo verranno presentate sintetizzate le nozioni teoriche per la
comprensione dei capitoli successivi.
Dapprima verranno presentate le algebre di processo come formalismo per
la denizione di programmi ad agenti concorrenti. In seguito verrà esposto
CCP, come esempio di linguaggio concorrente.
Nelle sezioni seguenti si scenderà in dettaglio su sCCP e gli argomenti neces-
sari per capire le tre semantiche a disposizione del framework.




1.1 Algebre di Processo
Le algebre di processo (in inglese, Process Algebras) sono un linguaggio for-
male che permette di descrivere l'evoluzione parallela di più processi con le
conseguenti modiche del sistema stesso. Il formalismo prevede che l'evolu-
zione segua tre regole principali:


  1. I processi (chiamati anche Agenti) comunicano tra loro tramite mes-
      saggi (attraverso memoria condivisa)


  2. La descrizione dei processi avviene tramite l'utilizzo di semplici primi-
      tive, composte per formare della azioni più complesse.


  3. Viene denita un'algebra che imponga delle regole per gli operatori dei
      processi.



1.1.1 Operazioni dei processi
Secondo la teoria, ogni processo è composto dalla concatenazione di più azioni
atomiche; nello specico queste sono:




                                        1
1. Composizione in parallelo


   2. Indicazione del canale per il trasferimento dati


   3. Composizione sequenziale delle azioni atomiche


   4. Restrizione di dati e comunicazioni


   5. Scelta tra più possibili azioni


   6. Chiamata ricorsiva ad un processo


   7. Azione nulla


Nelle sottosezioni successive verrà spiegato il signicato di ognuna di queste
operazioni.


Composizione in Parallelo
Per indicare una composizione in parallelo viene utilizzato l'operatore        ||   .
Un esempio può essere il seguente:


Agente1||Agente2

La semantica di questa azione è traducibile nell'istanziazione ed esecuzio-
ne parallela degli agenti (equivalente a processo) indicati come     Agente1   ed
Agente2.    Sebbene possa sembrare limitante il parallelo denito in questo
modo, basti pensare che uno dei due agenti composto da un altro parallelo
per vedere che il numero di Agenti da istanziare in parallelo con una singola
azione è illimitato.


Comunicazione
La comunicazione è un azione atomica che permette a degli agenti di comuni-
care tra loro. Si capisce subito come dei processi paralleli privi di possibilità
di comunicare risultino di scarso interesse e per questo motivo ques'azione è
così importante; solitamente vi sono due modi per due processi di comunicare:


   •   Tramite l'ausilio di variabili o aree di memoria condivise;


   •   Tramite il passaggio diretto di dati;


Il primo punto è autoesplicativo: basta dare libero accesso ad opportune aree
di memoria ed il gioco è fatto.
Per il secondo punto vanno invece deniti il canale, il usso di input e quello


                                        2
di output.
Generalmente si indica il usso di input come      x(v) e il usso di output come
xy
(supponendo   x il nome del canale, v il vettore di dati da ricevere e y il vettore
da spedire)
A livello semantico l'elemento di input specica che il processo è in attesa di
dati in arrivo, mentre l'elemento di output specica che il processo è pronto
a inviare sul canale i dati.


Composizione in sequenza
La composizione in sequenza permette di collegare nell'esecuzione un numero
indenito di azioni. Vediamo un semplice esempio della composizione delle
azioni che abbiamo n'ora visto.
Supponiamo di voler descrivere un agente che attenda un parametro di in-
gresso per poi istanziare due agenti (A1 e      A3)   in parallelo: Questo processo
potrebbe venir descritto come:


x(v).(A1(v)||A3(v))

Focalizzare dati / comunicazioni
Un processo può voler limitare il numero di connessioni che gli altri agenti
possono aprire con lui: l'hiding gli permette di nascondere il canale di comu-
nicazione (o variabile) ad altri agenti. In pratica l'agente fa il wrapper di
sé stesso e nasconde all'esterno parte dei suoi canali.


Scelta
La scelta permette ad un agente di scegliere in maniera non deterministica
l'azione da eseguire.
L'operatore per la scelta è il   +,   un'esempio di utilizzo potrebbe essere:


P0 :- P1 + P2;


In questo caso, al momento dell'esecuzione di P0, questi sceglierà quale azione
invocare.




                                           3
Chiamate Ricorsive
Una chiamata ricorsiva prevede la possibilità di far si che un processo ese-
gua sé stesso (o un altro processo), permettendo la costruzione di cicli e di
esecuzioni illimitate/innite.


Azione nulla
L'azione nulla (indicata in innumerevoli modi, come nil, null, 0) fa terminare
il processo che la invoca.   Questa capacità viene utilizzata per terminare
selettivamente un agente in determinate situazioni (sicchè non rimanga in
memoria ultimata la sua esecuzione).



1.1.2 CCP: Concurrent Constraint Programming
CCP è un linguaggio di programmazione a processi concorrenti basato sui
vincoli che sta alla base di sCCP. La dierenza principale tra i due sta nella
non-deterministicità di CCP che si contrappone alla stocasticità di sCCP.
Nelle prossime sezioni verranno presentate le componenti che contraddistin-
guono il linguaggio.


Constraint Store
Il Constraint Store è la rappresentazione che CCP ha della memoria. In esso
le variabili non assumono un semplice valore, ma rappresentano un insieme
di valori che la variabile stessa può assumere.
Questa denizione è più estesa rispetto quella di Von Neumann: permette
infatti di associare alle variabili insiemi di valori, ma anche insiemi con un
solo elemento e quindi sono evidenti le maggiori potenzialità.
È possibile accedere al Constraint Store attraverso due funzioni: Ask e Tell.
Ask è una chiamata che pone una domanda al gestore della memoria, nello
specico gli chiede la validità di una formula.
Tell invece impone un nuovo vincolo al sistema espresso come formula logica
al primo ordine.
Si noti come i diversi Tell vadano ad inserire nuovi vincoli, senza in alcun
modo toccare quelli esistenti: questa condizione può portare facilmente al-
l'inconsistenza del sistema, ma utilizzata nel modo corretto porta le variabili
ad appartenere a dei domini di accettazione sempre più ristretti.
È comprensibile allora il nome di questo linguaggio:


   •   Concurrent: deriva dalla presenza di Agenti in un ambiente conccoren-
       te;



                                       4
•   Constraint: deriva dall'utilizzo di una rappresentazione della memoria
       a vincoli come il Constraint Store;


   •   Programming: indica che si tratta di un linguaggio di programmazione;


Identicate le componenti di base, si può procedere alla denizione della
grammatica del linguaggio.


La Grammatica di CCP
Di seguito viene esposto la sintassi del linguaggio nella conveniente forma di
grammatica.




 P rogram ::= Declaration.Agente

 Declaration ::= ε | Declaration.Declaration | p(x): −Agente

 Azioni ::=   ask(c)   → tell(c)

 Scelta ::= Azione.Agente | Scelta + Scelta

 Agente ::= 0 | Agente.Agente | Scelta | Agente         Agente | ∃x Agente | p(x)



                         Tabella 1.1: La sintassi di CCP.




Programma        Programma è il punto di partenza della grammatica, in CCP
questi è costituito dalle dichiarazioni degli agenti e dall'agente iniziale.


Declaration      Le dichiarazioni possono essere una, più di una o anche nes-
suna; si indicano con la forma:


N omeAgente (v ) : − Agente

Una dichiarazione rappresenta il prototipo di un Agente; contiene le diverse
azioni che fanno parte del comportamento del processo stesso e le variabili
locali che gli appartengono.




                                        5
Azioni       Le azioni che permettono di eettuare degli update condizionati
del Constraint Store. L'agente eettua gli Ask e i Tell al Constaint Store.
Ricordiamo brevemente quali sono le azioni compiute da ask e tell:


     •   Ask(condizione) permette all'agente di domandare al Constraint Store
         la validità della condizione;


     •   Tell(condizione) permette all'agente di aggiungere al Constraint Store
         il vincolo espresso in condizione;


Si veda l'esempio quì riportato per capire l'utilizzo delle guardie stesse.


if (x  5) y = 9;

diventa:


ask(x  5).tell(y = 9)

Si è deciso, sempre prendendo spunto da un'idea trovata in [1], di adot-
tare la seguente scrittura per le guardie:


[   condizione → condizione     ]


La semantica scelta impone di interpretare come Ask tutte el condizione
che stanno a destra dell'operatore       →    , mentre ciò che sta dopo viene inter-
pretato come Tell.
La condizione prima esposta:


ask(x  5).tell(y = 9)

diventa:


[   x5→y=9         ]


Questa forma contratta non impone l'utilizzo di entrambe le azioni (Ask
e Tell), in quanto basta omettere le condizioni od utilizzare dei vincoli sem-
pre veri:


[   true → t = 10   ]


Contratto per comodità in:




                                             6
[   → t = 10]

Scelta     La scelta permette di associare più azioni ad un solo agente.
La scelta prevede, come si vede in grammatica, la distinzione tra le varie
azioni separate da il segno +. Ogni elemento che forma una somma è costi-
tuito da una guardia seguita da un'Agente.


Agente1 : − [x  0 → y = 0].Agente1()
+ [x == 0 → (x = 10) (y = 0)].Agente1();


Questo è la denizione di un'Agente, operante sulle variabili globali x ed
y che compie le seguenti azioni:


Se   x  0, impongo un nuovo vincolo per cui y debba essere positiva;
Se   x == 0, impongo un nuovo vincolo per cui x debba essere minore                 uguale
a 10.


Quando viene chiesto di eseguire ad un agente, questi sà quali sono le guardie
sono vere (con Ask    true)   e quali no: eseguirà solo le azioni corrispondenti
alle prime.
Si noti come in questo particolare esempio l'agente ha sempre e solo una sola
azione da eseguire: non è possibile infatti che entrambi le azioni superino le
guardie perchè presupporrebbe che nello stesso istante               x   sia maggiore a 0 e
anche uguale a 0. Nel caso più guardie siano attive contemporaneamente, la
scelta viene eettuata in modo non-deterministico.


Agente      L'agente è la parte centrale non solo della grammatica, ma del
linguaggio in generale: formato da azioni e variabili locale è l'elemento sotto
osservazione da parte della simulazione. Un'Agente è formalmente composto
da agenti, guardie e scelte che a loro volta vengono composte per ottenere la
forma dello stesso da noi voluta. Un esempio di Declaration potrebbe essere:


P (x = 0) : − [true → x = 0].( P 2()    ||   P 3()   ) +   P 4();

Questa viene interpretata come:


Declaration - Scelta tra (Guardia seguita da parallelo e chiamata P4)




                                         7
1.2 Algebre di Processo Stocastiche
Nel corso delle prossime sottosezioni verrà analizzato un ambiente in cui,
dato lo stato della memoria e l'indice dell'istruzione non è possibile sapere il
risultato che questa avrà, ma al massimo si potrà fare delle stime su questo
valore.




1.3 sCCP: Stocastic Concurrent Constraint Pro-
    gramming
sCCP è un linguaggio per la descrizione di modelli in cui agenti interagiscono
tra loro e con l'ambiente in modo concorrente; inoltre questa interazione è
governata da leggi probabilistiche.
sCCP è un'estensione stocastica di CCP e da esso eredita le peculiarità fon-
damentali: il Constraint Store e gli Agenti.      Questo linguaggio prevede la
comunicazione tra agenti come asincrona, ottenuta tramite l'utilizzo di va-
riabili globali condivise. sCCP è strutturato in modo da avere tutte le azioni
viste prima: scelta non deterministica, composizione in parallelo, chiamata
ricorsiva e in più la dichiarazione di variabili locali.
L'evoluzione temporale di sCCP è profondamente legata alle catene di Mar-
kov Tempo Continue, come spiegato in [1]. In questa sezione analizzeremo il
linguaggio e ne studieremo le dierenze con CCP.




1.3.1 Rate
Ad ogni azione interagente con il Constraint Store, viene associato un valore
∈ + che rappresenta il Rate. Il Rate è il prametro di una distribuzione di
probabilità esponenziale che descrive il tempo che l'azione impiega a venire
eseguita. Ad ogni passo si verica una Race Condition tra le diverse azioni
attive: verrà eseguita quella che impiega il tempo minore. Questa evoluzione
si può descrivere (dal punto di vista matematico) equivalentemente tramite
la scelta di un azione con probabilità proporzionale al rate, aumentando il
tempo secondo una distribuzione di probabilità esponenziale con Rate Tota-
le. Quest'ultimo si può calcolare come:


                     Rate(A) = π∈Actions Gπ (i) ∗ λπ
                     RateT otale = A∈ActiveAgents Rate(A)
Si evince che la probabilità di esecuzione di un Agente è:




                                        8
Rate(a)
P (A) =   RateT otale


In queste formule:

                        +
   • λπ : CS →              è il Rate dell'azione è dipendente dallo stato corrente
       del Constraint Store.

   • G(i) : CS          → 0, 1    rappresenta un valore booleano associato alla
       guardia: 1 se la condizione in Ask è vera, 0 se non lo è.

Lo scorrere del tempo, viene quindi calcolato come:


Tempo = Tempo +         ∆T

∆T = −1/T ∗ log U       (con U distribuzione uniforme di probabilità tra 0 e 1)


Azioni a Rate Innito
sCCP prevede la possibilità di avere delle azioni con Rate innito. Queste
azioni vengono chiamate Azioni Istantanee ed hanno le seguenti peculiarità:

   •   Non incrementano il tempo. (∆T         = 0)
   •   Vengono eseguite prima di ogni azione stocastica.



1.3.2 Constraint Store
Essendo un derivato diretto di CCP, anche sCCP ha un suo Constraint Sto-
re. Per aggiungere potenzialità al linguaggio, sono state aggiunte le Stream
Variables, come denite in [1]. In applicazioni di biologia o chimica, spesso
le variabili devono poter cambiare il loro valore, non solo l'insieme dei valori
che vi si possono attribuire.
Nel sequente esempio si capisce i limiti imposti da una struttura senza Stream
Variables:

[true- X=5]
[true- X=X+1]
Questa istruzione porta ad uno stato inconsistente. Per questo motivo è stato
pensato il sistema delle Stream Variables: associando ad ogni variabile una
lista (in particolare con variabile in coda non istanziata) possiamo aggiungere
in coda i nuovi valori. Nel momento in cui ci si trovi a volere il valore di quella
data variabile, basterà guardare il valore in coda, ma la presenza all'interno
di essa di tutta la sua storia non viola il resto della teoria. In tutto il resto
dell'elaborato, nelle situazioni in cui si trova una scrittura del tipo:


                                          9
[true - x=x+1]
Questa farà riferimento all'aggiunta del valore sulla destra nella lista denita
dal nome che compare sulla sinistra. Nell'approfondimento pratico vedremo
come questa gestione teorica può essere implementata con un sistema di
variabile standard a singolo valore.



1.3.3 Grammatica


                            P rogram = Declaration.Agente

             Declaration = ε | Declaration.Declaration | p(x) : −Agente

      Agente = 0 | [→ U]@∞.Agente | Scelta | ∃x Agente | Agente Agente
                        Scelta = π.Guardia | Scelta + Scelta
                           π = [G → U]@λ | [G → U]@∞
  Guardia = 0 | tell∞ (c).Guardia | p(y) | Scelta | ∃x Guardia | Guardia Guardia



                       Tabella 1.2: Sintassi del sCCP.


   L'sCCP ha una diversa grammatica per descriverlo, in cui la dierenza
principale sta nell'assegnazione dei valori di Rate. Oltre a ciò si vede come
ogni azione debba avere un peso e, essendo questo vincolato alle guardie, ogni
azione deve iniziare con una guardia. Un possibile esempio potrebbe essere
il seguente (dove @ è seguito dal Rate):



Agente1 : - [X=0-X=X+1]@{5}.Agente1() +[X3-X=X-5]@{3}.Agente1();
Agente2 : - [X0 -X=X*2]@{1/X}.Agente2();
Agente1 || Agente2
Analizziamo brevemente questo esempio, supponendo il valore iniziale di      X
sia 0.




                                       10
STEP   X    RATE     AZIONE
                          0      0    5        X   =X   +1
                          1      1    1        X   =X   ∗2
                          2      2    0.5      X   =X   ∗2
                          3      4    3.25     X   =X   −5
                          4      -1   5        X   =X   +1
                          5      0    5        X   =X   +1

Per quanto quasi tutti i punti siano deterministici (in questo esempio ad hoc)
al punto 3 è stata eettuata una scelta. Nello specico le azioni attive erano:


a)[X 3-X =X -5]@{3}
b)[X 0 -X =X *2]@{1/X}


Nello specico è stata fatta una scelta a favore della prima azione per motivi
statistici:


         3         0.25
p(a)=        p(b)=
        3.25       3.25


Ovviamente poteva anche accadere il contrario e avremmo raggiunto uno
STEP 4 con    X   pari a 8 e Rate totale pari a 3.125. A questo punto nuova-
mente si sarebbe eettuata una scelta, aggiornata con i nuovi valori di Rate.


          3         0.125
p(a)=         p(b)=
        3.125       3.125


Questo banalissimo esempio mostra un'oscillazione controllata del valore di
X.

1.3.4 Le potenzialità del sCCP
Da questo esempio si desume la versatilità del sistema e la possibilità di im-
plementare praticamente ogni tipo di algoritmo: si pensi per un attimo alla
macchina URM, gemella di quella Turing, e alle 4 operazioni da essa imple-
mentate.


sCCP ha tutte le potenzialità della macchina URM, e quindi di
quella di Turing.


Dimostrazione:       Per prima cosa l'enumerabilità dei registri:   nella mac-
china URM questi sono inniti ma, lo sono anche in questo caso, in quanto
le variabili sono le produzioni ottenibili da una grammatica del tipo:



                                          11
S   : lettera    S   |
Ed essendo un innito numerabile posso associare a ciascuna variabile che
genero un numero intero che diventerà il numero del registro della macchina
URM.
Le operazioni della macchina teorica URM sono:


    1.   Z(n),   n=1, 2, 3, ... . In risposta a questa istruzione la URM azzera il
         registro n, lasciando gli altri registri inalterati:                rn := 0.

    2.   S(n),   n=1, 2, 3, ... . In risposta a questa istruzione la URM aumen-
         ta il contenuto del registro n di una unità, lasciando gli altri registri
         inalterati,      rn := rn + 1.

    3.   T (m, n),       m,n=1, 2, 3, ...      .   In risposta a questa istruzione la URM
         trasferisce il contenuto del registro m nel registro n, tutti gli altri registri
         compreso Rm rimangono inalterati,                  rn := rm .

    4.   J(m, n, q),       m,n,q=1, 2, 3, ... .In risposta a questa istruzione la URM
         confronta il contenuto dei registri                rm   ed   rn   se:   rm = rn   allora con-
         tinua con l'istruzione successiva nel programma,                        rm = rn   allora salta
         all'istruzione q nel programma. Si vede subito allora che (supponendo
         x = rn      e   y = rm )

    1. Z(n) Azzeramento              → [true   -   x = 0]

    2. S(n) Incremento              → [true   -   x = x + 1]

    3. T(m,n) Scambio               → [true   -   x = y]

    4. J(m,n,q) Salto Condizionato                 → [x == y          -   true].IstrQ   + [x!   =y   -
         true]

Per aiutare a capire la dimostrazione in altro modo, è possibile esaminare un
algoritmo scritto in questo modo:
Agente1:- [x         == 0    -   x = x + 1]@1     . Istruzione + [x         == 1   -   x = x + 1]@1.
Istruzione
Agente2:- [x         == 2    - x = x + 1]@1 . Istruzione + . . .
In questo caso il          valore di x determina in maniera deterministica                 quale azio-
ne verrà eseguita: l'unica azione con la guardia attiva, infatti, sarà quella
eseguibile.      Si può fare un paragone tra la variabile                    x   di questo esempio e
l'Istruction Pointer di un normale calcolatore: agendo su questa otterremo
dei salti verso altre azioni.




                                                    12
Quindi, avendo vericato questo possiamo asserire che :


Eseguendo sCCP tutte le azioni della macchina URM può, co-
me CCP, per la Tesi di Church-Turing computare ogni funzione
computabile.



1.4 ITS
ITS è la seconda semantica di sCCP che è stata implementata.          In questa
sezione ne analizzeremo le qualità e i limiti che, dal punto di vista teorico,
ci han permesso di crearla. Dapprima vedremo le limitazioni del linguaggio,
analizzando poi variabili di stato, transizioni e inne un esempio. È neces-
sario ricordare che si vuole giungere ad una simulazione di tipo stocastico.
Dell'argomento viene data una trattazione superciale, per approfondimenti
si rimanda a [5].
Il procedimento che si è arontato prevede la creazione di una nuova seman-
tica per il nostro sorgente sCCP, in modo da descrivere in un altro modo il
modello descritto nel sorgente stesso. In questo caso si tratta di una visione
che passa dalla visione ad agenti ad una visione a transizioni.      Le tran-
sizioni, denite formalmente nella sezione specica, rappresentano in sunto
un passo eseguibile dal sistema per andare da uno stato ad un altro stato.
Nello specico possiamo creare una transizione partendo da qualunque delle
nostre azioni. Va ricordato che, non essendoci le variabili locali, ogni agente
è uguale a qualunque altro agente che implementi la stessa denizione. Per
descrivere ecientemente il sistema, si introducono le State Variables.



1.4.1 Limitazioni del linguaggio
Per poter funzionare il sistema a Transizioni il codice deve sottostare ai
seguenti vincoli:

   •   Non può essere utilizzata la composizione in parallelo nelle denizioni,
       ma solo per denire lo stato iniziale.


   •   Non esistono azioni istantanee (con Rate innito).


   •   Ogni azione è nella forma [Ask−       T ell]@{Rate}.Agente.
   •   Gli Agenti non posseggono variabili locali.

Queste condizioni portano a:

  1. Il numero di Agenti è costante.


                                       13
2. Ogni Agente del tipo A è uguale ad ogni altro Agente del tipo A.


   3. Ogni passaggio di variabili è fatto per riferimento.


Queste due asserzioni sono fondamentali ai ni pratici. Alla prima vi si arriva
tramite un procedimento molto semplice ed intuitivo. Siamo nella situazione
in cui:


   •    Ho N Agenti iniziali dati dallo stato iniziale.


   •    Non ho composizione parallela all'interno della denizione degli agen-
        ti(N non può crescere).


   •    Ogni azione è della forma [     Ask → T ell]@{Rate}.Agente,    quindi il
        numero di Agenti non può calare.


In generale, queste proprietà, specie l'assenza di variabili locali, garantiscono
che le variabili di stato siano una descrizione corretta dello stato del modello
sCCP.



1.4.2 Modello ITS
Un modello ITS viene dato da una tupla ITS =          (X, S, T )
Dove:


   • X     è l'insieme costituito dalle variabili globali


   • S    è l'insieme delle variabili di stato


   • T    è l'insieme delle transizioni


Le Variabili Globali sono le stesse viste per sCCP.



1.4.3 Le Variabili di Stato
Indicate con la lettera S nella denizione del sistema, le variabili di stato
permettono di descrivere e di gestire in maniera eciente lo stato delle tran-
sizioni del sistema. Ogni variabile di stato è associata ad una denizione di
un agente, e descrive il numero di agenti di quel tipo attualmente attivi nel
sistema. Di questa denizione, rappresenta il numero di agenti attivi che la
rappresentano. Il valore di una State Variable è dunque sempre un numero
naturale.
Ogni update delle transizioni sCCP dovrà essere modicato per descrivere
anche l'aggiornamento delle variabili di stato. Ad esempio:



                                          14
A1 : − [ X  0 → X = X + 1]@{k}.A2

diventa:


[ X  0 → X = X + 1; SV 1 = SV − 1; SV 2 = SV + 1]@{k}

Incrementare una variabile di stato equivale dunque ad aggiungere un agente
del tipo associato al sistema stesso.   Decrementarla equivale ad eliminarne
uno.
Supponiamo di avere il seguente agente A1 precedentemente descritto. La
guardia sarà passabile se:


X    0   ∧ SV 1    0


E il rate dato dagli agenti dello stesso tipo sarà:


A1λ = SV 1 ∗ k

In altri termini, la prima formula impone che se il numero di Agenti è pari a
0, nessuna azione è eseguibile. La seconda fa si che il Rate dato da tutti gli
agenti di un tipo sia pari al numero di essi moltiplicato per il rate del singolo.



1.4.4 Transizioni
Deniamo ora le transizioni:


T = (nome, guardia, update, rate)
πi := [guardia(X)−  update(X)]@λ
guardia(X) è passabile ⇔SVi  0 ∧ Ask(G(X)) == true
update(X) = update(X)s CCP, SVi = SVi − 1, SVj = SVj + 1

In altri termini:
La guardia è espressa come la guardia di sCCP solo che presenta un vincolo
di positività sulla variabile di stato associata.
L'update è uguale all'update visto in sCCP ma aggiorna anche lo stato delle
State Variables. Vedendo un esempio:


A1 : −[X  0 → X = X − 1]@{k1}.A2 + [X  10 → X = 0]@{k2}.A1;
A2 : −[true → X = X + 1]@{k1}.A1;
SI : A1

                                        15
Questo sistema, viene convertito in:


t1 = [SV 1  0 ∧ X  0−  X = X − 1; SV 1 = SV 1 − 1; SV 2 =
SV 2 + 1]@{k1}
t2 = [SV 1  0 ∧ X  10−  X = 0; ]@{k2}
t3 = [SV 2  0∧true−  X = X +1; SV 2 = SV 2−1; SV 1 = SV 1+1]@{k1}

Nell'esempio t2 non tocca le SV perchè incrementerebbe e decrementereb-
be la stessa variable.
È evidente come una tale forma racchiude tutte le informazioni necessarie
per un algoritmo che voglia simulare l'andamento del sistema descritto dal
sorgente sCCP ridotto.




1.5 ODE
Con ODE si indicano le Equazioni Dierenziali Ordinarie ed è proprio da
queste che prende il nome il compilatore di tipo ODE. In questa sezione si
esporrà brevemente il collegamento tra ITS ed ODE. Verrà esposto come,
sotto opportune ipotesi, sia possibile passare da un sistema di tipo ITS ad
un sistema di equazioni dierenziali. Un approfondito studio dell'argomento
si può trovare in [5].



1.5.1 Deterministicità del Linguaggio
Questa semantica per sCCP non presenta evoluzione stocastica: l'evoluzione
temporale è determinata solo dalle equazioni dierenziali associate al sistema
scritto in forma di sCCP ridotto. Questo è un ulteriore vincolo sul sistema
stesso.



1.5.2 La denizione di ODE
Come visto per sCCP e per ITS, si è dovuto denire in termini formali il
sistema. Nello specico, assumiamo che le transizioni del sistema siano della
seguente forma:


τ ∈ T , τ = (guardτ (x, s), X = X + k, S = S + h, fτ (X, S))

k   rappresenta l'aggiornamento delle variabili globali, il vettore   h rappresenta



                                        16
l'aggiornamento delle variabili di stato:




      ki   ∈ R,   se i è aggiornata esplicitamente
k=
      0,          altrimenti
      hi   ∈ R,   se i è aggiornata esplicitamente
h=
      0,          altrimenti



Si noti come richiediamo che gli update siano di una forma particolare, ov-
verro incrementi/decrementi delle variabili con quantità costanti. Da questa
denizione si ottiene il seguente sistema di ODE:

                          ˙
                          X=     τ ∈T   kτ gτ (X, S)fτ (X, S)
                          ˙
                          S=     τ ∈T   hτ gτ (X, Sfτ (X, S)

Dove X, S, h e k sono vettori.
In pratica, dal sorgente si deriva una denizione sintattica del sistema di
equazioni dierenziali.   Questo ha delle relazioni con il sistema stocastico
associabile allo stesso sorgente, per una discussione su questa relazione si
rimanda a [5]. Un programma sCCP che soddis i vincoli di cui sopra, può
essere visto come una descrizione di alto livello di un sistema di ODE.




                                          17
Capitolo 2
Analisi e Progettazione
In questo capitolo verranno analizzate le fasi di Analisi e di Progettazione
svolte per creare il progetto oggetto di questa tesi.
Nella prima sezione è stato analizzato il problema, partendo dai requisiti
funzionali.
Nella seconda sezione sono state progettate le componenti per rispondere ai
requisiti.




2.1 Analisi
Nel Capitolo 1 si sono viste le nozioni teoriche riguardanti sCCP e le due
varianti ITS e ODE.
Il progetto che si vuole creare, per l'appunto, consiste nell'implementazione
di sCCP nella maniera più versatile e più completa possibile, con un occhio
rivolto all'ecienza.
Il progetto è stato sviluppato in ambiente .NET, in particolare è stata uti-
lizzata la versione 4.0 del framework Microsoft. Le interfacce grache sono
state sviluppate in Windows Presentation Foundation (WPF).




2.1.1 Analisi dei Requisiti
È stato necessario interpellarsi sulle funzionalità necessarie al ne di creare
il framework. È facile immaginare che il requisito fondamentale sia quello di
comprendere codice di tipo sCCP: oltre a ciò è necessario che ne permetta
la simulazione in maniera integrata. Dato un codice, quindi, vogliamo ave-
re come riscontro dei dati sotto forma di graco o memorizzati in maniera
compatibile con la maggior parte dei sistemi di analisi dati. È stato deciso




                                      18
inoltre di permettere all'utente di poter simulare passo passo per compren-
dere l'andamento non solo in chiave temporale, ma anche in chiave di step
esecutivi.
Si è voluto fornire anche un'interfaccia per la stesura del codice ma, nel con-
tempo, si è voluto far in modo che non fosse l'unica interfaccia possibile in
modo da permettere di accedere alle funzionalità del codice anche da altre
GUI scritte in futuro.
Un requisito fondamentale che è stato scelto è la creazione del Constraint
Store on demand: partendo da un sorgente contenente le informazioni per
indicare le proprie speciche, il framework dovrà essere in grado di modellare
un oggetto che le implementi nella maniera migliore.
L'interfaccia graca deve permettere di salvare e riprendere in seguito il la-
voro che si sta arontando. Oltre a questo deve permettere di impostare dei
criteri di arresto dell'esecuzione (raggiungimento temporale o raggiugimento
in passi).
Deve esistere un'interfaccia simulativa di tipo batch che può gestire grandi
carichi di lavoro in maniera eciente e gestire la simulazione con variazione
dei parametri iniziali automatica.
Oltre a ciò è necessario rendere il sistema in grado di utilizzare diversi tipi
di compilatori in modo da dare all'utente la possibilità di utilizzare sia ITS
che ODE.
Quanto detto si può riassumere nei seguenti punti:

   •   Il framework deve tradurre del codice scritto in sCCP, comprenderlo e
       simularlo.

   •   Il framework deve fornire un'interfaccia all'utente in maniera da met-
       tere a disposizione tutte le sue funzionalità.

   •   Il framework deve fornire un'interfaccia ad altri programmi in maniera
       da mettere a disposizione tutte le sue funzionalità.

   •   Il framework deve generare un'output graco o numerico compatibile
       con gli altri standard.

   •   Il framework deve essere capace di creare un Constraint Store specico
       che risponda alle esigenze di ogni applicazione.

   •   Il framework deve poter gestire anche codice ITS e ODE.



2.1.2 Studio dei Casi d'Uso
Una volta analizzato il problema è stato denito il diagramma degli Use Case.
Si è visto, da quanto scritto sopra, che gli unici attori presenti sono:


                                       19
•   Utente


      •   Altri Software


Da quanto visto sopra, possiamo riassumere le attività che l'utente può fare
in:


      •   Scrivere il sorgente (salvare, caricare, compilarlo)


      •   Scegliere il compilatore


      •   Avviare la simulazione (graca o batch)


      •   Raccogliere i risultati


Mentre gli eventuali altri software dovranno poter:


      •   Scegliere il compilatore


      •   Avviare la simulazione (graca o batch)


      •   Raccogliere i risultati


Da questa prima analisi si arriva al graco in gura nella pagina successiva.




2.2 Progettazione
Ultimata la fase di analisi si è passati a quella di progettazione. In primis,
come illustrato nelle successivo sezioni, si è progettata la parte simulativa.
Nell'arontare l'argomento si è dovuto tener conto della possibilità di voler
scrivere altre IDE per i compilatori e di poter avere più compilatori per la
stessa IDE. Oltre a questo è stato necessario utilizzare un sistema standard
per l'output dei dati.
Per riuscire a mantenere il massimo distacco tra le componenti, si è deciso
di utilizzare delle interfacce per sottolineare i punti di contatto. In questo
modo se qualcuno dovesse volere riscrivere una parte del programma, non
deve far altro che reimplementare l'interfaccia associata.
È stato fondamentale dividere il codice sorgente dell'utente in due blocchi di-
stinti: una parte va a denire la congurazione degli agenti (compresi agenti
iniziali, denizioni agenti, ecc.) detta SourceAM, mentre l'altra serve a mo-
dellare il Constraint Store come l'utente desidera (variabili globali, funzioni,
constraints, parametri, operatori ... ) detta SourceCS.




                                          20
Use Cases Diagram



2.2.1 Standardizzazione di Input ed Output
Si è fortemente cercata l'indipendenza delle parti su tutti i fronti, per questo
si è deciso di utilizzare degli standard già aermati per gestire input ed out-
put. Principalmente si doveva rendere compatibile con future espansioni e
varianti l'input (rappresentato per la maggior parte dai sorgenti) e l'output
(i dati di risposta della simulazione).
Per modellare l'input serviva un linguaggio in grado di esser modellato per le
nostre esigenze e che fosse di semplice lettura: per questo motivo si è scelto
XML. Essendo molto utilizzato, un domani chiunque potrebbe creare un'in-
terfaccia graca diversa che generi il codice XML da fornire al compilatore
senza grossi sforzi. Un domani uno sviluppatore potrebbe voler creare una
IDE completamente graca in cui l'utente non debba scrivere una sola linea
di codice: grazie all'utilizzo di XML non necessiterà di alcun parser o vali-
datore se non il DTD stesso dei le XML utilizzati.
Per la verica della correttezza sintattica dei le XML sono stati creati dei




                                          21
les DTD apposta. L'utilizzo di questo sistema ha portato ad una sempli-
cazione anche nella creazione dei compilatori stessi: ogni compilatore avrà
un suo DTD per analizzare il codice così creato.
Per quanto concerne l'output si è scelto per un formato molto leggero ed
universale: il CSV (comma separated values). Questo formato è compatibile
con moltissimi programmi di analisi dati (come Mathlab o Excell) ed è prati-
camente un plain text e quindi leggibile anche con un qualunque text editor
(esattamente come XML).



2.2.2 I Macro Moduli
Per creare questo progetto è stato necessario utilizzare un approccio di tipo
Top-Down in cui si è iniziato immaginando dei macro blocchi che poi sono
andati a denirsi mano a mano che si scendeva nel dettaglio. Fin dal prin-
cipio si sapeva che dovevano esistere delle classi che assolvessero ai seguenti
compiti:


   •   Interfaccia Graca di Scrittura del Codice (Parser GUI)


   •   Parser da linguaggio a XML per il SourceCS


   •   Parser da linguaggio a XML per il SourceAM


   •   Interfaccia Graca per la simulazione graca in tempo reale


   •   Interfaccia Graca per la simulazione Batch


   •   Classi di scambio parametri di compilazione


   •   Compilatore


Con la congurazione esposta in gura un utente può utilizzare il progetto
in più modi:


   •   Utilizzare tutto il progetto, dal Parser GUI per la stesura al compilatore
       per simulare


   •   Utilizzare un proprio Editor e passare il codice per la simulazione
       Graca / Batch alle due classi predisposte


   •   Utilizzare solo il compilatore lasciando poi il proprio software a gestire
       i dati in input e output




                                       22
Figura 2.1: Primo Approccio Progettuale



2.2.3 Il Compilatore
Il Compilatore in questo progetto non è unico e non perchè si è scelto di
crearne più del dovuto, ma perchè ogni Compilatore deve comprendere un
particolare tipo di codice.
Avendo di base due tipi di codice, uno scritto per la denizione degli agenti
e l'altro per la denizione del Constraint Store, è evidente che ci dovranno
essere un modulo per comprendere l'uno e un per comprendere l'altro. Avre-
mo quindi, in generale, una suddivisione tra Parser per SourceAM e uno per
SourceCS.
È comprensibile come un codice scritto per il Parser X non necessariamente
debba funzionare per il Parser Y, ma la divisione in queste due categorie
serve per avere dei risultati comuni.
Ad esempio da un Parser per il SourceCS (ParserCS) ritornerà sempre un
contenitore con variabili, funzioni, constraint e quant'altro; allo stesso modo
un Parser per il SourceAM (ParserAM) ritornerà sempre un elenco di deni-
zioni di Agenti ed uno stato iniziale.
Avendo scelto di utilizzare in ingresso dei codici XML, i Parser non hanno
bisogno di librerie particolari per produrre il risultato ma gli basta saper
analizzare un le XML.
Va rispettato un vincolo:     ParserCS deve eseguire sempre prima di Parse-
rAM. La motivazione è molto semplice: ParserAM ha bisogno di sapere chi
sono le variabili, chi i constraint, chi le funzioni e quant'altro per poter fare



                                         23
correttamente il proprio lavoro.
ParserAM conosce in questo modo i dati per la denizione del nuovo Con-
straint Store; oltre a questo gli vengono forniti gli indirizzi dei RuntimeMa-
nager appena istanziati in modo da dare loro i risultati da esso prodotti.



2.2.4 Runtime Manager
Come ParserAM e ParserCS svolgono le funzioni di comprensione del sor-
gente, il Runtime Manager svolge quelle di simulatore. Esso infatti conosce,
grazie a ParserAM, tutte le denizioni sia in termini di Agenti che del Con-
straint Store.
Viene istanziato fornendogli semplicemente i criteri di arresto (durata tem-
porale   λ   o numero di passi). Un Runtime Manager espone (principalmente)
le seguenti funzioni:


   •   Start - Inizia la simulazione


   •   Stop - Interrompe la simulazione


   •   Step - Eettua un passo della simulazione


   •   GetGraphData - Fornisce tutti i dati relativi alle variabili ed al loro
       andamento temporale


   •   GetGlobalVars - Fornisce il valore attuale della variabili globali


   •   GetStatus - Fornisce un riassunto di Agenti Attivi, ultime azioni ese-
       guite, rate, ecc.


Come è evidente il Runtime Manager è in tutto e per tutto il cuore del pro-
getto: tutte le altre parti non sono che moduli che permettono l'interazione
con esso.
Una volta dato il comando Start, questo simulerà nchè non gli viene dato
lo Stop o soddisfa le condizioni di terminazione.
Analizzando il linguaggio sCCP ci si è resi conto che un simulatore ben
strutturato deve esser dotato di due elementi:


   •   Il Constraint Store


   •   Il Denition Store




                                       24
2.2.5 Constraint Store
Il Constraint Store (CS) sarà la memoria del nostro sistema.          In esso ci
saranno le variabili e vi si accederà tramite gli Ask e i Tell.     Oltre a ciò
dobbiamo poter richiedere al CS di ritornare il risultato di una formula:
questo viene usato per il calcolo dei Rate. Un'altra funzionalità è quella di
ritornare lo stato di tutte le variabili in un operazione sola. Al CS viene dato
anche il compito di modicare, se necessario, le formule lette dai Parser.
Ricapitolando:

   •    Ask

   •    Tell

   •    GetRate

   •    GetVariables

   •    Parse



2.2.6 Denition Store
Il Denition Store è il gestore delle denizioni di agenti.     Deve aiutare la
fase di Parsing del SourceAM e deve fornire al RuntimeManager gli agenti
richiesti. È unico per ogni Runtime Manager. I requisiti che deve soddisfare
sono:

   •    Creare una denizione

   •    Creare un'azione per una denizione

   •    Fornire le istanze delle denizioni

Vista la denizione degli agenti, si è deciso di progettare la singola denizione
partendo dalle seguenti considerazioni:

   •    Ogni Agente ha più scelte

   •    Ogni scelta ha una o più azioni

   •    Ogni azione può essere composta da una o più azioni atomiche

Per gestire questa condizione si è pensato al seguente sistema. Ogni Agente
ha una scelta tra le possibili azioni. Ogni serie di azioni composte in sequenza
sono gestite da un Action Manager. Le azioni implementano tutte la stessa
interfaccia che espone molti metodi, tra cui quello per l'esecuzione dell'azione
e quello per ricevere il Rate dell'azione stessa.
Vediamo ora un esempio sulla gestione dell'azione:


                                        25
Agente :- [X  0 - X = X-1]@{1}.Agente
  + [X == 0 - X = 10]@{1}.([ - Y= Y + 1]@{1}.Agente || Agente + Agente);
Questa struttura viene dapprima spezzata in due:


[X  0 - X = X-1]@{1}.Agente
[X == 0 - X = 10]@{1}.([ - Y= Y + 1]@{1}. Agente || Agente + Agente);
La prima azione ora diventa:


ActionManager - [Guardia][Call]
La seconda invece diventa:


ActionManager - [Guardia][Scelta]
[Scelta] - ActionManager - [Guardia][Parallelo([Call][Call])
   - ActionManager - [Call]
In pratica un ActionManager è una lista di Azioni collegate dalla Composi-
zione in Sequenza: quando il Parser individua una scelta aggiunge in coda
un'elemento Scelta, il quale avrà i suoi ActionManager per gestire le biforca-
zioni.
In questo modo si gestiscono le azioni come fossero un albero, in maniera
eciente e assolutamente non rigida.
In gura un diagramma approssimato ma riassuntivo.



2.2.7 Interfaccia Graca
È stato fondamentale progettare da subito anche l'interfaccia graca: grazie
ad un'approfondita analisi delle funzionalità che si volevano esporre si è riu-
sciti ad apportare modiche anche ai diagrammi delle classi che formano il
Core.
Per prima cosa è il caso di dividere l'interfaccia graca in tre blocchi distinti:


   •     GUI per la scrittura del codice


   •     GUI per la simulazione in tempo reale


   •     GUI per la simulazione Batch




                                           26
Figura 2.2: Rappresentazione concettuale delle classi



Parser GUI
Questa WPF Window è stata progettata per essere il più semplice possibile.
Divisa in due parti in cui scrivere il SourceAM e il SourceCS, ore le funzioni
di base (salva, carica, nuovo, esci) aancate dalla possibilità di compilare
(AM, CS, Entrambi), di scegliere il compilatore (sCCP, ITS, ODE) e inne
la possibilità di lanciare la simulazione (Graca o Batch).
Nel capitolo 3 vedremo un esempio pratico con tanto di immagini prese dal
programma.


Graphic Simulation GUI
Questa interfaccia si compone di tre nestre distinte che vengono mostrate
una di seguito all'altra.
Nella prima si è progettato che venga data la possibilità di scegliere i para-
metri di arresto, i le XML da caricare (SourceAM e SourceCS, impostati
dal Parser GUI con i giusti valori), la precisione del graco e il numero di
simulazioni parallele.
Nella seconda nestra è stata data la possibilità di scegliere i dettagli del
graco: si possono scegliere le variabili da analizzare mostrandole tracciate,
di quali variabili mostrare la media, di quali la varianza. Per ogni linea da
tracciare si può scegliere il colore e la didascalia.
Avendo concentrato le scelte prima dell'esecuzione, l'ultima nestra è quasi




                                        27
completamente dedicata al graco. Si sono volute mostrare anche le variabili
con i loro valori e gli agenti in vita, ma la maggior parte dello schermo è presa
dal graco. Questa nestra si è pensato debba avere funzionalità interattive
(permettndo di iniziare o fermare la simulazione o di fare un singolo passo),
permettendo di salvare e ricaricare lo stato ed anche di esportare un le .CSV
contente i dati raccolti.


Batch Simulation GUI
La simulazione batch deve raccogliere i seguenti dati:


    •    Scelta criteri di arresto


    •    Scelta numero di esecuzioni


    •    Scelta le da eseguire


    •    Scelta le da salvare


    •    Scelta delle variazioni delle variabili in ingresso


Come nel caso precedente si è pensato di procedere con tre schemate per
poter scegliere le opzioni. Nella prima si possono così concentrare le infor-
mazioni in merito ai criteri di arresto, le di eseguire, le da salvare e numero
di esecuzioni.
Nella seconda così ci si può concentrare sulle variazioni dello stato iniziale:
per ogni variabile ed ogni stato si devono poter impostare dei possibili valori
iniziali e il sistema deve poi valutare le esecuzioni sugli opportuni valori ini-
ziali.
A questo punto nella terza videata basta predisporre un indicatore di com-
pletamento e qualche controllo sulla durata delle operazioni (per evitare
loop).




                                          28
Capitolo 3
Interfaccia
In questo capitolo tratteremo l'utilizzo del framework in oggetto di questo
elaborato.
Nella prima parte analizzeremo le procedure per l'installazione.
Nella seconda discuteremo in merito alla stesura del codice, analizzando in
dettaglio come stendere un semplice codice d'esempio.
Nella terza sezione vedremo come simulare in forma graca e non.




3.1 Installazione
L'installazione del progetto risulta molto semplice.     Una volta scaricato il
le compresso del progetto, basta scompattare la cartella. A questo punto è
possibile eseguire il le sCCP-GUI.exe ed utilizzare il programma.
Se il programma non dovesse funzionare, è probabile che il computer sul qua-
le si sta lavorando non disponga del .NET Framework 4.0.
Per l'instazzazione di quest'ultimo, basta visitare il sito di Microsoft e scari-
care il software in questione.




3.2 Il Codice
Una volta lanciato l'eseguibile sCCP-GUI.exe, apparirà un'interfaccia gra-
ca per la stesura del codice.    Oltre ai soliti comandi che si trovano in una
usuale IDE (salva, carica, esci, nuovo, compila) ne sono stati aggiunti altri
per lanciare la simulazione di tipo Batch e di tipo Graco.
Il corpo della nestra principale è diviso in due aree di testo: in quella di
sinistra verrà scritto il Source AM, mentre in quella di destra il SourceCS.
Il menù   Compile   permette di scegliere di compilare il SourceAM, il Sour-
ceCS o entrambi.



                                       29
Nel menù     Engine   è possibile scegliere il simulatore tra i tre visti nelle
precedenti sezioni:

   •   sCCP

   •   ITS

   •   ODE

Se si dovesse scegliere ODE, verrà data la possibilità di scegliere quale meto-
do utilizzare per risolvere il problema (Implicit Runge Kutta...). Oltre a ciò
è possibile scegliere la precisione del solver. Nel menù    Constraint Store è
possibile scegliere se utilizzare il Constraint Store basato su muParser oppure
quello basato su Flee.
Se si volesse scavalcare la l'interfaccia graca per la stesura del codice, è possi-
bile lanciare i simulatori direttamente. Questi si trovano nella stessa cartella,
con il nome sCCP-GraphicSimulator.exe e sCCP-BatchSimulator.exe. Nel-
l'ultima sezione di questo capitolo verrà spiegato l'utilizzo di questi e come
interfacciarli ad eventuali altre IDE.



3.2.1 Il Codice SourceAM
In questa sezione si daranno alcune informazioni sul come scrivere il codice
SourceAM. Per prima cosa dobbiamo ricordare che a seconda del compila-
tore il linguaggio subisce delle restrizioni dovute alle limitazioni teoriche. In
questa sezione parleremo, in modo del tutto generale del codice sCCP.
Il SourceAM è costruito in questo modo:

Agent_Definitions
/* Definitions */
End_Agent_Definitions
Initial_State
/* Initial State */
End_Initial_State
All'interno dello spazio dedicato alle denizioni, possono venir scritti agenti
in questo modo:

NomeAgente(Variabili) :- Azione (.Azione)+
Variabili = Nome | Nome = Valore
Azione = Guardia | Chiamata | Parallelo | Scelta
Guardia = [Ask - Tell]@{Rate}
Chiamata = NomeAgente(Variabili)
Parallelo = Azione || Azione ...
Scelta = Azione + Azione ...

                                         30
Per la compatibilità delle istruzioni assegnate in Ask, Tell o Rate si rimanda
al Capitolo 4.   Un Tell può esser costituito da più chiamate al Constraint
Store; queste devono essere separate da un ;. Se il codice viene compila-
to da sCCP è possibile assegnare dei valori iniziali alle variabili locali così
denite, altrimenti rimangono dei semplici segnaposto: nel momento in cui
verrà chiamato l'Agente fornendogli dei riferimenti in ingresso, questo verrà
modicato per inserire la nuova variabile al posto del segnaposto.
In sCCP è previsto l'operatore di dereferenziazione, come in C.
Ad ogni assegnazione, se viene passata una variabile in una chiamata ricor-
siva, questa viene passata per riferimento, mentre se si vuole passare solo il
valore si deve utilizzare l'operatore *.
Esemplicando:


Agente(X):- [X  0 - X = X-1]@{k1}.Agente(X);
Agente2 :- Agente(Y);


Nel momento in cui viene invocato Agente(Y), il segnaposto viene sostituito:


Agente(Y):- [Y  0 - Y = Y-1]@{k1}.Agente(Y);


Se invece l'istruzione fosse stata:


Agente2 :- Agente(*Y);


Agente(X) sarebbe rimasto uguale ma sarebbe stato assegnato ad X il valore
delle variabile attuale della variabile Y.
Questo meccanismo è utilissimo per specicare lo Stato Iniziale, in quanto
permette di modellare degli agenti con lo stesso comportamento su variabili
diverse.
Lo Stato Iniziale è così composto.

Initial_State
/* Agenti */
End_Initial_State
Agenti = Numero * Chiamata || Chiamata
Chiamata = NomiAgente || NomiAgente(Variabili)
Un esempio di inizializzazione, facendo riferimento ad Agente(X) visto prima
può essere il seguente:

Initial_State
Agente || Agente(Y) || 2 * Agente(Z)
End_Initial_State

                                       31
3.2.2 Il Codice SourceCS
In questa sezione si vedrà come scrivere il SourceCS per modellare il Con-
straint Store con il quale interagiranno gli agenti del SourceAM.
Il sorgente deve dar la possibilità di denire:

   •   Variabili


   •   Parametri


   •   Costanti


   •   Operatori


   •   Funzioni


   •   Constraints

Per ogni elemento esiste una sintassi per la sue generazione. Il SourceCS ha
questa forma:

Global_Var
/* Var Defs */
End_Global_Var
Params
/* Param Defs */
End_Params
Functions_Def
/*Function Defs */
End_Functions_Def
Constraints_Def
/* Constraint Defs */
End_Constraints_Def
Var Defs := NomeVariabile = Valore ;
Param Defs := param NomeParametro Valore ;
Function Defs := Constant OR Function OR Operator
Constant := CONST costante valore ;
Function := Nome(Vars) = Semantica ;
Operator := operat Simbolo/i Semantica ;
Constraint Defs := Nome(Vars) = (Var = Semantica; Var = Semantica ...);
Ogni elemento dichiarato all'interno del SourceCS è richiamabile negli Ask,
nei Tell e nei Rate del SourceAM. Nel capitolo 5 sono illustrati alcuni esempi
completi di programmi funzionanti. Si rimanda il lettore a quella sezione per
vedere in pratica le denizioni viste in questa e nella precedente sezione.


                                      32
3.3 La Simulazione
In questa sezione si analizzeranno sCCP-GraphicSimulator e sCCP-BatchSimulator.
Entrambi possono venir eseguiti come programmi stand alone e vengono ese-
guiti dalla stessa sCCP-GUI quando si inviano i comandi di simulazione. Per
simulare dalla sCCP-GUI si deve utilizzare il Menu       Run, il quale permette
di scegliere tra Graphic Simulation e Batch Simulation.
Una volta mandata in esecuzione da sCCP-GUI, è come se questa non esi-
stesse più e ci si trova a contatto diretto con il simulatore.



3.3.1 Graphic Simulator
Il Graphic Simulator è composto da tre videate, ognuna con uno specico
utilizzo. Queste vengono mostrate in ordine e l'ultima è quella che mostra la
simulazione vera e propria. Queste servono a:


   1. Scelta dei criteri di arresto, scelta sorgenti e numero di simulazioni


   2. Scelta delle variabili da monitorare, dei colori delle linee etc


   3. Simulazione e graci


Prima Schermata
Nella prima schermata sono impostabili i criteri di arresto. Questi possono
essere di due tipi: sul numero di passi o sul tempo di sistema. Una volta scelto
il criterio di arresto si può passare alla scelta della precisione dell'analisi. Se
si è scelto di concludere a un dato tempo, si può scegliere di campionare N
punti (decretanto così la precisione dell'output) oppure si può scegliere un
passo temporale di campionamento ed utilizzare direttamente quello.
Nel caso la scelta ricada su un criterio di terminazione legato al numero di
passi, si può scegliere ogni quanti passi campionare.
Oltre a questo si possono scegliere altre cose:


   •   Il numero di simulazioni


   •   Il le XML che descrive il Constraint Store


   •   Il le XML che descrive l'Agent Manager


   •   Se mostrare il graco durante la simulazione o alla ne


Nel caso il simulatore venga caricato dalla sCCP-GUI, i campi contenenti i
percorsi dei les vengono già assegnati con i nomi corretti.


                                        33
Seconda Schermata
Nella seconda schermata l'utente può impostare le impostazioni riguardanti il
graco. Nella lista superiore vengono indicate le variabili globali del progetto.
Una volta selezionata, l'utente può scegliere se:


   •    Stampare i singoli valori della variabile delle diverse simulazioni


   •    Stampare la media dei valori della variabile derivanti dalle diverse
        simulazioni


   •    Stampare la varianza dei valori della variabile derivanti delle diverse
        simulazioni


Una volta cliccato su uno dei tre pulsanti, viene aggiunta una nuova riga
nella lista dei valori da stampare. In questa lista è possibile congurare più
parametri:


   •    Il nome da mostrare nella legenda del graco


   •    Il colore della linea


   •    La sorgente dei dati


La sorgente dei dati serve per selezionare di quale simulazione si vuole tener
traccia. Ad esempio è possibile calcolare la media tutte le simulazioni eccetto
una e di questa mostrare il valore singolo. In questo modo si può comparare,
per ni l'andamento medio con l'andamento di una singola simulazione.
Una volta selezionati i valori, si può premere sul tasto OK per passare alla
terza schermata.


Terza Schermata
La terza schemata è stata progettata per interfacciarsi con il RuntimeMa-
nager dando all'utente tutte le informazioni di cui ha bisogno. Buona parte
dello schermo è coperto dal graco. Sulla destra vengono riportati i valori
delle variabili e gli agenti vivi. In basso a sinistra una label riassume lo sta-
to del Runtime Manager (ultima azione eseguita se si va per step, rate del
sistema etc).
I Menù permettono di di interagire con il sistema:
File:
   •    New - Crea una nuova simulazione copia di quella in esecuzione


   •    Load Status - Carica una simulazione precedentemente salvata


                                        34
•   Save Status - Salva una simulazione


   •   Save CSV - Salva i dati su disco in Comma Separated Values


   •   Close - Chiude la simulazione


Run:
   •   Single Step - Esegue un passo nella simulazione


   •   Start/Stop - Avvia/Interrompe la simulazione



3.3.2 Batch Simulator
Il Batch Simulator è strutturato in 3 parti, come il Graphic Simulator. Le
tre nestre hanno scopi diversi rispetto a quanto precedentemente visto:


  1. Scelta criteri di arresto e precisione dei dati, scelta della locazione dei
       CSV con i risultati e dei le XML da compilare


  2. Scelta delle diverse congurazioni di valori iniziali e parametri nelle
       diverse simulazioni


  3. Semplice indicatore dell'avanzamento del lavoro


Prima Schermata
La prima nestra è stata impostata allo stesso modo della prima del Graphic
Simulator.   I criteri di arresto vengono introdotti nello stesso modo.    Nel-
l'interfaccia è sostituita la CheckBox che prima serviva la visualizzazione del
graco a run-time o alla ne della simulazione; questa ora serve per stabilire
se l'utente vuole il risultato salvato in un unico le o in uno diverso per ogni
simulazione. Oltre a questo una TextBox ore la possibilità di scegliere dove
salvare l'output prodotto.


Seconda Schermata
La seconda schermata permette all'utente di scegliere diverse congurazioni
di valori delle variabili e dei parametri. Questa schermata serve, ad esempio,
a vedere come varia il comportamento del sistema mano a mano che un pa-
rametro cresce. Da una ComboBox si può scegliere il valore da modicare,
una volta aggiunto si può scegliere come farlo variare. È possibile scegliere
che la variabile acquisica N valori uniformemente distribuiti su un'intervallo,
oppure che il valore di questa venga incrementato / decrementato ntanto



                                       35
che rimane all'interno di un intervallo.
Il numero di simulazioni sarà proporzionale al numero di combinazioni pos-
sibili. Se ad esempio si fa variare la prima variabile su 3 valori e un'altra su
2, ci saranno 6 simulazioni.


Terza Schermata
La terza schermata è assolutamente stringata: presenta solo una barra di
avanzamento dei processi. Quando le simulazioni vengono completate, que-
sta avanza.   Quando la simulazione è conclusa, viene riportato il tempo
impiegato, l'istante di inizio elaborazione e di ne elaborazione.




                                      36
Capitolo 4
Implementazione
Dopo aver esposto le nozioni teoriche nel capitolo 1, l'analisi e la progettazio-
ne nel capitolo 2 e aver mostrato l'interfaccia nel capitolo 3, in questo quarto
capitolo si presenterà l'implementazione.
Nella prima sezione verranno analizzate velocemente le schermate.          Nelle
successive si analizzeranno a turno i diversi compilatori.




4.1 Dettagli dell'Interfaccia Graca
Per la programmazione dell'interfaccia graca sono stati utilizzate delle com-
ponenti esterne, non scritte dal candidato.    Nello specico si sono usate le
seguenti librerie:


   •     ColorPicker


   •     DynamicDataDisplay


La prima consentiva di prelevare un colore da una tavolozza ed è stata inseri-
ta nella scelta dei colori nella simulazione graca. Sempre nella simulazione
graca si è utilizzato il DynamicDataDisplay. Questi altro non è se non un
controllo WPF che gestisce dei graci a linea.
Quando viene istanziato la nestra con il graco vengono letti i parametri e
desunte le linee da disegnare. A questo punto vengono memorizzate in un
dizionario, per ogni linea, una lista di ObservablePoint. Ogni volta che verrà
aggiunto un punto in una di queste liste, questo verrà tracciato nella corretta
linea.
Quando viene lanciata una simulazione, viene anche attivato un thread che
va a controllare ogni 500ms se vi sono nuovi dati disponibili dal Runtime-
Manager. Questi vengono convertiti in modo da essere utilizzabili e vengono



                                       37
inseriti nelle liste di punti opportune.
Nel gestire simulazioni parellele contemporanee, onde evitare problemi con
calcoli della media e inconsistenza dei dati, si è deciso di disegnare i punti no
all'istante temporale del RuntimeManager di tempo minimo. Ad esempio, si
considerino 4 simulazioni che dopo 500ms si trovano nel seguente stato:


Sim1 : T = 35 Sim2 : T = 50 Sim3 : T = 80 Sim4 : T = 12
A questo punto il simulatore vede che Sim4 è la simulazione più in ritardo e
disegna sul graco tutti i punti richiesti no al tempo 12.
Nel caso una delle simulazioni dovesse incontrare un blocco dovuto al codice
(rate pari a 0), non sarà possibile continuare la tracciatura del graco.
L'interfaccia graca si appoggia su un OutputManager che gli permette di
memorizzare su disco lo stato corrente, i risultati delle elaborazioni e di
ricaricarli all'occorrenza.




4.2 SCCP
SCCP è il primo compilatore e simulatore che è stato scritto per questo pro-
getto. È quello che presenta maggiori requisiti da implementare in quanto
deve poter simulare tutte le caratteristiche del linguaggio SCCP. Nelle pros-
sime sezioni vedremo nel dettaglio come sono state implementate le diverse
componenti che lo formano.
Inizieremo esaminando il Constraint Store, parleremo poi del Denition Sto-
re, del Runtime Manager e inne dei Parser (ParserCS a ParserAM).



4.2.1 Il Constraint Store
Nella sezione 1 abbiamo appreso come il Constraint Store debba rispondere
ad Ask e Tell, mentre nella fase di progettazione ci si è resi conti che le
funzionalità andavano ampliate. Nello specico si è giunti a:


   •   Ask


   •   Tell


   •   GetRate


   •   Parse


   •   Metodi per istanziare variabili, parametri, funzioni, operatori, con-
       straint e quant'altro.




                                       38
•   GetVariables


È stato necessario appoggiarsi ad un parser di espressioni matematiche per
gestire il Constraint Store. La scelta è ricaduta su muParser (modulo esterno
non scritto dal tesista).


muParser
MuParser è reperibile all'indirizzo muparser.sourceforge.net.
È gratuito e disponibile in forma nativa per C++ e Wrappato per ambiente
.NET.
Questa libreria permette di calcolare il valore di espressioni contenenti nu-
merosi operatori e dà anche la possibilità di espandere le proprie potenzialità
tramite opportuni metodi. Oltre a ciò permette di memorizzare al proprio
interno parametri e variabili. È uno dei migliori parser matematici gratuiti
a livello di performances.
In questa prima tabella vengono esposte le funzioni built-in in muParser.




                                      39
Name    ARC    Explanation
sin     1      sine function
cos     1      cosine function
tan     1      tangens function
asin    1      arcus sine function
acos    1      arcus cosine function
atan    1      arcus tangens function
sinh    1      hyperbolic sine function
cosh    1      hyperbolic cosine
tanh    1      hyperbolic tangens function
asinh   1      hyperbolic arcus sine function
acosh   1      hyperbolic arcus tangens function
atanh   1      hyperbolic arcur tangens function
log2    1      logarithm to the base 2
log10   1      logarithm to the base 10
log     1      logarithm to the base 10
ln      1      logarithm to base e (2.71828...)
exp     1      e raised to the power of x
sqrt    1      square root of a value
sign    1      sign function -1 if x0; 1 if x0
rint    1      round to nearest integer
abs     1      absolute value
min     var.   min of all arguments
max     var.   max of all arguments
sum     var.   sum of all arguments
avg     var.   mean value of all arguments




                       40
Operator    Meaning                     Priority
                =           assignement                 -1
                and         logical and                 1
                or          logical or                  1
                xor         logical xor                 1
                =          less or equal               4
                =          greater or equal            4
                !=          not equal                   4
                ==          equal                       4
                           greater than                4
                           less than                   4
                +           addition                    5
                -           subtraction                 5
                            multiplication              6
                /           division                    6
                ^           raise x to the power of y   7
                ?:          if then else operator       1

In questa tabella vengono esposti gli operatori built-in in muParser.


Interfacciamento con muParser
Come visto, muParser ha delle peculiarità molto importanti per quanto ri-
guarda la denizione di funzioni, variabili e quant'altro. Per quanto riguarda
Ask, Tell e GetRate la loro denizione diventa banale: basta che il Constraint
Store faccia da Wrapper, facendo attenzione a casi particolari. Ad esempio
il parsing di un'istruzione vuota genera un'eccezione, ma si è deciso invece
che l'Ask di una tale istruzione sia sempre valido, quindi si è dovuta gestire
l'eccezione e ritornare il valore true.
La denizioni di variabili e parametri è molto semplice, così come l'ottenere
il valore delle variabili in muParser; basta anche in questo caso fare poco più
che un Wrapper. Gli argomenti più spinosi rimangono: la denizione di User
Dened Funcion (UDF) e il Parsing delle stringhe per i Parser.
Per risolvere il problema delle UDF è stato escogitato un metodo molto mal-
leabile che permette di gestire funzioni molto complicate e con molti para-
metri. Per denire una nuova funzione in muParser, questo non si aspetta
altro se non un delegato da invocare passando i parametri quando la incontra
durante il parsing.
Per creare a runtime una funzione che risolva questo problema si sono usate
opportune classi neutre. Viene denita una classe Function che si aspetta in
ingresso una lista parametri e la semantica della stessa. I parametri non han-
no un valore, ma solo il nome del segnaposto nella semantica. Questa classe


                                          41
prevede un metodo Solve che accetta come parametri un array di double e un
intero contenente il numero di parametri. Questa rma è esattamente quella
che si aspetta muParser per creare una nuova funzione.
Associato il nome alla funzione Solve della classe appena generata, il Parser
la invocherà al momento opportuno.
Quando questa viene invocata, va a sostituire tutti i parametri che riceve
in ingresso (dei double) ai segnaposti indicati prima come parametri (delle
string). A questo punto la stringa può venir risolta da muParser in maniera
ricorsiva risolvendo il problema.
Vediamo ora un semplice esempio:


F(X,Y,Z) = (X + Y) / Z;
Il Parser la spezza in modo da ottenere una lista di stringhe contente [X,Y,Z]
e la semantica (X+Y) / Z. A questo punto crea la Function passando i valori.
Nel momento della chiamata:


F(1,3,5)
Invoke Solve([1,3,5],3)
Sostituzione Parametri ai segnaposto: (X + Y) / Z     ⇒   (1 + 3) / 5
return Parser.Solve((1 + 3) / 5);


Da questo pseudocodice si comprende subito la linearità dei passaggi e la
correttezza degli stessi.
Un problema altrettando spinoso da trattare per il Constraint Store è il Par-
sing per il ParserAM. Questo serve per rendere compatibili le stringhe che
poi verranno passate a muParser.
Un esempio banale è dato dalla gestione delle variabili globali: per distingue-
re le une dalle altre, alle variabili globali viene applicato il presso GLOBAL.
Se non viene fatto un parsing corretto, un Agente che avesse un Ask del tipo
[X  0] creerebbe un'eccezione per variabile non trovata. Il Constraint Store
deve, per l'appunto, controllare le formule e modicarle:


[X  0]    ⇒ [GLOBALX        0]


Il Constraint è una particolare UDF che serve ad eettuare molteplici opera-
zioni parametrizzate. Un esempio di Constraint potrebbe essere il seguente:


CS(ix, ipsilon) = ( X = ix/2; ipsilon = Y+2;);
Il seguente constraint pone ad X il valore di ix /2 (qualunque sia il valore di
ix) e modica il valore di ipsilon ponendolo a Y + 2.



                                      42
È facile comprendere il caos che si può creare durante questa conversione.
È stato necessario convertire le stringe in maniera che ogni chiamata diven-
tasse diversa dalle altre:     è da ricordare infatti che le funzioni denite in
muParser accettano solo parametri double e non stringhe.
La soluzione che si è adottata prevede di parsare le stringhe associando un
diverso constraint per ogni sua invocazione, così da poter modicare la se-
mantica a seconda della chiamata.
Si consideri ad esempio il constraint CS prima denito e si analizzi la chia-
mata:

[ - CS(K,MyCount)]@{...
È necessario creare il constraint partendo dalla denizione e tenendo conto
di:

      •   Variabili Globali (se X è globale diventa GLOBALX)

      •   Nome del Constraint Store (deve essere diverso per ogni invocazione)

      •   Sostituire in tutte le istruzioni il nome della variabile presente nella
          chiamata.

Tenendo conto di queste particolari condizioni, il Constraint Store produrrà
in risposta alla richiesta di parsing:

CS1(GLOBALK, MyCount)
Dove in muParser è denita una funzione che esegue:

GLOBALX = GLOBALK / 2
MyCount = GLOBALY + 2
Per quanto concerne la creazione degli operatori deniti dall'utente, muParser
gestisce il tutto in maniera simile.
La sintassi denita è come:
operat SIMBOLO (elemento1, elemento2, precedenza)
Ad esempio:

operat ^= (p1, p2 ,1) = (p1 - p2) /2;
Questo operatore, ad esempio fa la media dei due elementi. La gestione in
muParser è simile, l'unica dierenza è la precedenza dell'operatore, indicata
dal terzo parametro. È possibile capirne il signicato guardando la tabella
con i built-in operators. Dopo aver costruito il Constraint Store basato su
muParser si è riscontrata una mancanza di performance dovuta alla non
compilazione delle formule. Per questo motivo si è creato un altro Constraint
Store basato su un altra libreria: FLEE.


                                         43
FLEE
FLEE(Fast Lightweight Expression Evaluator) è un valutatore di espressioni
molto veloce dalle funzionalità ridotte. La libreria è gratuita e disponibile su
ee.codeplex.com.
Vediamo ora i vantaggi di questa libreria:


   •   Compila le formule, fornendo delle prestazioni molto maggiori


   •   Si interfaccia facilmente con altre librerie per aggiungere funzionalità


   •   Supporta la chiamata di funzioni di sistema e codice IL


Flee presenta anche dei notevoli svantaggi:


   •   Non permette l'assegnazione come elemento delle formule (X = X+1
       risponde false)


   •   Non permette la creazione di parametri o costanti


   •   Non permette di creare degli operatori custom


A questo punto si è deciso di creare un Constraint Store limitato ma decisa-
mente più veloce. In questo non sarà possibile:


   •   Denire Constraints


   •   Denire Operatori custom


Se per un particolare programma non servono queste due funzionalità è pos-
sibile utilizzare questo Constraint Store che, come sarà esposto nel quinto
capitolo, ha delle performance di gran lunga superiori.     La denizione del-
le funzioni è stata implementata in una maniera simile a quanto visto per
muParser. In questo caso si è creato un Function Manager che espone una
funzione F che accetta come parametro una stringa. Il Constraint Store mo-
dicherà tutte le chiamate alle funzioni che trova in questo modo:


miaF(X,2,K)    →   F(miaF,X,2,K)


Quando FLEE incontrerà F, invocherà la funzione del Function Manager.
Questi spezzerà la stringa usando come divisore le virgole. Al primo posto
trova il nome della funzione da evocare e la evocherà dall'elendo di funzioni
denite.
I Tell sarebbero inutili se impossibilitati a modicare il sistema. Si è quin-
di intervenuti per rendere possibile la modica delle variabili.     Quando il


                                       44
Constraint Store riceve un Tell, verica se la stringa è formata da nome va-
riabile seguita dal simbolo =. Se così è allora viene risolta la parte successiva
all'uguale e il risultato viene assegnato alla variabile. Nel caso la variabile
appartenga alla lista di parametri fornita dal SourceCS, l'assegnazione non
viene fatta, trattando di fatto la variabile come una costante.
Ora verranno brevemente esposte le funzionalità di Flee:


Operazioni Aritmetiche          Flee permette di eseguire tutte le operazioni
aritmetiche come somme, prodotti, elevamenti a potenza e moduli.
ES: X * 2 + B ^ 100 % 10


Operazioni di Confronto         Le operazioni di confronto ammesse sono tutte
le più comuni. Per indicare il diverso si utilizza l'operatore , mentre per
vericare l'uguaglianza di due oggetti si può usare semplicemente l'uguale.
ES: (X  Y)


Operazioni di And/Or/Xor/Not                Essendo ogni operazione in Flee for-
temente tipizzata, l'utilizzo di questi operatori varia a seconda del contesto.
In alcuni casi Flee utilizzerà l'And logico, mentre in altri farà quello Bit a
Bit per esempio.
ES (logico): a  100 And Not b = 100
ES (bit a bit): (100 or 2) and 1


Operazioni di Shift      Grazie agli operatori  e  è possibile fare degli Shift
dei valori.
ES: 100  2


Operatori di Contatenazione          Come in molti liguaggi di programmazio-
ne moderni, il + in Flee sta ad indicare la concatenazione tra stringhe.
ES: abc + def 
ES: the number is:  + 100


Operatori di Indicizzazione        Con Flee si possono modellare ed utilizzare
Array dentro le formule. ES: arr[i + 1] + 100


Scrittura dei Simboli       In Flee ogni valore viene interpretato in un parti-
colar modo per tipizzarlo nella maniera corretta:


   •   Char - Un carattere tra singoli apici 'a'




                                       45
•   Boolean - true o false


   •   Real - Ogni numero con un punto decimale.            Con 'd' ed 'f ' si può
       specicare la precisione (oat, double)


   •   Integral - Ogni numero intero. Con 'U' lo si specica Unsigned, mentre
       con 'L' lo si considera a 64 bit


   •   Hex - Numero esadecimale, espresso nella notazione: 0xFF12


   •   String - Insieme di caratteri racchiuso tra due doppi apici


   •   Null - Alla variabile viene assegnato il valore null


   •   DateTime - Una data scritta come: #08/06/2008#


Casting     Essendo tutte le variabili fortemente tipizzate (e non tutte double
come in muParser), la conversione si fa tramite cast.
ES: 100 + cast(obj, int)


Operatori Condizionali          Come visto in muParser, anche quì è presente
un operatore condizionale.
ES: If(a  100 and b  10, both greater, less)


Operatore In       Questo operatore è un operatore booleano che ritorna l'ap-
partenenza di un valore o meno ad un insieme. Lo si può utilizzare con un
valore ed una lista di valori dello stesso tipo.
ES (List): If(100 in (100, 200, 300, -1), in, not in)
ES (Collection): if(100 in collection, in, not in)


Le funzioni messe a disposizione da Flee sono le stesse disponibili nella libreria
Math di .NET. Grazie alla sua essibilità, infatti, tramite questa istruzione
si può fargli utilizzare l'intero pacchetto:


context.Imports.AddType(typeof(Math));
Questa si può utilizzare con qualunque namespace o classe, di questa impor-
terà tutte le funzioni publiche e statiche.
Nonostante tutte queste funzionalità di Flee non è stato possibile implemen-
tare degli operatori custom come fatto in muParser.           Non è stato altresì
possibile permettere la gestione dei Constraint.
All'utente verrà data la possibilità di scegliere tra i due Constraint Store a
seconda delle sue esigienze: in caso di performance si consiglia Flee, in caso


                                          46
di semplicità di scrittura tramite Constraint si consiglia muParser.
Per una descrizione più approfondita di Flee, si rimanda al sito del progetto.



4.2.2 Denition Store
Come è stato denito il Constraint Store per la gestione dei vincoli, ora verrà
analizzato il lavoro che è stato svolto per il Denition Store. Dalla teoria e
dalle fasi di analisi e progettazione è emerso che il Denition Store deve:

   •   Gestire la creazione di una denizione

   •   Gestire la modica delle denizioni

   •   Fornire un'interfaccia al ParserAM per aiutarlo nella creazione delle
       denizioni

   •   Istanziare su richiesta le denizioni

Oltre a fornire le funzioni sopra esposte, il Denition Store deve creare degli
oggetti utilizzabili dal Runtime Manager, ossia Agenti pronti ad eseguire le
proprio azioni.
Si è subito deciso che il Denition Store dovesse, in primis, contenere una
lista di denizioni. Il passo successivo è stato decidere che, al momento della
creazione di una nuova denizione, questa venisse fornita al chiamante.
In questo modo il chiamante, utilizzando i metodi della denizione può mo-
dicarla aggiungendoci azioni e variabili locali.
Questo è possibile grazie all'implementazione di interfacce contenute nel Pro-
getto Commons, in comune all'intera soluzione.
Il Denition Store contiene tutte le classi che deniscono le azioni viste in
teoria. Queste sono intercambiabili in quanto tutte implementano la classe
IAction (presente anch'essa in Commons).
Avremo quindi le seguenti azioni:

   •   Guard: gestisce un'azione di tipo guardia

   •   Choose: gestisce una scelta

   •   Parallel: gestisce un parallelo

   •   Call: gestisce la chiamata

   •   Tell: gestisce un Tell a rate innito (all'interno dei Parallel)

   •   Ask: gestisce un Ask a rate innito (all'interno dei Parallel)

Oltre alle azioni e le denizioni, il Denition Manager deve fornire anche gli
Agenti.


                                         47
Le Azioni
Le azioni (come visto nel capitolo 2.2.6) vengono raccolte in ActionManager
che a loro volta vengono contenuti da Actions. Actions gestisce più Action-
Manager (come fosse una scelta), mentre un ActionManager gestisce una lista
di Azioni nchè si trova il bivio dato da una scelta.
È ora riportato un esempio che aiuterà a spiegare l'utilizzo di Actions e
ActionManager.


Ag :- [- X=X+1]@{1} . Ag . [X  0 - ]@{X}.Ag + [ - ]@{1}.Ag2
     + [ X5 - X=0]@{1} . Ag || Tell(Y=X);
Questo agente avrà come azioni un oggetto costituito come quello in gura:
 Le azioni implementano l'interfaccia IAction, che garantisce la loro esposi-




zione dei seguenti metodi:


   •   Execute: fa eseguire l'azione


   •   ReceiveLocalVariables: permette di impostare le variabili locali all'a-
       zione


   •   GetRate: ritorna il rate dell'azione


   •   GetAskVars: ritorna le variabili che inuiscono sull'eseguibilità dell'a-
       zione


   •   GetTellVars: ritorna le variabili che vengono modicate dall'azione


   •   Refresh:   aggiorna l'azione se sono state modicate variabili che la
       interessano


   •   IsRateInnite: permette di sapere se l'azione ha rate innito



                                       48
•    ForceRefresh: forza il refresh


   •    GetActionData: ritorna un oggetto con i dettagli dell'azione


L'utilizzo di funzioni come Refresh, GetAskVas e GetTellVars sono indispen-
sabili al ne di ottenere un miglioramento delle performance. Nella sezione
dedicata al Constraint Store, vedremo come queste verranno utilizzate.


Agent e AgentDenition
AgentDenition è una classe che contiene tutte i dati utili per la creazione
di un agente e i metodi per far si che il parser possa crearla.
Agent viene creato dalla AgentDenition ed è l'oggetto centrale di sCCP.
Dalla teoria si evince che un agente è costituito dalle Variabili Locali e dal-
l'elenco delle proprie azioni. Questo è importante anche perchè ci fa capire
che inizialmente tutti gli agenti dello stesso tipo sono uguali.
Da questo si può desumere che l'istanziazione di un Agent da un AgentDe-
nition sia alquanto semplice in quanto consta della crezione dello stesso e del
passaggio delle proprie azioni e delle proprie variabili locali. Nello specico
ogni Agent implementerà l'interfaccia IAgent. Per le speciche dell'interfac-
cia IAgent e delle altre, si rimanda ai sorgenti del codice, dove i commenti
spiegano l'utilizzo di ogni funzione.
Verrà ora spiegato velocemente cosa succede quando viene invocato l'Excecu-
te a un Agente. Assieme all'Execute viene passato un valore è Reale: questo
generato dal Runtime Manager e serve nella scelta dell'azione.
Vediamo ora uno pseudo codice:


Execute(RATE)
i := 0
while(RATE  0)
    RATE = RATE - RateAzione[i]
    if (RATE  0)
         Esegui Azione[i]
    else
         i ++
Nello specico tale azione viene compiuta dall'oggetto Actions che ogni Agent
ha. Azione[i] è un ActionManager e come tale inizierà l'esecuzione eseguen-
do ogni IAction che ha in lista.    Se dovessimo incontrare un'azione di tipo
Choose, questa gestirà autonomamente (con il rate residuo) la scelta che deve
fare.




                                         49
4.2.3 Runtime Manager
Il Runtime Manager è forse l'elemento più importante dell'intero modulo: è
il vero e proprio motore della simulazione. Nella fase di progettazione si sono
discusse la operazioni che deve sostenere, in questa fase vedremo, in forma
ridotta, gli elementi principali.
Un possibile pseudocodice per rappresentare l'operato di uno Step simulativo
è il seguente:


if (IsWorkEnded è vero) return;
if (Ci sono Agenti Con Rate Infinito)
     Esegui il Primo
     Rimuovilo dalla lista
else
     Ottieni il Rate Totale
     Execute(Rate Totale * Rand(0,1))
     Aggiorna il tempo
if (Il tempo passato supera la precisione)
     Aggiorna GraphData

Terminazione
La condizione di IsWorkEnded viene posta vera dopo il raggiungimento del
criterio di arresto. Questo può essere di due tipi: temporale o sul numero di
passi.
Questo ag è accessibile anche dal chiamante in modo che sappia quando il
lavoro è terminato.


Agent Pool
Agent Pool è una classe appoggio del Runtime Manager che gestisce gli agen-
ti.   Nello specico ritorna i valori del Rate del Sistema, sceglie l'agente da
eseguire in base al valore casuale generato dal Runtime manager e gestisce
l'eliminazione degli agenti dopo l'esecuzione.
Una delle cose più importanti che vengono fatte dall'Agent Pool è la gestione
dei Refresh. Questi sono gestiti in maniera intelligente ragioni di performan-
ce.
Prima si è mostrato lo scheletro della classe IAction e si è rimandato il trat-
tamento di metodi come GetAskVars e GetTellVars.           Questi servono per
l'appunto per la gestione dei Refresh.
Dopo ogni esecuzione, Agent Pool controlla quali sono le variabili modicate




                                       50
dell'azione che ha eseguito (GetTellVars) e sa quali sono gli agenti (memoriz-
zati in opportune liste) che subiscono un cambiamento a causa delle variabili
globali cambiate. Questo può essere di due tipologie:


    •    Modica di variabili presenti nell'Ask


    •    Modica di variabili presenti nel Rate


Se nessuna delle due condizioni si verica, allora quel dato agente avrà lo
stesso stato del passo precedente (valori delle guardie e rate). In questo mo-
do si migliora l'ecienza mano a mano che sale il numero di agenti. È facile
immaginare sistemi con centinaia di agenti di tipi diversi, che condividono
poche variabili: in questi casi l'aumento di ecienza è molto rilevante.
Se durante il Refresh un'azione ha rate innito, questa avvisa subito il Run-
time Manager che mette l'agente nella coda speciale dei Rate inniti. L'ope-
razione di aggiornamento continua e se vi sono altre azioni a Rate innito,
queste vengono messe in coda. In questo modo al passo successivo, eseguirà.


Aggiornamento GraphData
GraphData è stato costruito per fornire lo stato delle variabili. Inizialmente
era costituito da un dizionario di stringhe e liste di double in cui ogni lista
tracciava l'andamento della variabile indicata dalla stringa.
Ad esempio con:


GraphData[X ]


Si ottiene la lista di valori che ha assunto la variabile X. Per motivi di perfor-
mance alla classe GraphData è stato aggiunto l'elemento Time. Questo viene
modicato nel momento in cui vengono inseriti i nuovi valori nel dizionario.
È stato implementato in questo modo per favorire il lettore dei dati: basta
vedere se è stato incrementato Times piuttosto che contare tutti i valori nelle
liste.



4.2.4 ParserCS
Il ParserCS è una classe costruita per leggere e interpretare degli opportuni
les XML. Questi devono fornire una modellazione del Constraint Store e
come tale possono contenere:


    •    Dichiarazioni di Variabili


    •    Dichiarazioni di Parametri


                                        51
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi
Banovaz Diego - Tesi

Weitere ähnliche Inhalte

Was ist angesagt?

Tesi Laurea Sergio Taddia
Tesi Laurea Sergio TaddiaTesi Laurea Sergio Taddia
Tesi Laurea Sergio TaddiaSergio Taddia
 
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D Andrea Bidinost
 
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEM
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEMTesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEM
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEMDavide Ciambelli
 
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...maaske
 
Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di PythonAmmLibera AL
 
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...Myrteza Kertusha
 
Tesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGPTesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGPFabio Pustetto
 
Il mio libro - My book (intro)
Il mio libro - My book (intro)Il mio libro - My book (intro)
Il mio libro - My book (intro)pls3d
 
Un componente NER Multi-language per il TermExtractor
Un componente NER Multi-language per il TermExtractorUn componente NER Multi-language per il TermExtractor
Un componente NER Multi-language per il TermExtractorVannutelli Sofien
 
Learning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks ThesisLearning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks ThesisGuido Colangiuli
 
Monitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di MarkovMonitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di Markovrkjp
 
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)Gerardo Di Iorio
 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiPietro Corona
 
I promessi sposi 3.0 Mobile User Experience & Usability nel settore dei beni...
I promessi sposi 3.0  Mobile User Experience & Usability nel settore dei beni...I promessi sposi 3.0  Mobile User Experience & Usability nel settore dei beni...
I promessi sposi 3.0 Mobile User Experience & Usability nel settore dei beni...RiccardoPietra
 
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...Pasquale Naclerio
 
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084suku dim
 

Was ist angesagt? (20)

Tesi Laurea Sergio Taddia
Tesi Laurea Sergio TaddiaTesi Laurea Sergio Taddia
Tesi Laurea Sergio Taddia
 
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
Sviluppo e confronto di tecniche di stima della traiettoria di sensori 3D
 
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEM
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEMTesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEM
Tesi Triennale - Grid Credit System: un portale per la sostenibilità di COMPCHEM
 
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
 
Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di Python
 
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
Progetto e realizzazione di un kernel linux per il controllo dinamico degli s...
 
Tesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGPTesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGP
 
Il mio libro - My book (intro)
Il mio libro - My book (intro)Il mio libro - My book (intro)
Il mio libro - My book (intro)
 
Tesi Nicola Pretto
Tesi Nicola PrettoTesi Nicola Pretto
Tesi Nicola Pretto
 
Un componente NER Multi-language per il TermExtractor
Un componente NER Multi-language per il TermExtractorUn componente NER Multi-language per il TermExtractor
Un componente NER Multi-language per il TermExtractor
 
Learning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks ThesisLearning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks Thesis
 
Dv100
Dv100Dv100
Dv100
 
Tesiandroid
TesiandroidTesiandroid
Tesiandroid
 
Monitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di MarkovMonitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di Markov
 
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzati
 
Tesi R. Offredi
Tesi R. OffrediTesi R. Offredi
Tesi R. Offredi
 
I promessi sposi 3.0 Mobile User Experience & Usability nel settore dei beni...
I promessi sposi 3.0  Mobile User Experience & Usability nel settore dei beni...I promessi sposi 3.0  Mobile User Experience & Usability nel settore dei beni...
I promessi sposi 3.0 Mobile User Experience & Usability nel settore dei beni...
 
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
 
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084
Vdohnovenie123 ef7bb245 819c-439d-819a-97ac014c0084
 

Ähnlich wie Banovaz Diego - Tesi

Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxCe.Se.N.A. Security
 
Pattern Recognition Lecture Notes
Pattern Recognition Lecture NotesPattern Recognition Lecture Notes
Pattern Recognition Lecture NotesRobertoMelfi
 
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...michael_mozzon
 
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...Daniele Ciriello
 
[Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System [Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System Stefano Bonetta
 
Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques Maurizio Cacace
 
Applicazioni intelligenzaartificiale
Applicazioni intelligenzaartificialeApplicazioni intelligenzaartificiale
Applicazioni intelligenzaartificialeAntonella79
 
Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.Raul Cafini
 
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARYMARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARYvantasso
 
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - TesiIl Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - TesiFrancesco Magagnino
 
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...Antonio Sanfelice
 
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Francesco De Giorgi
 
GaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in LinuxGaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in LinuxAmmLibera AL
 
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...danielenicassio
 
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientaleInterfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientaleLuigi De Russis
 
mastertesi
mastertesimastertesi
mastertesiReply
 
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...guest85785c7
 

Ähnlich wie Banovaz Diego - Tesi (20)

Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linux
 
Pattern Recognition Lecture Notes
Pattern Recognition Lecture NotesPattern Recognition Lecture Notes
Pattern Recognition Lecture Notes
 
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
 
Monitoraggio di rete con nagios
Monitoraggio di rete con nagiosMonitoraggio di rete con nagios
Monitoraggio di rete con nagios
 
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
 
[Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System [Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System
 
Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques
 
Applicazioni intelligenzaartificiale
Applicazioni intelligenzaartificialeApplicazioni intelligenzaartificiale
Applicazioni intelligenzaartificiale
 
Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.
 
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARYMARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARY
MARKETING ED ECOMMERCE NELL’EDITORIA: IL CASO TRADING LIBRARY
 
Sat howto
Sat howtoSat howto
Sat howto
 
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - TesiIl Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
 
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con a...
 
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
 
GaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in LinuxGaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in Linux
 
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
Progetto e Realizzazione di un Software per la Rilevazione Automatica di Codi...
 
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientaleInterfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
 
mastertesi
mastertesimastertesi
mastertesi
 
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
Progetto e realizzazione di un sistema per la caratterizzazione su larga scal...
 
Andrea_Gangemi_tesi
Andrea_Gangemi_tesiAndrea_Gangemi_tesi
Andrea_Gangemi_tesi
 

Banovaz Diego - Tesi

  • 1. UNIVERSITÀ DEGLI STUDI DI TRIESTE FACOLTÀ DI INGEGNERIA CORSO DI LAUREA SPECIALISTICA IN INGEGNERIA INFORMATICA IMPLEMENTAZIONE IN .NET DI UN FRAMEWORK PER L'ANALISI DI SISTEMI BIOLOGICI BASATO SULLA PROGRAMMAZIONE CONCORRENTE CON VINCOLI. Laureando Relatore Diego Banovaz prof. Luca Bortolussi ANNO ACCADEMICO 2009 - 2010
  • 3. Ringraziamenti Scrivere i ringraziamenti di questa tesi è un passo importante, nel fare il quale spero di non dimenticare nessuno. In primis vorrei ringraziare il mio relatore, Luca Bortolussi, per avermi ac- compagnato in questo viaggio verso la follia della durata di sei mesi. In molte occasioni ha saputo spronarmi o fustigarmi per spingermi ad andare avanti con il lavoro. In particolar modo è a lui che si deve la stesura corretta dell'e- laborato; senza il suo intervento infatti non sempre avrei trovato la forza di riordinare quella che era una matassa intricata di idee `gettate su un foglio'. Voglio ringraziare poi la mia famiglia: mia madre Silvia, in arte Iena, la quale ha saputo insegnarmi con dolcezza e pugno di ferro che cosa signichi prendersi un impegno; mio padre Loris, meglio noto come Bao, che non ha mai lesinato un gesto aettuoso o un incoraggiamento. Spero possano trarre da questa occasione almeno una parte dell'entusiasmo e della graticazione che loro hanno sempre saputo darmi. Ringrazio poi mio fratello Daniele, o Menion, per avermi trasmesso innume- revoli passioni e ben pochi sani principi. Devo sicuramente a questa `guerra dei venticinque anni' buona parte della mia formazione caratteriale. Azzar- dando che almeno un lettore su due abbia pensato `purtroppo', non posso fare altro che far ricadere sul fratello malvagio la colpa. Il mio pensiero va poi ai miei Nonni, Alda, Cornelio, Danira e Giordano per gli insegnamenti che hanno saputo darmi nel corso degli anni e per quanto di buono mi hanno trasmesso. Un grande grazie va a Giordana, per avermi reso (e rendermi) ogni giorno più felice. Un grazie per essere sempre al mio anco, nei momenti belli e in quelli brutti. Fine della pseudo-serietà. Un grazie di proporzioni bibliche va al Sig. Federico Morsut (quel de Gra- do!), per avermi accompagnato in tutto questo percorso di studi e non solo; per esser stato sempre ad ascoltare e sempre disponibile. Unico! Al Dott. Mr.P per l'amicizia di mille mila anni, dalla sabbionaia agli stiva- i
  • 4. letti di spritz! A m3kka, per aver implementato una List in Java e per le mille altre stupi- daggini che ci hanno portato a sghignazzare insieme. Al buon lelìn per le mille avventure arontate insieme (quando torniamo a Novalia?) A PoL, perchè i motivi da elencare sarebbero troppi. A ZaK, per essere una delle persone migliori che conosco. Grazie a tutti i fenomeni del DMI: dal furlanissimo Ghise, al karate-kid- spartano Alex, alla New Entry Luka, al buon vecchio Peo, al PortaNOT tr3, ad Alice e a tutti quelli che mi odieranno per essermeli dimenticati! Un grazie va anche a tutti i compagni di LAN della Tana: a kapa per il falsetto potente, a Spruss per le cene di Bio, a Spino per essere un camper, a Conza per la risata suina, a Defy per i rosik trascendentali, a Max per la fede nel Dark Cocumber, a Iccio per la perdita dell'olfatto, a Jack per i tormentoni immancabili, a 0rka per l'Arroganza, a minivap per l'arroganza, a jockey per nominarmi tra le due e le trecento volte a LAN, a Diu per l'uso scorretto di qualunque Zombie a Left, a Kane per essersi beccato con gioia i miei Commando in CnC, a Baz per avermi fornito una scena alla Porky's che dicilmente dimenticherò, a Turbo per lo Strip CnC con la corriera di svedesi, a Tora per le sponte in ET, a Fil per la corretta fede nel sacro UT serale, a Sick perchè tutto è un GdR, a Pislner Urquel per l'UT in esecuzione automatica, a Angel per i quintali di gamberetti in salsa rosa, a Gandalf per l'utilizzo corretto della parole Bollione, a Pietro per aver involontariamente assaggiato, a Toom per la risata contagiosa e letale, a Gibo per il wood rivela scritte idiote, a bubez per esser sempre più sfalcià, al Wolf per le Storie del Lupo e alla sk0d3 per essere la prova vivente che una donna non può essere forte ad UT, per quanto ci provi. Ai miei cuginetti condividi-pasto/cartoni-inutili del pranzo dalla nonna, An- gelica e Davide (e ovviamente anche a Fede e Roby). A tutta la musica, in particolar modo agli Opeth. Grazie anche agli Insanity Fair (Jo, Tati, Alf, Mauro) e agli Overtures (Meek, Dani, Luka, Cum, Guitty) per le tournè/viaggi e per le incredibili serate vis- sute insieme. Al Gippo (alias el Bomber) per le innumerevoli volte che mi ha lasciato vince- re a PES adducendo innumerevoli scuse improbabili, alla pazientissima Sara e al suo acerrimo nemico Rudy. A Niha, Maru, m3kka e Diu per la GdR experience in montagna. A butra, per i racconti dei Mig Russi e del cemento per el controllo climatico. A Nebbia, el Folpo, el Guru, Patachini e a tutti i compagni di carretto della Sagra. Un grazie anche ai Bodri per tutte le Bodrate insieme: Hale, Ophy, Sara, ii
  • 5. Vale, Xander, Biz, Ushti, la ragazza di Ushti, Scano, Jessica, Marta, Mono, i ba di Mono. Come da consuetudine i ringraziamenti son stati scritti 10 minuti prima di mandare in stampa la tesi, quindi saranno sicuramente carichi di mancanze e lacune. iii
  • 6. Indice Ringraziamenti i Introduzione vii 1 Nozioni Teoriche 1 1.1 Algebre di Processo . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.1 Operazioni dei processi . . . . . . . . . . . . . . . . . . 1 1.1.2 CCP: Concurrent Constraint Programming . . . . . . . 4 1.2 Algebre di Processo Stocastiche . . . . . . . . . . . . . . . . . 8 1.3 sCCP: Stocastic Concurrent Constraint Programming . . . . . 8 1.3.1 Rate . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.3.2 Constraint Store . . . . . . . . . . . . . . . . . . . . . 9 1.3.3 Grammatica . . . . . . . . . . . . . . . . . . . . . . . . 10 1.3.4 Le potenzialità del sCCP . . . . . . . . . . . . . . . . 11 1.4 ITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.1 Limitazioni del linguaggio . . . . . . . . . . . . . . . . 13 1.4.2 Modello ITS . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4.3 Le Variabili di Stato . . . . . . . . . . . . . . . . . . . 14 1.4.4 Transizioni . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.5 ODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5.1 Deterministicità del Linguaggio . . . . . . . . . . . . . 16 1.5.2 La denizione di ODE . . . . . . . . . . . . . . . . . . 16 2 Analisi e Progettazione 18 2.1 Analisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.1.1 Analisi dei Requisiti . . . . . . . . . . . . . . . . . . . 18 2.1.2 Studio dei Casi d'Uso . . . . . . . . . . . . . . . . . . . 19 2.2 Progettazione . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.2.1 Standardizzazione di Input ed Output . . . . . . . . . 21 2.2.2 I Macro Moduli . . . . . . . . . . . . . . . . . . . . . . 22 2.2.3 Il Compilatore . . . . . . . . . . . . . . . . . . . . . . . 23 iv
  • 7. 2.2.4 Runtime Manager . . . . . . . . . . . . . . . . . . . . . 24 2.2.5 Constraint Store . . . . . . . . . . . . . . . . . . . . . 25 2.2.6 Denition Store . . . . . . . . . . . . . . . . . . . . . . 25 2.2.7 Interfaccia Graca . . . . . . . . . . . . . . . . . . . . 26 3 Interfaccia 29 3.1 Installazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.2 Il Codice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.2.1 Il Codice SourceAM . . . . . . . . . . . . . . . . . . . 30 3.2.2 Il Codice SourceCS . . . . . . . . . . . . . . . . . . . . 32 3.3 La Simulazione . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.3.1 Graphic Simulator . . . . . . . . . . . . . . . . . . . . 33 3.3.2 Batch Simulator . . . . . . . . . . . . . . . . . . . . . . 35 4 Implementazione 37 4.1 Dettagli dell'Interfaccia Graca . . . . . . . . . . . . . . . . . 37 4.2 SCCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4.2.1 Il Constraint Store . . . . . . . . . . . . . . . . . . . . 38 4.2.2 Denition Store . . . . . . . . . . . . . . . . . . . . . . 47 4.2.3 Runtime Manager . . . . . . . . . . . . . . . . . . . . . 50 4.2.4 ParserCS . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.2.5 ParserAM . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.3 ITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.3.1 Constraint Store e Denition Store . . . . . . . . . . . 55 4.3.2 Runtime Manager . . . . . . . . . . . . . . . . . . . . . 56 4.3.3 ParserCS e ParserAM . . . . . . . . . . . . . . . . . . 59 4.4 ODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.4.1 ParserAM e ParserCS . . . . . . . . . . . . . . . . . . 60 4.4.2 Transition System . . . . . . . . . . . . . . . . . . . . . 60 5 Test 63 5.1 Esempio #1: client server . . . . . . . . . . . . . . . . . . . . 63 5.1.1 Analisi del problema . . . . . . . . . . . . . . . . . . . 63 5.1.2 Modello sCCP . . . . . . . . . . . . . . . . . . . . . . . 65 5.1.3 Analisi delle prestazioni . . . . . . . . . . . . . . . . . 66 5.2 Esempio #2: Lotka-Volterra . . . . . . . . . . . . . . . . . . . 67 5.2.1 Analisi del Sistema . . . . . . . . . . . . . . . . . . . . 67 5.2.2 Modello sCCP . . . . . . . . . . . . . . . . . . . . . . . 68 5.2.3 Analisi delle Prestazioni . . . . . . . . . . . . . . . . . 69 5.3 Esempio #3: Sintesi di Glucosio da Lattosio in E-Coli . . . . . 70 5.3.1 Analisi del Sistema . . . . . . . . . . . . . . . . . . . . 70 v
  • 8. 5.3.2 Modello sCCP . . . . . . . . . . . . . . . . . . . . . . . 71 5.3.3 Analisi delle Prestazioni . . . . . . . . . . . . . . . . . 73 5.4 Esempio 4: Numero elevato di Agenti . . . . . . . . . . . . . . 73 6 Conclusioni 75 Bibliograa 76 vi
  • 9. Introduzione La costruzione di modelli di alcuni aspetti della realtà è sempre stata un tassello fondamentale del metodo di indagine scientico. Le tecniche di modellizzazione dei giorni nostri permettono di descrivere e ra- gionare su aspetti sempre più complessi del mondo. In questo la matematica e l'informatica hanno un ruolo fondamentale: la prima fornisce una cornice formale entro cui costruire dei modelli, la seconda mette a disposizione po- tenti strumenti computazionali per l'analisi. L'aumento della potenza computazionale e il miglioramento delle tecniche di analisi non sono tuttavia sucienti a rendere la modellizzazione matematica pervasiva anche nelle discipline scientiche storicamente più descrittive (a causa della loro complessità), come la biologia. Costruire modelli formali e analizzarli a calcolatore sono attività complicate che richiedono nozioni approfondite di matematica ed informatica, oltre che nell'ambito specico del modello. Per queste ragioni oggigiorno c'è la tendenza a creare degli ambienti di svi- luppo integrato per la creazione ed analisi di modelli, che rendano questa attività accessibile anche a non specialisti. Sull'onda di questa evoluzione si è deciso di arontare l'argomento di questa tesi: creare un ambiente di sviluppo per SCCP, un linguaggio per la creazione di modelli ad agenti con- correnti ad evoluzione stocastica. Nel corso del progetto sono stati svolte le fasi di analisi, progettazione e realizzazione dello stesso e sono state portate tutte a termine: il framework adesso esiste e rispetta tutte le speciche preventivate. Lo stesso è composto da un'interfaccia graca che si interfaccia tramite XML e CSV e tre compilatori diversi che sono stati scritti appositamente per ri- spondere a tre diverse esigenze. Nel primo capitolo tratteremo le nozioni teoriche che sono le fondamenta ne- cessarie per arontare il problema: si parlerà infatti di Algebre di Processo, Algebre di Processo Stocastiche e si daranno alcuni tratti sul lavoro svolto dai tre compilatori che sono stati creati. Nel secondo capitolo si aronteranno l'Analisi e la Progettazione del fra- vii
  • 10. mework: si partirà dalle basi teoriche esposte nel primo capitolo per proget- tare la visione funzionale dei moduli del progetto. Nel terzo capitolo si darà una visione esterna del progetto, si tratterà l'in- stallazione e l'utilizzo delle diverse componenti che formano il progetto. Nel quarto capitolo si guarderà più da vicino al progetto: si analizzeranno le classi più importanti, si vedranno i punti di forza e di debolezza delle scelte operate, e si vedranno a livello pratico la dierenza tra i diversi compilatori. Il quinto capitolo sarà un'analisi prestazionale e funzionale del framework: si studieranno le prestazioni rispetto a diversi programmi SCCP, si confron- teranno le tempistiche e le performance dei diversi compilatori cercando di trovare dei punti nei quali approfondire gli sforzi per migliorare il framework stesso. Inne, nel sesto capitolo, si trarranno le conclusioni su quanto è stato fatto. L'intero codice è stato scritto dal tesista, eccezzion fatta per alcuni mo- duli di supporto esterno che verranno segnalati per la corretta valutazione dell'operato. viii
  • 11. 1 1
  • 12. Capitolo 1 Nozioni Teoriche In questo capitolo verranno presentate sintetizzate le nozioni teoriche per la comprensione dei capitoli successivi. Dapprima verranno presentate le algebre di processo come formalismo per la denizione di programmi ad agenti concorrenti. In seguito verrà esposto CCP, come esempio di linguaggio concorrente. Nelle sezioni seguenti si scenderà in dettaglio su sCCP e gli argomenti neces- sari per capire le tre semantiche a disposizione del framework. 1.1 Algebre di Processo Le algebre di processo (in inglese, Process Algebras) sono un linguaggio for- male che permette di descrivere l'evoluzione parallela di più processi con le conseguenti modiche del sistema stesso. Il formalismo prevede che l'evolu- zione segua tre regole principali: 1. I processi (chiamati anche Agenti) comunicano tra loro tramite mes- saggi (attraverso memoria condivisa) 2. La descrizione dei processi avviene tramite l'utilizzo di semplici primi- tive, composte per formare della azioni più complesse. 3. Viene denita un'algebra che imponga delle regole per gli operatori dei processi. 1.1.1 Operazioni dei processi Secondo la teoria, ogni processo è composto dalla concatenazione di più azioni atomiche; nello specico queste sono: 1
  • 13. 1. Composizione in parallelo 2. Indicazione del canale per il trasferimento dati 3. Composizione sequenziale delle azioni atomiche 4. Restrizione di dati e comunicazioni 5. Scelta tra più possibili azioni 6. Chiamata ricorsiva ad un processo 7. Azione nulla Nelle sottosezioni successive verrà spiegato il signicato di ognuna di queste operazioni. Composizione in Parallelo Per indicare una composizione in parallelo viene utilizzato l'operatore || . Un esempio può essere il seguente: Agente1||Agente2 La semantica di questa azione è traducibile nell'istanziazione ed esecuzio- ne parallela degli agenti (equivalente a processo) indicati come Agente1 ed Agente2. Sebbene possa sembrare limitante il parallelo denito in questo modo, basti pensare che uno dei due agenti composto da un altro parallelo per vedere che il numero di Agenti da istanziare in parallelo con una singola azione è illimitato. Comunicazione La comunicazione è un azione atomica che permette a degli agenti di comuni- care tra loro. Si capisce subito come dei processi paralleli privi di possibilità di comunicare risultino di scarso interesse e per questo motivo ques'azione è così importante; solitamente vi sono due modi per due processi di comunicare: • Tramite l'ausilio di variabili o aree di memoria condivise; • Tramite il passaggio diretto di dati; Il primo punto è autoesplicativo: basta dare libero accesso ad opportune aree di memoria ed il gioco è fatto. Per il secondo punto vanno invece deniti il canale, il usso di input e quello 2
  • 14. di output. Generalmente si indica il usso di input come x(v) e il usso di output come xy (supponendo x il nome del canale, v il vettore di dati da ricevere e y il vettore da spedire) A livello semantico l'elemento di input specica che il processo è in attesa di dati in arrivo, mentre l'elemento di output specica che il processo è pronto a inviare sul canale i dati. Composizione in sequenza La composizione in sequenza permette di collegare nell'esecuzione un numero indenito di azioni. Vediamo un semplice esempio della composizione delle azioni che abbiamo n'ora visto. Supponiamo di voler descrivere un agente che attenda un parametro di in- gresso per poi istanziare due agenti (A1 e A3) in parallelo: Questo processo potrebbe venir descritto come: x(v).(A1(v)||A3(v)) Focalizzare dati / comunicazioni Un processo può voler limitare il numero di connessioni che gli altri agenti possono aprire con lui: l'hiding gli permette di nascondere il canale di comu- nicazione (o variabile) ad altri agenti. In pratica l'agente fa il wrapper di sé stesso e nasconde all'esterno parte dei suoi canali. Scelta La scelta permette ad un agente di scegliere in maniera non deterministica l'azione da eseguire. L'operatore per la scelta è il +, un'esempio di utilizzo potrebbe essere: P0 :- P1 + P2; In questo caso, al momento dell'esecuzione di P0, questi sceglierà quale azione invocare. 3
  • 15. Chiamate Ricorsive Una chiamata ricorsiva prevede la possibilità di far si che un processo ese- gua sé stesso (o un altro processo), permettendo la costruzione di cicli e di esecuzioni illimitate/innite. Azione nulla L'azione nulla (indicata in innumerevoli modi, come nil, null, 0) fa terminare il processo che la invoca. Questa capacità viene utilizzata per terminare selettivamente un agente in determinate situazioni (sicchè non rimanga in memoria ultimata la sua esecuzione). 1.1.2 CCP: Concurrent Constraint Programming CCP è un linguaggio di programmazione a processi concorrenti basato sui vincoli che sta alla base di sCCP. La dierenza principale tra i due sta nella non-deterministicità di CCP che si contrappone alla stocasticità di sCCP. Nelle prossime sezioni verranno presentate le componenti che contraddistin- guono il linguaggio. Constraint Store Il Constraint Store è la rappresentazione che CCP ha della memoria. In esso le variabili non assumono un semplice valore, ma rappresentano un insieme di valori che la variabile stessa può assumere. Questa denizione è più estesa rispetto quella di Von Neumann: permette infatti di associare alle variabili insiemi di valori, ma anche insiemi con un solo elemento e quindi sono evidenti le maggiori potenzialità. È possibile accedere al Constraint Store attraverso due funzioni: Ask e Tell. Ask è una chiamata che pone una domanda al gestore della memoria, nello specico gli chiede la validità di una formula. Tell invece impone un nuovo vincolo al sistema espresso come formula logica al primo ordine. Si noti come i diversi Tell vadano ad inserire nuovi vincoli, senza in alcun modo toccare quelli esistenti: questa condizione può portare facilmente al- l'inconsistenza del sistema, ma utilizzata nel modo corretto porta le variabili ad appartenere a dei domini di accettazione sempre più ristretti. È comprensibile allora il nome di questo linguaggio: • Concurrent: deriva dalla presenza di Agenti in un ambiente conccoren- te; 4
  • 16. Constraint: deriva dall'utilizzo di una rappresentazione della memoria a vincoli come il Constraint Store; • Programming: indica che si tratta di un linguaggio di programmazione; Identicate le componenti di base, si può procedere alla denizione della grammatica del linguaggio. La Grammatica di CCP Di seguito viene esposto la sintassi del linguaggio nella conveniente forma di grammatica. P rogram ::= Declaration.Agente Declaration ::= ε | Declaration.Declaration | p(x): −Agente Azioni ::= ask(c) → tell(c) Scelta ::= Azione.Agente | Scelta + Scelta Agente ::= 0 | Agente.Agente | Scelta | Agente Agente | ∃x Agente | p(x) Tabella 1.1: La sintassi di CCP. Programma Programma è il punto di partenza della grammatica, in CCP questi è costituito dalle dichiarazioni degli agenti e dall'agente iniziale. Declaration Le dichiarazioni possono essere una, più di una o anche nes- suna; si indicano con la forma: N omeAgente (v ) : − Agente Una dichiarazione rappresenta il prototipo di un Agente; contiene le diverse azioni che fanno parte del comportamento del processo stesso e le variabili locali che gli appartengono. 5
  • 17. Azioni Le azioni che permettono di eettuare degli update condizionati del Constraint Store. L'agente eettua gli Ask e i Tell al Constaint Store. Ricordiamo brevemente quali sono le azioni compiute da ask e tell: • Ask(condizione) permette all'agente di domandare al Constraint Store la validità della condizione; • Tell(condizione) permette all'agente di aggiungere al Constraint Store il vincolo espresso in condizione; Si veda l'esempio quì riportato per capire l'utilizzo delle guardie stesse. if (x 5) y = 9; diventa: ask(x 5).tell(y = 9) Si è deciso, sempre prendendo spunto da un'idea trovata in [1], di adot- tare la seguente scrittura per le guardie: [ condizione → condizione ] La semantica scelta impone di interpretare come Ask tutte el condizione che stanno a destra dell'operatore → , mentre ciò che sta dopo viene inter- pretato come Tell. La condizione prima esposta: ask(x 5).tell(y = 9) diventa: [ x5→y=9 ] Questa forma contratta non impone l'utilizzo di entrambe le azioni (Ask e Tell), in quanto basta omettere le condizioni od utilizzare dei vincoli sem- pre veri: [ true → t = 10 ] Contratto per comodità in: 6
  • 18. [ → t = 10] Scelta La scelta permette di associare più azioni ad un solo agente. La scelta prevede, come si vede in grammatica, la distinzione tra le varie azioni separate da il segno +. Ogni elemento che forma una somma è costi- tuito da una guardia seguita da un'Agente. Agente1 : − [x 0 → y = 0].Agente1() + [x == 0 → (x = 10) (y = 0)].Agente1(); Questo è la denizione di un'Agente, operante sulle variabili globali x ed y che compie le seguenti azioni: Se x 0, impongo un nuovo vincolo per cui y debba essere positiva; Se x == 0, impongo un nuovo vincolo per cui x debba essere minore uguale a 10. Quando viene chiesto di eseguire ad un agente, questi sà quali sono le guardie sono vere (con Ask true) e quali no: eseguirà solo le azioni corrispondenti alle prime. Si noti come in questo particolare esempio l'agente ha sempre e solo una sola azione da eseguire: non è possibile infatti che entrambi le azioni superino le guardie perchè presupporrebbe che nello stesso istante x sia maggiore a 0 e anche uguale a 0. Nel caso più guardie siano attive contemporaneamente, la scelta viene eettuata in modo non-deterministico. Agente L'agente è la parte centrale non solo della grammatica, ma del linguaggio in generale: formato da azioni e variabili locale è l'elemento sotto osservazione da parte della simulazione. Un'Agente è formalmente composto da agenti, guardie e scelte che a loro volta vengono composte per ottenere la forma dello stesso da noi voluta. Un esempio di Declaration potrebbe essere: P (x = 0) : − [true → x = 0].( P 2() || P 3() ) + P 4(); Questa viene interpretata come: Declaration - Scelta tra (Guardia seguita da parallelo e chiamata P4) 7
  • 19. 1.2 Algebre di Processo Stocastiche Nel corso delle prossime sottosezioni verrà analizzato un ambiente in cui, dato lo stato della memoria e l'indice dell'istruzione non è possibile sapere il risultato che questa avrà, ma al massimo si potrà fare delle stime su questo valore. 1.3 sCCP: Stocastic Concurrent Constraint Pro- gramming sCCP è un linguaggio per la descrizione di modelli in cui agenti interagiscono tra loro e con l'ambiente in modo concorrente; inoltre questa interazione è governata da leggi probabilistiche. sCCP è un'estensione stocastica di CCP e da esso eredita le peculiarità fon- damentali: il Constraint Store e gli Agenti. Questo linguaggio prevede la comunicazione tra agenti come asincrona, ottenuta tramite l'utilizzo di va- riabili globali condivise. sCCP è strutturato in modo da avere tutte le azioni viste prima: scelta non deterministica, composizione in parallelo, chiamata ricorsiva e in più la dichiarazione di variabili locali. L'evoluzione temporale di sCCP è profondamente legata alle catene di Mar- kov Tempo Continue, come spiegato in [1]. In questa sezione analizzeremo il linguaggio e ne studieremo le dierenze con CCP. 1.3.1 Rate Ad ogni azione interagente con il Constraint Store, viene associato un valore ∈ + che rappresenta il Rate. Il Rate è il prametro di una distribuzione di probabilità esponenziale che descrive il tempo che l'azione impiega a venire eseguita. Ad ogni passo si verica una Race Condition tra le diverse azioni attive: verrà eseguita quella che impiega il tempo minore. Questa evoluzione si può descrivere (dal punto di vista matematico) equivalentemente tramite la scelta di un azione con probabilità proporzionale al rate, aumentando il tempo secondo una distribuzione di probabilità esponenziale con Rate Tota- le. Quest'ultimo si può calcolare come: Rate(A) = π∈Actions Gπ (i) ∗ λπ RateT otale = A∈ActiveAgents Rate(A) Si evince che la probabilità di esecuzione di un Agente è: 8
  • 20. Rate(a) P (A) = RateT otale In queste formule: + • λπ : CS → è il Rate dell'azione è dipendente dallo stato corrente del Constraint Store. • G(i) : CS → 0, 1 rappresenta un valore booleano associato alla guardia: 1 se la condizione in Ask è vera, 0 se non lo è. Lo scorrere del tempo, viene quindi calcolato come: Tempo = Tempo + ∆T ∆T = −1/T ∗ log U (con U distribuzione uniforme di probabilità tra 0 e 1) Azioni a Rate Innito sCCP prevede la possibilità di avere delle azioni con Rate innito. Queste azioni vengono chiamate Azioni Istantanee ed hanno le seguenti peculiarità: • Non incrementano il tempo. (∆T = 0) • Vengono eseguite prima di ogni azione stocastica. 1.3.2 Constraint Store Essendo un derivato diretto di CCP, anche sCCP ha un suo Constraint Sto- re. Per aggiungere potenzialità al linguaggio, sono state aggiunte le Stream Variables, come denite in [1]. In applicazioni di biologia o chimica, spesso le variabili devono poter cambiare il loro valore, non solo l'insieme dei valori che vi si possono attribuire. Nel sequente esempio si capisce i limiti imposti da una struttura senza Stream Variables: [true- X=5] [true- X=X+1] Questa istruzione porta ad uno stato inconsistente. Per questo motivo è stato pensato il sistema delle Stream Variables: associando ad ogni variabile una lista (in particolare con variabile in coda non istanziata) possiamo aggiungere in coda i nuovi valori. Nel momento in cui ci si trovi a volere il valore di quella data variabile, basterà guardare il valore in coda, ma la presenza all'interno di essa di tutta la sua storia non viola il resto della teoria. In tutto il resto dell'elaborato, nelle situazioni in cui si trova una scrittura del tipo: 9
  • 21. [true - x=x+1] Questa farà riferimento all'aggiunta del valore sulla destra nella lista denita dal nome che compare sulla sinistra. Nell'approfondimento pratico vedremo come questa gestione teorica può essere implementata con un sistema di variabile standard a singolo valore. 1.3.3 Grammatica P rogram = Declaration.Agente Declaration = ε | Declaration.Declaration | p(x) : −Agente Agente = 0 | [→ U]@∞.Agente | Scelta | ∃x Agente | Agente Agente Scelta = π.Guardia | Scelta + Scelta π = [G → U]@λ | [G → U]@∞ Guardia = 0 | tell∞ (c).Guardia | p(y) | Scelta | ∃x Guardia | Guardia Guardia Tabella 1.2: Sintassi del sCCP. L'sCCP ha una diversa grammatica per descriverlo, in cui la dierenza principale sta nell'assegnazione dei valori di Rate. Oltre a ciò si vede come ogni azione debba avere un peso e, essendo questo vincolato alle guardie, ogni azione deve iniziare con una guardia. Un possibile esempio potrebbe essere il seguente (dove @ è seguito dal Rate): Agente1 : - [X=0-X=X+1]@{5}.Agente1() +[X3-X=X-5]@{3}.Agente1(); Agente2 : - [X0 -X=X*2]@{1/X}.Agente2(); Agente1 || Agente2 Analizziamo brevemente questo esempio, supponendo il valore iniziale di X sia 0. 10
  • 22. STEP X RATE AZIONE 0 0 5 X =X +1 1 1 1 X =X ∗2 2 2 0.5 X =X ∗2 3 4 3.25 X =X −5 4 -1 5 X =X +1 5 0 5 X =X +1 Per quanto quasi tutti i punti siano deterministici (in questo esempio ad hoc) al punto 3 è stata eettuata una scelta. Nello specico le azioni attive erano: a)[X 3-X =X -5]@{3} b)[X 0 -X =X *2]@{1/X} Nello specico è stata fatta una scelta a favore della prima azione per motivi statistici: 3 0.25 p(a)= p(b)= 3.25 3.25 Ovviamente poteva anche accadere il contrario e avremmo raggiunto uno STEP 4 con X pari a 8 e Rate totale pari a 3.125. A questo punto nuova- mente si sarebbe eettuata una scelta, aggiornata con i nuovi valori di Rate. 3 0.125 p(a)= p(b)= 3.125 3.125 Questo banalissimo esempio mostra un'oscillazione controllata del valore di X. 1.3.4 Le potenzialità del sCCP Da questo esempio si desume la versatilità del sistema e la possibilità di im- plementare praticamente ogni tipo di algoritmo: si pensi per un attimo alla macchina URM, gemella di quella Turing, e alle 4 operazioni da essa imple- mentate. sCCP ha tutte le potenzialità della macchina URM, e quindi di quella di Turing. Dimostrazione: Per prima cosa l'enumerabilità dei registri: nella mac- china URM questi sono inniti ma, lo sono anche in questo caso, in quanto le variabili sono le produzioni ottenibili da una grammatica del tipo: 11
  • 23. S : lettera S | Ed essendo un innito numerabile posso associare a ciascuna variabile che genero un numero intero che diventerà il numero del registro della macchina URM. Le operazioni della macchina teorica URM sono: 1. Z(n), n=1, 2, 3, ... . In risposta a questa istruzione la URM azzera il registro n, lasciando gli altri registri inalterati: rn := 0. 2. S(n), n=1, 2, 3, ... . In risposta a questa istruzione la URM aumen- ta il contenuto del registro n di una unità, lasciando gli altri registri inalterati, rn := rn + 1. 3. T (m, n), m,n=1, 2, 3, ... . In risposta a questa istruzione la URM trasferisce il contenuto del registro m nel registro n, tutti gli altri registri compreso Rm rimangono inalterati, rn := rm . 4. J(m, n, q), m,n,q=1, 2, 3, ... .In risposta a questa istruzione la URM confronta il contenuto dei registri rm ed rn se: rm = rn allora con- tinua con l'istruzione successiva nel programma, rm = rn allora salta all'istruzione q nel programma. Si vede subito allora che (supponendo x = rn e y = rm ) 1. Z(n) Azzeramento → [true - x = 0] 2. S(n) Incremento → [true - x = x + 1] 3. T(m,n) Scambio → [true - x = y] 4. J(m,n,q) Salto Condizionato → [x == y - true].IstrQ + [x! =y - true] Per aiutare a capire la dimostrazione in altro modo, è possibile esaminare un algoritmo scritto in questo modo: Agente1:- [x == 0 - x = x + 1]@1 . Istruzione + [x == 1 - x = x + 1]@1. Istruzione Agente2:- [x == 2 - x = x + 1]@1 . Istruzione + . . . In questo caso il valore di x determina in maniera deterministica quale azio- ne verrà eseguita: l'unica azione con la guardia attiva, infatti, sarà quella eseguibile. Si può fare un paragone tra la variabile x di questo esempio e l'Istruction Pointer di un normale calcolatore: agendo su questa otterremo dei salti verso altre azioni. 12
  • 24. Quindi, avendo vericato questo possiamo asserire che : Eseguendo sCCP tutte le azioni della macchina URM può, co- me CCP, per la Tesi di Church-Turing computare ogni funzione computabile. 1.4 ITS ITS è la seconda semantica di sCCP che è stata implementata. In questa sezione ne analizzeremo le qualità e i limiti che, dal punto di vista teorico, ci han permesso di crearla. Dapprima vedremo le limitazioni del linguaggio, analizzando poi variabili di stato, transizioni e inne un esempio. È neces- sario ricordare che si vuole giungere ad una simulazione di tipo stocastico. Dell'argomento viene data una trattazione superciale, per approfondimenti si rimanda a [5]. Il procedimento che si è arontato prevede la creazione di una nuova seman- tica per il nostro sorgente sCCP, in modo da descrivere in un altro modo il modello descritto nel sorgente stesso. In questo caso si tratta di una visione che passa dalla visione ad agenti ad una visione a transizioni. Le tran- sizioni, denite formalmente nella sezione specica, rappresentano in sunto un passo eseguibile dal sistema per andare da uno stato ad un altro stato. Nello specico possiamo creare una transizione partendo da qualunque delle nostre azioni. Va ricordato che, non essendoci le variabili locali, ogni agente è uguale a qualunque altro agente che implementi la stessa denizione. Per descrivere ecientemente il sistema, si introducono le State Variables. 1.4.1 Limitazioni del linguaggio Per poter funzionare il sistema a Transizioni il codice deve sottostare ai seguenti vincoli: • Non può essere utilizzata la composizione in parallelo nelle denizioni, ma solo per denire lo stato iniziale. • Non esistono azioni istantanee (con Rate innito). • Ogni azione è nella forma [Ask− T ell]@{Rate}.Agente. • Gli Agenti non posseggono variabili locali. Queste condizioni portano a: 1. Il numero di Agenti è costante. 13
  • 25. 2. Ogni Agente del tipo A è uguale ad ogni altro Agente del tipo A. 3. Ogni passaggio di variabili è fatto per riferimento. Queste due asserzioni sono fondamentali ai ni pratici. Alla prima vi si arriva tramite un procedimento molto semplice ed intuitivo. Siamo nella situazione in cui: • Ho N Agenti iniziali dati dallo stato iniziale. • Non ho composizione parallela all'interno della denizione degli agen- ti(N non può crescere). • Ogni azione è della forma [ Ask → T ell]@{Rate}.Agente, quindi il numero di Agenti non può calare. In generale, queste proprietà, specie l'assenza di variabili locali, garantiscono che le variabili di stato siano una descrizione corretta dello stato del modello sCCP. 1.4.2 Modello ITS Un modello ITS viene dato da una tupla ITS = (X, S, T ) Dove: • X è l'insieme costituito dalle variabili globali • S è l'insieme delle variabili di stato • T è l'insieme delle transizioni Le Variabili Globali sono le stesse viste per sCCP. 1.4.3 Le Variabili di Stato Indicate con la lettera S nella denizione del sistema, le variabili di stato permettono di descrivere e di gestire in maniera eciente lo stato delle tran- sizioni del sistema. Ogni variabile di stato è associata ad una denizione di un agente, e descrive il numero di agenti di quel tipo attualmente attivi nel sistema. Di questa denizione, rappresenta il numero di agenti attivi che la rappresentano. Il valore di una State Variable è dunque sempre un numero naturale. Ogni update delle transizioni sCCP dovrà essere modicato per descrivere anche l'aggiornamento delle variabili di stato. Ad esempio: 14
  • 26. A1 : − [ X 0 → X = X + 1]@{k}.A2 diventa: [ X 0 → X = X + 1; SV 1 = SV − 1; SV 2 = SV + 1]@{k} Incrementare una variabile di stato equivale dunque ad aggiungere un agente del tipo associato al sistema stesso. Decrementarla equivale ad eliminarne uno. Supponiamo di avere il seguente agente A1 precedentemente descritto. La guardia sarà passabile se: X 0 ∧ SV 1 0 E il rate dato dagli agenti dello stesso tipo sarà: A1λ = SV 1 ∗ k In altri termini, la prima formula impone che se il numero di Agenti è pari a 0, nessuna azione è eseguibile. La seconda fa si che il Rate dato da tutti gli agenti di un tipo sia pari al numero di essi moltiplicato per il rate del singolo. 1.4.4 Transizioni Deniamo ora le transizioni: T = (nome, guardia, update, rate) πi := [guardia(X)− update(X)]@λ guardia(X) è passabile ⇔SVi 0 ∧ Ask(G(X)) == true update(X) = update(X)s CCP, SVi = SVi − 1, SVj = SVj + 1 In altri termini: La guardia è espressa come la guardia di sCCP solo che presenta un vincolo di positività sulla variabile di stato associata. L'update è uguale all'update visto in sCCP ma aggiorna anche lo stato delle State Variables. Vedendo un esempio: A1 : −[X 0 → X = X − 1]@{k1}.A2 + [X 10 → X = 0]@{k2}.A1; A2 : −[true → X = X + 1]@{k1}.A1; SI : A1 15
  • 27. Questo sistema, viene convertito in: t1 = [SV 1 0 ∧ X 0− X = X − 1; SV 1 = SV 1 − 1; SV 2 = SV 2 + 1]@{k1} t2 = [SV 1 0 ∧ X 10− X = 0; ]@{k2} t3 = [SV 2 0∧true− X = X +1; SV 2 = SV 2−1; SV 1 = SV 1+1]@{k1} Nell'esempio t2 non tocca le SV perchè incrementerebbe e decrementereb- be la stessa variable. È evidente come una tale forma racchiude tutte le informazioni necessarie per un algoritmo che voglia simulare l'andamento del sistema descritto dal sorgente sCCP ridotto. 1.5 ODE Con ODE si indicano le Equazioni Dierenziali Ordinarie ed è proprio da queste che prende il nome il compilatore di tipo ODE. In questa sezione si esporrà brevemente il collegamento tra ITS ed ODE. Verrà esposto come, sotto opportune ipotesi, sia possibile passare da un sistema di tipo ITS ad un sistema di equazioni dierenziali. Un approfondito studio dell'argomento si può trovare in [5]. 1.5.1 Deterministicità del Linguaggio Questa semantica per sCCP non presenta evoluzione stocastica: l'evoluzione temporale è determinata solo dalle equazioni dierenziali associate al sistema scritto in forma di sCCP ridotto. Questo è un ulteriore vincolo sul sistema stesso. 1.5.2 La denizione di ODE Come visto per sCCP e per ITS, si è dovuto denire in termini formali il sistema. Nello specico, assumiamo che le transizioni del sistema siano della seguente forma: τ ∈ T , τ = (guardτ (x, s), X = X + k, S = S + h, fτ (X, S)) k rappresenta l'aggiornamento delle variabili globali, il vettore h rappresenta 16
  • 28. l'aggiornamento delle variabili di stato: ki ∈ R, se i è aggiornata esplicitamente k= 0, altrimenti hi ∈ R, se i è aggiornata esplicitamente h= 0, altrimenti Si noti come richiediamo che gli update siano di una forma particolare, ov- verro incrementi/decrementi delle variabili con quantità costanti. Da questa denizione si ottiene il seguente sistema di ODE: ˙ X= τ ∈T kτ gτ (X, S)fτ (X, S) ˙ S= τ ∈T hτ gτ (X, Sfτ (X, S) Dove X, S, h e k sono vettori. In pratica, dal sorgente si deriva una denizione sintattica del sistema di equazioni dierenziali. Questo ha delle relazioni con il sistema stocastico associabile allo stesso sorgente, per una discussione su questa relazione si rimanda a [5]. Un programma sCCP che soddis i vincoli di cui sopra, può essere visto come una descrizione di alto livello di un sistema di ODE. 17
  • 29. Capitolo 2 Analisi e Progettazione In questo capitolo verranno analizzate le fasi di Analisi e di Progettazione svolte per creare il progetto oggetto di questa tesi. Nella prima sezione è stato analizzato il problema, partendo dai requisiti funzionali. Nella seconda sezione sono state progettate le componenti per rispondere ai requisiti. 2.1 Analisi Nel Capitolo 1 si sono viste le nozioni teoriche riguardanti sCCP e le due varianti ITS e ODE. Il progetto che si vuole creare, per l'appunto, consiste nell'implementazione di sCCP nella maniera più versatile e più completa possibile, con un occhio rivolto all'ecienza. Il progetto è stato sviluppato in ambiente .NET, in particolare è stata uti- lizzata la versione 4.0 del framework Microsoft. Le interfacce grache sono state sviluppate in Windows Presentation Foundation (WPF). 2.1.1 Analisi dei Requisiti È stato necessario interpellarsi sulle funzionalità necessarie al ne di creare il framework. È facile immaginare che il requisito fondamentale sia quello di comprendere codice di tipo sCCP: oltre a ciò è necessario che ne permetta la simulazione in maniera integrata. Dato un codice, quindi, vogliamo ave- re come riscontro dei dati sotto forma di graco o memorizzati in maniera compatibile con la maggior parte dei sistemi di analisi dati. È stato deciso 18
  • 30. inoltre di permettere all'utente di poter simulare passo passo per compren- dere l'andamento non solo in chiave temporale, ma anche in chiave di step esecutivi. Si è voluto fornire anche un'interfaccia per la stesura del codice ma, nel con- tempo, si è voluto far in modo che non fosse l'unica interfaccia possibile in modo da permettere di accedere alle funzionalità del codice anche da altre GUI scritte in futuro. Un requisito fondamentale che è stato scelto è la creazione del Constraint Store on demand: partendo da un sorgente contenente le informazioni per indicare le proprie speciche, il framework dovrà essere in grado di modellare un oggetto che le implementi nella maniera migliore. L'interfaccia graca deve permettere di salvare e riprendere in seguito il la- voro che si sta arontando. Oltre a questo deve permettere di impostare dei criteri di arresto dell'esecuzione (raggiungimento temporale o raggiugimento in passi). Deve esistere un'interfaccia simulativa di tipo batch che può gestire grandi carichi di lavoro in maniera eciente e gestire la simulazione con variazione dei parametri iniziali automatica. Oltre a ciò è necessario rendere il sistema in grado di utilizzare diversi tipi di compilatori in modo da dare all'utente la possibilità di utilizzare sia ITS che ODE. Quanto detto si può riassumere nei seguenti punti: • Il framework deve tradurre del codice scritto in sCCP, comprenderlo e simularlo. • Il framework deve fornire un'interfaccia all'utente in maniera da met- tere a disposizione tutte le sue funzionalità. • Il framework deve fornire un'interfaccia ad altri programmi in maniera da mettere a disposizione tutte le sue funzionalità. • Il framework deve generare un'output graco o numerico compatibile con gli altri standard. • Il framework deve essere capace di creare un Constraint Store specico che risponda alle esigenze di ogni applicazione. • Il framework deve poter gestire anche codice ITS e ODE. 2.1.2 Studio dei Casi d'Uso Una volta analizzato il problema è stato denito il diagramma degli Use Case. Si è visto, da quanto scritto sopra, che gli unici attori presenti sono: 19
  • 31. Utente • Altri Software Da quanto visto sopra, possiamo riassumere le attività che l'utente può fare in: • Scrivere il sorgente (salvare, caricare, compilarlo) • Scegliere il compilatore • Avviare la simulazione (graca o batch) • Raccogliere i risultati Mentre gli eventuali altri software dovranno poter: • Scegliere il compilatore • Avviare la simulazione (graca o batch) • Raccogliere i risultati Da questa prima analisi si arriva al graco in gura nella pagina successiva. 2.2 Progettazione Ultimata la fase di analisi si è passati a quella di progettazione. In primis, come illustrato nelle successivo sezioni, si è progettata la parte simulativa. Nell'arontare l'argomento si è dovuto tener conto della possibilità di voler scrivere altre IDE per i compilatori e di poter avere più compilatori per la stessa IDE. Oltre a questo è stato necessario utilizzare un sistema standard per l'output dei dati. Per riuscire a mantenere il massimo distacco tra le componenti, si è deciso di utilizzare delle interfacce per sottolineare i punti di contatto. In questo modo se qualcuno dovesse volere riscrivere una parte del programma, non deve far altro che reimplementare l'interfaccia associata. È stato fondamentale dividere il codice sorgente dell'utente in due blocchi di- stinti: una parte va a denire la congurazione degli agenti (compresi agenti iniziali, denizioni agenti, ecc.) detta SourceAM, mentre l'altra serve a mo- dellare il Constraint Store come l'utente desidera (variabili globali, funzioni, constraints, parametri, operatori ... ) detta SourceCS. 20
  • 32. Use Cases Diagram 2.2.1 Standardizzazione di Input ed Output Si è fortemente cercata l'indipendenza delle parti su tutti i fronti, per questo si è deciso di utilizzare degli standard già aermati per gestire input ed out- put. Principalmente si doveva rendere compatibile con future espansioni e varianti l'input (rappresentato per la maggior parte dai sorgenti) e l'output (i dati di risposta della simulazione). Per modellare l'input serviva un linguaggio in grado di esser modellato per le nostre esigenze e che fosse di semplice lettura: per questo motivo si è scelto XML. Essendo molto utilizzato, un domani chiunque potrebbe creare un'in- terfaccia graca diversa che generi il codice XML da fornire al compilatore senza grossi sforzi. Un domani uno sviluppatore potrebbe voler creare una IDE completamente graca in cui l'utente non debba scrivere una sola linea di codice: grazie all'utilizzo di XML non necessiterà di alcun parser o vali- datore se non il DTD stesso dei le XML utilizzati. Per la verica della correttezza sintattica dei le XML sono stati creati dei 21
  • 33. les DTD apposta. L'utilizzo di questo sistema ha portato ad una sempli- cazione anche nella creazione dei compilatori stessi: ogni compilatore avrà un suo DTD per analizzare il codice così creato. Per quanto concerne l'output si è scelto per un formato molto leggero ed universale: il CSV (comma separated values). Questo formato è compatibile con moltissimi programmi di analisi dati (come Mathlab o Excell) ed è prati- camente un plain text e quindi leggibile anche con un qualunque text editor (esattamente come XML). 2.2.2 I Macro Moduli Per creare questo progetto è stato necessario utilizzare un approccio di tipo Top-Down in cui si è iniziato immaginando dei macro blocchi che poi sono andati a denirsi mano a mano che si scendeva nel dettaglio. Fin dal prin- cipio si sapeva che dovevano esistere delle classi che assolvessero ai seguenti compiti: • Interfaccia Graca di Scrittura del Codice (Parser GUI) • Parser da linguaggio a XML per il SourceCS • Parser da linguaggio a XML per il SourceAM • Interfaccia Graca per la simulazione graca in tempo reale • Interfaccia Graca per la simulazione Batch • Classi di scambio parametri di compilazione • Compilatore Con la congurazione esposta in gura un utente può utilizzare il progetto in più modi: • Utilizzare tutto il progetto, dal Parser GUI per la stesura al compilatore per simulare • Utilizzare un proprio Editor e passare il codice per la simulazione Graca / Batch alle due classi predisposte • Utilizzare solo il compilatore lasciando poi il proprio software a gestire i dati in input e output 22
  • 34. Figura 2.1: Primo Approccio Progettuale 2.2.3 Il Compilatore Il Compilatore in questo progetto non è unico e non perchè si è scelto di crearne più del dovuto, ma perchè ogni Compilatore deve comprendere un particolare tipo di codice. Avendo di base due tipi di codice, uno scritto per la denizione degli agenti e l'altro per la denizione del Constraint Store, è evidente che ci dovranno essere un modulo per comprendere l'uno e un per comprendere l'altro. Avre- mo quindi, in generale, una suddivisione tra Parser per SourceAM e uno per SourceCS. È comprensibile come un codice scritto per il Parser X non necessariamente debba funzionare per il Parser Y, ma la divisione in queste due categorie serve per avere dei risultati comuni. Ad esempio da un Parser per il SourceCS (ParserCS) ritornerà sempre un contenitore con variabili, funzioni, constraint e quant'altro; allo stesso modo un Parser per il SourceAM (ParserAM) ritornerà sempre un elenco di deni- zioni di Agenti ed uno stato iniziale. Avendo scelto di utilizzare in ingresso dei codici XML, i Parser non hanno bisogno di librerie particolari per produrre il risultato ma gli basta saper analizzare un le XML. Va rispettato un vincolo: ParserCS deve eseguire sempre prima di Parse- rAM. La motivazione è molto semplice: ParserAM ha bisogno di sapere chi sono le variabili, chi i constraint, chi le funzioni e quant'altro per poter fare 23
  • 35. correttamente il proprio lavoro. ParserAM conosce in questo modo i dati per la denizione del nuovo Con- straint Store; oltre a questo gli vengono forniti gli indirizzi dei RuntimeMa- nager appena istanziati in modo da dare loro i risultati da esso prodotti. 2.2.4 Runtime Manager Come ParserAM e ParserCS svolgono le funzioni di comprensione del sor- gente, il Runtime Manager svolge quelle di simulatore. Esso infatti conosce, grazie a ParserAM, tutte le denizioni sia in termini di Agenti che del Con- straint Store. Viene istanziato fornendogli semplicemente i criteri di arresto (durata tem- porale λ o numero di passi). Un Runtime Manager espone (principalmente) le seguenti funzioni: • Start - Inizia la simulazione • Stop - Interrompe la simulazione • Step - Eettua un passo della simulazione • GetGraphData - Fornisce tutti i dati relativi alle variabili ed al loro andamento temporale • GetGlobalVars - Fornisce il valore attuale della variabili globali • GetStatus - Fornisce un riassunto di Agenti Attivi, ultime azioni ese- guite, rate, ecc. Come è evidente il Runtime Manager è in tutto e per tutto il cuore del pro- getto: tutte le altre parti non sono che moduli che permettono l'interazione con esso. Una volta dato il comando Start, questo simulerà nchè non gli viene dato lo Stop o soddisfa le condizioni di terminazione. Analizzando il linguaggio sCCP ci si è resi conto che un simulatore ben strutturato deve esser dotato di due elementi: • Il Constraint Store • Il Denition Store 24
  • 36. 2.2.5 Constraint Store Il Constraint Store (CS) sarà la memoria del nostro sistema. In esso ci saranno le variabili e vi si accederà tramite gli Ask e i Tell. Oltre a ciò dobbiamo poter richiedere al CS di ritornare il risultato di una formula: questo viene usato per il calcolo dei Rate. Un'altra funzionalità è quella di ritornare lo stato di tutte le variabili in un operazione sola. Al CS viene dato anche il compito di modicare, se necessario, le formule lette dai Parser. Ricapitolando: • Ask • Tell • GetRate • GetVariables • Parse 2.2.6 Denition Store Il Denition Store è il gestore delle denizioni di agenti. Deve aiutare la fase di Parsing del SourceAM e deve fornire al RuntimeManager gli agenti richiesti. È unico per ogni Runtime Manager. I requisiti che deve soddisfare sono: • Creare una denizione • Creare un'azione per una denizione • Fornire le istanze delle denizioni Vista la denizione degli agenti, si è deciso di progettare la singola denizione partendo dalle seguenti considerazioni: • Ogni Agente ha più scelte • Ogni scelta ha una o più azioni • Ogni azione può essere composta da una o più azioni atomiche Per gestire questa condizione si è pensato al seguente sistema. Ogni Agente ha una scelta tra le possibili azioni. Ogni serie di azioni composte in sequenza sono gestite da un Action Manager. Le azioni implementano tutte la stessa interfaccia che espone molti metodi, tra cui quello per l'esecuzione dell'azione e quello per ricevere il Rate dell'azione stessa. Vediamo ora un esempio sulla gestione dell'azione: 25
  • 37. Agente :- [X 0 - X = X-1]@{1}.Agente + [X == 0 - X = 10]@{1}.([ - Y= Y + 1]@{1}.Agente || Agente + Agente); Questa struttura viene dapprima spezzata in due: [X 0 - X = X-1]@{1}.Agente [X == 0 - X = 10]@{1}.([ - Y= Y + 1]@{1}. Agente || Agente + Agente); La prima azione ora diventa: ActionManager - [Guardia][Call] La seconda invece diventa: ActionManager - [Guardia][Scelta] [Scelta] - ActionManager - [Guardia][Parallelo([Call][Call]) - ActionManager - [Call] In pratica un ActionManager è una lista di Azioni collegate dalla Composi- zione in Sequenza: quando il Parser individua una scelta aggiunge in coda un'elemento Scelta, il quale avrà i suoi ActionManager per gestire le biforca- zioni. In questo modo si gestiscono le azioni come fossero un albero, in maniera eciente e assolutamente non rigida. In gura un diagramma approssimato ma riassuntivo. 2.2.7 Interfaccia Graca È stato fondamentale progettare da subito anche l'interfaccia graca: grazie ad un'approfondita analisi delle funzionalità che si volevano esporre si è riu- sciti ad apportare modiche anche ai diagrammi delle classi che formano il Core. Per prima cosa è il caso di dividere l'interfaccia graca in tre blocchi distinti: • GUI per la scrittura del codice • GUI per la simulazione in tempo reale • GUI per la simulazione Batch 26
  • 38. Figura 2.2: Rappresentazione concettuale delle classi Parser GUI Questa WPF Window è stata progettata per essere il più semplice possibile. Divisa in due parti in cui scrivere il SourceAM e il SourceCS, ore le funzioni di base (salva, carica, nuovo, esci) aancate dalla possibilità di compilare (AM, CS, Entrambi), di scegliere il compilatore (sCCP, ITS, ODE) e inne la possibilità di lanciare la simulazione (Graca o Batch). Nel capitolo 3 vedremo un esempio pratico con tanto di immagini prese dal programma. Graphic Simulation GUI Questa interfaccia si compone di tre nestre distinte che vengono mostrate una di seguito all'altra. Nella prima si è progettato che venga data la possibilità di scegliere i para- metri di arresto, i le XML da caricare (SourceAM e SourceCS, impostati dal Parser GUI con i giusti valori), la precisione del graco e il numero di simulazioni parallele. Nella seconda nestra è stata data la possibilità di scegliere i dettagli del graco: si possono scegliere le variabili da analizzare mostrandole tracciate, di quali variabili mostrare la media, di quali la varianza. Per ogni linea da tracciare si può scegliere il colore e la didascalia. Avendo concentrato le scelte prima dell'esecuzione, l'ultima nestra è quasi 27
  • 39. completamente dedicata al graco. Si sono volute mostrare anche le variabili con i loro valori e gli agenti in vita, ma la maggior parte dello schermo è presa dal graco. Questa nestra si è pensato debba avere funzionalità interattive (permettndo di iniziare o fermare la simulazione o di fare un singolo passo), permettendo di salvare e ricaricare lo stato ed anche di esportare un le .CSV contente i dati raccolti. Batch Simulation GUI La simulazione batch deve raccogliere i seguenti dati: • Scelta criteri di arresto • Scelta numero di esecuzioni • Scelta le da eseguire • Scelta le da salvare • Scelta delle variazioni delle variabili in ingresso Come nel caso precedente si è pensato di procedere con tre schemate per poter scegliere le opzioni. Nella prima si possono così concentrare le infor- mazioni in merito ai criteri di arresto, le di eseguire, le da salvare e numero di esecuzioni. Nella seconda così ci si può concentrare sulle variazioni dello stato iniziale: per ogni variabile ed ogni stato si devono poter impostare dei possibili valori iniziali e il sistema deve poi valutare le esecuzioni sugli opportuni valori ini- ziali. A questo punto nella terza videata basta predisporre un indicatore di com- pletamento e qualche controllo sulla durata delle operazioni (per evitare loop). 28
  • 40. Capitolo 3 Interfaccia In questo capitolo tratteremo l'utilizzo del framework in oggetto di questo elaborato. Nella prima parte analizzeremo le procedure per l'installazione. Nella seconda discuteremo in merito alla stesura del codice, analizzando in dettaglio come stendere un semplice codice d'esempio. Nella terza sezione vedremo come simulare in forma graca e non. 3.1 Installazione L'installazione del progetto risulta molto semplice. Una volta scaricato il le compresso del progetto, basta scompattare la cartella. A questo punto è possibile eseguire il le sCCP-GUI.exe ed utilizzare il programma. Se il programma non dovesse funzionare, è probabile che il computer sul qua- le si sta lavorando non disponga del .NET Framework 4.0. Per l'instazzazione di quest'ultimo, basta visitare il sito di Microsoft e scari- care il software in questione. 3.2 Il Codice Una volta lanciato l'eseguibile sCCP-GUI.exe, apparirà un'interfaccia gra- ca per la stesura del codice. Oltre ai soliti comandi che si trovano in una usuale IDE (salva, carica, esci, nuovo, compila) ne sono stati aggiunti altri per lanciare la simulazione di tipo Batch e di tipo Graco. Il corpo della nestra principale è diviso in due aree di testo: in quella di sinistra verrà scritto il Source AM, mentre in quella di destra il SourceCS. Il menù Compile permette di scegliere di compilare il SourceAM, il Sour- ceCS o entrambi. 29
  • 41. Nel menù Engine è possibile scegliere il simulatore tra i tre visti nelle precedenti sezioni: • sCCP • ITS • ODE Se si dovesse scegliere ODE, verrà data la possibilità di scegliere quale meto- do utilizzare per risolvere il problema (Implicit Runge Kutta...). Oltre a ciò è possibile scegliere la precisione del solver. Nel menù Constraint Store è possibile scegliere se utilizzare il Constraint Store basato su muParser oppure quello basato su Flee. Se si volesse scavalcare la l'interfaccia graca per la stesura del codice, è possi- bile lanciare i simulatori direttamente. Questi si trovano nella stessa cartella, con il nome sCCP-GraphicSimulator.exe e sCCP-BatchSimulator.exe. Nel- l'ultima sezione di questo capitolo verrà spiegato l'utilizzo di questi e come interfacciarli ad eventuali altre IDE. 3.2.1 Il Codice SourceAM In questa sezione si daranno alcune informazioni sul come scrivere il codice SourceAM. Per prima cosa dobbiamo ricordare che a seconda del compila- tore il linguaggio subisce delle restrizioni dovute alle limitazioni teoriche. In questa sezione parleremo, in modo del tutto generale del codice sCCP. Il SourceAM è costruito in questo modo: Agent_Definitions /* Definitions */ End_Agent_Definitions Initial_State /* Initial State */ End_Initial_State All'interno dello spazio dedicato alle denizioni, possono venir scritti agenti in questo modo: NomeAgente(Variabili) :- Azione (.Azione)+ Variabili = Nome | Nome = Valore Azione = Guardia | Chiamata | Parallelo | Scelta Guardia = [Ask - Tell]@{Rate} Chiamata = NomeAgente(Variabili) Parallelo = Azione || Azione ... Scelta = Azione + Azione ... 30
  • 42. Per la compatibilità delle istruzioni assegnate in Ask, Tell o Rate si rimanda al Capitolo 4. Un Tell può esser costituito da più chiamate al Constraint Store; queste devono essere separate da un ;. Se il codice viene compila- to da sCCP è possibile assegnare dei valori iniziali alle variabili locali così denite, altrimenti rimangono dei semplici segnaposto: nel momento in cui verrà chiamato l'Agente fornendogli dei riferimenti in ingresso, questo verrà modicato per inserire la nuova variabile al posto del segnaposto. In sCCP è previsto l'operatore di dereferenziazione, come in C. Ad ogni assegnazione, se viene passata una variabile in una chiamata ricor- siva, questa viene passata per riferimento, mentre se si vuole passare solo il valore si deve utilizzare l'operatore *. Esemplicando: Agente(X):- [X 0 - X = X-1]@{k1}.Agente(X); Agente2 :- Agente(Y); Nel momento in cui viene invocato Agente(Y), il segnaposto viene sostituito: Agente(Y):- [Y 0 - Y = Y-1]@{k1}.Agente(Y); Se invece l'istruzione fosse stata: Agente2 :- Agente(*Y); Agente(X) sarebbe rimasto uguale ma sarebbe stato assegnato ad X il valore delle variabile attuale della variabile Y. Questo meccanismo è utilissimo per specicare lo Stato Iniziale, in quanto permette di modellare degli agenti con lo stesso comportamento su variabili diverse. Lo Stato Iniziale è così composto. Initial_State /* Agenti */ End_Initial_State Agenti = Numero * Chiamata || Chiamata Chiamata = NomiAgente || NomiAgente(Variabili) Un esempio di inizializzazione, facendo riferimento ad Agente(X) visto prima può essere il seguente: Initial_State Agente || Agente(Y) || 2 * Agente(Z) End_Initial_State 31
  • 43. 3.2.2 Il Codice SourceCS In questa sezione si vedrà come scrivere il SourceCS per modellare il Con- straint Store con il quale interagiranno gli agenti del SourceAM. Il sorgente deve dar la possibilità di denire: • Variabili • Parametri • Costanti • Operatori • Funzioni • Constraints Per ogni elemento esiste una sintassi per la sue generazione. Il SourceCS ha questa forma: Global_Var /* Var Defs */ End_Global_Var Params /* Param Defs */ End_Params Functions_Def /*Function Defs */ End_Functions_Def Constraints_Def /* Constraint Defs */ End_Constraints_Def Var Defs := NomeVariabile = Valore ; Param Defs := param NomeParametro Valore ; Function Defs := Constant OR Function OR Operator Constant := CONST costante valore ; Function := Nome(Vars) = Semantica ; Operator := operat Simbolo/i Semantica ; Constraint Defs := Nome(Vars) = (Var = Semantica; Var = Semantica ...); Ogni elemento dichiarato all'interno del SourceCS è richiamabile negli Ask, nei Tell e nei Rate del SourceAM. Nel capitolo 5 sono illustrati alcuni esempi completi di programmi funzionanti. Si rimanda il lettore a quella sezione per vedere in pratica le denizioni viste in questa e nella precedente sezione. 32
  • 44. 3.3 La Simulazione In questa sezione si analizzeranno sCCP-GraphicSimulator e sCCP-BatchSimulator. Entrambi possono venir eseguiti come programmi stand alone e vengono ese- guiti dalla stessa sCCP-GUI quando si inviano i comandi di simulazione. Per simulare dalla sCCP-GUI si deve utilizzare il Menu Run, il quale permette di scegliere tra Graphic Simulation e Batch Simulation. Una volta mandata in esecuzione da sCCP-GUI, è come se questa non esi- stesse più e ci si trova a contatto diretto con il simulatore. 3.3.1 Graphic Simulator Il Graphic Simulator è composto da tre videate, ognuna con uno specico utilizzo. Queste vengono mostrate in ordine e l'ultima è quella che mostra la simulazione vera e propria. Queste servono a: 1. Scelta dei criteri di arresto, scelta sorgenti e numero di simulazioni 2. Scelta delle variabili da monitorare, dei colori delle linee etc 3. Simulazione e graci Prima Schermata Nella prima schermata sono impostabili i criteri di arresto. Questi possono essere di due tipi: sul numero di passi o sul tempo di sistema. Una volta scelto il criterio di arresto si può passare alla scelta della precisione dell'analisi. Se si è scelto di concludere a un dato tempo, si può scegliere di campionare N punti (decretanto così la precisione dell'output) oppure si può scegliere un passo temporale di campionamento ed utilizzare direttamente quello. Nel caso la scelta ricada su un criterio di terminazione legato al numero di passi, si può scegliere ogni quanti passi campionare. Oltre a questo si possono scegliere altre cose: • Il numero di simulazioni • Il le XML che descrive il Constraint Store • Il le XML che descrive l'Agent Manager • Se mostrare il graco durante la simulazione o alla ne Nel caso il simulatore venga caricato dalla sCCP-GUI, i campi contenenti i percorsi dei les vengono già assegnati con i nomi corretti. 33
  • 45. Seconda Schermata Nella seconda schermata l'utente può impostare le impostazioni riguardanti il graco. Nella lista superiore vengono indicate le variabili globali del progetto. Una volta selezionata, l'utente può scegliere se: • Stampare i singoli valori della variabile delle diverse simulazioni • Stampare la media dei valori della variabile derivanti dalle diverse simulazioni • Stampare la varianza dei valori della variabile derivanti delle diverse simulazioni Una volta cliccato su uno dei tre pulsanti, viene aggiunta una nuova riga nella lista dei valori da stampare. In questa lista è possibile congurare più parametri: • Il nome da mostrare nella legenda del graco • Il colore della linea • La sorgente dei dati La sorgente dei dati serve per selezionare di quale simulazione si vuole tener traccia. Ad esempio è possibile calcolare la media tutte le simulazioni eccetto una e di questa mostrare il valore singolo. In questo modo si può comparare, per ni l'andamento medio con l'andamento di una singola simulazione. Una volta selezionati i valori, si può premere sul tasto OK per passare alla terza schermata. Terza Schermata La terza schemata è stata progettata per interfacciarsi con il RuntimeMa- nager dando all'utente tutte le informazioni di cui ha bisogno. Buona parte dello schermo è coperto dal graco. Sulla destra vengono riportati i valori delle variabili e gli agenti vivi. In basso a sinistra una label riassume lo sta- to del Runtime Manager (ultima azione eseguita se si va per step, rate del sistema etc). I Menù permettono di di interagire con il sistema: File: • New - Crea una nuova simulazione copia di quella in esecuzione • Load Status - Carica una simulazione precedentemente salvata 34
  • 46. Save Status - Salva una simulazione • Save CSV - Salva i dati su disco in Comma Separated Values • Close - Chiude la simulazione Run: • Single Step - Esegue un passo nella simulazione • Start/Stop - Avvia/Interrompe la simulazione 3.3.2 Batch Simulator Il Batch Simulator è strutturato in 3 parti, come il Graphic Simulator. Le tre nestre hanno scopi diversi rispetto a quanto precedentemente visto: 1. Scelta criteri di arresto e precisione dei dati, scelta della locazione dei CSV con i risultati e dei le XML da compilare 2. Scelta delle diverse congurazioni di valori iniziali e parametri nelle diverse simulazioni 3. Semplice indicatore dell'avanzamento del lavoro Prima Schermata La prima nestra è stata impostata allo stesso modo della prima del Graphic Simulator. I criteri di arresto vengono introdotti nello stesso modo. Nel- l'interfaccia è sostituita la CheckBox che prima serviva la visualizzazione del graco a run-time o alla ne della simulazione; questa ora serve per stabilire se l'utente vuole il risultato salvato in un unico le o in uno diverso per ogni simulazione. Oltre a questo una TextBox ore la possibilità di scegliere dove salvare l'output prodotto. Seconda Schermata La seconda schermata permette all'utente di scegliere diverse congurazioni di valori delle variabili e dei parametri. Questa schermata serve, ad esempio, a vedere come varia il comportamento del sistema mano a mano che un pa- rametro cresce. Da una ComboBox si può scegliere il valore da modicare, una volta aggiunto si può scegliere come farlo variare. È possibile scegliere che la variabile acquisica N valori uniformemente distribuiti su un'intervallo, oppure che il valore di questa venga incrementato / decrementato ntanto 35
  • 47. che rimane all'interno di un intervallo. Il numero di simulazioni sarà proporzionale al numero di combinazioni pos- sibili. Se ad esempio si fa variare la prima variabile su 3 valori e un'altra su 2, ci saranno 6 simulazioni. Terza Schermata La terza schermata è assolutamente stringata: presenta solo una barra di avanzamento dei processi. Quando le simulazioni vengono completate, que- sta avanza. Quando la simulazione è conclusa, viene riportato il tempo impiegato, l'istante di inizio elaborazione e di ne elaborazione. 36
  • 48. Capitolo 4 Implementazione Dopo aver esposto le nozioni teoriche nel capitolo 1, l'analisi e la progettazio- ne nel capitolo 2 e aver mostrato l'interfaccia nel capitolo 3, in questo quarto capitolo si presenterà l'implementazione. Nella prima sezione verranno analizzate velocemente le schermate. Nelle successive si analizzeranno a turno i diversi compilatori. 4.1 Dettagli dell'Interfaccia Graca Per la programmazione dell'interfaccia graca sono stati utilizzate delle com- ponenti esterne, non scritte dal candidato. Nello specico si sono usate le seguenti librerie: • ColorPicker • DynamicDataDisplay La prima consentiva di prelevare un colore da una tavolozza ed è stata inseri- ta nella scelta dei colori nella simulazione graca. Sempre nella simulazione graca si è utilizzato il DynamicDataDisplay. Questi altro non è se non un controllo WPF che gestisce dei graci a linea. Quando viene istanziato la nestra con il graco vengono letti i parametri e desunte le linee da disegnare. A questo punto vengono memorizzate in un dizionario, per ogni linea, una lista di ObservablePoint. Ogni volta che verrà aggiunto un punto in una di queste liste, questo verrà tracciato nella corretta linea. Quando viene lanciata una simulazione, viene anche attivato un thread che va a controllare ogni 500ms se vi sono nuovi dati disponibili dal Runtime- Manager. Questi vengono convertiti in modo da essere utilizzabili e vengono 37
  • 49. inseriti nelle liste di punti opportune. Nel gestire simulazioni parellele contemporanee, onde evitare problemi con calcoli della media e inconsistenza dei dati, si è deciso di disegnare i punti no all'istante temporale del RuntimeManager di tempo minimo. Ad esempio, si considerino 4 simulazioni che dopo 500ms si trovano nel seguente stato: Sim1 : T = 35 Sim2 : T = 50 Sim3 : T = 80 Sim4 : T = 12 A questo punto il simulatore vede che Sim4 è la simulazione più in ritardo e disegna sul graco tutti i punti richiesti no al tempo 12. Nel caso una delle simulazioni dovesse incontrare un blocco dovuto al codice (rate pari a 0), non sarà possibile continuare la tracciatura del graco. L'interfaccia graca si appoggia su un OutputManager che gli permette di memorizzare su disco lo stato corrente, i risultati delle elaborazioni e di ricaricarli all'occorrenza. 4.2 SCCP SCCP è il primo compilatore e simulatore che è stato scritto per questo pro- getto. È quello che presenta maggiori requisiti da implementare in quanto deve poter simulare tutte le caratteristiche del linguaggio SCCP. Nelle pros- sime sezioni vedremo nel dettaglio come sono state implementate le diverse componenti che lo formano. Inizieremo esaminando il Constraint Store, parleremo poi del Denition Sto- re, del Runtime Manager e inne dei Parser (ParserCS a ParserAM). 4.2.1 Il Constraint Store Nella sezione 1 abbiamo appreso come il Constraint Store debba rispondere ad Ask e Tell, mentre nella fase di progettazione ci si è resi conti che le funzionalità andavano ampliate. Nello specico si è giunti a: • Ask • Tell • GetRate • Parse • Metodi per istanziare variabili, parametri, funzioni, operatori, con- straint e quant'altro. 38
  • 50. GetVariables È stato necessario appoggiarsi ad un parser di espressioni matematiche per gestire il Constraint Store. La scelta è ricaduta su muParser (modulo esterno non scritto dal tesista). muParser MuParser è reperibile all'indirizzo muparser.sourceforge.net. È gratuito e disponibile in forma nativa per C++ e Wrappato per ambiente .NET. Questa libreria permette di calcolare il valore di espressioni contenenti nu- merosi operatori e dà anche la possibilità di espandere le proprie potenzialità tramite opportuni metodi. Oltre a ciò permette di memorizzare al proprio interno parametri e variabili. È uno dei migliori parser matematici gratuiti a livello di performances. In questa prima tabella vengono esposte le funzioni built-in in muParser. 39
  • 51. Name ARC Explanation sin 1 sine function cos 1 cosine function tan 1 tangens function asin 1 arcus sine function acos 1 arcus cosine function atan 1 arcus tangens function sinh 1 hyperbolic sine function cosh 1 hyperbolic cosine tanh 1 hyperbolic tangens function asinh 1 hyperbolic arcus sine function acosh 1 hyperbolic arcus tangens function atanh 1 hyperbolic arcur tangens function log2 1 logarithm to the base 2 log10 1 logarithm to the base 10 log 1 logarithm to the base 10 ln 1 logarithm to base e (2.71828...) exp 1 e raised to the power of x sqrt 1 square root of a value sign 1 sign function -1 if x0; 1 if x0 rint 1 round to nearest integer abs 1 absolute value min var. min of all arguments max var. max of all arguments sum var. sum of all arguments avg var. mean value of all arguments 40
  • 52. Operator Meaning Priority = assignement -1 and logical and 1 or logical or 1 xor logical xor 1 = less or equal 4 = greater or equal 4 != not equal 4 == equal 4 greater than 4 less than 4 + addition 5 - subtraction 5 multiplication 6 / division 6 ^ raise x to the power of y 7 ?: if then else operator 1 In questa tabella vengono esposti gli operatori built-in in muParser. Interfacciamento con muParser Come visto, muParser ha delle peculiarità molto importanti per quanto ri- guarda la denizione di funzioni, variabili e quant'altro. Per quanto riguarda Ask, Tell e GetRate la loro denizione diventa banale: basta che il Constraint Store faccia da Wrapper, facendo attenzione a casi particolari. Ad esempio il parsing di un'istruzione vuota genera un'eccezione, ma si è deciso invece che l'Ask di una tale istruzione sia sempre valido, quindi si è dovuta gestire l'eccezione e ritornare il valore true. La denizioni di variabili e parametri è molto semplice, così come l'ottenere il valore delle variabili in muParser; basta anche in questo caso fare poco più che un Wrapper. Gli argomenti più spinosi rimangono: la denizione di User Dened Funcion (UDF) e il Parsing delle stringhe per i Parser. Per risolvere il problema delle UDF è stato escogitato un metodo molto mal- leabile che permette di gestire funzioni molto complicate e con molti para- metri. Per denire una nuova funzione in muParser, questo non si aspetta altro se non un delegato da invocare passando i parametri quando la incontra durante il parsing. Per creare a runtime una funzione che risolva questo problema si sono usate opportune classi neutre. Viene denita una classe Function che si aspetta in ingresso una lista parametri e la semantica della stessa. I parametri non han- no un valore, ma solo il nome del segnaposto nella semantica. Questa classe 41
  • 53. prevede un metodo Solve che accetta come parametri un array di double e un intero contenente il numero di parametri. Questa rma è esattamente quella che si aspetta muParser per creare una nuova funzione. Associato il nome alla funzione Solve della classe appena generata, il Parser la invocherà al momento opportuno. Quando questa viene invocata, va a sostituire tutti i parametri che riceve in ingresso (dei double) ai segnaposti indicati prima come parametri (delle string). A questo punto la stringa può venir risolta da muParser in maniera ricorsiva risolvendo il problema. Vediamo ora un semplice esempio: F(X,Y,Z) = (X + Y) / Z; Il Parser la spezza in modo da ottenere una lista di stringhe contente [X,Y,Z] e la semantica (X+Y) / Z. A questo punto crea la Function passando i valori. Nel momento della chiamata: F(1,3,5) Invoke Solve([1,3,5],3) Sostituzione Parametri ai segnaposto: (X + Y) / Z ⇒ (1 + 3) / 5 return Parser.Solve((1 + 3) / 5); Da questo pseudocodice si comprende subito la linearità dei passaggi e la correttezza degli stessi. Un problema altrettando spinoso da trattare per il Constraint Store è il Par- sing per il ParserAM. Questo serve per rendere compatibili le stringhe che poi verranno passate a muParser. Un esempio banale è dato dalla gestione delle variabili globali: per distingue- re le une dalle altre, alle variabili globali viene applicato il presso GLOBAL. Se non viene fatto un parsing corretto, un Agente che avesse un Ask del tipo [X 0] creerebbe un'eccezione per variabile non trovata. Il Constraint Store deve, per l'appunto, controllare le formule e modicarle: [X 0] ⇒ [GLOBALX 0] Il Constraint è una particolare UDF che serve ad eettuare molteplici opera- zioni parametrizzate. Un esempio di Constraint potrebbe essere il seguente: CS(ix, ipsilon) = ( X = ix/2; ipsilon = Y+2;); Il seguente constraint pone ad X il valore di ix /2 (qualunque sia il valore di ix) e modica il valore di ipsilon ponendolo a Y + 2. 42
  • 54. È facile comprendere il caos che si può creare durante questa conversione. È stato necessario convertire le stringe in maniera che ogni chiamata diven- tasse diversa dalle altre: è da ricordare infatti che le funzioni denite in muParser accettano solo parametri double e non stringhe. La soluzione che si è adottata prevede di parsare le stringhe associando un diverso constraint per ogni sua invocazione, così da poter modicare la se- mantica a seconda della chiamata. Si consideri ad esempio il constraint CS prima denito e si analizzi la chia- mata: [ - CS(K,MyCount)]@{... È necessario creare il constraint partendo dalla denizione e tenendo conto di: • Variabili Globali (se X è globale diventa GLOBALX) • Nome del Constraint Store (deve essere diverso per ogni invocazione) • Sostituire in tutte le istruzioni il nome della variabile presente nella chiamata. Tenendo conto di queste particolari condizioni, il Constraint Store produrrà in risposta alla richiesta di parsing: CS1(GLOBALK, MyCount) Dove in muParser è denita una funzione che esegue: GLOBALX = GLOBALK / 2 MyCount = GLOBALY + 2 Per quanto concerne la creazione degli operatori deniti dall'utente, muParser gestisce il tutto in maniera simile. La sintassi denita è come: operat SIMBOLO (elemento1, elemento2, precedenza) Ad esempio: operat ^= (p1, p2 ,1) = (p1 - p2) /2; Questo operatore, ad esempio fa la media dei due elementi. La gestione in muParser è simile, l'unica dierenza è la precedenza dell'operatore, indicata dal terzo parametro. È possibile capirne il signicato guardando la tabella con i built-in operators. Dopo aver costruito il Constraint Store basato su muParser si è riscontrata una mancanza di performance dovuta alla non compilazione delle formule. Per questo motivo si è creato un altro Constraint Store basato su un altra libreria: FLEE. 43
  • 55. FLEE FLEE(Fast Lightweight Expression Evaluator) è un valutatore di espressioni molto veloce dalle funzionalità ridotte. La libreria è gratuita e disponibile su ee.codeplex.com. Vediamo ora i vantaggi di questa libreria: • Compila le formule, fornendo delle prestazioni molto maggiori • Si interfaccia facilmente con altre librerie per aggiungere funzionalità • Supporta la chiamata di funzioni di sistema e codice IL Flee presenta anche dei notevoli svantaggi: • Non permette l'assegnazione come elemento delle formule (X = X+1 risponde false) • Non permette la creazione di parametri o costanti • Non permette di creare degli operatori custom A questo punto si è deciso di creare un Constraint Store limitato ma decisa- mente più veloce. In questo non sarà possibile: • Denire Constraints • Denire Operatori custom Se per un particolare programma non servono queste due funzionalità è pos- sibile utilizzare questo Constraint Store che, come sarà esposto nel quinto capitolo, ha delle performance di gran lunga superiori. La denizione del- le funzioni è stata implementata in una maniera simile a quanto visto per muParser. In questo caso si è creato un Function Manager che espone una funzione F che accetta come parametro una stringa. Il Constraint Store mo- dicherà tutte le chiamate alle funzioni che trova in questo modo: miaF(X,2,K) → F(miaF,X,2,K) Quando FLEE incontrerà F, invocherà la funzione del Function Manager. Questi spezzerà la stringa usando come divisore le virgole. Al primo posto trova il nome della funzione da evocare e la evocherà dall'elendo di funzioni denite. I Tell sarebbero inutili se impossibilitati a modicare il sistema. Si è quin- di intervenuti per rendere possibile la modica delle variabili. Quando il 44
  • 56. Constraint Store riceve un Tell, verica se la stringa è formata da nome va- riabile seguita dal simbolo =. Se così è allora viene risolta la parte successiva all'uguale e il risultato viene assegnato alla variabile. Nel caso la variabile appartenga alla lista di parametri fornita dal SourceCS, l'assegnazione non viene fatta, trattando di fatto la variabile come una costante. Ora verranno brevemente esposte le funzionalità di Flee: Operazioni Aritmetiche Flee permette di eseguire tutte le operazioni aritmetiche come somme, prodotti, elevamenti a potenza e moduli. ES: X * 2 + B ^ 100 % 10 Operazioni di Confronto Le operazioni di confronto ammesse sono tutte le più comuni. Per indicare il diverso si utilizza l'operatore , mentre per vericare l'uguaglianza di due oggetti si può usare semplicemente l'uguale. ES: (X Y) Operazioni di And/Or/Xor/Not Essendo ogni operazione in Flee for- temente tipizzata, l'utilizzo di questi operatori varia a seconda del contesto. In alcuni casi Flee utilizzerà l'And logico, mentre in altri farà quello Bit a Bit per esempio. ES (logico): a 100 And Not b = 100 ES (bit a bit): (100 or 2) and 1 Operazioni di Shift Grazie agli operatori e è possibile fare degli Shift dei valori. ES: 100 2 Operatori di Contatenazione Come in molti liguaggi di programmazio- ne moderni, il + in Flee sta ad indicare la concatenazione tra stringhe. ES: abc + def ES: the number is: + 100 Operatori di Indicizzazione Con Flee si possono modellare ed utilizzare Array dentro le formule. ES: arr[i + 1] + 100 Scrittura dei Simboli In Flee ogni valore viene interpretato in un parti- colar modo per tipizzarlo nella maniera corretta: • Char - Un carattere tra singoli apici 'a' 45
  • 57. Boolean - true o false • Real - Ogni numero con un punto decimale. Con 'd' ed 'f ' si può specicare la precisione (oat, double) • Integral - Ogni numero intero. Con 'U' lo si specica Unsigned, mentre con 'L' lo si considera a 64 bit • Hex - Numero esadecimale, espresso nella notazione: 0xFF12 • String - Insieme di caratteri racchiuso tra due doppi apici • Null - Alla variabile viene assegnato il valore null • DateTime - Una data scritta come: #08/06/2008# Casting Essendo tutte le variabili fortemente tipizzate (e non tutte double come in muParser), la conversione si fa tramite cast. ES: 100 + cast(obj, int) Operatori Condizionali Come visto in muParser, anche quì è presente un operatore condizionale. ES: If(a 100 and b 10, both greater, less) Operatore In Questo operatore è un operatore booleano che ritorna l'ap- partenenza di un valore o meno ad un insieme. Lo si può utilizzare con un valore ed una lista di valori dello stesso tipo. ES (List): If(100 in (100, 200, 300, -1), in, not in) ES (Collection): if(100 in collection, in, not in) Le funzioni messe a disposizione da Flee sono le stesse disponibili nella libreria Math di .NET. Grazie alla sua essibilità, infatti, tramite questa istruzione si può fargli utilizzare l'intero pacchetto: context.Imports.AddType(typeof(Math)); Questa si può utilizzare con qualunque namespace o classe, di questa impor- terà tutte le funzioni publiche e statiche. Nonostante tutte queste funzionalità di Flee non è stato possibile implemen- tare degli operatori custom come fatto in muParser. Non è stato altresì possibile permettere la gestione dei Constraint. All'utente verrà data la possibilità di scegliere tra i due Constraint Store a seconda delle sue esigienze: in caso di performance si consiglia Flee, in caso 46
  • 58. di semplicità di scrittura tramite Constraint si consiglia muParser. Per una descrizione più approfondita di Flee, si rimanda al sito del progetto. 4.2.2 Denition Store Come è stato denito il Constraint Store per la gestione dei vincoli, ora verrà analizzato il lavoro che è stato svolto per il Denition Store. Dalla teoria e dalle fasi di analisi e progettazione è emerso che il Denition Store deve: • Gestire la creazione di una denizione • Gestire la modica delle denizioni • Fornire un'interfaccia al ParserAM per aiutarlo nella creazione delle denizioni • Istanziare su richiesta le denizioni Oltre a fornire le funzioni sopra esposte, il Denition Store deve creare degli oggetti utilizzabili dal Runtime Manager, ossia Agenti pronti ad eseguire le proprio azioni. Si è subito deciso che il Denition Store dovesse, in primis, contenere una lista di denizioni. Il passo successivo è stato decidere che, al momento della creazione di una nuova denizione, questa venisse fornita al chiamante. In questo modo il chiamante, utilizzando i metodi della denizione può mo- dicarla aggiungendoci azioni e variabili locali. Questo è possibile grazie all'implementazione di interfacce contenute nel Pro- getto Commons, in comune all'intera soluzione. Il Denition Store contiene tutte le classi che deniscono le azioni viste in teoria. Queste sono intercambiabili in quanto tutte implementano la classe IAction (presente anch'essa in Commons). Avremo quindi le seguenti azioni: • Guard: gestisce un'azione di tipo guardia • Choose: gestisce una scelta • Parallel: gestisce un parallelo • Call: gestisce la chiamata • Tell: gestisce un Tell a rate innito (all'interno dei Parallel) • Ask: gestisce un Ask a rate innito (all'interno dei Parallel) Oltre alle azioni e le denizioni, il Denition Manager deve fornire anche gli Agenti. 47
  • 59. Le Azioni Le azioni (come visto nel capitolo 2.2.6) vengono raccolte in ActionManager che a loro volta vengono contenuti da Actions. Actions gestisce più Action- Manager (come fosse una scelta), mentre un ActionManager gestisce una lista di Azioni nchè si trova il bivio dato da una scelta. È ora riportato un esempio che aiuterà a spiegare l'utilizzo di Actions e ActionManager. Ag :- [- X=X+1]@{1} . Ag . [X 0 - ]@{X}.Ag + [ - ]@{1}.Ag2 + [ X5 - X=0]@{1} . Ag || Tell(Y=X); Questo agente avrà come azioni un oggetto costituito come quello in gura: Le azioni implementano l'interfaccia IAction, che garantisce la loro esposi- zione dei seguenti metodi: • Execute: fa eseguire l'azione • ReceiveLocalVariables: permette di impostare le variabili locali all'a- zione • GetRate: ritorna il rate dell'azione • GetAskVars: ritorna le variabili che inuiscono sull'eseguibilità dell'a- zione • GetTellVars: ritorna le variabili che vengono modicate dall'azione • Refresh: aggiorna l'azione se sono state modicate variabili che la interessano • IsRateInnite: permette di sapere se l'azione ha rate innito 48
  • 60. ForceRefresh: forza il refresh • GetActionData: ritorna un oggetto con i dettagli dell'azione L'utilizzo di funzioni come Refresh, GetAskVas e GetTellVars sono indispen- sabili al ne di ottenere un miglioramento delle performance. Nella sezione dedicata al Constraint Store, vedremo come queste verranno utilizzate. Agent e AgentDenition AgentDenition è una classe che contiene tutte i dati utili per la creazione di un agente e i metodi per far si che il parser possa crearla. Agent viene creato dalla AgentDenition ed è l'oggetto centrale di sCCP. Dalla teoria si evince che un agente è costituito dalle Variabili Locali e dal- l'elenco delle proprie azioni. Questo è importante anche perchè ci fa capire che inizialmente tutti gli agenti dello stesso tipo sono uguali. Da questo si può desumere che l'istanziazione di un Agent da un AgentDe- nition sia alquanto semplice in quanto consta della crezione dello stesso e del passaggio delle proprie azioni e delle proprie variabili locali. Nello specico ogni Agent implementerà l'interfaccia IAgent. Per le speciche dell'interfac- cia IAgent e delle altre, si rimanda ai sorgenti del codice, dove i commenti spiegano l'utilizzo di ogni funzione. Verrà ora spiegato velocemente cosa succede quando viene invocato l'Excecu- te a un Agente. Assieme all'Execute viene passato un valore è Reale: questo generato dal Runtime Manager e serve nella scelta dell'azione. Vediamo ora uno pseudo codice: Execute(RATE) i := 0 while(RATE 0) RATE = RATE - RateAzione[i] if (RATE 0) Esegui Azione[i] else i ++ Nello specico tale azione viene compiuta dall'oggetto Actions che ogni Agent ha. Azione[i] è un ActionManager e come tale inizierà l'esecuzione eseguen- do ogni IAction che ha in lista. Se dovessimo incontrare un'azione di tipo Choose, questa gestirà autonomamente (con il rate residuo) la scelta che deve fare. 49
  • 61. 4.2.3 Runtime Manager Il Runtime Manager è forse l'elemento più importante dell'intero modulo: è il vero e proprio motore della simulazione. Nella fase di progettazione si sono discusse la operazioni che deve sostenere, in questa fase vedremo, in forma ridotta, gli elementi principali. Un possibile pseudocodice per rappresentare l'operato di uno Step simulativo è il seguente: if (IsWorkEnded è vero) return; if (Ci sono Agenti Con Rate Infinito) Esegui il Primo Rimuovilo dalla lista else Ottieni il Rate Totale Execute(Rate Totale * Rand(0,1)) Aggiorna il tempo if (Il tempo passato supera la precisione) Aggiorna GraphData Terminazione La condizione di IsWorkEnded viene posta vera dopo il raggiungimento del criterio di arresto. Questo può essere di due tipi: temporale o sul numero di passi. Questo ag è accessibile anche dal chiamante in modo che sappia quando il lavoro è terminato. Agent Pool Agent Pool è una classe appoggio del Runtime Manager che gestisce gli agen- ti. Nello specico ritorna i valori del Rate del Sistema, sceglie l'agente da eseguire in base al valore casuale generato dal Runtime manager e gestisce l'eliminazione degli agenti dopo l'esecuzione. Una delle cose più importanti che vengono fatte dall'Agent Pool è la gestione dei Refresh. Questi sono gestiti in maniera intelligente ragioni di performan- ce. Prima si è mostrato lo scheletro della classe IAction e si è rimandato il trat- tamento di metodi come GetAskVars e GetTellVars. Questi servono per l'appunto per la gestione dei Refresh. Dopo ogni esecuzione, Agent Pool controlla quali sono le variabili modicate 50
  • 62. dell'azione che ha eseguito (GetTellVars) e sa quali sono gli agenti (memoriz- zati in opportune liste) che subiscono un cambiamento a causa delle variabili globali cambiate. Questo può essere di due tipologie: • Modica di variabili presenti nell'Ask • Modica di variabili presenti nel Rate Se nessuna delle due condizioni si verica, allora quel dato agente avrà lo stesso stato del passo precedente (valori delle guardie e rate). In questo mo- do si migliora l'ecienza mano a mano che sale il numero di agenti. È facile immaginare sistemi con centinaia di agenti di tipi diversi, che condividono poche variabili: in questi casi l'aumento di ecienza è molto rilevante. Se durante il Refresh un'azione ha rate innito, questa avvisa subito il Run- time Manager che mette l'agente nella coda speciale dei Rate inniti. L'ope- razione di aggiornamento continua e se vi sono altre azioni a Rate innito, queste vengono messe in coda. In questo modo al passo successivo, eseguirà. Aggiornamento GraphData GraphData è stato costruito per fornire lo stato delle variabili. Inizialmente era costituito da un dizionario di stringhe e liste di double in cui ogni lista tracciava l'andamento della variabile indicata dalla stringa. Ad esempio con: GraphData[X ] Si ottiene la lista di valori che ha assunto la variabile X. Per motivi di perfor- mance alla classe GraphData è stato aggiunto l'elemento Time. Questo viene modicato nel momento in cui vengono inseriti i nuovi valori nel dizionario. È stato implementato in questo modo per favorire il lettore dei dati: basta vedere se è stato incrementato Times piuttosto che contare tutti i valori nelle liste. 4.2.4 ParserCS Il ParserCS è una classe costruita per leggere e interpretare degli opportuni les XML. Questi devono fornire una modellazione del Constraint Store e come tale possono contenere: • Dichiarazioni di Variabili • Dichiarazioni di Parametri 51