università di pisa

annuncio pubblicitario
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
Scarica