3.3 Implementazione
3.3.2 Validazione
Per quanto riguarda la validazione del sistema, ovvero confermare che i requisiti, almeno in riferimento a determinati usi sono stati soddisfatti, si è costruita una piccola demo: grazie alla piattaforma per aggregate programming si sono creati 9 nodi virtuali e posizionati con determinate coordinate geospaziali creando una griglia 3 x 3, su ognuno di questi nodi si è predisposto un sensore sorgente, impostato a "true" per solo un nodo, e al fine di valutare la correttezza dell’integrazione si è aggiunta una funzione del gradiente scritta in scala con primitive scafi e un’altra funzione del gradiente scritta in java di cui si è già validato il corretto funzionamento. Questa demo come si può notare anche dallo snapshot di figura 3.12 ha riportato esito positivo in quanto i valori derivanti dalla computazione delle due funzioni coincidono.
Capitolo 4
Integrazione di Scafi e Alchemist
Questo capitolo riguarda l’integrazione del framework scafi (sezione 2.2) con il simulatore Alchemist [14] (sottosezione 2.4.2). Anche questo lavoro è stato svolto passando attraverso tutte le fasi del processo di produzione del software, di seguito riportate unitamente ai vari documenti e artefatti prodotti.4.1
Analisi dei requisiti e del problema
4.1.1
Requisiti
Il requisito assegnato è il seguente: "effettuare l’integrazione del framework scafi con il simulatore Alchemist, in modo da riuscire a simulare il compor- tamento di una determinata rete di nodi scritto avvalendosi di primitive scala offerte da scafi".
4.1.2
Casi d’uso
I principali casi d’uso del prodotto emergente da questa integrazione sono riportati di seguito (figura 4.1) con un diagramma UML, che mostra le principali funzionalità del sistema ottenuto e che rappresenta un modello dei requisiti sopraesposti.
Figura 4.1: Diagramma UML dei casi d’uso dell’integrazione di scafi con il simulatore Alchemist
Il principale caso d’uso del sistema ottenuto da questa integrazione è offrire la possibilità di poter simulare sistemi nell’ambito di Spatial Com- puting [9] [4] o Pervasive Computing [13], secondariamente si trova la fun- zionalità che permette la costruzione di questi sistemi virtuali da simulare avvalendosi del framework scafi per aggregate programming.
4.1.3
Architettura logica
Si riporta in questa sezione l’architettura logica, ovvero una sintesi di tutte le considerazione e le opinioni emerse in questa fase di analisi del problema suddivise nella dimensione di interazione e di struttura.
4.1. ANALISI DEI REQUISITI E DEL PROBLEMA 43
Interazione In una prima analisi si è cercato di focalizzare l’attenzione
su cosa deve avvenire piuttosto che sul come, in particolare si evince che l’idea di fondo per realizzare questa integrazione, astraendo da diversi dettagli, è come nel caso precedente riuscire ad effettuare tramite chiamata a procedura l’invocazione al metodo round di scafi, come si può notare dal diagramma UML sottoriportato 4.2. In tal modo Alchemist può simulare un comportamento per ciascun nodo descritto in termini di primitive scala e computato dal framework scafi.
Figura 4.2: Diagramma UML dell’interazione tra i due sottosistemi
Struttura Dal diagramma sopraesposto emerge anche la struttura del
sistema costituita principalmente dal sottosistema alchemist e scafi. Come nel caso precedente dovendo far interagire due componenti con interfacce diverse si desume la necessità del pattern adapter [7]. L’adpter adottato (ScafiProgram) è rappresentato nel digramma in figura 4.3 in particolare quest’ultimo estende dall’entità Action di alchemist e invece di estendere anche la classe da adattare viene creata un’istanza di quest’ultima diret-
tamente al suo interno previo passaggio del suo nome al momento della costruzione. Questo tipo di pattern adapter prende il nome di Object Adapter. L’utilizzo dell’approccio basato sulla reflection è spinto dal volere costruire questa estensione al simulatore mantenendo una certa uniformità con le metodologie già utilizzate al suo interno.
Figura 4.3: Diagramma UML del pattern adapter relativo a questo sistema
Un’altra considerazione effettuata a questo punto del processo di produ- zione è relativa alla natura fortemente modulare ed estendibile del simulatore alchemist: infatti nonostante questo fu inizialmente concepito per simula- zioni in ambito prettamente chimico molte entità di esso possono essere opportunamente ridefinite e reimplementate al fine di effettuare simulazioni in un qualsiasi ambito. Questa sua caratteristica, come si noterà nella fase di progetto, gioverà particolarmente questo sviluppo, in quanto è suf- ficiente effettuare una nuova definizione di alcune entità (p.es. molecole, azioni, condizioni, reazioni o nodi) per creare una nuova incarnazione del simulatore.
4.2. PROGETTO 45
4.2
Progetto
Il sistema è stato progettato seguendo le linee tracciate nell’analisi del problema, in particolar modo relativamente al concetto di incarnazione e al pattern adapter per effettuare l’interfacciamento dei due sottosistemi: si riporta in questa sezione una descrizione formale di questa fase progettuale concentrandosi sulla dimensione strutturale e di interazione.
4.2.1
Struttura
La soluzione adottata sfrutta il supporto all’ incarnazione messo a dispo- sizione da Alchemist già accennato nella fase di analisi. In particolare per questa incarnazione col framework scafi si è provveduto a definire:
• un tipo di azione, ScafiProgram, che costituisce l’entità nella quale specificare il comportamento del singolo nodo ed inoltre funge da adapter per interfacciare i due sottosistemi;
• un tipo di nodo, chiamato ScafiNode che rappresenta il singolo dispositivo;
• un nuovo tipo di molecola, denominata ScafiMolecule per rappre- sentare i sensori e il valore delle funzioni di ciascun dispositivo. ScafiProgram
Il diagramma UML in figura 4.4 è rappresentativo della struttura dell’entità ScafiProgram e si basa sui seguenti concetti:
• ScafiProgram rappresenta l’entità adapter in quanto implementa l’entità Action di Alchemis e mantiene al suo interno un’istanza di un’entità di tipo ExecutionTemplate contente quindi il metodo round che deve essere invocato dal simulatore;
• quest’ultima entità deve implementare il metodo astratto main ere- ditato da AggregateProgramSpecification con il comportamento aggregato desiderato;
Figura 4.4: Diagramma UML strutturale dell’entità ScafiProgram
• ScafiProgram costituisce inoltre una nuova definizione di azione im- plementando l’interfaccia Action di Alchemist, di particolare impor- tanza vi è l’implementazione del metodo execute nel quale avviene la preparazione dell’oggetto Context reperendo tutte le informazioni necessarie dall’ambiente di simulazione e successivamente viene ef- fettuata l’invocazione al metodo round, facendo così interagire i due sottosistemi;
• il risultato della computazione della round, l’export viene salvato direttamente nel nodo.
4.2. PROGETTO 47 ScafiNode
E’ stato definito questo nuovo tipo di nodo, la cui struttura è raffigurata nell’immagine 4.5, allo scopo di introdurre un campo nel quale salvare il risultato di tipo Export della computazione della round: questo dato è necessario al framework scafi per la successiva computazione sia locale che quella del proprio vicinato.
ScafiMolecule
Infine si è definito anche un nuovo tipo di molecola (4.6) per rappresentare i sensori in scafi e il valore di ritorno delle funzioni. Non è stato possibile mappare il concetto di sensore sulla molecola già esistente in Alchemist, SimpleMolecule, in quanto non aveva un attributo nel quale poter man- tenere il tipo del sensore (p.es. sensore di distanza, temperatura, ecc.), astrazione invece indispensabile nel framework scafi.
Figura 4.6: Diagramma UML strutturale dell’entità ScafiMolecule
ScafiSimulation
Si è creato inoltre l’entità ScafiSimulation che permette di facilitare la creazione delle simulazioni con l’incarnazione in scafi. Come si nota dal diagramma UML in figura tale entità dispone di tutta una serie di primitive atte a sgravare lo sviluppatore della simulazione da diverse operazioni e passaggi che a lui non interessano (p.es. alcuni aspetti legati all’ambiente di simulazione, azioni, reazioni, ecc.) senza comunque perdere il controllo
4.3. IMPLEMENTAZIONE 49 sulla personalizzazione dei vari nodi relativamente alla loro posizione e alle loro molecole.
Figura 4.7: Diagramma UML strutturale dell’entità ScafiSimulation
4.2.2
Interazione
Il diagramma in figura 4.8 mostra la sequenza di azioni che avvengono durante l’esecuzione di un’azione di un nodo, avviate dall’entità Engine di Alchemist. Si sono riportati solamente le entità strettamente connesse al lavoro effettuato ovvero al punto di unione fra i due sottosistemi. Da notare che in questo primo approccio di integrazione si è scelto di salvare localmente a ogni nodo il risultato della propria computazione in tal modo ogni nodo al momento della preparazione del context per reperire i risultati delle computazioni di tutti i vicini è sufficiente che reperisca per mezzo dell’Environment i nodi del proprio vicinato dai quali ottenere poi il relativo oggetto Export.
4.3
Implementazione
Anche in questa integrazione, grazie alla svolgimento di un’accurata fase di progettazione, l’implementazione è risultata piuttosto immediata . Si
Figura 4.8: Diagramma UML d’interazione della fase progettuale
riportano in questa sezione alcune note riguardanti il linguaggio utilizzato, qualche demo effettuata al fine di assicurarsi del corretto funzionamento del sistema ed infine si riporta un test sulle performance e la scalabilità, confrontando poi i risultati ottenuti con l’incarnazione di protelis.
4.3.1
Cenni implementativi
Data l’analogia con la precedente integrazione e i vantaggi riscontrati grazie all’utilizzo di scala [17], si è mantenuto anche per questo sviluppo tale
4.3. IMPLEMENTAZIONE 51 linguaggio come tecnologia di programmazione, usufruendo sempre della sua sintassi espressiva e concisa. Per sottolineare queste caratteristiche si riporta di seguito il codice scala inerente alla costruzione dell’oggetto Context.
val ctx = new ContextImpl(
selfId = ""+node.getId,
neighbours = nbr.map(n => ""+n.getId).toSet, exports = { var nbrExp = nbr .filter(n => n.asInstanceOf[ScafiNode].getExport != null) .map(n => ""+n.getId -> n.asInstanceOf[ScafiNode].getExport).toMap if(node.asInstanceOf[ScafiNode].getExport != null){ nbrExp + (""+node.getId -> node.asInstanceOf[ScafiNode].getExport) }else{ nbrExp } }, localSensor = node.getContents .map(sv => sv._1.asInstanceOf[ScafiMolecule].getName -> sv._2),
nbrSensor = Map("nbrRange" -> (nbr .map(n => ""+n.getId ->
env.getDistanceBetweenNodes(node, n)) .toMap + (""+node.getId -> 0.0))))
In questa integrazione però, non si è usufruito del suo supporto all’ere- ditarietà multipla nella realizzazione del pattern adapter : più precisamente l’adapter estende solo da una delle due entità da interfacciare, l’altra viene instanziata al suo interno attraverso un meccanismo basato sulla reflection. Come già riportato nelle sezioni precedenti questa scelta è dovuta al mante- nimento di una certa uniformità con le metodologie adottate nel simulatore alchemist.
di utilizzo, in quanto è sufficiente definire una nuova classe che estende da ExecutionTemplate implementando solamente il metodo main con il comportamento desiderato e passare il nome di questa classe al costruttore dell’adapter ScafiProgram.
4.3.2
Validazione
Per validare il sistema ottenuto si sono effettuate alcune simulazioni, ognuna delle quali si basa su una rete di nodi costituita da una griglia bidimensionale, dove ogni nodo occupa una posizione casuale all’interno della sua specifica cella; questo garantisce una configurazione del sistema diversa per ogni simulazione. Nell’immagine 4.9 riportata di seguito, viene mostrato un esempio di queste reti con i relativi collegamenti di vicinato per ogni nodo.
Figura 4.9: Rete di nodi con i relativi collegamenti di vicinato Le simulazioni sono state eseguite avvalendosi della GUI SingleRunGUI grazie alla quale si è potuto appurare, anche se solo qualitativamente, del loro corretto funzionamento. Si sono provati diversi programmi aggregati,
4.3. IMPLEMENTAZIONE 53 ad esempio il calcolo del numero dei propri vicini, il calcolo della distanza fra due dispositivi oppure il calcolo del gradiente. Si riporta di seguito qualche snapshot effettuato durante una simulazione relativa al calcolo del gradiente in cui la sorgente è posizionata nel nodo nell’angolo in basso a sinistra. Nell’immagine 4.10 si riprende il sistema al tempo di simulazione 8 durante la sua fase transitoria iniziale, dove ancora ai nodi più lontanti dalla sorgente non si è propagata l’informazione per poter computare il proprio valore.
Figura 4.10: Snapshot 1 della simulazione del calcolo del gradiente Lo snapshot in figura 4.11 scattato al tempo di simulazione 16 è relativo invece al sistema a regime, ovvero quando si è stabilizzato, in particolare in questa immagine l’effetto di colori prodotto dalla GUI mette in evidenza il corretto funzionamento della simulazione, in quanto l’intensità del colore che è inversamente proporzionale al valore del gradiente diminuisce con l’allontanarsi dalla sorgente.
Un altro test di validazione concluso con esito positivo è stato eseguito confrontando i valori del gradiente computati da ogni nodo fra una simula-
Figura 4.11: Snapshot 2 della simulazione del calcolo del gradiente
zione effettuata con questa incarnazione in scafi e una con l’incarnazione in protelis, di cui si è certi del corretto funzionamento.
4.3.3
Test di performance
Infine si sono sviluppati due test di performance che mettono a confronto il framework scafi con protelis. Questi test sono stati svolti su una macchina con due processori da 2.53GHz.
Confronto variando la cardinalità del vicinato Il primo test è ba-
sato sul programma aggregato relativo al calcolo del gradiente, l’idea è quella di fissare un determinato tempo di simulazione (100) e confrontare i tempi di esecuzione impiegati da entrambe le piattaforme per compiere una simulazione di tale lunghezza. Ovviamente entrambe le simulazioni sono svolte sulla medesima configurazione della rete dei nodi, dove ognuno di essi viene disposto in maniera casuale in una griglia di dimensioni 20 x 20. Tale
4.3. IMPLEMENTAZIONE 55 confronto viene ripetuto per diverse cardinalità del vicinato dei nodi, in modo da avere delle informazioni circa la scalabilità delle due piattaforme.
Si riporta nell’immagine 4.12 un grafico a barre riassuntivo dei risultati ottenuti.
Figura 4.12: Confronto tra scafi e protelis al variare della cardinalità del vicinato dei nodi
Dal grafico si nota che per un numero di vicini circa pari a 8 le due piattaforme si equivalgono, aumentando considerevolmente il numero dei vicini fino a 40 possiamo notare che per entrambe non vi è stato un grosso aumento di tempo impiegato, quindi con questo aumento di vicini sia Scafi che Protelis presentano una buona scalabilità, con un piccolo vantaggio di Protelis di circa 2 secondi. Raddoppiando il numero dei vicini, quindi da 40 a 80, viene invece raddoppiato anche il tempo impiegato dalle piattaforme, da notare però che la differenza tra le due è rimasta di circa 2 secondi, questo significa che a fronte di tale aumento della cardinalità dei vicini Scafi e Protelis hanno scalato esattamente nello stesso modo.
Confronto variando la complessità dell’espressione da computare Questo secondo test è sempre incentrato sul voler calcolare il tempo im- piegato per l’esecuzione di una simulazione di una determinata lunghezza (100) utilizzando le due piattaforme; il test è sempre basato su più coppie di simulazioni di Scafi e Protelis, tenendo fisso però, a differenza del primo test, la cardinalità del vicinato e variando la dimensione dell’espressione che queste due piattaforme dovranno computare ad ogni reazione del simulatore. Più precisamente si è fissato il numero dei vicini circa pari a 12 per ogni nodo e l’espressione da computare è costituita dalla somma del calcolo di un numero ("n") di gradienti preimpostato.
Si riporta nell’immagine 4.12 un grafico a barre riassuntivo dei risultati ottenuti anche per questo test.
Figura 4.13: Confronto tra scafi e protelis al variare della complessità dell’espressione da computare
Sin da subito tale diagramma mette in evidenza una maggior scalabilità da parte del linguaggio scafi: fino al calcolo e la relativa somma di 10 gradienti per ogni reazione i due linguaggi si equivalgono, ma già con un
4.3. IMPLEMENTAZIONE 57 valore di "n" pari a 50 si nota che la piattaforma scafi ottiene un vantaggio di circa 2 minuti, fino ad un vantaggio di circa 7 minuti con "n" pari a 100.
Tuttavia i test riportati sono piuttosto indicativi in quanto entram- be le piattaforme sono in continua evoluzione e quindi soggette a future ottimizzazioni.
Capitolo 5
Esecuzione di Scafi in Android
5.1
Introduzione
Le applicazioni Android sono di solito sviluppate utilizzando il linguaggio di programmazione Java e Android Software Development Kit (Android SDK ). Il codice del programma viene compilato in bytecode java e successivamente tradotto nel così detto bytecode Dalvik (specifico formato di Android) per poi essere eseguito sul dispositivo tramite Android Runtime (ART).
Nonostante java è l’unico linguaggio ufficialmente supportato e docu- mentato per la creazione di applicazioni SDK, l’implicita compatibilità di Android con il bytecode java apre la porta a una varietà di altre tecnologie Java Virtual Machine (JVM). Infatti, ogni linguaggio di programmazione JVM che è in grado di usufruire della API Java può essere usato come un’alternativa a quest’ultimo.
Il linguaggio di programmazione scala è una delle importanti tecnologie JVM che soddisfa tali requisiti. Questo linguaggio copre la maggior parte delle caratteristiche java e aggiunge una serie di funzionalità molto utili, come ad esempio: l’inferenza dei tipi, paradigma di programmazione fun- zionale, impliciti e traits (miglioramento delle interfacce Java) giusto per citarne alcuni.
Nella restante parte di questo breve capitolo vengono riportati i prerequi- siti per poter sviluppare con scala su android, alcuni possibili modi volti alla creazione della configurazione necessaria allo sviluppo di un’applicazione
scala e infine si riportano tutti i passaggi volti alla creazione dell’ambiente nel quale si è effettuato un test di esecuzione del framework scafi unitamente a qualche cenno implementativo.