UNIVERSITÀ DI PISA Facoltà di Scienze, Matematiche, Fisiche e Naturali Corso di Laurea Specialistica in Informatica Tesi di Laurea Studio ed implementazione di un algoritmo per generare i prodotti validi in Product Family Engineering Relatore Candidato Prof.ssa Stefania Gnesi Aldi Sulova Relatore Dott. Franco Mazzanti Anno Accademico 2010/2011 Alla mia famiglia... Sommario Questo lavoro di tesi si colloca all'interno dell'attività di ricerca svolta presso il gruppo di metodi formali dell'ISTI al CNR di Pisa. I temi principali sono la Product Family Engineering (PFE) ed il Model Checking. Più specicatamente mi sono occupato dell'implementazione di un algoritmo che genera i prodotti validi a partire da un modello astratto di una famiglia di prodotti. Inoltre, è stato realizzato un ambiente che presenta le seguenti funzionalità: 1) descrivere il modello di una famiglia mediante una sintassi ben denita, 2) esprimere vincoli statici e comportamentali sulle funzionalità dei prodotti, 3) generare i prodotti validi, 4) vericare formalmente proprietà sul modello della famiglia e sui singoli prodotti. Il contributo principale e più signicativo è stato nel punto 3, cosa che ha dato il titolo anche a questa tesi. Per realizzare gli obbiettivi il lavoro si è focalizzato sull'attività di ricerca eseguita dal gruppo di metodi formali nell'ambito del PFE, e sull'utilizzo di FMC, un model checker con logica branching basata su azioni (ACTL), per reti di automi deniti come algebra dei processi in un formalismo CCS-like. Come risultato nale è ottenuta una applicazione a linea di comando accessibile anche mediante una più elaborata interfaccia web. ii Indice 1 2 Introduzione 1 1.1 Contributo della tesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Sintesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Product Family Engineering 6 2.1 Ingengneria del Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.2 Product Family Engineering . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.3 La variabilità . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3 Model Checking 12 3.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.2 Modelli formali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.3 Logica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.4 Model checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4 Attività di ricerca 25 4.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 4.2 Esempio della macchina del caè . . . . . . . . . . . . . . . . . . . . . . . 26 4.3 Feature Modelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 iii 4.4 Logica deontica e Feature Models . . . . . . . . . . . . . . . . . . . . . . . 28 4.5 Modal Transition System . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.6 MHML, logica temporale in Product Families . . . . . . . . . . . . . . . . 34 4.7 Proprietà statiche e comportamentali in MHML . . . . . . . . . . . . . . . 37 5 Generazione dei prodotti validi di una famiglia 39 5.1 Il modello di una famiglia . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5.2 Algoritmo per generare i prodotti validi . . . . . . . . . . . . . . . . . . . . 41 5.3 Implementazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 5.4 Prodotti validi della macchina per caè . . . . . . . . . . . . . . . . . . . . 57 5.5 Validità di una sottofamiglia oppure di un prodotto . . . . . . . . . . . . . 57 5.6 Osservazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6 Interfaccia Web 61 6.1 Denire il modello della famiglia . . . . . . . . . . . . . . . . . . . . . . . . 61 6.2 Verica di proprietà con VMC . . . . . . . . . . . . . . . . . . . . . . . . . 66 7 Conclusioni e lavoro futuro 69 iv Elenco delle gure 3.1 Modelli per una macchina da caè . . . . . . . . . . . . . . . . . . . . . . . 16 3.2 Signicato degli operatori temporali in LTL . . . . . . . . . . . . . . . . . 18 3.3 Esempi di predicati in CTL . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.4 Operatori temporali in HML . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.1 Feature Diagram per la famiglia di macchine da caè . . . . . . . . . . . . 28 4.2 MTS per la macchina da caè . . . . . . . . . . . . . . . . . . . . . . . . . 32 5.1 Passo dell'algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5.2 Generazione delle combinazioni. . . . . . . . . . . . . . . . . . . . . . . . . 55 5.3 LTS della macchina da caè per il mercato europeo . . . . . . . . . . . . . 57 5.4 LTS della macchina da caè per il mercato statunitense . . . . . . . . . . . 58 5.5 a alternative b, perché non posso tener i prodotti intermedi in MTS . . . . 60 6.1 VMC, pagina iniziale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 6.2 VMC, scegliere il modello . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 6.3 VMC, descivere il modello . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 6.4 VMC, modello caricato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 6.5 VMC, lista prodotti validi della famiglia . . . . . . . . . . . . . . . . . . . 64 6.6 VMC, LTS di un prodotto . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 v 6.7 VMC, MTS della famiglia . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 6.8 VMC, vericare proprietà sulla famiglia . . . . . . . . . . . . . . . . . . . . 67 6.9 VMC, vericare proprietà sui prodotti . . . . . . . . . . . . . . . . . . . . 68 vi Capitolo 1 Introduzione I sistemi software sono sempre più complessi, questo fa si che le aziende si orientino verso le cosiddette Product Family. Una Software Product Family [14] è una gamma di prodotti che condivide una base comune di funzionalità. Diversi modelli si ottengono estendendo il prodotto base con caratteristiche aggiuntive per, ad esempio, soddisfare una particolare tipologia di clienti oppure soddisfare mercati di paesi dierenti. Possiamo distinguere due parti in una famiglia, la parte condivisa e la parte estendibile. La parte estendibile viene riferita nel campo con il termine variabilità , e rappresenta quelle funzionalità che sono usate per costruire diversi prodotti della famiglia. Un formalismo ampiamente utilizzato e al quale si fa riferimento in questa tesi per descrivere una famiglia di prodotti è il Feature Modelling [9]. Nella modellazione della variabilità in Feature Modelling , l'interesse sta nel denire quali funzionalità o componenti di un si- stema siano opzionali oppure necessari e quali siano le relazioni tra loro. Le relazioni vincolanti ed ulteriori proprietà dei prodotti si possono formalizzare mediante una logica proposizionale [15] e vericate utilizzando algoritmi ecienti per trovare un assegnamento che rende vere le formule (SAT Solvers). In questo modo posso stabilire le 1 funzionalità che un prodotto nale deve, non deve, o può avere. Mediante questo procedimento però, non si ha la possibilità di esprimere il comportamento nel tempo dei prodotti e quali caratteristiche nell'evoluzione sono obbligatorie o permesse. Il Modal Transition System (MTS) [8] è riconosciuto come il modello formale per descrivere il comportamento nel tempo delle famiglie di prodotti. Un MTS è simile ad un Labelled Transition System (LTS), ma diversamente dall'LTS le transizioni si presentano in due tipi, must e . Una transizione may must indica che l'azione in essa contenuta è obbligatoria, ovvero che ogni prodotto nale deve avere la possibilità di eseguire l'azione, mentre la transizione may indica che un prodotto nale può anche non avere tale possibilità. Questo formalismo esprime in modo naturale le transizioni che devono essere disponibili in un prodotto e quelle che sono transizioni opzionali per estendere il prodotto. Data una famiglia di prodotti, un singolo MTS permette di denire: • il comportamento della famiglia mediante stati ed azioni comuni a tutti gli prodotti, transizioni must, • la variabilità, ovvero i punti dove il comportamento rende i prodotti estendibili mediante le transizioni may. La logica deontica [3] fornisce un modo naturale per formalizzare concetti come la violazione, obbligo, permesso e divieto. Una logica deontica contiene gli operatori proposizionali logici classici, negazione (¬), congiunzione (∨), disgiunzione (∧), implicazione (⇒) a cui sono aggiunti gli operatori deontici. I due principali operatori deontici sono; è obbligatorio che (O) ed è permesso che (P). Una caratterizzazione deontica di un Feature Model è un insieme di formule deontiche la congiunzione delle quali descrive in modo preciso la famiglia dei prodotti. In [1] si descrive anche una caratterizzazione di un MTS con formule deontiche mediante la logica 2 proposizionale deontica completa denita in [3]. Quello che è importante dire è che a partire da questi studi si hanno le basi per denire MHML. MHML [2][16] è una logica deontica temporale branching basata su azioni ed interpretata su un MTS, con la quale è possibile esprimere concetti di variabilità su una famiglia di prodotti. In confronto con il Feature Modelling, MHML aggiunge la possibilità di specicare ed analizzare nello stesso ambiente proprietà statiche e comportamentali delle famiglie. I concetti di variabilità trattati in questa tesi e che hanno origine nel riguardano le funzionalità opzionali espresse mediante le transizioni Feature Modelling may nell'MTS che descrive la famiglia. In particolare, siamo interessati alla espressione dei seguenti vincoli fra tali funzionalità: • a alternative b, solo una delle due funzionalità è presente; • a requires b, se a è presente nel prodotto nale anche b lo è; • a exclude b, a e b non possono co-esistere nello stesso prodotto; ed alla loro espressione mediante predicati nella logica MHML. Per esempio la formula logica: (EF h ai true) ⇒ (EF h bi true) rappresenta il vincolo h a requires bi. In ogni prodotto della famiglia questa proprietà deve essere valida. In MHML i vincoli che riguardano le funzionalità alternative, exclude e requires si rappresentano con opportune formule, come vedremo più avanti, simili a quella introdotta precedentemente. Una importante operazione in PFE è derivare tutti i prodotti validi di una famiglia. Il contributo principale di questa tesi è lo studio e l'implementazione di un algoritmo che 3 realizza questa operazione. L'algoritmo parte dall'MTS che modella la famiglia e dall'insieme di formule esprimenti vincoli di variabilità denite in MHML. Il risultato della sua esecuzione è una lista di prodotti validi: un prodotto valido è un LTS con tutte le azioni presenti in transizioni must della famiglia, la selezione di qualche azione presente in una transizione may, e che rispetta i vincoli espressi in MHML. 1.1 Contributo della tesi L'obbiettivo principale della tesi è l'implementazione di un algoritmo che genera i prodotti validi a partire da un modello astratto di una famiglia di prodotti. Inoltre, è stato realizzato un ambiente di analisi e verica che permette di: • descrivere il modello di una famiglia di prodotti mediante una sintassi ben denita, • esprimere vincoli statici e comportamentali sulle funzionalità dei prodotti, • generare i prodotti validi, • vericare formalmente proprietà sul modello della famiglia e sui singoli prodotti. Il contributo principale e più signicativo è stato nel punto 3. Per realizzare gli obbiettivi il mio lavoro si è focalizzato sull'attività di ricerca eseguita dal gruppo di metodi formali nell'ambito del PFE [1][2][16][17] , e sull'utilizzo di FMC [12], un model checker con logica branching basata su azioni (ACTL), per reti di automi deniti come algebra dei processi in un formalismo CCS-like. Come risultato nale è ottenuta una applicazione command line accessibile anche mediante una più elaborata interfaccia web. 4 1.2 Sintesi Questa tesi è organizzata come segue. Il Capitolo 2 e 3 orono una presentazione sintetica dei concetti principali della tesi, la Product Family Engineering ed il Model Checking. Nel capitolo 4 viene presentato il lavoro di ricerca sul quale si basa questa tesi. Nel capitolo 5 sono descritte le scelte, le problematiche ed i risultati ottenuti. Il capitolo 6 presenta l'interfaccia web ed un semplice esempio su come si può utilizzare. Nel capitolo 7 le conclusioni e qualche possibile lavoro futuro. 5 Capitolo 2 Product Family Engineering In questo capitolo si presenta la Product Family Engineering [14]. Inizialmente viene introdotto l'ingengneria del software come una disciplina ormai consolidata per assistere un team di sviluppatori nel processo di realizzazione di un sistema software. Il capitolo procede con una breve descrizione della PFE e del contesto nel quale questo approccio ingegneristico del software presenta dei vantaggi. Inne, viene introdotto il concetto principale di questo paradigma che è la variabilità. Gran parte della ricerca sulla PFE si concentra su questo concetto, inoltre, ha un ruolo importante nella mia tesi in quanto l'algoritmo realizzato per generare i prodotti validi della famiglia deve analizzare modelli che esprimono variabilità. 2.1 Ingengneria del Software Il primo calcolatore data negli anni 40 del secolo scorso. Si trattava di un semplice esecutore automatico di istruzioni in grado di elaborare funzioni pre stabilite. Il programma era cablato dentro la macchina e non c'era possibiltà di cambiarlo. Per eseguire altre 6 funzionalità si doveva ricostruire la macchina. In pratica non esisteva la distinzione tra software e hardware. Negli anni 50 vengono in luce i primi linguaggi di programmazione, il linguaggio assembler e successivamente Fortran per calcoli scientici e Cobol per applicazioni gestionali. La tecnologia continuava ad evolversi ma non l'approccio allo sviluppo del software, che si deniva come un processo artigianale dove il programmatore gestiva tutte le fasi: costruzione, manutenzione e utilizzo della applicazione. Negli anni 60 il costo del sviluppo di nuove applicazioni software lievitò drasticamente a seguito di due principali cause: • le richieste dal mercato per funzionalità sempre piu complesse, rese disponibili anche dalle nuove potenzialità di calcolo introdotte da nuovi potenti calcolatori, • la seria dicoltà del programmatore nel gestire individualmente una quantita di lavoro che aumentava di dimensioni. Il risultato era software poco adabile, troppo costoso e che generalmente non rispettava i termini di scadenza. Queste conseguenze implicavano la impossibilità di continuare a vedere il software come un prodotto artigianale creato da una sola persona, ma come una attività che doveva essere svolta in gruppo. Il software doveva diventare il prodotto di un processo ingegneristico, con compiti dierenziati del personale coinvolto e con metodologie di sviluppo ben denite. Il problema della costruzione di un software doveva essere arontato nello stesso modo adottato dagli ingegneri tradizionali per costruire sistemi grandi e complessi come ponti, navi, aeroplani, ecc. L'obbiettivo era quello di stabilire metodologie, strumenti, teorie e tecniche simili a quelle utilizzate in un approccio ingegneristico classico. Possiamo denire l'ingegneria del software come l'applicazione dell'ingegneria al software. Più precisamente, l'IEEE Standard 610.12-1990 Glossario standard della terminologia 7 dell'ingegneria del software(ANSI) denisce l'ingegneria del software come l'applicazione di un approccio sistematico, disciplinato e quanticabile nello sviluppo, funzionamento e manutenzione del software. 2.2 Product Family Engineering La diversità del software richiesto dal mercato ha dato origine allo sviluppo di nuove tecniche ingegneristiche. Naturalmente, particolare interesse si è mostrato per i sistemi software complessi e di grandi dimensioni. Le caratteristiche di questo insieme di prodotti hanno portato gli ingegneri del software a considerare la possibilità del riuso degli artefatti software. Varie tecnologie sono state proposte tra le quali "l'object-oriented system development", "software design patterns" oppure il "component-oriented software development". Il riuso si è quindi trasformato in un concetto chiave nel campo. Questo perchè la sua applicazione porta a miglioramenti in termini di produttività, volta alla: • riduzione dei costi, non si deve rifare tutto dall'inizio; • risposta al mercato, si può avere un prodotto nale in tempi più brevi; • qualità, utilizzo di componenti già utilizzati e vericati. Nel contesto del riuso nasce anche la Product Family Engineering. La PFE è un approccio ingegneristico nel processo di sviluppo software nel quale, i prodotti generati condividono una base comune di funzionalità. L'obbiettivo è quello di denire delle metodologie formali per assistere il team di sviluppo nel riutilizzo delle architetture, codice sorgente, test cases, ecc. ai ni di ridurre i costi ed i tempi di messa ad opera di un prodotto. La PFE ha una visione del riuso diversa dalle tecnologie menzionate precedentemente. Si 8 passa da una visione opportunistica, dove il team di sviluppatori cerca di utilizzare componenti standard oppure componenti deniti in altri progetti, ad una visione pianicata dove il sistema che rappresenta il dominio applicativo viene progettato specicatamente per praticare un ecace riuso di componenti e architetture. Una famiglia di prodotti è una gamma di prodotti che condivide una base comune di funzionalità. Diversi modelli si ottengono congurando il prodotto base con caratteristiche aggiuntive per, ad esempio, soddisfare una particolare tipologia di clienti oppure soddisfare mercati di paesi dierenti. Si può fare l'esempio di una famiglia di software per macchine da caè. Per soddisfare il mercato europeo la macchina deve accettare come moneta l'euro e avere la possibilità di scegliere il cappuccino. La macchina per il mercato statunitense invece, prende come moneta il dollaro e la possibilità di orire il cappuccino non è obbligatoria. I produttore, quindi, deve riprodurre e/o adattare un suo prodotto un numero di volte pari al numero di tutte le varianti individuate. Questo signica di dover gestire n prodotti diversi anche se questi sono estremamente simili tra loro (il caè, il tè, ecc. sono oerte in tutte le macchine). L'economicità della metodologia sta proprio nella gestione del nucleo comune di tutti i prodotti e nel costo ridotto della gestione delle parti dierenti. I vantaggi di questo approccio sono: • analizzare i requisiti per l'intera famiglia e specicare solo le dierenze tra i singoli prodotti invece di descrivere i requisiti per ognuno di questi; • riutilizzo degli artefatti software, si intende parte dell'architettura, documentazione oppure codice sorgente, ovvero un qualsiasi prodotto del processo di sviluppo; • limitare alcuni tipi di analisi costosi relativi alla qualità del software solo sul nucleo. La PFE si compone di due sotto processi relativamente indipendenti tra loro: la domain engineering e la . La application engineering 9 domain engineering si focalizza nell'iden- ticazione degli artefatti software comuni alla famiglia e nell'evidenziazione delle parti variabili che caratterizzano i prodotti. La application engineering si occupa della crea- zione dei prodotti a partire dalla piattaforma creata nella denizione del dominio. Nella specica di un nuovo prodotto vengono scelte le caratteristiche che il nuovo prodotto deve avere oltre alle caratteristiche di base. 2.3 La variabilità Anché il paradigma del PFE abbia successo si devono attentamente valutare le parti comuni e le parti estendibili dei prodotti della famiglia. La parte congurabile è riconosciuta nel campo con il termine variabilità , e rappresenta quegli aspetti che sono usati per costruire diversi prodotti. Un formalismo ampiamente utilizzato e al quale si fa riferimento in questa tesi per descrivere una famiglia di prodotti è il Feature Model. Nella fase della domain engineering il dominio del sistema software viene rappresentato mediante un insieme di funzionalità e ogni prodotto si caratterizza da una opportuna selezione delle medesime. Le features sono classicate nel modo seguente: • optional features, funzionalità opzionali; • mandatory features, funzionalità obbligatorie; Si possono denire anche vincoli tra le funzionalità: • alternative features, un insieme di funzionalità tra le quali solo una è presente. , se a è presente nel prodotto nale anche b lo è; • a require b • a exclude b , a e b non possono co-esistere nello stesso prodotto. 10 Nella denizione della variabilità l'interesse sta nel descrivere quali funzionalità o componenti di un sistema siano opzionali oppure necessari e quali siano le relazioni tra loro. Successivamente, tecniche e strumenti sono stati sviluppati per stabilire se un prodotto fa parte della famiglia, oppure per derivare un prodotto da una famiglia selezionando le funzionalità o gli componenti che si vuole. 11 Capitolo 3 Model Checking In questo capitolo si presenta la tecnica del Model Checking [4]. Una breve introduzione iniziale da una panoramica generale del metodo. Il capitolo procede con la denizione dei modelli formali utilizzati per descrivere un modello di un sistema software, solitamente espresso mediante un sistema di transizioni, cioè grafo orientato formato da nodi e archi. Successivamente si introduce la logica temporale, che consente di formalizzare proprietà relative all'evoluzione nel tempo del sistema. Inne, si presentano i due approcci comunemente utilizzati per scrivere algoritmi di verica che sono il global ed il local model checking. La conoscenza del model checking è necessaria per studiare l'attività di ricerca descritta in dettaglio nel capitolo successivo, dove quest'ultima ha come obiettivo la denizione di un framework logico sul quale si possono esprimere e vericare proprietà su una famiglia di prodotti. Inoltre, per denire in modo corretto la procedura di generazione dei prodotti validi si poteva far riferimento ad algoritmi di model checking, ovvero l'esplorazione dei nodi e degli archi di un sistema di transizioni. 12 3.1 Introduzione La tecnica del model checking, introdotta da Clarke, Emerson [4] e contemporaneamente da Quielle e Sifakis agli inizi degli anni '80, è basata su idee estremamente semplici ed è probabilmente uno dei più signicativi avanzamenti della ricerca in informatica di base di questi ultimi decenni. Nella verica tramite model checking il sistema sotto analisi viene descritto con un linguaggio formale e successivamente modellato mediante un sistema di transizione (Kripke Structure oppure Labelled Transition System). Le proprietà da vericare su di esso sono rappresentate tramite un linguaggio preciso e non ambiguo, tipicamente in logica temporale, e la loro soddisfacibilità sul sistema di transizione che modella il sistema viene vericata in modo eciente ed automatico. Se le proprietà non sono soddisfatte una traccia di esecuzione (controesempio) è mostrata al ne di evidenziare perche si ha il fallimento nella verica. In sintesi la verica tramite model checking consiste, dato un sistema di transizione M modello di un sistema e una formula di logica temporale φ, che rappresenta una proprietà che si desidera che M abbia, nel vericare se M soddisfa φ. 3.2 Modelli formali In generale, il comportamento del sistema software viene rappresentato mediante una struttura a grafo, dove i nodi rappresentano gli stati del sistema e gli archi le transizioni tra gli stati. I gra di per se non sono molto espressivi quindi a loro viene aggiunto dell'informazione. Da qui nascono anche i due approcci comunemente utilizzati per formalizzare una descrizione del sistema nelle prime fasi del processo di sviluppo, che sono; 13 a) Kripke Structure dove i nodi sono annotati con le proposizioni atomiche (AP, atomic propositions) e, b) Labelled Transition System (LTS), sistemi di transizioni etichettati dove gli archi vengono annotati con le azioni. Le due descrizioni sono ampiamente accettate come delle notazioni formali chiare, semplici e sucientemente astratte. . Un Kripke Kripke Structure 1. S Structure K è una tupla K = (S, S0 , R, L, AP) dove: è un insieme nito di stati; 2. S0 ⊆ S è l'insieme degli stati iniziali; 3. R ⊆ S × S è una funzione di transizione totale, ovvero che per ogni stato s ∈ R esiste uno stato s' ∈ R tale che R(s,s') ; 4. L: S → AP 2 è una funzione che associa ogni stato con l'insieme delle proposizioni vere in quel stato. Un cammino nella struttura di Kripke K che parte da uno stato s è una sequenza innita di stati π = s0 s1 s2 ... tale che s = s0 e per ogni i ≥ 0, R(si ,si+1 ). . Un LTS è una tupla L Labelled Transition System 1. S = (S, S0 , Act, →) dove: è un insieme nito di stati; 2. S0 ⊆ S è un l'insieme degli stati iniziali; 3. Act è l'insieme delle azioni; 4. → ⊆ S × Act × S è la funzione di transizione, (s,a,s') a oppure s → − il sistema si muove dallo stato s allo stato s' eseguendo l'azione a. 14 s' descrive che Un cammino in un LTS L che parte da uno stato e transizioni alternati π = s0 a1 s1 a2 s2 ... tale che (si ,ai+1 , s s è una sequenza innita di stati = s 0 , ai ∈ Act e per ogni i ≥ 0, si+1 ) ∈ →. 3.3 Logica Delle proprietà tipiche che si possono vericare su un sistema modellato mediante un Kripke Structure sono: • a partire dallo stato s0 esiste uno stato s' in qualche cammino dove la proposizione logica p è vera, ovvero: ∃ π = s0 s1 ... ed una i ≥ 0 tale che si ∈ π e si (p) = true, • a partire dallo stato s0 si ha un cammino tale che la proposizione logica p è vera su tutti gli stati del cammino. In un LTS una proprietà da vericare può essere: • a partire dallo stato s0 esiste in qualche cammino uno stato s' dove s' → − s , ovvero: b ∃ π = s0 a1 s1 a2 s2 ... ed una i ≥ 0 e ai ∈ Act b tale che si → − si+1 e b ∈ Act. Si può notare come le domande proposte hanno implicitamente il senso del tempo. In un cammino arriverò nel futuro in uno stato con una particolare proprietà (eventually) oppure, tutti gli stati del cammino hanno una qualche proprietà (always). Per logica temporale si intende una logica classica in cui le formule possono essere arricchite da dei quanticatori temporali (always, eventually), anche se questi non hanno alcuna misura esplicita del tempo. La logica predica su variabili di stato della struttura di Kripke oppure sulle azioni di un LTS considerato. Sono interpretate su alberi di computazioni, i cammini possibili di una esecuzione a partire dallo stato iniziale. 15 I due tipi di logiche temporali più comunemente utilizzate sono: branching-time logic linear-time logic e la . La nozione qualitativa del tempo è denita sul cammino. Nella logica linear-time in ogni istante esiste un unico possibile successore e quindi un solo possibile stato futuro. In questo senso il tempo è lineare. Questo modello considera il comportamento del sistema come l'insieme di tutti i possibili cammini da uno stato particolare. Un predicato φ è valido se lo è per ogni computazione dell'insieme. Nella logica branching la nozione del tempo non è lineare bensì ha una struttura ad albero, ad ogni istante esiste un insieme di possibili stati successori. Le computazioni sono raggruppate in alberi computazionali le cui ramicazioni rappresentano le diverse possibilità di continuare in una computazione. Una proprietà φ è valida se l'albero di computazione generato da uno stato particolare soddisfa φ. Per rendere più chiari i concetti introdotti prendiamo come esempio due modelli diversi di una macchina da caè. La macchina Figura 3.1: Modelli per una macchina da caè dopo l'inserimento di una moneta può servire il caè oppure il tè. Nel primo modello è il cliente che sceglie la bevanda, nel secondo invece, è la macchina che fa una scelta interna. Tutti a due i modelli hanno lo stesso insieme di computazioni possibili: {(moneta, caè), (moneta, tè)}. Una logica linear-time non sarebbe in grando di distinguere tra i due modelli. In una logica branching-time invece posso esprimere la proprietà: è possibile scegliere un caè dopo aver inserito una moneta. Tale proprietà distingue i due modelli 16 di una macchina per caè. In seguito vengono introdotte la LTL (Linear Temporal Logic) e la CTL (Computation Tree Logic), logiche linear-time e branching-time rispettivamente e che vengono interpretate su un Kripke Structure. Inoltre, sono introdote anche la ACTL (Action-Based Computation Logic) e la Hennessy Milner Logic, logiche interpretate su un LTS. . La logica LTL consente di predicare formule senza alcuna consi- Linear Temporal Logic derazione della struttura ad albero dei cammini eettuati dal sistema nella sua evoluzione dallo stato scelto. Nel vericare la validità di una proprietà devo considerare tutte le possibili computazioni uno ad uno. La formule nella logica LTL sono denite come segue: φ ::= p | ¬φ | φ1 ∨ φ2 | X(φ) | U (φ1 , φ2 ) | F (φ) | G(φ) Le formule sono interpretate sui cammini di un Kripke Structure K = (S, S0 , R, I, AP). Un cammino nito è una sequenza nita, non vuota π = hs0 ...sn−1 i di stati s0 , ..., sn−1 ∈ S tale che (si , si+1 ) ∈ R per ogni 0 ≤ i < n − 1. n viene chiamata la lunghezza del cammino, e si denota con |π|. Un path innito è una innita sequenza π = hs0 , s1 , s2 ...i di stati in S tale che (si , si+1 ) ∈ R per ogni i ≥ 0. La lunghezza di un cammino innito è ∞. Per 0 ≤ i < |π|, πi denota l'i-esimo stato nel cammino π , mentre π i = hsi , si+1 , ...i è la coda del cammino che inizia in si . In particolare, s0 = π . Sia K = (S, R, L) un Kripke Structure e sia π un cammino in K, la relazione |= è denita induttivamente come: • π |= p sse p ∈ L(π0 ) • π |= ¬φ sse π 6|= φ 17 • π |= φ1 ∨ φ2 sse π |= s1 oppure π |= φ2 • π |= X(φ) sse |π| > 1 e π 1 |= φ • π |= G(φ) sse per ogni k con 0 ≤ k < |π|, sk |= ϕ • π |= F (φ) sse esiste k, 0 ≤ k < |π|, con sk |= ϕ • π |= U (φ, ϕ) sse esiste k, 0 ≤ k < |π|, con sk |= ϕ e per ogni i, 0 ≤ i < k, si |= φ L'operatore temporale X(φ) stabilisce se φ è valido oppure no nel prossimo stato del cammino; G(φ) se φ è valido in tutti gli stati del cammino; F(φ) se prima o poi (in qualche stato nel futuro) φ vale; U(φ, ψ ) se ψ diventera vero in uno stato e φ è vero in tutti gli stati visitati precedentemente. Il signicato degli operatori temporali è mostrato nella gura 3.2. Una struttura di Kripke K in uno stato s ∈ S soddisfa la formula φ (K, s |= φ) Figura 3.2: Signicato degli operatori temporali in LTL se tutti i cammini di K che partono da s soddisfano φ. Computation Tree Logic . Le formule in CTL consentono di predicare sulla struttura ad albero delle possibili computazioni che partono da un determinato stato iniziale. Arrivato in un particolare stato che verica la proprietà p la sua struttura ad albero verica la proprietà q. Cioè si possono esprimere proprietà della forma; per ogni cammino da 18 uno stato iniziale s si puo trovare nel futuro uno stato s' tale che la proprietà q vale nel sottoalbero delle computazioni che iniziano in s'. Si può notare come le proprietà riguardano non solo il cammino ma anche un particolare stato nel cammino. Le formule in CTL sono divise in formule di stato (state formula) e in formule di cammino (path formula). Le formule di stato sono aermazioni sul valore di una proposizione atomica in uno stato scelto oppure sulla struttura ad albero delle computazioni che partono da questo stato. Le path formula sono formule sui cammini che partono da uno stato. Per specicare queste proprietà vengono introdotti gli operatori di quanticazione universale ed esistenziale. Formalmente: Formule di Stato: φ ::= true | p | φ1 ∨ φ2 | ¬φ | ∃ϕ | ∀ϕ per p proprietà atomica e ϕ una formula di cammino. Formule di cammino: ϕ ::= X(φ) | U (φ1 , φ2 ) | F (φ) | G(φ) dove φ, φ1 , φ2 sono state formula. La gura 3.3 illustra il signicato degli operatori temporali. Sia K = (R, S, L) un Kripke Structure e sia s ∈ S uno stato qualunque. La relazione |= è denita nel modo seguente: • K, s |= p sse p ∈ L(s) • K, s |= ¬φ sse K, s 6|= φ • K, s |= φ1 ∨ φ2 sse K, s |= φ1 oppure K, s |= φ2 • K, s |= Aϕ sse K, s |= ϕ per ogni cammino π di K che inizia in s • K, s |= Eϕ sse K, s |= ϕ per qualche cammino π di K che inizia in 19 s Figura 3.3: Esempi di predicati in CTL Gli operatori temporali X, G, F, U sono deniti in maniera uguale come per la logica lineare. . E una logica temporale branching il cui dominio di interpretazione Hennessy-Milner Logic è il Labelled Transition System. Le formule sono denite come segue: φ ::= true | f alse | φ1 ∧ φ2 | φ1 ∨ φ2 | [a]φ | haiφ dove a ∈ Act. La logica viene interpretata su un LTS. Sia L = (S, Act, −→), la relazione |= viene denita induttivamente, • L, s |= true sse L, s 6|= f alse • L, s |= φ1 ∧ φ2 sse L, s |= φ1 e L, s |= φ2 • L, s |= φ1 ∨ φ2 sse L, s |= φ1 oppure L, s |= φ2 • L, s |= [a]φ sse per ogni a tale che s → − s0 , s0 |= φ a 20 • L, s |= haiφ sse esiste a tale che s → − s0 e s0 |= φ a Il potere espressivo di questa logica è limitato. Si possono esprimere proprietà di una lunghezza nita nell'albero delle computazioni, proprietà che garantiscono il funzionamento per n volte ma non per sempre. La gura 3.4 illustra il signicato degli operatori temporali. Figura 3.4: Operatori temporali in HML Action-based Computation Tree Logic . Come HML anche nella logica ACTL il dominio di interpretazione è il LTS. Gli operatori temporali sono gli stessi con quelli deniti in CTL, solo che in ACTL le proprietà da vericare riguardano le azioni che deniscono il sistema. La sintassi delle formule è denita nel modo seguente: Formule di azioni: χ ::= true | f alse | a ∈ Act | ¬χ | χ ∨ χ | χ ∧ χ Formule di stato: φ ::= true | f alse | φ1 ∨ φ2 | φ1 ∧ φ2 | Aϕ | Eϕ Formule di cammino: ϕ ::= Xχ (φ) | φ1 χU φ2 | φ1 χU χ0 φ2 La logica mantiene la struttura della logica denita in [5]. Comunque non è dicile denire gli operatori temporali G ed F da quelli presenti. Valgono le equivalenze: • Fχ φ = true{true} Uχ φ • Gχ φ = ¬Fχ ¬φ 21 La relazione |= per le formule di azione è denita come segue: • a |= b se e solo se a = b; • a |= χ se e solo se a 6|= χ; • a |= χ ∧ χ0 se e solo se a |= χ e a |= χ0 . La semantica degli operatori ACTL si denisce come: sia L = (S, Act, →) • L, s |= true sempre valido • L, s |= φ1 ∧ φ2 sse L, s |= φ1 e L, s |= φ2 • L, π |= Xχ φ sse |π| > 1 e (s0 , a, s1 ) ∈→ e a |= χ e s1 |= φ • L, π |= φχ U φ0 sse esiste i ≥ 1 tale che L, si |= φ0 , e per ogni 1 ≤ j ≤ i−1, L, sj |= φ e (sj , a, sj+1 ) ∈→ e a |= χ • L, π |= φχ U χ0 φ0 sse esiste i ≥ 2 tale che L, si |= φ0 e (si−1 , a, si ) ∈→ e a |= χ0 , e per ogni 1 ≤ j ≤ i − 1, L, sj |= φ e (sj−1 , b, sj ) ∈→ e b |= χ 3.4 Model checking La verica tramite model checking consiste, dato un sistema di transizione M modello di un sistema e una formula di logica temporale φ, che rappresenta una proprietà che si desidera che M abbia, nel vericare se M soddisfa φ. In letteratura, due sono gli approcci di model-checking maggiormente applicati per vericare la validità di una formula logica; global and local model checking. Un algoritmo globale prima costruisce l'intero spazio degli stati del sistema, successivamente algoritmi di ricerca e di etichettatura vengono applicati per trovare particolari stati in cui la 22 proprietà desiderata vale. Un inconveniente dell'approccio globale è la generazione anche degli stati che non sono rilevanti per dimostrare la formula, specialmente quando lo spazio degli stati da analizzare diventa troppo grande. Nel modello locale (on-the-y model checking ) vengono visitati solo gli stati che sono necessari per dimostrare il valore di verità della formula, espressa rispetto ad un determinato stato iniziale. Un model checker locale può controllare solo una piccola parte della struttura per decidere il problema, la parte che non serve non viene nemmeno costruita. L'algoritmo seguente mostra come viene eettuata l'etichettatura degli stati quando si deve vericare una proprietà della forma E[f1 Algoritmo: U f2 ] in un model checker globale. Procedura per etichettare gli stati con formule della forma EU f1 , f2 T := {s | f2 ∈ lable(s) }; for all s ∈ T do label(s) := label(s) ∪ { E[f1 U f2 ]}; Input: end for while T 6= ∅ do choose s ∈ T ; T := T \ {s}; for all t tale che R(t, s) do if E[f1 U f2 ] 6∈ label(t) e f1 ∈ label(t) then label(t) := label(t) ∪ {E[f1 U f2 ]}; T := T ∪ {t}; end if end for end while In seguito viene illustrato lo pseudo codice di un algoritmo standard di model checking locale. L'algoritmo si basa su una visita breadth-rst oppure depth-rst del sistema di transizione. 23 Algoritmo: Procedura per vericare le formule in un model checker locale F:Formula ,E:ENV, S:State caso base: true, false, F = p e p ∈ AP then return il risultato Input: if else salva l'informazione che sto valutando la formula F nello stato S facendo riferimento all'ambiente E (per esempio, inserisci (F,E,S) in una pila) for all sub-formula F' di F, con S' lo stato successivo ad S, l'ambiente E' aggiornato in S' do chiama ricorsivamente (F', E', S'); if il risultato di (F', E', S') è suciente per stabilire il risultato di (F, E, S) then esci dal ciclo for; end if end for A questo punto abbiamo un risultato. Rimuovi (F, E, S) dalla pila. return il risultato end if L'algoritmo realizzato per generare i prodotti validi e che viene descritto in dettaglio nel capitolo 5, è simile ad un algoritmo di model checking locale. Viene esplorato lo spazio degli stati mantenendo informazione su quello che si è visto no allo stato corrente. La parte alla quale si fa più riferimento è la gestione dell'ambiente da passare al prossimo passo nell'algoritmo. 24 Capitolo 4 Attività di ricerca In questo capitolo si presenta il lavoro teorico realizzato dal gruppo dei metodi formali del CNR di Pisa [1][2][16][17]. Viene descrito il framework logico creato e su come questo è utilizzato per esprimere: a) un modello di una famiglia di prodotti e, b) variabilità statica e comportamentale. Inizialmente si introduce il Feature Modelling [9], un formalismo ampiamente utilizato per descrivere una famiglia di prodotti. Successivamente si descrive la logica deontica [3] e si mostrano le sue capacità di caratterizzare un Feature Model , creando le basi per un struttura logica sulla quale esprimere proprietà delle famiglie. Con l'introduzione anche del Modal Transition System [8], formalismo capace di descrivere in modo naturale il comportamento di una famiglia, si ha il supporto teorico necessario per denire MHML [2][16]. MHML è una logica deontica temporale branching basata su azioni, interpretata su un MTS, per esprimere in una famiglia di prodotti concetti di variabilità. In confronto con il Feature Modelling, MHML aggiunge la possibilità di specicare nello stesso framework anche proprietà comportamentali delle famiglie di prodotti. 25 4.1 Introduzione Una famiglia è un insieme di prodotti che condividono una base comune di funzionalità. Diversi modelli si ottengono estendendo il prodotto base con caratteristiche aggiuntive per soddisfare una particolare tipologia di clienti oppure per soddisfare mercati di paesi digerenti. Quindi possiamo distinguere due parti in una famiglia, la parte condivisa e la parte estendibile. La parte estendibile viene riferita nel campo con il termine tà variabili- , e rappresenta quei aspetti che sono usati per costruire diversi prodotti della famiglia. La modellazione della variabilità è stata ampiamente studiata in letteratura, soprattutto quella relativa al Feature Modelling (sezione 4.3). In questo formalismo l'interesse nella modellazione della variabilità sta nel denire quali funzionalità o componenti di un sistema siano opzionali oppure necessari e quali siano le relazioni tra loro. Successivamente, tecniche e strumenti sono stati sviluppati per stabilire se un prodotto fa parte della famiglia, oppure per derivare un prodotto da una famiglia selezionando le funzionalità o i componenti che si vuole. 4.2 Esempio della macchina del caè Per rendere più chiaro il contenuto di questo capitolo prendiamo un semplice esempio di una famiglia di macchine per caè. Le seguenti regole caratterizzano i prodotti di questa famiglia: 1. La macchina viene attivata da una moneta. Le monete accettate sono quella da un euro (1e) per i prodotti del mercato europeo, e quella da un dollaro (1$) per i prodotti del mercato statunitense. 26 2. Dopo aver inserito una moneta, l'utente deve scegliere se vuole lo zucchero o meno, per poi continuare con la selezione della bevanda. 3. La scelta delle bevanda (caè, tè, cappuccino) dipende dal prodotto. Ogni macchina deve dare la possibilità di scegliere il caè, inoltre la scelta del cappuccino deve essere disponibile solo nelle macchine per il mercato europeo. 4. Dopo aver preparato il caè la macchina può emettere un suono. Il suono ci deve essere dopo la preparazione del cappuccino. 5. La macchina ritorna sul suo stato iniziale non attivo dopo che l'utente ha preso la bevanda. I requisiti 1, 3 e parzialmente anche il 4, sono considerati come aspetti statici della famiglia. Non riguardano il comportamento nel tempo dei prodotti ma semplicemente quelle funzionalità che un prodotto nale può o non può avere. I requisiti 2 e 5 e parzialmente il 4 invece, sono vincoli su quello che deve essere il comportamento dei prodotti validi della famiglia. 4.3 Feature Modelling Un formalismo ampiamente utilizzato per descrivere una famiglia di prodotti è il Feature Modelling. Nella fase del domain engineering (vedi sezione 2.2) il dominio del sistema software viene rappresentato mediante un insieme di funzionalità (feature) e ogni prodotto si caratterizza da una opportuna selezione di quest'ultime. Le feature sono classicate nel modo seguente: • optional feature, funzionalità opzionale, è presente solo se il padre lo è; 27 • mandatory feature, funzionalità obbligatoria, è presente se e solo se il padre lo è; Si possono denire anche vincoli tra le feature: • alternative features, un insieme di funzionalità tra le quali solo una è presente. , se a è presente nel prodotto nale anche b lo è; • a require b • a exclude b , a e b non possono co-esistere nello stesso prodotto. Una rappresentazione graca di un Feature Model è il Feature Diagram; le features sono i nodi di un albero nel quale la famiglia è la radice. Il Feature Diagram della macchina per caè introdotta nel paragrafo 4.2 viene mostrato nella gura 4.1. Figura 4.1: Feature Diagram per la famiglia di macchine da caè 4.4 Logica deontica e Feature Models La logica deontica fornisce un modo naturale per formalizzare concetti come violazione, obbligo, permesso e divieto. Una logica deontica contiene gli operatori proposizionali logici classici, negazione(¬), congiunzione(∧), disgiunzione(∨), implicazione(⇒) ed aggiungendo gli operatori deontici. In questa ricerca sono considerati solo i due principali operatori 28 deontici; è obbligatorio che (O) ed è permesso che (P ). Nelle classiche versioni della logica vale la proprietà duale: P (α) = ¬O(¬α), qualcosa è permessa se e solo se la sua negazione non è obbligatoria. Una caratterizzazione deontica di un Feature Model è un insieme di formule deontiche, la congiunzione delle quali, descrive in modo preciso la famiglia dei prodotti. La costruzione viene denita nel modo seguente: • Se A è una feature e, A1 e A2 sono due sub-feature (alternative, opzionali oppure obbligatorie), allora aggiungi la formula: A =⇒ Φ(A1 , A2 ), dove la formula Φ(A1 , A2 ) vale: Φ(A1 , A2 ) = (O (A1 ) ∨ O (A2 )) ∧ ¬(P (A1 ) ∧ P (A2 )) se A1 e A2 sono marcati come due feature alternativi, altrimenti la formula Φ(A1 , A2 ) vale: Φ(A1 , A2 ) = φ(A1 ) ∧ φ(A2 ), dove Ai , per i ∈ {1,2}, è denita come: P (Ai ), se Ai è opzionale; φ(Ai ) = O(Ai ), se Ai è obbligatorio. • se , allora aggiungi la formula: A requires B 29 A • se =⇒ ( ) O B , allora aggiungi la formula: A excludes B (A =⇒ ¬ P (B )) ∧ (B =⇒ ¬P (A)) Applichiamo la costruzione appena denita all'esempio della macchina del caè introdotta nel paragrafo 4.2. Le formule deontiche risultanti sono: O (Moneta) ∧ O (Bevanda) ∧ P (Suono) Moneta =⇒ (O (1$) ∨ O (1e)) ∧ ¬(P (1$) ∧ P (1e)) Bevanda =⇒ O (Caè) ∧ P (Tè) ∧ P (Cappuccino) Cappuccino =⇒ O (Suono) (1$ =⇒ ¬P (Cappuccino)) ∧ (Cappuccino =⇒ ¬P (1$)) Mediante la caratterizzazione con formule deontiche di un Feature Model posso stabilire se un prodotto appartiene alla famiglia. Prendiamo per esempio le formule denite qui sopra e supponiamo di avere due modelli della macchina da caè: CM1 = {Moneta, 1e, Bevanda, Caè} CM2 = {Moneta, 1e, Bevanda, Caè, Cappuccino} La macchina CM1 soddisfa la caratterizzazione deontica della macchina da caè ed è quindi un prodotto corretto della famiglia. La CM2 non soddisfa le formule deontiche in quanto rende falso il vincolo che dopo aver preparato il cappuccino si deve emettere un suono. L'appartenenza (oppure la non appartenenza) si può vericare formalmente rappresentando queste formule come una lista di assiomi messi in congiunzione. La formula 30 risultante sarà vera se il prodotto appartiene alla famiglia e falsa altrimenti. Il problema di trovare un prodotto che soddisfa la caratterizzazione deontica di un Feature Model si può rappresentare come il problema di trovare un assegnamento che rende vera la congiunzione delle formule (SAT). Algoritmi ecienti per SAT si possono utilizzare per risolvere questi tipi di problemi. Abbiamo dimostrato che la logica deontica è un formalismo che in modo naturale riesce ad esprimere nozioni di permesso ed obbligo, fondamentali nel gestire la variabilità nello sviluppo di Product Families. Si può notare che gli Feature Models esprimono solo gli aspetti statici di una famiglia di prodotti. Per descrivere anche come i prodotti evolvono nel tempo e quali caratteristiche nell'evoluzione sono obbligatorie o permesse, si deve ricorrere ad un formalismo che riesce a descrivere queste particolarità. Uno dei formalismi più utilizzati in questo contesto è il Labelled Transition System (vedi sez. 3.2). Con gli LTSs però, non si ha la possibilità di distinguere tra le azioni possibili e quelle necessarie, per questo che vengono introdotti gli Modal Transition Systems. 4.5 Modal Transition System Il Modal Transition System (MTS) è riconosciuto come il modello formale per esprimere il comportamento nel tempo delle famiglie dei prodotti. Un MTS è un LTS dove le transizioni sono di due tipi, must e . Una transizione may must indica che l'azione in essa contenuta è obbligatoria, ovvero che ogni prodotto nale deve avere la possibilità di eseguire l'azione, mentre la transizione may indica che un prodotto nale può anche non avere tale possibilità. Questo formalismo esprime in modo naturale le transizioni che devono essere disponibili in un prodotto e quelle che sono transizioni opzionali da aggiungere al prodotto. Data una famiglia di prodotti un singolo MTS permette di denire: 31 • il comportamento della famiglia mediante stati ed azioni comuni a tutti gli prodotti, transizioni must, • la variabilità, ovvero i punti dove il comportamento rende i prodotti congurabili, mediante gli transizioni may. . Un MTS è una quintupla (Q, A, q0 , δ , δ ♦ ), e ha due relazioni di Modal Transition System transizione distinte: δ ⊆ Q×A×Q è la relazione may che esprime le transizioni possibili, δ ♦ ⊆ Q × A × Q è la relazione must che stabilisce chi sono le transizioni obbligatorie. Per denizione una transizione obbligatoria è anche permessa, δ ⊆ δ ♦ . L'MTS per la macchina da caè dell'esempio introdotto nel paragrafo 1 è visualizzato nella gura 4.2. Le transizioni may sono rappresentate da frecce tratteggiate mentre quelle must da frecce solide. Figura 4.2: MTS per la macchina da caè a i+1 . Sia M un MTS, σ è una must path (da q0 ) in M se qi −− → qi+1 , per ogni Cammino must 32 i ≥ 0. L'insieme di tutti i cammini must M da q0 si denota con -path(q0 ). Un cammino si denota con σ . Famiglie di un MTS di must . Sia M = (Q, A, q0 , δ ♦ , δ ) un MTS. L'insieme delle famiglie possibili si possono rappresentare mediante gli MTSs {Mi dove preso Ri insieme delle transizioni trasformate da δi ⊆ δ ∪ Ri . Gli stati Qi sono un sottoinsieme di Q = (Qi , A, may a must q0 , δi♦ , δi ) | i ≥ 0 }, , si ha δi♦ ⊆ δ ♦ \ Ri e (Qi ⊆ Q) tale che q0 ∈ Qi , e per ogni q ∈ Qi esiste un cammino da q0 in q con transizioni in δi♦ ∪ δi . Formalmente: Mi è una sottofamiglia di M con Ri insieme di transizioni may trasformati in must, Mi ` M , se e solo se vale qi 0 ` q0 , dove qi ` q , per qualche qi ∈ Qi e q ∈ Q vale se e solo se: − i qi0 e • se q → − q 0 , per qualche q 0 ∈ Q, allora ∃qi0 ∈ Qi tale che qi → a a qi0 ` q 0 e, • se q → − ♦ q 0 denita in Ri , per qualche q 0 ∈ Q, allora ∃qi0 ∈ Qi tale che a qi → − i qi0 e qi0 ` q 0 e, a • se qi → − ♦i qi0 denita in δ ♦ \ Ri , per qualche qi0 ∈ Qi , allora ∃q 0 ∈ Q tale che a q→ − ♦ q 0 e qi0 ` q 0 . a Si può notare che quando δi♦ = ∅ le transizioni dell'MTS risultante sono tutti must . In questo caso l'MTS è equivalente ad un LTS dove le transizioni sono tutte obbligatorie e non si distingue tra must e may. Nella sezione 4.4 abbiamo mostrato le capacità della logica deontica a modellare una famiglia di prodotti, descrivendo una trasformazione da un Feature Model in una congiunzione di formule logiche. In questa sezione abbiamo introdotto il Modal Transition System come formalismo che riesce ad esprimere in maniera naturale il comportamento di 33 una famiglia di prodotti. In [1] viene descritto come caratterizzare un MTS con formule deontiche mediante la logica proposizionale deontica completa denita in [3]. Si rimanda alla lettura degli articoli per approfondire il procedimento. Quello che è importante dire è che a partire da questi studi si hanno le basi per denire un framework logico per esprimere proprietà statiche e comportamentali sulle famiglie di prodotti. Il risultato è una nuova logica temporale con operatori modali deontici che vengono interpretati in maniera naturale in un MTS. 4.6 MHML, logica temporale in Product Families MHML è una logica temporale branching basata su azioni simile alla logica Henessy-Milner con Until[5], aggiungendo anche il quanticatore esistenziale ed universale da CTL. Il suo dominio di interpretazione è un MTS. MHML è composta da formule di stato φ, formule dei cammini π e formule di azioni ϕ (vedi sezione 3.3, action-based logic) deniti su un insieme di azioni atomiche Act . ={a, b, ...} La sintassi della logica MHML è denita come segue: State Formula: φ ::= true | ¬φ | φ ∧ φ0 | haiφ | [a]φ | Eπ | Aπ Path Formula: π ::= φ{ϕ}U {ϕ0 }φ0 | φ{ϕ}U {ϕ0 }φ0 Action Formula: ϕ := true | f alse | a ∈ Act | ¬ϕ | ϕ0 ∨ ϕ00 | ϕ0 ∧ ϕ00 Il fatto che MHML viene interpretata su un MTS fa si che le classiche modalita box e diamond, abbiano una interpretazione deontica. Il signicato non formale degli operatori di MHML è come segue: • haiφ: esiste uno stato, raggiungibile da una transizione must(a) con a ∈ Act dove φ è valida, 34 • [a]φ: in tutti gli stati, raggiungibili da una transizione must(a) oppure may(a) con a ∈ Act, φ è valida, • Eπ : esiste un camino nel quale π è valida, • Aπ : in tutti i camini, π e valida, • φ{ϕ} U {ϕ0 }φ0 : esiste uno stato nel cammino raggiungibile da una azione che sod- disfa ϕ0 dove φ0 è valida e φ vale in tutti gli stati precedenti a questo stato nel cammino, le azioni nel cammino soddisfano ϕ; • φ{ϕ} U {ϕ0 }φ0 : come sopra, ma in questo caso il cammino che porta allo stato in futuro dove φ0 vale è un cammino must. La semantica formale di MHML viene interpretata in un MTS. Sia (Q, A, q0 , → , →♦ ) una MTS, sia q ∈ Q e sia σ un cammino. La relazione di soddisfacibilità di MHML è denita da: • q |= true, sempre valida • q |= ¬φ, se e solo se 6 q |= φ • q |= φ ∧ φ0 se e solo se q |= φ e q |= φ0 • q |= haiφ se e solo se ∃q 0 ∈ Q : q → − q 0 e q 0 |= φ a • q |= [a]φ se e solo se ∀q 0 ∈ Q: q → − ♦ q 0 , vale q 0 |= φ a • q |= Eπ se e solo se ∃σ 0 ∈ path(q) : σ 0 |= π • q |= Aπ se e solo se ∀σ 0 ∈ path(q) : σ 0 |= π 35 • q |= φ {ϕ} U {ϕ0 } φ0 se e solo se ∃j ≥ 1 : σ(j) |= φ0 , σ{j} |= φ0 e σ(j + 1) |= φ0 , e ∀i, 1 ≤ i ≤ j : σ(i) |= φ e σ{i} |= φ • q |= φ {ϕ} U {ϕ0 } φ se e solo se σ è un cammino must σ e σ |= φ {ϕ} U {ϕ0 }φ0 La regola della dualità in Henessy-Milner, la quale stabilisce che haiφ è equivalente a ¬[a]¬φ, non vale in MHML. La ¬[a]¬φ corrisponde ad una versione piu debole dell'ope- ratore classico diamond e che viene denotata con P (a)φ: esiste uno stato, raggiungibile da una transizione may(a) con a ∈ Act e φ valida. Formalmente, sia (Q, A, q0 , → , →♦ ) un MTS, sia q ∈ Q, allora: • q |= haiφ se e solo se ∃q 0 ∈ Q : q → − ♦ q 0 e q 0 |= φ. a Una esempio di una formula ben denita in MHML è: [a](P (b) true ∧ (φ =⇒ hci true)), dopo l'esecuzione di una azione a, il sistema si trova in uno stato nel quale: 1) è permesso eseguire l'azione b (una transizione may(b)) e, 2) quando la formula φ è valida allora l'esecuzione di c è obligatoria(una transizione must(c)). Altri operatori logici si possono derivare da quelli sopra deniti: false (¬ F φ è equivalente a true ), φ ∨ φ0 a ¬ (¬φ ∧ ¬φ0 ) e φ ⇒ φ0 a ¬φ ∨ φ0 . (true {true } U {true } φ), esiste uno stato nel futuro dove φ vale. valente a (true {true } U {ϕ} true F è equivalente a {ϕ} true è equi- ), esiste uno stato nel futuro raggiungibile da una transizione che soddisfa ϕ. F è equivalente a (true {true } U {true } φ), esiste uno stato nel futuro raggiungibile da un cammino must dove φ vale. AG φ è equivalente a ¬EF ¬φ, in tutti gli stati di tutti i cammini φ vale. AG φ è equivalente a ¬ EF ¬φ, in tutti gli stati di tutti i cammini must, φ vale. 36 4.7 Proprietà statiche e comportamentali in MHML MHML arricchisce la descrizione comportamentale di un MTS con ulteriori concetti di variabilità. Questo viene realizzato aggiungendo vincoli sulle azioni che compongono i prodotti di una famiglia. Mediante MHML si possono denire proprietà statiche e comportamentali che un MTS non riesce ad esprimere. Tornando all'esempio della macchina del caè i requisiti si possono formalizzare con le seguenti formule. Per la parte statica: • Le azioni 1e e 1$ sono alternativi (1e alternative 1$), requisito 1. ((EF h1ei true) ∨ (EF h1$i true)) ∧ ¬ ((EF P (1e) true) ∧ (EF P (1$) true)) • Il cappuccino non deve essere disponibile in prodotti per il mercato statunitense (cappuccino excludes 1$), seconda parte del requisito 3. ((EF P (cappuccino) true) =⇒ (AG ¬ P (1$) true)) ∧ ((EF P (1$) true) =⇒ (AG ¬ P (cappuccino) true)) • Le macchine che orono il cappuccino devono emettere un suono (cappuccino requires suono), requisito 4. (EF P (cappuccino) true) =⇒ (EF h suonoi true) Il requisito 2 rappresenta un vincolo sul comportamento dei prodotti della famiglia. Un caè non si può consegnare se non si è inserito la moneta prima. In MHML si può denire con la formula seguente: 37 A [ true {¬caè} U {1e ∨ 1$} true] L'applicazione delle formule divide la famiglia originale in sottofamiglie. Le sottofamiglie sono degli MTSs con le transizioni must , qualche may cambiato in must e le rimanenti transizioni may dell'MTS iniziale (vedi denizione dell'MTS nella sezione 4.5). Ad esempio la formula che esprime il vincolo h1e alternative 1$i crea due sottofamiglie. Nella prima rimuovo la transizione s0 −dollar −−→ s1 e modico l'altra transizione uscente dallo stato s0 , s0 −−→ s1 , da may a must. Si procede in modo simile anche per la seconda sottofamieuro glia e si può notare che la formula esprimente il vincolo entrambi i casi. 38 alternative addesso è valida per Capitolo 5 Generazione dei prodotti validi di una famiglia In questo capitolo si presenta il lavoro eseguito. Inizialmente si descrive un modello testuale per denire una famiglia di prodotti. Successivamente viene introdoto l'algoritmo per generare i prodotti validi e vengono descritte le principali procedure implementate. Il risultato nale è uno modulo nel linguaggio di programmazione Ada [10] [11] aggiunto al model checker FMC [12] per includere su questo la procedura di generazione. 5.1 Il modello di una famiglia Come abbiamo denito nel capitolo precedente una famiglia di prodotti è un MTS più una serie di vincoli espressi nella logica temporale MHML. Per rappresentare un MTS è suciente l'utilizzo dell'operatore di ricorsione e dell'operatore della scelta non deterministica oltre ad una chiara distinzione tra i due tipi d'archi. Nella macchina del caè per esempio lo stato iniziale viene modellato come: 39 T0 = may(1e).T1 + may(1$).T1 L'interpretazione è abbastanza intuitiva, nello stato T0 ho due scelte possibili che sono permesse ma non obbligatorie. Per denire i vincoli invece, sono utilizzate le parole chiave ALT, EXC e REQ che rappresentano le formule dei vincoli alternative, exclude e requires rispettivamente. L'esempio della macchina del caè mediante questo formalismo si può denire nel modo seguente: Modello della macchina da caè T0 = may(dollar).T1 + may(euro).T1 T1 = must(sugar).T2 + must(no_sugar).T3 T2 = must(coee).T4 + may(tea).T5 + may(cappuccino).T6 T3 = may(cappuccino).T7 + may(tea).T8 + must(coee).T9 T4 = must(pour_sugar).T9 T5 = must(pour_sugar).T7 T6 = must(pour_sugar).T7 T7 = must(pour_coee).T10 T8 = must(pour_tea).T11 T9 = must(pour_coee).T11 T10= must(pour_milk).T11 T11= may(no_ring).T12 + may(ring_a_tone).T12 T12= must(cup_taken).T0 net SYS = T0 Constraints { dollar ALT euro dollar EXC cappuccino cappuccino REQ ringatone } Un semplice confronto con FMC penso che sia necessario. L'MTS che descrive il comportamento della famiglia si può denire mediante un'algebra di processi sequenziali in un formalismo CCS-like, quest'ultima è anche la sintassi utilizzata per descrivere i modelli in FMC. Il processo a.P esegue l'azione a per poi comportarsi come il processo P. Nello 40 stesso modo un prodotto dell'MTS può eseguire l'azione euro nello stato T0 per spostarsi successivamente nello stato T1 e comportarsi come se T1 fosse lo stato iniziale. Si può notare anche la sintassi utilizzata per distinguere le azioni must da azioni may, costrutti che in FMC si deniscono come "typed actions". 5.2 Algoritmo per generare i prodotti validi Inizio questo paragrafo con una osservazione. Per implementare l'algoritmo si possono seguire due approcci di base, quello globale oppure quello locale. Nell'approccio globale inizialmente vengono generate tutte le famiglie dell'MTS e successivamente vericata la validità delle formule che rappresentano i vincoli. Da notare che questo modello introduce ridondanza, nel senso che sottofamiglie oppure prodotti vengono valutati molte volte perchè presenti in una sottofamiglia già valutata. Nell'approccio locale invece, ogni volta che aggiungo un arco verico le formule. Risulta più eciente in una situazione dove la famiglia si presenta con un numero abbastanza grande di archi may e vincoli tra loro. Questo perchè posso tagliare interi sottoalberi a causa della non soddisfazione di qualche vincolo. Nell'approccio locale però, tenere gli archi may in prodotti intermedi è complicato come sarà descritto nella sezione 5.6. In quanto siamo interessati alla generazione dei prodotti nali penso che la scelta ottimale sia quella di generare i prodotti nali di un MTS seguendo l'approccio locale. In questa sezione viene descritto un algoritmo per generare i prodotti validi di una famiglia. Un prodotto valido nale è un LTS dove gli archi sono tutti obbligatori e non esiste la distinzione fatta per MTS nel quale gli archi sono di due tipi, archi possibili e archi obbligatori. L'algoritmo parte dall'MTS che modella la famiglia e dall'insieme di formule espresse in MHML. Il risultato è un sottoinsieme dei prodotti possibili di un MTS (vedi 41 denizione delle famiglie di un MTS, sezione 4.5); un elemento di questo sottoinsieme è un LTS con tutte le azioni presenti in una transizione must, qualche azione presente nelle transizioni may e che rispetta i vincoli espressi in MHML. L'idea dell'algoritmo è di costruire LTSs intermedi che sono i prodotti dell'MTS seguendo la logica sopra descritta e che sono composti dalle azioni e dagli stati no ad uno particolare stato della famiglia. Prendiamo l'esempio dell'MTS della macchina per caè mostrato in gura 5.1, dallo stato iniziale ho 4 possibili LTSs intermedi: Figura 5.1: Passo dell'algoritmo Un passo generale dell'algoritmo viene denito come: aggiungi ad un LTS intermedio un arco dell'MTS iniziale e verica le formule che esprimono i vincoli alternative ed exclude, continuando solo con gli LTSs che soddisfano le formule. Quando non è più possibile eseguire altri passi perchè abbiamo analizzato tutti gli stati e tutti gli archi dell'MTS, esegui la verica nale delle formule dei vincoli La verica nale della formula del vincolo alternative alternative (vedi in seguito) e . requires è necessaria in quanto l'algoritmo in un passo intermedio verica semplicemente che nell'LTS non siano presenti entrambi gli operandi della formula ma non che almeno uno di questi sia presente. In questo senso è necessario eseguire la verica nale in modo da selezionare quei prodotti nali dove almeno uno dei operandi ci sia. Consideriamo la proprietà: 1e e 1$ sono alternativi. L'algoritmo prende uno ad uno le situazioni illustrate nella gura 5.1. Per ognuna di queste verica la validità della formula che esprime il vincolo alternative : (EF h1$i true ∨ EF h1ei true) ∧ ¬(EF 42 P(1$) true ∧ EF P(1e) true) Qui si deve fare una precisazione. Le formule sono interpretate su un MTS e quindi il procedimento sopra introdotto è sensato se diciamo che un prodotto valido, ovvero l'LTS, in realtà è un MTS dove le transizioni sono tutte must. Se si considera l'LTS come dominio dell'interpretazione delle formule allora si deve utilizzare una logica simile a MHML ma senza l'interpretazione deontica degli operatori box e diamond. La formula si trasforma in: (EF h1$i true ∨ EF h1ei true) ∧ ¬(EF h1$i true ∧ EF h1ei true) All'inizio di questo lavoro si pensava ad un algoritmo che poteva generare anche le sottofamiglie valide, ma questo è complicato come sarà descritto in dettaglio nella sezione 5.6. Quindi per esprimere i vincoli è suciente una logica simile ad MHML ma senza l'interpretazione deontica degli operatori box e diamond, osservazione presa in considerazione anche in [6]. Ritornando all'esempio, per ognuno degli LTSs intermedi si può dire che l'algoritmo continuerà a procedere in avanti solo nei casi (ii) ed (iii). In questo modo si garantisce che negli LTSs nali almeno una delle due azioni in relazione è presente. Riassumendo, il problema si può specicare come: data una MTS M ed un insieme Φ di vincoli sulle azioni, espressi mediante formule φi in MHML per i ≥ 0, derivare un insieme P di LTSs Lj , per qualche j ≥ 0, tale che per ogni t ≥ 0 e t ≤ j , Pt ` M e Pt |= φi per ogni i ≥ 0. . Un passo di generazione generate(M,p,L,q) si applica ad uno stato Passo di generazione p dell'MTS M e ad uno stato q di un LTS L intermedio. In particolare, q è una foglia non visitata prima (non ci sono archi in uscita). I possibili eetti dell'applicazione di un passo generate(M,p,L,q) sono: 43 • si aggiunge uno stato q' ed un arco q → − q' all'LTS L in corrispondenza ad uno stato a p' a e ad un arco p → − p' dell'MTS M, • come sopra ma si aggiunge solo l'arco in quanto lo stato q' dell'LTS L risulta visitato in un passo precedente, • si crea una copia L' di L se q contiene archi may in uscita, esegue i passi 1) e/o 2) ed aggiunge L' nell'insieme degli LTSs intermedi, • si marca q come visitato a causa della applicazione di una delle prime due regole qui sopra, • si aggiorna l'insieme D dei passi di generazione di L che l'algoritmo deve eseguire successivamente, da notare che ogni LTS intermedio ha il suo insieme D di passi di generazione. Prima di introdurre l'algoritmo faccio due considerazioni. La prima riguarda gli archi must e may. Per semplicità, quando si parla di un arco may non sono inclusi gli archi must, diversamente da come abbiamo denito l'MTS nella sezione 4.5. La seconda riguarda le formule. L'inisieme Φ contiene le formule dei vincoli exlude ed alternative mentre ΦREQ contiene solo la formula del vincolo requires. Algoritmo di generazione . L'algoritmo inizia con la MTS M , l'insieme delle formule Φ ed un ambiente di lavoro P = {L}. L'insieme dei passi di generazione D di L inizialmente contiene solo generate(M, q0 , L, q0 ) e L solo lo stato iniziale q0 di M . L'algoritmo esegue un passo di generazione da un qualche D, no a quando tutti gli D non sono vuoti. Un passo di generazione generate(M, p, L, q) a 1. Per ogni arco must(a), p → − p0 , in M : 44 è denito nel modo seguente: a (a) se p = p', aggiungi l'arco q → − q a L, (b) se lo stato p0 è stato visitato in qualche passo di generazione generate(M,p',L,q') b oppure è stato aggiunto nel passo corrente da un arco p → − p0 , allora aggiungi a l'arco q → − q 0 a L; (c) altrimenti aggiungi uno stato q' a e una nuovo arco q → − q 0 a L, e aggiungi il passo di generazione generate(M,p',L,q') a D ; (d) inne, marca q come visitato e per ogni formula φ ∈ Φ \ ΦREQ dove l'azione a occorre, verica se L |= φ. Se L 6|= φ, rimuovi L dall'ambiente di lavoro P ; 2. Per tutti gli archi may(a1 ) ... may(an ) an 1 , p −a→ →♦ pn , in M, il passo 1) deve ♦ p1 ... p − essere ripetuto per ogni combinazione degli archi, ovvero per ogni Act ⊆ a1 ...an : (a) aggiungi una copia LAct di L nell'ambiente di lavoro P, a (b) per ogni arco may p → − ♦ pj in M dove 1 ≤ j ≤ n e tale che aj ∈ Act: aj • se pj = p, aggiungi un arco q − → q in LAct : • se pj risulta visitato in un passo di generazione generate(M,pj ,L,q') prece- b b dente oppure nel gestire un arco della forma p → − ♦ pj oppure p → − pj nel a passo di generazione corrente, allora aggiungi un arco q → − q 0 a LAct : aj • altrimenti, aggiungi uno nuovo stato q 0 ed un arco q − → q 0 a LAct ed aggiungi il passo generate(M, pj , LAct , q 0 ) all'insieme D di LAct (c) marca q come visitato e per ogni formula φ ∈ Φ \ ΦREQ dove occorre un azione che sta in Act, verica se L |= φ. Se L 6|= φ, rimuovi L dall'ambiente di lavoro P ; Quando non sarà più possibile eseguire un passo di generazione perché nessuna delle liste D di qualche L che sta in P ne contiene, l'algoritmo verica se per ogni prodotto LTS 45 in P valgono le formule esprimenti i vincoli φ ∈ ΦREQ ∪ ALT verica se L requires |= φ. Se per qualche L e alternative ∈ P . Ovvero, ∀ L in P e la formula φ non vale, L 6|= φ, allora L viene rimosso dall'ambiente di lavoro P. Quando l'algoritmo termina P contiene un insieme di LTSs che rappresentano i prodotti validi della famiglia. 5.3 Implementazione Il modulo per generare i prodotti validi viene aggiunto al model checker FMC ed è implementato nel linguaggio di programmazione Ada. Ada è un linguaggio di programmazione general-purpose e unisce in un'unica soluzione principi e tecniche provenienti da diversi paradigmi di programmazione, in particolare programmazione modulare, programmazione orientata agli oggetti, programmazione concorrente e programmazione distribuita. Un programma in Ada è composto da unità di . Un'unità può essere: programmazione • un sottoprogramma, nella forma di una funzione oppure di una procedura; • un package, i sottoprogrammi e tipi di dato che hanno una relazione logica tra loro possono essere raggruppati in un package; • un task , attività che può essere realizzata in concorrenza con altre, simile ad un package, a dierenza dei package viene specicato il comportamento in relazione con gli altri task ; • un'unità generica, forma parametrica di package o di programma. Un programma Ada completo è concepito come una procedura con un nome appropriato, costituente essa stessa un'unità di programma e che richiama funzionalità rese disponibili 46 da altre unità di programma. Le unità utilizzate possono essere dei sottoprogrammi ma è piu probabile che siano pacchetti applicativi (packages). Un pacchetto applicativo è costituito da un gruppo di argomenti correlati che possono rappresentare sia altri pacchetti sia dei sottoprogrammi. Ogni pacchetto applicativo si compone di due parti, l'interfaccia e l'implementazione. L'interfaccia denisce la parte di specica, contiene l'informazione su quali sono le funzionalità e i tipi di dato visibili ad altre unità, ha l'estensione .ads . L'implementazione (il body) è la parte che realizza l'interfaccia e di solito non è visibile ad altre unità; ha l'estensione .adb. In questo paragrafo sono descritte le unità create e il loro ruolo nella realizzazione dell'algoritmo introdotto nel paragrafo precedente. Il codice è organizzato nelle seguenti unità di programmazione Ada: • ProductFamily_Types.ads , la specica dei tipi, strutture dati, funzioni e procedure; denisce l'interfaccia dei sottoprogrammi utilizzati nell'algoritmo di generazione. • ProductFamily_Types.adb , implementazione della specica, realizzazione delle pro- cedure e delle funzioni. Riorganizza i sottoprogrammi correlati ragruppandoli in tre nuovi paccheti, ProductFamily_FormulaVerify, ProdutFamily_Congurations, ProdutFamily_Derivations e ProdutFamily_Combinations . Dichiara la struttura dei nuovi pacchetti e, mediante la parola chiave separate, indica che l'implementazione della unità si trova nel le con il rispettivo nome e l'estensione .adb ; • ProdutFamily_FormulaVerify.adb FormulaVerify l'implementazione del pacchetto ProdutFamily_- denito nel modulo ProductFamily_Types.adb, realizza le procedure per vericare negli LTSs intermedi la validità delle formule esprimenti i vincoli. Osservazione. Per eseguire le veriche si poteva procedere in due modi. Nel primo si interfacciava il codice dell'algoritmo di generazione con quello del model checker 47 FMC. FMC è organizzato in due pacchetti principali, nel primo sono denite le strutture dati che contengono il modello (l'MTS nel nostro caso) e nel secondo le procedure per vericare la validità delle formule. Quindi, in riferimento ai punti 1.d), 2.c) e verica nale dell'algoritmo, si poteva caricare il modello e vericare le formule chiamando procedure del codice di FMC. Questa scelta è molto dipendente dal codice di FMC e in più, analizzando la struttura delle formule che rappresentano i vincoli si può capire che la verica si può realizzare in modo alternativo, semplicemente tenendo un array delle azioni presenti nelle transizioni che compongono l'LTS intermedio. Quando all'LTS si aggiunge una transizione in riferimento ai punti 1.a), 1.b), 1.c) e 2.b), basta controllare se l'azione in essa contenuta compare in qualche vincolo, e se questo è vero, controllare che l'altra azione nella relazione vincolante sia (o non sia) presente nell'array. Abbiamo scelto la seconda modalità. Il pseudocodice introdotto più avanti in questa sezione da una descrizione dettagliata dell'approccio seguito. • ProdutFamily_Congurations.adb , realizza le procedure necessarie per esplorare gli stati e le transizioni del modello della famiglia di prodotti descritta mediante un MTS; • ProductFamily_Derivations.adb , realizza le procedure per gestire i passi di genera- zione; • ProductFamily_Combinations.adb , realizza le procedure per creare le combinazioni delle azioni che compaiono in transizioni ritmo di generazione; 48 may come descritto nel passo 2 dell'algo- • ProductFamily.adb , il main dell'algoritmo di generazione. Questo modulo mette assieme tutte le procedure denite nei moduli descritti qui sopra. Continuo questo capitolo cercando di descrivere in linea di massima le strutture dati e le procedure principali, facendo riferimento all'algoritmo del paragrafo precedente per rendere più chiaro il signicato del codice. ProductFamily_Types.ads . È il pacchetto dove sono deniti i tipi di dato, le funzioni e le procedure necessarie per implementare l'algoritmo. I tipi di dato piu signicativi sono quelli che rappresentano il passo di generazione e l'LTS intermedio. Tipo di dato: Il tipo generate generate is record state: Positive tempLTS : Positive type end record Il record generate a dierenza del passo "generate" denito nell'algoritmo del paragrafo precedente, contiene solo lo stato q e l'LTS intermedio. L'MTS M e lo stato p dell'MTS non servono. Questo perchè M è la stessa per tutta l'esecuzione dell'algoritmo e gli stati p e q rappresentano lo stesso stato sia nel modello M che nell'LTS intermedio. Nella descrizione del paragrafo precedente sono introdotte per rendere più chiaro l'approccio seguito. Il seguente codice presenta il tipo che modella un LTS: 49 Tipo di dato: Il tipo LTS LTS is record valid_product:is_valid_product := VALID seen_Table: Bool_Array_Ref generate_list: Generate_Container.Vector lts_actions : array_of_actions_ref lts_labels: String_Container.Vector type end record Il campo valid_product stabilisce se l'LTS intermedio è un prodotto valido oppure no. La rimozione di un LTS non valido dall'ambiente P, in riferimento ai passi 1.d), 1.c) e verica nale, viene eseguita cambiando il valore di questo campo in "NON_VALID". Dopo la terminazione dell'esecuzione dell'algoritmo si possono consultare anche i prodotti non validi e quali transizioni hanno causato la loro non validità. Il campo seen_table tiene informazione su quali stati sono visitati. Si riferiscono ai passi 1.d) e 2.c) dell'algoritmo di generazione. Il campo generate_list contiene i passi di generazione che devono ancora essere eseguiti dall'algoritmo; lts_actions contiene le azioni dell'LTS intermedio nella forma target, source, label ; in questo modo si può costruire il modello che rappresenta l'LTS. Inne, lts_labels contiene le etichette delle azioni presenti in questo LTS. Quest'ultime servono per vericare la validità delle formule. Un altro compito importante di questo pacchetto è realizzare la connessione con il codice di FMC. Per utilizzare le funzionalità delle unità di programma di FMC si inserisce la riga: package MyCongurations is new Congurations il signicato del quale è che le funzionalità sotto il pacchetto Congurations di FMC sono disponibili nell'unita di programma che realizza l'algoritmo di generazione. Si tratta principalmente di tipi, strutture dati e funzioni per recuperare e contenere il modello della famiglia di prodotti espressa in MTS. 50 ProductFamily_Congurations.adb . Realizza una procedura, la BreadthFirstExplore, per esplorare gli stati e le transizioni del modello MTS. Come descritto sopra posso utilizzare le funzionalità rese disponibili dal pacchetto Congurations di FMC. In particolare, una struttura dati che contiene il modello MTS della famiglia di prodotti. Analizzando questa struttura dati posso recuperare gli stati e le transizioni e inserirli in un array più semplice Transitions che contiene le transizioni, dove ogni transizione è un record con tre campi; source, target e label . Il codice della procedura dipende da strutture dati e funzionalità disponibili nel pacchetto Congurations, per questo motivo non viene mostrato. ProductFamily_Derivations.adb . Ogni LTS intermedio contiene una lista di passi di ge- nerazione. Gli LTSs intermedi sono inseriti nell'array lts_list denito nell'unità ProductFamily.adb . A causa della verica del passo 2.a) la lista aumenta di un LTS intermedio. L'algoritmo in questo caso continua con il recupero dei passi "generate" dell'LTS corrente. Mediante questo ragionamento la procedura successivo da elaborare. 51 Get_Next_Derive() restituisce il passo Algoritmo: Recupero delle generate lts_list Output: has_next_generate, generate 1: exit := false 2: while not exit do 3: if lts_list(lts_index).derives is Empty then 4: lts_index := lts_index + 1 Input: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: else generate := lts_list(lts_index).generates.FirstElement remove lts_list(lts_index).generates.FirstElement from generates exit := true has_next_generate := true end if if lts_list.length < lts_index then exit := true has_next_generate := false end if end while ProductFamily_FormulaVerify.adb . Il tipo di dato LTS contiene il campo lts_label. Que- sto campo è un array di etichette che specicano quali sono le azioni che compongono l'LTS intermedio. In questo modo si ha tutta l'informazione necessaria per vericare la validità delle formule. Le procedure denite in questo pacchetto fanno riferimento ai punti 1.d), 2.c) e alla verica nale delle formule esprimenti i vincoli requires e alternative nell'algoritmo di generazione. Le tre procedure per la verica delle formule sono descritte in seguito. 1) Il signicato intodotto dalle formule dei vincoli alternative ed exclude è lo stesso con l'unica dierenza che uno dei due operandi in alternative deve essere presente nel prodotto nale. La procedura descritta in seguito realizza la verica della formula del vincolo exclude e della prima parte della formula del vincolo alternative (nel senso che sarà riva- lutato nella parte nale dell'algoritmo). La procedura prende in input l'azione che è stata aggiunta a causa di uno dei passi 1.b) e 1.c) e le etichette dell'LTS in esame. Per i casi 2.b) 52 e 2.d) l'algoritmo è un po piu complicato perché in questi casi le azioni da aggiungere sono più di uno. Siccome la base è la stessa per tutti e due le situazioni descrivo la struttura solo per i casi 1.b) e 1.c) che è la seguente: Algoritmo: Verica del vincolo exclude e (parziale) di alternative current_action, current_lts_labels true, false for i in Constraints do if Constraints(i) is ALT or EXC then if una delle azioni in Constraints(i) è uguale alla current_action then verica che current_lts_label non contenga l'altra azione nella relazione vincolante return false se esiste Input: Output: 1: 2: 3: 4: 5: 6: 7: 8: 9: 2) end if end if end for return true Verica nale della formula del vincolo alternative. Una delle due azioni che la formula mette in relazione deve essere presente nel prodotto nale. Algoritmo: Verica della del vincolo alternative per i prodotti nali current_lts_labels true, false for i in Constraints do if Constraints(i) is ALT then for j in lts_labels do if una delle azioni in Constraints(i) è uguale alla lts_labels(j) then Input: Output: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 3) return true end if end for end if end for return false Verica della formula del vincolo . L'algoritmo verica che il primo operando requires della formula è presente nella lts_labels e solo quando questo è vero, verica la presenza nella lts_labels del secondo operando. 53 Algoritmo: Verica del vincolo requires per i prodotti nali current_lts_labels Output: true, false 1: for i in Constraints do 2: if Constraints(i) is REQ then 3: for j in lts_labels do 4: if la prima azione nella relazione vincolante Constraints(i) è uguale alla lts_labels(j) then 5: for k in lts_labels do 6: if la seconda azione nella relazione vincolante Constraints(i) è uguale all lts_labels(k) then 7: return true; Input: 8: 9: 10: 11: 12: 13: 14: end if end for end if end for end if end for return false ProductFamily_Combinations.adb . In questo pacchetto sono denite le procedure ne- cessarie per generare l'insieme delle parti di un insieme di etichette. Questo modulo si riferisce al punto 2 dell'algoritmo di generazione. Nel punto 2 si richiede di generare le combinazioni delle azioni che compaiono in transizioni may uscenti dallo stato in esame (si ricordi generate(L,q) ) e di vericare che i nuovi LTSs intermedi, ai quali si aggiungono queste azioni sono nelle condizioni di diventare prodotti validi. Questo modulo ha due procedure; la InitializeCombinations(may_actions) e la Get_Next_Comb(). La prima crea l'insieme delle parti a partire da una lista di azioni. È un procedimento iterativo sulla lista delle azioni dove per ogni azione viene creata una lista di insiemi a partire da insiemi creati nei passi precedenti ed aggiungendo l'azione corrente. La gura 5.2 illustra il risultato dell'applicazione della procedura ad un insieme di 3 elementi. Get_Next_Comb() , restituisce il prossimo insieme considerando la struttura degli array mostrata nella gura 5.2. 54 Figura 5.2: Generazione delle combinazioni. ProductFamily.adb . Questo è il modulo principale dell'algoritmo di generazione. Contiene la logica dell'algoritmo presentato nel paragrafo precedente. Il pseudocodice dell'algoritmo è il seguente: Algoritmo per generare i prodotti validi di una famiglia Algoritmo: Modello testuale della famiglia di prodotti. Insieme di LTSs che rappresentano prodotti validi. LoadModel; . carica il modello BreadthFirstExplore; . esplora la MTS e crea l'array delle azioni while has_next_generate do get_next_generate(has_next_generate, current_generate) get_out_actions(current_generate.state); . le transizioni in uscita dallo stato nella generate corrente for i in out_actions do if out_actions(i) è una must action then isVeried := Verify_Formula(out_actions(i), current_generate.tempLTS).actions) if not isVeried then Delete_LTS(lts_list , current_generate.tempLTS) Input: Output: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: else lts_list(current_generate.tempLTS).lts_labels.Append(out_actions(i).label); lts_list(current_generate.tempLTS).lts_actions.Append(out_actions(i)); end if else may_actions.Append(out_actions(i)) end if end for 55 . out_actions(i) è una transizione may Algoritmo: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: Algoritmo per generare i prodotti validi di una famiglia (continua) Initialize_Combinations(may_actions) while has_next_comb do get_next_comb(current_combination_actions,has_next_comb) isVeried := Verify_Formula(current_combinations_actions, lts_list(current_generate.tempLTS).lts_actions); if not isVeried then Delete_LTS(lts_list , current_generate.tempLTS) else . crea una coppia della LTS e aggiuingi le nuove azioni create new_lts; crea una coppia lts_list(current_generate.tempLTS) in new_lts; lts_list(current_generate.tempLTS).lts_actions.Append(may_actions(i)); lts_list(current_generate.tempLTS).lts_labels.Append(may_actions(i).label); agggiungi new_lts in lts_list; end if end while end while for . Verica nale delle formule REQ e ALT(parziale) i in lts_list do if not Verify_ALT_Formula(lts_list(I).lts_labels) then Delete_LTS(lts_list(I)); end if ; if not Verify_REQ_Formula(lts_list(I).lts_labels) then Delete_LTS(lts_list(I)); end if ; end for Il codice descritto ha prodotto un le eseguibile che introduco solo a scopo illustrativo in quanto la procedura di generazione è più signicativa se si mette in relazione con le capacità di FMC di vericare proprietà espressse in formule logiche (vedi capitolo 6). Prendiamo il modello testuale della macchina da caè del paragrafo 5.2 ed eseguiamo l'algoritmo. > ProductFamily m_cae.txt 56 Nella directory corrente vengono create due cartelle. La prima ha il nome "ValidProducts" e contiene i prodotti validi della famiglia, mentre la cartella "NonValidProducts" contiene i prodotti non validi e le azioni che hanno causato la non validità. 5.4 Prodotti validi della macchina per caè Le gure 5.3 e 5.4 mostrano due modelli di macchina per caè, risultanti dall'esecuzione dell'algoritmo di generazione sull'esempio introdotto nel paragrafo 2 di questo capitolo. Figura 5.3: LTS della macchina da caè per il mercato europeo 5.5 Validità di una sottofamiglia oppure di un prodotto Stabilire se un prodotto oppure una sottofamiglia fa parte della famiglia originale può essere una operazione molto utile in Product Family Engineering. Una sottofamiglia oppure un prodotto è un MTS dove ho cambiato alcune transizioni dell'MTS della famiglia 57 Figura 5.4: LTS della macchina da caè per il mercato statunitense iniziale da may a must e ho selezionate qualche may (vedi la denizione delle famiglie di un MTS, sezione 4.5). Successivamente viene applicato l'algoritmo di generazione e analizzata la lista dei prodotti validi risultanti. Se la lista è vuota signica che il prodotto oppure la sottofamiglia non è corretta rispetto ai vincoli espressi nella logica MHML. 5.6 Osservazioni L'algoritmo viene realizzato in un modello on-the-y, nel senso che non sono costruiti esplicitamente tutti gli LTSs possibili dell'MTS per poi vericare le formule, ma ogni volta che una azione viene aggiunta all'LTS intermedio si procede con la verica delle formule. Se una delle formule non vale allora l'LTS viene rimosso dall'ambiente di lavoro P e non può diventare un prodotto valido della famiglia. La complessità nel tempo dipende dai passi di generazione. In totale, in un modello senza vincoli sulle azioni, il numero totale dei passi generate è 58 archi(must) × 2archi(may) Se dobbiamo aggiungere anche i vincoli allora la complessità nel tempo dell'algoritmo è O(archi(must) × 2archi(may) × k) dove k rappresenta il tempo necessario per vericare la validità delle formule (sezione 5.3, ProductFamily_FormulaVerify ). Comunque, in un modello con un numero abbastanza grande di vincoli tale limite è decisamente più contenuto. Si poteva fare meglio? Diversi tentativi sono stati eettuati per cercare di ottimizare la complessità in tempo dell'algoritmo. Abbiamo cercato di realizzare un algoritmo dove i prodotti intermedi non erano LTS ma MTS, mantenendo archi may nei prodotti intermedi. In questo modo non si doveva generare tutto lo spazio degli LTS di un ramo dell'MTS originale, quando nessuna delle transizioni del sottoalbero era inclusa in qualche relazione vincolante. Così si poteva ridurre la complessità mantenendo sottofamiglie invece di singoli prodotti. In un secondo passo a partire dalle sottofamiglie si potevano derivare i prodotti nali. Comunque, questa operazione non era possibile a causa delle formule che esprimono i vincoli alternative e requires. La formula del vincolo alternative mi dice che una delle due azioni in relazione deve essere per forza nel prodotto nale. Se un'azione in compare nel sottoalbero di una qualche transizione may alternative allora devo cambiare tutto il percorso no alla radice in un cammino must per essere sicuro che l'azione sarà presente in tutti gli prodotti nali. La gura 5.5 mostra la impossibilità di mantenere archi may in prodotti intermedi. Si può notare come non tutti i prodotti dell'MTS in 5.5(ii) sono validi rispetto al vincolo ha alternative bi. 59 Figura 5.5: a alternative b, perché non posso tener i prodotti intermedi in MTS La stessa situazione si presenta anche per azioni presenti in una formula del vincolo . requires 60 Capitolo 6 Interfaccia Web In questo capitolo si presenta una semplice interfaccia web per utilizzare le funzionalità dell'ambiente realizzato. Le operazioni disponibili sono: 1) descrivere il modello di una famiglia di prodotti mediante la sintassi denita nella sezione 5.1, 2) la possibilità di generare i prodotti validi come descritto nelle sezioni 5.2 e 5.3, 3) vericare formalmente proprietà sul modello della famiglia e sui singoli prodotti. Abbiamo chiamato questo ambiente VMC, Variabilty Model Checker [6]. 6.1 Denire il modello della famiglia La pagina web si trova sull'indirizzo: http://fmtlab.isti.cnr.it/vmc/V5.0/vmc.html . La prima pagina che viene visualizzata è la pagina della gura 6.1. Nella parte a sinistra ci sono i comandi che si possono eseguire. Inizialmente è disponibile solo il comando Model Denition... ; selezionandolo il contenuto della pagina cambia, addesso è possibile sceglie- re un esempio predenito oppure di creare un modello nuovo come illustrato nella gura 61 Figura 6.1: VMC, pagina iniziale 6.2. Prendiamo l'esempio della macchina da caè che sta sotto il nome deontic.ccs . La Figura 6.2: VMC, scegliere il modello desrizione testuale del modello viene visualizzata sull'editor di testo nella parte centrale della nestra, gura 6.3. Cliccando sul comando Load Current Model viene caricato il modello testuale della macchina da caè, gura 6.4. Nella parte a sinistra sono visualizzati i 62 Figura 6.3: VMC, descivere il modello nuovi comandi che si possono eseguire sul modello, mentre la parte centrale visualizza le possibili evoluzioni del sistema a partire dallo stato iniziale. Figura 6.4: VMC, modello caricato In seguito viene descritto il signicato dei comandi disponibili dopo che il modello è stato caricato. Il comando New Model... riporta la pagina nella situazione iniziale, descritta 63 dalla gura 6.2, il comando Edit Current Model alla situazione della gura 6.3 ed il comando Explore the MTS riporta la pagina nella situazione attuale, visualizzando le possibili evoluzioni dallo stato iniziale. Con il comando Generate All Products si possono genera- re i prodotti validi della famiglia. Cliccando su questo comando il contenuto dell'editor di testo nella parte centrale della pagina cambia. Vengono listati i prodotti validi della famiglia, vedi gura 6.5. Si può notare che il nome del prodotto è un link ad un'altra Figura 6.5: VMC, lista prodotti validi della famiglia pagina. I prodotti a questo punto sono degli LTSs sui quali si possono eseguire veriche utilizzando la versione base di FMC. Cliccando su uno dei link una nuova pagina si apre come mostrato nella gura 6.6. La struttura della pagina è simile a quella descritta per VMC. Un altra operazione utile è la visualizzazione della MTS mediante archi e nodi. Questo è possibile mediante il comando . Cliccando su questo comando nella View Family MTS parte centrale della pagina viene visualizzata la famiglia gracamente, gli archi must sono frecce non tratteggiate e gli archi may sono frecce tratteggiate. 64 Figura 6.6: VMC, LTS di un prodotto Figura 6.7: VMC, MTS della famiglia 65 6.2 Verica di proprietà con VMC VMC è un ambiente dove si può descrivere testualmente una famiglia di prodotti e successivamente si possono vericare proprietà espresse in una logica temporale. Fa parte di una serie di model checker sviluppati preso ISTI-CNR e che comprendono anche FMC, UMC e CMC [13]. Le proprietà da vericare vengono espresse in formule scritte nella logica SocL [7], una logica temporale branching basata su stati e azioni. VMC è una derivazione di FMC. Prima di continuare con la descrizione dell'interfaccia web vorrei introdurre le modalità con le quali si può passare da SocL a MHML, quest'ultima logica di VMC. da MHML a SocL 1: 2: 3: 4: 5: 6: in MHML hai φ [a] φ P(a) φ E [φ{a} U {b} φ0 ] E [φ{a} U {b} φ0 ] in SocL [must(a)] φ [must(a) ∨ may(a)] φ hmust(a) ∨ may(a)i φ E [ φ {must(a)} U {must(b)} φ0 ] E [ φ {must(a) ∨ may(a)} U {must(b) ∨ may(b)} φ0 ] Da notare che le formule sono vericate nella famiglia e non sui singoli prodotti. Le formule logiche che esprimono proprietà sui singoli prodotti non distinguono tra archi may e archi must , e quindi non contengono informazioni su quest'ultime. Continuiamo questo paragrafo con la descrizione dell'interfaccia. Dopo aver caricato il modello, nella parte in basso della pagina viene visualizzato un editor di testo dove si possono inserire le formule logiche da vericare sulla famiglia. Le formule si possono applicare alla famiglia (da considerare che le transizioni sono must e may ) oppure ai singoli prodotti. La gura 6.4 mostra il primo caso e si può notare come il nome dell'editor di testo è SoCL/MTS, e che quindi le formule sono scritte considerando il fatto che le transizioni sono di tipo must oppure may. Un esempio di formula in SoCL/MTS è: nella famiglia di macchine da caè dopo aver inserito una moneta è sempre possibile scegliere la bevanda caè, 66 AG [may(dollar) or may(euro)] E [true {must(*)} U {must(coee)} true] Il risultato della verica viene mostrato nella parte centrale della pagina, vedi gura 6.8. La validità della formula mi garantisce che ogni prodotto della famiglia ha questa Figura 6.8: VMC, vericare proprietà sulla famiglia proprietà, includendo anche i prodotti non validi rispetto i vincoli espressi mediante le formule in MHML. Se la formula non è valida invece, allora esiste qualche prodotto nel quale la proprietà non vale, ciò non signica però che tale proprietà sia valida per tutti i prodotti validi rispetto ai vincoli. Infatti, la verica non tiene conto dei vincoli che vengono utilizzati per generare i prodotti validi. Le formule si posso applicare anche ai singoli prodotti. In quanto i singoli prodotti sono LTSs le formule non includono informazione su transizioni must e may. Ad esempio sulla lista dei prodotti validi si può vericare la seguente formula: EX {euro} true i prodotti con il risultato true sono le macchine per il mercato europeo, le altre per il mercato statunitense. 67 Figura 6.9: VMC, vericare proprietà sui prodotti 68 Capitolo 7 Conclusioni e lavoro futuro Questa tesi conclude la prima parte dell'attività di ricerca presentata nel capitolo 4, dove quest'ultima si pone l'obiettivo di formalizzare un ambiente di verica e analisi in Product Family Engineering (PFE). Una famiglia di prodotti è un Modal Transition System (MTS) ed un insieme di vincoli deniti sulle funzionalità dei prodotti ed espressi nella logica temporale deontica branching MHML. Il mio lavoro, in particolare, è stato quello di implementare una procedura che permette di generare i prodotti validi considerando i vincoli e di integrarlo in FMC, un model checker basato su stati ed azioni. Durante lo studio e l'implementazione dell'algoritmo sono state fatte alcune osservazioni. Una prima osservazione si è dovuta fare sulla struttura dell'algoritmo da implementare. Si è pensato ad un algoritmo globale in alternativa ad un algoritmo locale. Nell'approccio globale prima si generano tutte le famiglie dell'MTS in esame per poi vericare su queste la validità delle formule che rappresentano i vincoli. Nell'approccio locale invece, eseguo una successione di passi dove in ogni passo aggiungo un arco dell'MTS originale ad un prodotto intermedio e su questo verico la validità delle formule. Nell'approccio locale però avere MTS come prodotti intermedi era complicato. Inoltre, un algoritmo locale risulta più 69 eciente se applicato ad una famiglia che si presenta con un numero abbastanza grande di vincoli. Questo perché posso tagliare interi sottoalberi a causa della non soddisfazione di qualche vincolo. In quanto eravamo interessati alla generazione dei prodotti nali ho pensato che la scelta ottimale era quella di generare i prodotti (con soli archi must ) di un MTS seguendo l'approccio locale. La seconda osservazione riguardava la verica delle formule logiche che rappresentavano i vincoli. La prima soluzione consisteva nell'utilizzo continuo del model checker FMC. Quando si doveva vericare la validità di una formula, la descrizione del prodotto intermedio veniva caricato nel model checker e in seguito valutate le formule. Analizzando la struttura dei vincoli si è capito che tale verica si poteva realizzare in modo alternativo, semplicemente tenendo una struttura dati che contiene le azioni presenti nelle transizioni che compongono il prodotto intermedio. In ogni passo una scansione della struttura e suciente per stabilire la validità delle formule che rappresentano i vincoli. L'integrazione con FMC era relativamente facile in quanto per descrivere una famiglia si utilizza un sottoinsieme degli operatori sinattici di FMC. Abbiamo mostrato anche come formule logiche in MHML si traducono in SocL che è la logica di FMC. Variability Model Checker (VMC) è un ambiente completo di analisi e verica in PFE e mette in condizioni di considerare altri sviluppi futuri. Un possibile sviluppo futuro può essere quello di identicare e successivamente aggiungere all'algoritmo altri vincoli signicativi espressi in MHML (oltre a , alternative exclude e requires ), da vericare durante la generazione dei prodotti validi. Si può realizzare uno strumento con il quale sia possibile descrivere gracamente una famiglia in MTS+MHML oppure mediante un Feature Diagram. Inoltre, si può realizzare anche un trasformatore da modelli descritti in Feature Model a modelli descritti in MTS+MHML e viceversa, in modo da mettere in relazione i due formalismi. 70 Un algoritmo per derivare sottofamiglie valide rispetto ai vincoli si può realizzare e può essere utile in termini di Product Family Engineering. Un'altra importante questione è di studiare come questo approccio scala in una situazione reale dove le famiglie si presentano con molte funzionalità e molti vincoli tra loro. 71 Bibliograa [1] P. Asirelli, M.H. ter Beek, A. Fantechi, and S. Gnesi, Deontic Logics for Modelling Behavioural Variability. In: D. Benavides, A. Metzger, and U.Eisenecker (Eds.): Proceedings of the Third International Workshhop on Variability Modelling , ICB Research report 29, Universität of Software-intensive Systems (VaMos'09) Duisburg-Essen, 2009, 71-76. [2] P. Asirelli, M.H. ter Beek, A. Fantechi, and S. Gnesi, A deontical logical framework for modelling product families. In: D. Benavides, D. Batory, P. Grünbacher (Eds.): , ICB Proceedings Variability Modelling of Software.intensive Systems (VaMoS'10) Research report 37, Universität Duisburg-Essen, 2010, 37-44. [3] P.F. Castro and T.S.E. Maibaum, A Complete and Compact Propositional Deontic Logic. In: C.B. Jones, ZH. Liu and J. Woodcock (Eds.): Theoretical Aspects of Computing (ICTAC'07) International Colloquium ,LNCS 4711, Springer, 2007, 109-123. [4] E.M. Clarke, O. Grumberg and D.A. Peled, Model Checking, MIT . Press 1999 [5] R. De Nicola and F.W. Vaandrager, Three Logics for Branching Bisimulation. Journal of the ACM 42, 2 (1995) , 458-487. 72 [6] Maurice H. ter Beek, Franco Mazzanti, and Aldi Sulova, VMC: A Tool for the Analysis of Product Variability. To appear in Sixth International Workshop on Va- , Leipzig, Germany, riability Modelling of Software-intensive Systems (VaMoS 2012) January 25-27, 2012. [7] Stefania Gnesi and Franco Mazzanti, An Abstract, on the Fly Framework for the Verication of Service-Oriented Systems SENSORIA BOOK - Lecture Notes in Computer Science - to appear [8] K.G. Larsen and B. Thomsen, A Modal Process Logic. Proceedings Logic in , IEEE, 1988, 203-210. Computer Science (LICS'88) [9] K. Kang, S. Choen, J. Hess, W. Novak and S. Peterson, Feature Oriented Domain Analysis (FODA) Feasibility Study. Technical Report SEI-90-TR-21, Carnegie Mellon University, Nov. 1990. [10] Ada 2005 Reference Manual, ISO/IEC 8652:2007(E) Ed. 3 [11] Rationale for Ada 2005, John Barnes. [12] S. Gnesi and F. Mazzanti. On the Fly Verication of Networks of Automata. In PDPTA'99 Conference Proceedings, pages 1040-1046. CSREA Press, Athens, GA, 1999. [13] M.H. ter Beek, F. Mazzanti and A. Fantechi. CMC-UMC: A Framework for the Verication of Abstract Service-oriented Properties. In SAC'09 Conference Proceedings, pages 2111-2117. ACM Press, New York, NY, 2009. [14] K. Pohl, G. Böckle and F. van der Linden, Software Product Line Engineering: Foundations, Principles, and Techniques, Springer, 2005 73 [15] D.S. Batory, Feature Models, Grammars, and Propositional Formulas. In J.H. Obbink and K. Pohl (Eds.): , Proceedings Software Product Line Conference (SPLC'05) LNCS 3714, Springer, 2005, 7-20. [16] P. Asirelli, M.H. ter Beek, A. Fantechi, and S. Gnesi, Formal Description of Variability in Product Families. In Proceedings of the 15th International Software Product . IEEE Computer Society, Los Line Conference (SPLC 2011), Munich, Germany Alamitos, CA, 2011, 130-139 [17] P. Asirelli, M.H. ter Beek, A. Fantechi, and S. Gnesi, A Logical Framework to Deal with Variability. In Proceedings of the 8th International Conference on Integrated Formal Methods (IFM'10), Nancy, France (D. Méry and S. Merz, eds.) Notes in Computer Science 6396, Springer-Verlag, Berlin, 2010, 43-58. 74 , Lecture