Professional Documents
Culture Documents
Indice
1 Introduzione
1.1
Il problema della correttezza dei sistemi informatici . . .
1.2
Approcci alla semantica dei linguaggi di programmazione
1.3
Sistemi concorrenti . . . . . . . . . . . . . . . . . . . . .
1.4
Calcoli di processo . . . . . . . . . . . . . . . . . . . . . .
1.5
Schema delle note . . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
sequenziali
. . . . . . .
. . . . . . .
. . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Preliminari Matematici
2 Nozioni preliminari
2.1
Insiemi . . . . . . . . . . . . . . .
2.2
Relazioni e funzioni . . . . . . . .
2.3
Principi di induzione . . . . . . .
2.3.1 Induzione matematica . .
2.3.2 Induzione strutturale . . .
2.4
Sistemi di inferenza . . . . . . . .
2.4.1 Induzione sulle derivazioni
2.4.2 Induzione sulle regole . . .
2.5
Contesti e congruenze . . . . . . .
2.6
Esercizi . . . . . . . . . . . . . . .
7
7
8
11
14
18
21
.
.
.
.
.
.
.
.
.
.
23
23
25
29
29
32
35
37
38
39
41
.
.
.
.
.
.
.
43
43
50
52
54
57
60
62
4 Sintassi e denotazioni
4.1
Notazioni sintattiche e denotazioni semantiche . . . . . . . . . . . . . . . . .
4.2
Una calcolatrice tascabile . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
65
65
68
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Indice
4.3
4.4
4.5
4.6
II
5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Sistemi Sequenziali
-calculus
5.1
La -convenzioni semplificative .
5.2
Il principio di estensionalit . .
5.3
Operatori di n-upla . . . . . . .
5.4
Operatori di composizione . . .
5.5
Il sistema di calcolo . . . . . . .
5.5.1 Sintassi del -calculus . .
5.5.2 Semantica del -calculus
5.6
Esercizi . . . . . . . . . . . . . .
70
73
77
77
79
85
88
89
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
91
92
95
96
98
99
99
101
106
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
109
110
113
117
122
122
123
127
128
132
133
135
139
143
145
.
.
.
.
.
147
147
148
152
156
161
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Indice
8.3
8.4
8.5
8.6
8.7
III
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
167
170
173
175
179
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
181
181
182
184
187
190
190
191
193
194
196
Sistemi Concorrenti
197
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
199
199
200
201
202
204
206
210
213
217
219
222
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
225
225
227
227
230
235
237
239
240
241
242
246
248
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Indice
11.4
11.5
11.6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . .
. . . .
. . . .
. . . .
. . . .
debole
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
254
256
257
259
.
.
.
.
.
.
.
.
.
.
.
.
261
261
265
268
270
270
274
280
281
282
292
298
300
.
.
.
.
.
.
.
.
301
301
303
305
306
311
315
318
321
325
A Tabelle
329
A.1 Elenco degli operatori per la concorrenza . . . . . . . . . . . . . . . . . . . . 329
A.2 Alcuni calcoli di processi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
Capitolo 1
Introduzione
SOMMARIO
Questo capitolo introduttivo presenta le problematiche principali legate alla verifica della
correttezza dei sistemi informatici e di quelli concorrenti in particolare.
1.1
Il problema della correttezza dei sistemi informatici, siano essi composti da componenti software e/o hardware, cio il problema di accertare se un sistema informatico si comporta effettivamente in accordo alle sue specifiche, uno dei problemi cruciali dellInformatica e sta
acquistando unimportanza sempre maggiore. Infatti, i sistemi informatici sono vitali per
la societ moderna dal momento che, ad esempio, gestiscono gli aspetti finanziari, regolano
le comunicazioni e la produzione di energia, controllano il traco aereo e i processi industriali, anche quelli critici da un punto di vista della sicurezza, ed elaborano informazioni
critiche. Inoltre, computer e microprocessori sono ormai usati per controllare ogni sorta di
dispositivo duso giornaliero, dai tablet ai telefonini, dalle automobili agli elettrodomestici.
In pratica si sta realizzando un nuovo modello di interazione persona-computer, denominato
ubiquitous computing (o anche pervasive computing), in cui lelaborazione dellinformazione
completamente integrata in tutti gli oggetti, le attivit e gli aspetti della vita quotidiana.
Tuttavia, malgrado la sua importanza sia da un punto di vista scientifico che pratico, il
problema di garantire la correttezza dei sistemi informatici non sempre riceve lattenzione che
merita. Spesso si privilegia lesigenza di mantenere bassi i costi di sviluppo. Di conseguenza
abbiamo che i sistemi informatici si guastano con una certa frequenza e talvolta tali guasti
hanno ripercussioni molto serie sia da un punto di vista economico che da quello della sicurezza
per la vita delluomo. Due esempi tra tutti sono il bug che ha aitto il processore Pentium-II
della Intel (1994), nel quale secondo una stima della rivista Byte lunit che si occupava della
divisione in virgola mobile generava un errore ogni nove miliardi di operazioni, e lesplosione
del vettore spaziale Ariane-5 (1996), la cui costruzione costata 7 miliardi di dollari allAgenzia
Spaziale Europea, causata da un overflow nella conversione di alcuni dati da rappresentazione
in virgola mobile in interi con segno a 16-bit. Tant che solo qualche anno fa il premio Turing
Tony Hoare scriveva:
programming is the only engineering profession that spends half its time and eort
on detecting and correcting mistakes made in the other half of its time [BHH+ 06].
Capitolo 1 Introduzione
Negli ultimi anni per, i metodi formali per la descrizione, la costruzione, lanalisi e la
verifica dei moderni sistemi informatici, basati soprattutto sulla logica ed altri strumenti matematici, sono diventati pi maturi. Secondo la definizione data da R. W. Butler
(Wikipedia),
in computer science, specifically software engineering and hardware engineering,
formal methods are a particular kind of mathematically-based techniques for the
specification, development and verification of software and hardware systems.
Tali metodi possono fornire un supporto fondamentale alla validazione dei sistemi informatici
fin dalle prime fasi del loro sviluppo. Sono praticamente indispensabili soprattutto nellambito
della verifica di sistemi critici da un punto di vista della sicurezza o da quello del costo. Sono
sempre pi usati in pratica e c da aspettarsi che in un prossimo futuro essi complementino,
ed in parte rimpiazzino, i metodi tradizionali dellingegneria del software.
Lo scopo principale di queste note quello di introdurre alcuni dei metodi formali utilizzati
per la verifica della correttezza dei programmi, sia sequenziali che concorrenti.
La prima parte di queste note dedicata alla introduzione di alcune nozioni preliminari
necessarie per la comprensione e lo sviluppo dei metodi formali che saranno introdotti nelle
due parti successive. Pi precisamente, tali nozioni riguardano matematica discreta e tecniche
di prova (Capitolo 2), grammatiche, sintassi, automi a stati finiti e sistemi di transizioni
etichettate (Capitolo 3), denotazioni e funzioni di interpretazione semantica (Capitolo 4).
1.2
Nel caso dei linguaggi di programmazione sequenziali introdurremo alcune tecniche ormai
ben consolidate per la definizione precisa e non ambigua della loro semantica. Diversamente
dal linguaggio naturale, che evolve nel tempo e risulta ricco di ambiguit, un linguaggio di
programmazione deve avere una definizione precisa e non ambigua, essendo progettato per
istruire una macchina priva di capacit di apprendimento e discernimento. Daltra parte
un linguaggio di programmazione ha in comune col linguaggio naturale alcune importanti
caratteristiche. Ogni linguaggio ha una sua sintassi ed una sua semantica: la sintassi definisce
la struttura delle frasi del linguaggio, la semantica attribuisce un significato a tali frasi.
La teoria riguardante le tecniche per specificare la sintassi stata sviluppata a lungo ed
ha portato a risultati chiari e importanti. I requisiti matematici di supporto alla specifica
sintattica (espressioni regolari, grammatiche libere dal contesto, ecc.) sono ormai ben noti ed
ampiamente applicati.
Per attribuire un significato a una frase di un linguaggio di programmazione bisogna
specificare il comportamento, in esecuzione, del programma che la frase rappresenta. Lo
sviluppo di metodologie per specificare precisamente (ossia, formalmente) il comportamento
di programmi in esecuzione risultato storicamente complesso. per questo che inizialmente
la semantica di un linguaggio di programmazione veniva data attraverso descrizioni informali,
in linguaggio naturale, dei vari costrutti. Tuttavia un tale approccio aveva gravi difetti. In
primo luogo il linguaggio naturale ambiguo, per cui capitava che implementazioni diverse
dello stesso linguaggio mostrassero comportamenti diversi. In secondo luogo le descrizioni
informali non potevano essere trattate formalmente con strumenti matematici per dimostrare
propriet del linguaggio in questione o per dimostrare propriet di programmi scritti con tale
linguaggio.
per questo motivo che sono stati sviluppati strumenti teorici atti a dare definizioni
matematiche degli aspetti dinamici dei linguaggi di programmazione.
Descriviamo ora i tre approcci principali che si possono adottare per attribuire una semantica esatta ad un linguaggio di programmazione. Tali approcci vanno sotto il nome di
semantica denotazionale, semantica operazionale e semantica assiomatica (o algebrica).
Semantica denotazionale
Le idee alla base dellapproccio denotazionale alla semantica dei linguaggi di programmazione
sono due: definire delle funzioni che associano ad ogni frase del linguaggio un appropriato
oggetto matematico, che costituisce la semantica del frammento di programma rappresentato
dalla frase, e realizzare tale associazione in modo composizionale, ossia in modo che loggetto associato ad un costrutto del linguaggio sia costruito a partire dagli oggetti associati alle
componenti del costrutto stesso. Le funzioni suddette sono dette funzioni di interpretazione
semantica, i loro codomini sono detti domini semantici, e gli elementi di questi ultimi sono detti denotazioni. Le denotazioni sono oggetti matematici (insiemi, funzioni, ecc.) che
permettono di ragionare formalmente sui programmi. Ad esempio, le denotazioni possono
essere utilizzate per dimostrare la correttezza di un programma rispetto a determinate specifiche, per dimostrare la correttezza di determinate trasformazioni da un programma ad un
altro, e per dimostrare lequivalenza semantica di programmi diversi.
Generalmente una semantica denotazionale cerca di catturare il significato intrinseco dei
termini del linguaggio piuttosto che definire una strategia di valutazione dei termini stessi.
Il significato di un termine , secondo questo approccio, loggetto matematico ad esso associato (ossia loggetto matematico che esso implicitamente denota); per cui due termini sono
equivalenti se ad essi associato lo stesso oggetto matematico.
Questo approccio adatto a trasformare le questioni riguardanti i programmi in problemi
matematici. Come vedremo, nellambito dei linguaggi per la descrizione di sistemi concorrenti
questo approccio risulta poco utilizzabile perch esso tende a interpretare un programma come
una funzione che produce un valore e quindi, dicilmente, cattura il concetto di interazione
tra programmi.
Semantica operazionale
Lapproccio operazionale mette laccento su come i vari costrutti di un linguaggio possono
essere eseguiti da unipotetica macchina astratta. Il significato dei costrutti viene spiegato in
termini di passi elementari della macchina. Tipicamente, come modello per le macchine astratte, vengono usati gli automi a stati finiti o i sistemi di transizioni etichettate. Un passo di una
tale macchina consiste nel passaggio da uno stato allaltro del sistema tramite una transizione.
Una semantica operazionale pu quindi essere vista come una formalizzazione matematica di
una strategia di implementazione del linguaggio. In tal senso la semantica operazionale non
definisce completamente il significato dei termini ma ne descrive solo lesecuzione per mezzo
di computazioni.
Per definire completamente il significato dei termini possibile, come vedremo ampiamente nei prossimi capitoli, eettuare un processo di astrazione e definire una semantica
osservazionale che identifichi due termini se nessun osservatore esterno, interagendo con le
10
Capitolo 1 Introduzione
un po come se uno dicesse che il colore rosso in realt linsieme di tutti gli oggetti rossi. Questo
pu risultare strano ma se facciamo lo sforzo di pensare a quando abbiamo imparato le parole da bambini ci
accorgiamo che il processo simile: dopo che ci sono stati indicati molti oggetti dicendoci che erano rossi, la
nostra mente ha eettuato involontariamente unoperazione di quoziente, ossia si chiesta qual lunica cosa
in comune tra questi oggetti?. Il nome di questa cosa comune la parola rosso.
1.3
11
Sistemi concorrenti
La nozione di sistema concorrente non esclusiva del mondo dei computer; una colonia di
formiche ed un aggregato di particelle elementari sono esempi di sistemi concorrenti nel campo
della biologia e della fisica. Da un punto di vista informatico, un sistema concorrente pu
astrattamente essere visto come un insieme di componenti autonome, hardware o software,
che possono interagire e comunicare.
Lutilizzo di sistemi concorrenti si molto ampliato negli ultimi decenni. Ci grazie al
fatto che la programmazione concorrente ore diversi vantaggi potenziali, quali, ad esempio,
performance (per via di un migliore sfruttamento del parallelismo oerto dallhardware), distribuzione (poich alcuni problemi richiedono soluzioni distribuite, si pensi ad esempio alle
applicazioni client-server ), facilit di programmazione (poich alcuni problemi hanno una soluzione naturale di tipo concorrente), risposte pi rapide, maggiore throughput, ed in generale
migliore strutturazione dei sistemi che interagiscono con lambiente, controllano varie attivit
e gestiscono eventi multipli (per il fatto di essere organizzati in pi thread di controllo).
La concorrenza, tradizionalmente ingrediente essenziale di componenti software quali sistemi operativi, basi di dati e sistemi di comunicazione, ha assunto un ruolo sempre pi rilevante
anche nellarea delle applicazioni. Per trarre vantaggio, anche a livello di programmazione,
del maggiore parallelismo disponibile, molti linguaggi di programmazione di pi recente concezione (per esempio, OCCAM, CML, Facile, Obliq, Telescript, Pict, Java, Aglets, Odissey)
sono stati dotati di primitive per la descrizione ed il controllo dellinterazione tra le varie
componenti.
Data la loro naturale capacit di modellizzare la realt, i sistemi concorrenti sono usati,
per esempio, per gestire processi industriali, per il controllo del traco aereo o per il controllo
di robot.
Naturalmente, cos come la programmazione sequenziale, anche la programmazione concorrente soggetta ad errori. Due esempi tra tutti sono il Therac-25, una macchina per
radioterapia controllata da un calcolatore che negli anni tra il 1985 ed il 1987 ha subito perlomeno sei incidenti che hanno causato gravi danni e persino la morte di alcuni pazienti (la
commissione di indagine ha concluso che il progetto del software era tale che fosse realisticamente impossibile testarlo in maniera chiara ed automatica), ed il rover Mars Pathfinder
(1997), in cui un problema ben noto in programmazione concorrente col nome di inversione
della priorit tra task concorrenti ha causato un continuo riavvio del computer di bordo,
riducendo cos la disponibilit per lesplorazione e la capacit della batteria, cosa che ha poi
impedito definitivamente la comunicazione dei dati raccolti alla base terrestre. Inoltre, a
tutti noi sar capitato di dover riavviare il calcolatore a causa del verificarsi di una qualche
situazione anomala che impediva di poter continuare ad usarlo!
Quindi, eventuali errori nelle applicazioni del tipo summenzionato possono avere importanti ripercussioni per la vita delluomo. Ne deriva che lo studio formale e la comprensione del comportamento dei sistemi concorrenti ha assunto unestrema importanza, cos come
agli albori dellinformatica si rese necessario comprendere il comportamento dei programmi
sequenziali. Come spesso accade lesigenza di una teoria nasce dalla pratica.
Lo studio di tecniche per la descrizione e lanalisi dei sistemi concorrenti emerso come
unarea della ricerca in informatica in risposta alle dicolt incontrate dai progettisti di
sistemi concorrenti. Uno dei principali fattori alla base di tali dicolt la presenza di pi
componenti, o thread di controllo, allinterno di uno stesso sistema che possono interagire in
12
Capitolo 1 Introduzione
(P )
(P )
(Q)
(Q)
dove indichiamo tra {} le asserzioni sul valore assunto da x e tra () la componente che esegue
una data istruzione.
Supponiamo invece di eseguire P e Q simultaneamente, fatto che denotiamo come P |Q;
in questo caso c anche la possibilit che il valore finale di x sia 3, e non 2, infatti si potrebbe
13
(P )
(Q)
(P )
(Q)
{x = v0 }
P |Q
{x = 2 _ x = 3}
14
Capitolo 1 Introduzione
linterattivit e per tener conto del fatto che non sempre i sistemi concorrenti sono progettati
per raggiungere uno stato terminale o perch il risultato eventualmente prodotto sia unico.
Sistemi concorrenti, anche piccoli, possono essere dicili da analizzare. Perci abbiamo
bisogno di rispondere ad alcune domande:
1. Come possiamo sviluppare/progettare un sistema che funzioni correttamente?
2. Come possiamo analizzare/verificare tale sistema?
Nel campo dellinformatica teorica, si quindi presentata la necessit di estendere la teoria,
valida per i processi sequenziali algoritmici, a sistemi dove la concorrenza e linterazione
giocano un ruolo essenziale ed a volte predominante. necessaria a tale scopo una teoria
della concorrenza che comprenda:
1. modelli matematici per la descrizione e lanalisi formale di sistemi concorrenti;
2. linguaggi formali per la specifica del possibile comportamento dei sistemi;
3. strumenti di verifica (semi-)automatici e relative tecniche di implementazione.
Lambizione degli studiosi quella di fare per i sistemi concorrenti quello che agli albori
della scienza dei calcolatori stato fatto per spiegare il comportamento dei programmi sequenziali ed algoritmici. Allora furono sviluppati modelli computazionali basati sulle attivit
elementari di leggere e scrivere in memoria (macchine di Turing) e sulla possibilit di definire ed invocare funzioni ( -calcolo). Nel caso dei sistemi e dei programmi concorrenti, lo
scopo quindi quello di sviluppare un modello con un piccolo numero di concetti di base, in
termini dei quali sia possibile spiegare il comportamento interattivo e concorrente di diverse
componenti.
Uno dei primi modelli, sviluppato negli anni 60, sono le reti di Petri, che generalizzano la
teoria degli automi e permettono la descrizione delloccorrenza contemporanea di pi azioni
(transizioni tra stati). Nel modello delle reti di Petri, particolare attenzione riservata alle
nozioni di conflitto, indipendenza e dipendenza causale tra azioni.
per negli ultimi tre decenni che la teoria della concorrenza ha avuto il massimo sviluppo,
soprattutto grazie allapproccio basato sui calcoli di processo (o algebre di processo). Un
calcolo di processi costituito da una notazione per descrivere sistemi concorrenti e da un
insieme di strumenti matematici (algebrici o logici) che aiutano a studiare le propriet dei
sistemi descritti con tale notazione. Un sistema concorrente rappresentato in termini di
processi e la sua evoluzione consiste quindi nella trasformazione di un processo in un altro
tramite lesecuzione di unazione. Tale visione, dovuta a Tony Hoare e Robin Milner (1980),
pu essere riassunta nel motto qualsiasi cosa (o pu esser vista come) un processo. Tutte
le componenti di un sistema, sia attive che passive, quali ad esempio canali di comunicazione,
buer di memoria, memoria condivisa, spazi di tuple, mittenti, destinatari, client, server,
sono processi.
1.4
Calcoli di processo
Tra i vari modelli e metodi proposti per descrivere ed analizzare sistemi concorrenti, uno di
quelli che ha riscosso pi successo lapproccio basato sui calcoli di processo.
15
Le idee alla base dei calcoli di processo sono due. Da un lato il principio secondo il quale
la comunicazione tra due processi debba essere di tipo handshake (stretta di mano), ossia
debba avvenire grazie ad azioni simultanee eseguite dai processi che comunicano attraverso
un canale (interfaccia). Dallaltro lidea che il linguaggio associato ad un calcolo di processi
debba basarsi su un numero ristretto di operatori corrispondenti ciascuno ad una qualche idea
intuitiva di composizione tra processi (quale, ad esempio, composizione sequenziale, composizione nondeterministica, composizione parallela) e sucienti nel loro insieme a raggiungere
un potere espressivo completamente generale.
Alcuni autori parlano di algebre di processo piuttosto che di calcoli, per alludere agli
strumenti dellalgebra che sono utilizzati da questi formalismi; noi preferiamo per chiamarli
calcoli perch molti di tali formalismi, oltre allalgebra, utilizzano strumenti di altre branche
della matematica (come, ad esempio, della logica). Un altro nome utilizzato in letteratura
linguaggi di descrizione di processi, ma anche questo riduttivo per le motivazioni che
abbiamo appena illustrato.
Il lavoro di Robin Milner sul Calculus of Communicating Processes (CCS, [Mil80, Mil89]
generalmente riconosciuto come liniziatore e il punto di riferimento di questa area. Ispirato
dal -calcolo, ma anche dal linguaggio CSP (un semplice linguaggio di programmazione concorrente basato sullo scambio esplicito di messaggi, [Hoa78]), CCS basato su un linguaggio
per la descrizione di processi con pochi costrutti primitivi ciascuno dei quali riflette semplici
idee operazionali: interazione sincrona tra processi concorrenti tramite canali di comunicazione, composizione sequenziale, parallela e non-deterministica, astrazione e ridenominazione
di canali, processi ricorsivi. I costrutti scelti sono quindi notevolmente diversi da quelli del
-calcolo. Ci dovuto ai dierenti obiettivi dei due calcoli: mentre il -calcolo studia le
funzioni ed il loro comportamento applicativo, quindi descrive essenzialmente computazioni
sequenziali, il CCS rivolto alle computazioni concorrenti, per cui interazione e parallelismo
sono le idee fondamentali.
Parallelamente al CCS, sono stati sviluppati altri calcoli di processo che condividono le
motivazioni del CCS; tra questi CSP [BHR84], ACP [BK84a, BK84b], Meije [AB84] e (ISOStandard) LOTOS [BB87].
Un calcolo di processi generalmente costituito da una sintassi per la descrizione formale
dei sistemi concorrenti, una semantica e un insieme di strumenti (tipicamente costituiti da
equivalenze e logiche) utili per studiare e dimostrare propriet dei sistemi descritti con la
notazione oerta dal calcolo.
A livello linguistico, vengono messi a disposizione un certo numero di costrutti che mirano
a cogliere il concetto di interazione tra processi concorrenti, il concetto di composizione
modulare dei processi per mezzo di operatori di composizione sequenziale, parallela o nondeterministica ed il concetto di astrazione per descrivere i sistemi a livelli di dettaglio dierenti.
Una novit rispetto ai modelli di calcolo sequenziali lintroduzione di operatori di astrazione
che permettono di fornire descrizioni di sistemi a diversi livelli di dettaglio e di concentrarsi
sugli aspetti pi rilevanti ai fini della validazione di specifiche propriet dei sistemi. Una
descrizione astratta potr essere vista come una specifica, mentre una descrizione pi dettagliata, che d informazioni sulla struttura logico/fisica del sistema, sar vista come una
implementazione.
Per definire un modello adeguato per la programmazione concorrente, una questione importante a cui bisogna rispondere quella di chiarire quando due sistemi hanno comportamenti equivalenti, nel senso che possiamo sostituire luno allaltro allinterno di un ambiente
16
Capitolo 1 Introduzione
di esecuzione e non notare alcuna dierenza. Questa una questione teorica che risulta di
vitale importanza nella pratica. Finch non viene stabilito con precisione il significato di
similarit o dierenza di comportamento di sistemi, non siamo in grado di dire cosa fa esattamente un certo sistema. Inoltre, la nozione di equivalenza di comportamenti pu essere usata
come mezzo per specificare come si dovrebbe comportare un sistema implementato: il sistema
implementato si potr dire corretto se il suo comportamento eettivo sar equivalente alla
specifica del comportamento.
Cerchiamo di chiarire con un esempio lutilit pratica della nozione di equivalenza di
comportamenti. In questo esempio introduciamo informalmente il CCS, che tratteremo in
maniera completa e dettagliata nel Capitolo 12.
Supponiamo che due processi A1 ed A2 debbano eseguire una porzione del loro programma
in mutua esclusione perch si tratta di sezioni critiche. Per far questo, si servono di un
semaforo S, realizzato tramite un altro processo. Per semplicit, rappresentiamo una sezione
critica semplicemente con la sequenza di azioni b.e di inizio e termine della sezione critica. In
CCS, possiamo scrivere A1 , A2 e S nel modo seguente:
A1 , p.b1 .e1 .v.A1
A2 , p.b2 .e2 .v.A2
S , p.v.S
In generale, se a un canale (o porta) di comunicazione, lazione di input sul canale rappresentata da a e quella di output corrispondente da a. Il processo A1 , per esempio, esegue:
un output su p, lazione b1 , lazione e1 , un output su v e poi ritorna allo stato iniziale. Lidea
che le primitive standard sui semafori sono qui realizzate tramite sincronizzazioni sui canali
p e v (in questo semplice esempio utilizziamo sincronizzazione pura sui canali, cio sincronizzazione senza scambio di dati). Il sistema complessivo risulta dalla composizione parallela di
tutti e tre i processi:
Sys , (A1 | S | A2 ) \ {p, v}
In realt, si vuole anche indicare che i canali p e v sono destinati ad uso interno del sistema,
per questo si usa loperatore di restrizione (\), che li rende invisibili allesterno.
A questo punto si pone il problema di verificare se il sistema ottenuto Sys si comporta
correttamente, cio se il semaforo utilizzato correttamente. In pratica, ci vuol dire che le
sezioni critiche dei processi A1 e A2 non sono mai sovrapposte (per esempio, non accade mai
che il sistema eettui la sequenza di azioni b1 .b2 .e1 .e2 ). In altre parole, le uniche sequenze di
azioni permesse devono essere quelle del tipo (b1 .e1 + b2 .e2 ) . Possiamo specificare questo
comportamento corretto come il processo
Spec , b1 .e1 .Spec
b2 .e2 .Spec
in grado di eettuare la sequenza b1 .e1 o la sequenza b2 .e2 per poi in ogni caso tornare allo
stato iniziale ( denota la composizione non-deterministica interna). Ci serve quindi una
teoria matematica che ci permetta di dimostrare che il sistema Sys e la specifica Spec sono
equivalenti:
Spec Sys
ossia che, a meno di sincronizzazioni interne (sui canali p e v), i due sistemi esibiscono lo stesso
comportamento esterno. Questo proprio il ruolo degli strumenti matematici che trattano il
concetto di equivalenza tra processi.
17
18
1.5
Capitolo 1 Introduzione
Queste note sono divise in tre parti. La prima parte introduce alcune nozioni preliminari
riguardanti matematica discreta e tecniche di prova, grammatiche e sintassi, automi a stati
finiti e sistemi di transizioni etichettate. La seconda parte verte su semantica operazionale e
denotazionale di linguaggi sequenziali; a tale scopo introduce anche la -notazione e i concetti
di base della teoria dei domini. La terza ed ultima parte presenta alcuni formalismi per
progettare, specificare, implementare, analizzare e dimostrare propriet di sistemi concorrenti
e distribuiti. Tali formalismi includono operatori per formare processi e calcoli di processo,
equivalenze comportamentali e logiche modali e temporali.
Il resto di queste note organizzato come segue.
Capitolo 2: Nozioni preliminari. Si introducono alcune nozioni matematiche preliminari:
insiemi, relazioni, funzioni, induzione e sistemi di inferenza. Particolare attenzione
dedicata alle propriet delle relazioni, a vari principi di induzione, ai sistemi di inferenza
ed al concetto di congruenza. Tali argomenti giocheranno infatti un ruolo fondamentale
nel seguito.
Capitolo 3: Sintassi e modelli semantici. Si introducono alcune nozioni della teoria dei
linguaggi (grammatiche ed automi) e si definiscono i sistemi di transizioni etichettate.
Si mostra un esempio che illustra sintassi e semantica operazionale delle espressioni
aritmetiche.
Capitolo 4: Sintassi e denotazioni. Si introducono alcune nozioni e definizioni preliminari di semantica denotazionale e li si illustra tramite due esempi di descrizione della
semantica di semplici formalismi. Si mostrano anche i tre approcci alla semantica nel
caso del linguaggio delle espressioni regolari.
Capitolo 5: -calculus. Si presenta il -calculus, un sistema formale che ha un ruolo importante nello studio dei fondamenti dei linguaggi di programmazione. Il -calculus
fornisce infatti sia una notazione semplice per la rappresentazione di funzioni nonch di
altri importanti concetti di programmazione, sia un sistema di calcolo basato su un insieme di regole di riduzione che consente di studiare le propriet semantiche di funzioni
e programmi.
Capitolo 6: Domini per la semantica denotazionale. Si presentano le basi matematiche per la semantica denotazionale dei linguaggi di programmazione. Vengono prima
introdotti i concetti di insieme parzialmente ordinato completo, funzione continua, minimo punto fisso e soluzione di un sistema di equazioni mutuamente ricorsive. Quindi si
presentano i concetti di base della teoria dei domini ed alcuni operatori che permettono
di costruire domini a partire da domini pi semplici. Infine, viene definito un metalinguaggio per esprimere le funzioni utilizzate per descrivere la semantica denotazionale di
una vasta classe di linguaggi di programmazione e viene dimostrato che tutti i costrutti
del metalinguaggio preservano la continuit.
Capitolo 8: Un semplice linguaggio imperativo. Si presentano alcuni concetti comuni
a vari linguaggi di programmazione e le tecniche utilizzate per la loro descrizione formale.
Si considera TINY, un semplice linguaggio di programmazione imperativo, di cui viene
19
20
Capitolo 1 Introduzione
Parte I
Preliminari Matematici
Capitolo 2
Nozioni preliminari
SOMMARIO
Questo capitolo introduce alcune nozioni preliminari di matematica. Particolare attenzione
dedicata alle propriet delle relazioni, a vari principi di induzione, ai sistemi di inferenza
ed al concetto di congruenza. Tali argomenti giocheranno infatti un ruolo fondamentale nel
seguito.
2.1
Insiemi
Un insieme A una qualunque collezione di oggetti, chiamati elementi di A.1 Un insieme non
pu contenere pi di una copia di un suo elemento e lordine degli elementi in un insieme non
ha alcuna rilevanza. Due insiemi A e B sono uguali se ogni elemento di A anche elemento
di B, e viceversa. La relazione di appartenenza di un elemento ad un insieme viene denotata
attraverso il simbolo 2. Se indichiamo con A linsieme dei numeri pari, 4 2 A e 7 62 A.
Scriveremo A B e diremo che A contenuto in B (anche, A un sottoinsieme di B) se
ogni elemento di A anche elemento di B (B A sinonimo di A B). Scriveremo invece
A B quando A B ed esiste un elemento di B che non appartiene ad A. Chiaramente A
uguale a B, e scriveremo A = B, quando A B e B A.
Linsieme vuoto linsieme che non contiene alcun elemento e viene indicato con il simbolo ; (o, in taluni contesti, con la notazione {}). Gli insiemi finiti (vedremo tra breve la
definizione di insieme finito) possono essere descritti attraverso la sequenza dei loro elementi
racchiusa fra parentesi grae. Ad esempio, {0, 1, 2} rappresenta linsieme finito i cui elementi
sono i numeri 0, 1 e 2.
Una propriet un predicato P che ad ogni elemento o insieme x associa un valore di
verit. Scriveremo P (x) per significare che x soddisfa il predicato P e, in tal caso, diremo
anche che P (x) vale.
Gli insiemi possono anche essere descritti utilizzando propriet dei loro elementi: la
notazione
{x | P (x)}
rappresenta linsieme costituito da tutti gli elementi x che soddisfano la propriet P . Con
questa notazione possibile descrivere anche insiemi infiniti come
{x | x 2 N e x
3}.
1
Le nozioni di insieme e di appartenenza a un insieme sono le uniche nozioni che le teorie matematiche
assumono come primitive e di cui non danno una definizione.
24
La notazione
{x 2 X | P (x)}
sinonimo di
{x | x 2 X e P (x)}.
2. Lintersezione di A e B linsieme
A \ B = {x | x 2 A e x 2 B}.
Pi in generale se {Ai } una famiglia di insiemi, al variare di i in un certo insieme di
indici I, lintersezione degli Ai linsieme
\
Ai = {x | x 2 Ai per ogni i 2 I}.
i2I
3. La dierenza di A e B linsieme
A
B = {x | x 2 A e x 62 B}.
i=1
Nel caso in cui A1 , . . . An siano tutti uguali a un certo insieme A, il prodotto cartesiano
degli Ai si indica con An .
2
Volendo essere rigorosi bisognerebbe definire formalmente anche il concetto di coppia ordinata. Ci accontenteremo tuttavia di fare adamento allidea intuitiva che in generale si ha di tale concetto. Basti solo
ricordare che, contrariamente a quanto avviene per gli insiemi, una coppia ordinata (o, in generale, una n-upla)
una struttura in cui lordine degli elementi rilevante cos come la loro molteplicit. In tal senso (a, a)
una coppia ordinata valida e (a, b) 6= (b, a) quando a 6= b. Due coppie (a, b) e (c, d) sono uguali se e solo se
a = c e b = d. Per le coppie si usa in taluni contesti la notazione < a, b >.
3
possibile anche definire il prodotto cartesiano tra un numero infinito di insiemi ma la definizione risulta
piuttosto sofisticata. Non ne avremo comunque bisogno.
25
ossia linsieme i cui elementi sono tutti i sottoinsiemi di A. Per questo insieme si usano
talvolta anche le notazioni Pow(A) o P(A).
Esempio 2.1. Siano A = {1, 2} e B = {2, 3}. Allora
A [ B = {1, 2, 3}, A \ B = {2}, A
B = {1},
A B = {(1, 2), (1, 3), (2, 2), (2, 3)}, 2A = {;, {1}, {2}, A}.
Due insiemi A e B si dicono avere la stessa cardinalit se esiste una funzione biunivoca fra
A e B (si veda la prossima sezione per la definizione di funzione biunivoca). Questa definizione
coglie il concetto intuitivo di insiemi con lo stesso numero di elementi.
Diremo che un insieme A finito se esiste n 2 N tale che A pu essere messo in corrispondenza biunivoca con linsieme {i 2 N | 1 i n}; in tal caso n sar detto cardinalit
di A. La cardinalit di un insieme A si indica con |A| o con #A.
Diremo che A infinito se non finito. Si consideri linsieme dei numeri naturali N
e linsieme dei numeri pari P . Essi hanno la stessa cardinalit, infatti la funzione che al
numero n associa il numero 2n una funzione biunivoca tra tali insiemi, tuttavia risulta
anche P N. Il fatto che un insieme possa essere messo in corrispondenza biunivoca con un
suo sottoinsieme proprio caratterizzante degli insiemi infiniti e potrebbe essere preso come
definizione di insieme infinito.
Un insieme si dice numerabile se pu essere messo in corrispondenza biunivoca con
linsieme N dei numeri naturali.
Se A e B sono finiti con |A| = n e |B| = m allora abbiamo
|2A | = 2n
2.2
|A B| = n m
Relazioni e funzioni
Tra tutte le relazioni possibili tra due insiemi A e B ve ne sono due speciali che sono
la relazione vuota ; e la relazione totale A B. Inoltre, ad ogni insieme A associata la
relazione (funzione) identit IdA dove IdA = {(a, a) | a 2 A}.
Introduciamo ora alcune operazioni sulle relazioni.
Definizione 2.3 (Operazioni sulle relazioni).
26
1,
la relazione
= {(y, x) | (x, y) 2 R} B A.
=
=
=
=
IdA ,
n
R
S R , n
R
Sn 0 n
n 1 R .
1), x1 = x, xn = y} .
27
riflessiva
*
*
*
simmetrica
*
antisimmetrica
*
transitiva
*
*
*
28
Si definisce insieme quoziente di A modulo R, e lo si indica con A/R, linsieme delle classi
di equivalenza, ossia
A/R = {X A | X una classe di equivalenza rispetto a R} .
Figura 2.1: Quoziente di un insieme A rispetto a una relazione di equivalenza R. Ogni classe
di equivalenza contiene elementi in relazione fra loro. Gli elementi di una classe non sono in
relazione con quelli di unaltra classe
facile provare che le classi di equivalenza di una relazione di equivalenza su A costituiscono una partizione di A nel senso che ogni elemento di A appartiene ad una ed una sola
classe di equivalenza.
Definizione 2.10 (Relazione di ordine). Una relazione binaria R su un insieme A si dice
essere una relazione dordine (parziale) se riflessiva, antisimmetrica e transitiva. La relazione R si dice relazione dordine totale se R una relazione dordine e se per ogni x, y 2 A
risulta (x, y) 2 R o (y, x) 2 R.
Un esempio di ordine parziale la relazione R sullinsieme delle parti di un insieme A
definita dallinclusione, vale a dire (X, Y ) 2 R se X Y per X, Y A.
Definizione 2.11 (Preordine). Una relazione binaria R su un insieme A si dice essere un
preordine se riflessiva e transitiva.
29
2.3
Principi di induzione
I procedimenti induttivi, ossia che fanno uso del principio di induzione, sono strumenti fondamentali per descrivere insiemi infiniti o per dimostrarne le propriet. Illustreremo in questa
sezione le forme di induzione pi comunemente usate: linduzione matematica e linduzione
strutturale.
2.3.1
Induzione matematica
30
Dimostrazione. Supponiamo per assurdo che P non valga per tutti i numeri naturali e sia h
non vale. Abbiamo che h
6= 0 (dato che P (0)
il pi piccolo numero naturale tale che P (h)
vale) quindi h = h + 1 per un certo h. Siccome h il pi piccolo numero naturale per il quale
vale e questo
P non vale, abbiamo che P (h) vale ma allora, per il punto 2, P (h + 1) = P (h)
assurdo.
Il teorema aerma che per dimostrare che una propriet P vera per un qualsiasi numero
naturale n, suciente dimostrare che la propriet vale per il numero 0 e che il fatto che sia
vera per un numero k implica che vera per il numero successivo.
Esempio 2.16. Si dice che quando era bambino, Gauss deriv la seguente formula
sum(n) =
n
X
i=1
i=
n(n + 1)
2
per la somma dei primi n interi non-negativi. Proviamo la correttezza di questa formula per
induzione usando lo schema descritto in precedenza.
Scopo: Dimostrare sum(n) = n(n+1)
per ogni numero naturale n.
2
Caso base: Dobbiamo provare che sum(0) = 0(0+1)
= 0. Questo vero perch la somma
2
dei numeri da 0 a 0 0.
Passo induttivo: Dobbiamo provare che per ogni naturale n, se sum(n) = n(n+1)
allora
2
(n+1)(n+2)
n(n+1)
sum(n + 1) =
. Assumiamo allora che sum(n) =
per un n arbitrario e
2
2
proviamo che la formula valida per il successivo numero naturale n + 1. Siccome la somma
dei primi n+1 naturali non altro che la somma dei primi n cui viene aggiunto n+1, abbiamo
sum(n + 1) = sum(n) + (n + 1). Applichiamo a questo punto lipotesi induttiva, vale a dire
sum(n) = n(n+1)
. Otteniamo
2
sum(n + 1) = sum(n) + (n + 1) =
n(n + 1)
+ (n + 1)
2
ossia se vera per il numero 0 e se dal fatto che sia vera per i numeri minori di k + 1 si riesce
a dedurre che vera per il numero k + 1.
Non dicile provare il principio di induzione matematica completa mimando la dimostrazione data per il principio di induzione matematica. Sussiste in realt un risultato pi
forte che dice che i due principi sono equivalenti nel senso che se possibile provare una
certa propriet dei numeri interi con linduzione completa allora possibile provare la stessa
propriet anche con linduzione standard (e viceversa). Abbiamo infatti il seguente risultato.
31
Proposizione 2.17 (Equivalenza tra induzione e induzione completa). Il principio di induzione matematica (PIM) e il principio di induzione matematica completa (PIMC) sono
equivalenti, ossia, per ogni propriet P sui numeri naturali risulta
P dimostrabile con PIM se e solo se dimostrabile con PIMC.
Dimostrazione. )) ovvio che se una propriet P soddisfa i punti 1) e 2) del PIM allora
soddisfa anche i punti 1) e 2b) del PIMC.
() Sia ora P una propriet che soddisfa i punti 1) e 2b) del PIMC, vogliamo provare che
P (n) vera per ogni n usando solo il PIM. Sia Q(n) la propriet
P (k) vale per ogni k n.
Vogliamo dimostrare (usando il PIM) che Q(n) vale per ogni n, dobbiamo quindi provare che
Q(0) vale e che Q(k) implica Q(k + 1) per ogni k. Dato che Q(0) asserisce che P (0) vale e
che P soddisfa il punto 1), Q(0) vale. Limplicazione Q(k) =) Q(k + 1) si traduce in
P (0), . . . , P (k) =) P (0), . . . , P (k + 1)
ma questo vero perch
P (0), . . . , P (k) =) P (0), . . . , P (k)
e, per il punto 2b),
P (0), . . . , P (k) =) P (k + 1).
Quindi abbiamo provato che Q(n) vale per ogni n e ci, per definizione di Q(n), implica che
P (n) vale per ogni n.
Osserviamo che le condizioni 1) e 2b) del principio di induzione matematica completa
possono essere riscritte con ununica condizione nel modo seguente:
P (i) per ogni i < k =) P (k), per ogni k 2 N.
; =) P (0),
32
Per capire meglio la natura del principio di induzione matematica consideriamo la famiglia
di tutti gli insiemi X che soddisfano
a) 0 2 X,
b) k 2 X =) k + 1 2 X, per ogni k.
Elementi di tale famiglia sono per esempio N, Z, R. La particolarit di N, rispetto a tutti gli
altri insiemi X che soddisfano a) e b), di essere linsieme pi piccolo (ossia, se X soddisfa
a) e b) allora N X).
Proposizione 2.19. Il principio di induzione matematica implica che N il pi piccolo tra
gli insiemi X che soddisfano a) e b).
Dimostrazione. Sia X un insieme che soddisfa a) e b); dobbiamo dimostrare che, nellipotesi
che il principio di induzione matematica valga, N X. Si consideri la propriet P (n) definita
da n 2 X. Poich X soddisfa a) e b), si ha che P (n) soddisfa i punti 1) e 2) del principio
di induzione matematica. Lapplicazione del principio ci permette di concludere che P (n)
vera per ogni n 2 N e quindi, per definizione di P (n), che N X.
Possiamo anche dimostrare lasserzione opposta.
Proposizione 2.20. Se N il pi piccolo tra gli insiemi X che soddisfano a) e b), allora il
principio di induzione matematica vale.
Dimostrazione. Lipotesi N il pi piccolo tra gli insiemi X che soddisfano a) e b) implica
che se X un insieme che soddisfa a) e b) allora N X. Sia ora P (n) una propriet
che verifica i punti 1) e 2) del principio di induzione matematica. Dimostrare la validit
del principio stesso equivale a dimostrare che P (n) vera per ogni n 2 N. Poniamo ora
X = {k : P (k)}. Abbiamo che X soddisfa a) e b), quindi N X. Da ci, per definizione di
X, segue che P (n) vera per ogni n 2 N, che quanto volevamo dimostrare.
Il fatto che N sia il pi piccolo insieme che soddisfa a) e b) e che per N valga il principio
di induzione matematica non una coincidenza fortuita ma un caso particolare di uno schema
pi generale che illustriamo nella prossima sezione.
2.3.2
Induzione strutturale
La situazione vista nella sezione precedente per N vale pi in generale per gli insiemi definiti
per induzione tramite costruttori. Spiegheremo il significato di queste parole in questa sezione.
Cominciamo prima con qualche esempio4 .
Esempio 2.21. Linsieme Lists(N) delle liste di elementi in N pu essere definito come il
pi piccolo insieme tra gli insiemi X tali che
a. [ ] 2 X,
b. ` 2 X implica n :: ` 2 X, per ogni n 2 N .
4
Non saremo eccessivamente formali in questa sezione per non ouscare le idee che stanno dietro ai principi
con pesanti formalismi.
33
dove sum(`) indica la somma degli elementi della lista `, max(`) indica il pi grande elemento
di ` (con max([ ]) = 0) e len(`) indica il numero di elementi di `.
Ponendo P (x) = sum(x) max(x) len(x), abbiamo che:
1) P ([ ]) vera, infatti 0 = sum([ ]) max([ ]) len([ ]) = 0,
2) P (`) implica P (n :: `) vera, infatti supponendo sum(`) max(`) len(`) abbiamo
sum(n :: `) = n + sum(`) n + max(`) len(`)
max(n :: `) + max(n :: `) len(`)
Non si pu parlare di funzione perch il dominio e il codominio di un costruttore possono non essere
insiemi. Si consideri per esempio il costruttore che ad ogni insieme A associa linsieme {A}. Esso ha come
dominio la famiglia di tutti gli insiemi ma si pu dimostrare che tale famiglia non un insieme.
34
esempi di costruttori: il costruttore che, presi A e B, costruisce la coppia (A, B); il costruttore
che, senza prendere valori, rende il numero 0; il costruttore che, fissato n 2 N e preso `, rende
la scrittura formale n :: `.6
facile definire gli analoghi degli insiemi visti negli esempi precedenti per mezzo di costrut(n)
tori. Consideriamo per esempio linsieme degli alberi con foglie in N. Detto 0 il costruttore
che, presi 0 valori, rende il numero n e detto k il costruttore che, presi k valori A1 , . . . , Ak ,
rende la k-pla (A1 , . . . , Ak ), abbiamo che linsieme degli alberi con foglie in N pu essere
definito come il pi piccolo insieme tra gli insiemi X tali che
a.
(n)
0 ()
b. t1 , . . . , tk 2 X implica
k (t1 , . . . , tk )
2 X, per ogni k 2 N.
In questa rappresentazione gli alberi sono oggetti del tipo (1, (2, (3)), (5, 5)).
Definizione 2.23 (Definizione per induzione tramite costruttori). Un insieme Y definito
per induzione tramite la famiglia di costruttori se la sua definizione della forma
Y il pi piccolo tra gli insiemi X che soddisfano:
s1 , . . . , sk 2 X =) k (s1 , . . . , sk ) 2 X per ogni k 2
dove k lariet di
k.
In altre parole Y il pi piccolo insieme chiuso (si veda Definizione 2.32) rispetto a ogni
2 .
Siamo ora in grado di enunciare il principio di induzione strutturale nella sua forma
generale.
Teorema 2.24 (Principio di induzione strutturale). Una propriet P vera per tutti gli
elementi di un insieme S definito per induzione tramite una famiglia di costruttori se
P (s1 ), . . . , P (sk ) =) P
per ogni
k (s1 , . . . , sk )
k.
Nel caso di Lists(N), abbiamo il costruttore [ ] (di ariet 0, non prende argomenti e rende
la lista vuota) e la famiglia dei costruttori della forma n :: _ (di ariet 1, prendono una lista
e rendono la lista con in pi il numero n in testa). Se istanziato sulle liste di naturali, il
principio di induzione strutturale aerma che per dimostrare che una propriet vera per
tutte le liste di naturali suciente dimostrare che essa vera per la lista vuota e che
preservata da tutti i costruttori utilizzati per formare liste di naturali.
Anche il principio di induzione matematica pu essere visto come un caso particolare del
principio di induzione strutturale. Infatti abbiamo visto che N pu essere caratterizzato come
il pi piccolo insieme tra gli insiemi X che soddisfano
a)
6
(0)
0 ()
2X
Una scrittura formale pu essere identificata con una ennupla. Per esempio, la scrittura formale n :: `
pu essere identificata con la terna (n, cod(::), `) dove cod(::) rappresenta il numero associato al carattere ::
secondo una qualche codifica.
35
1 (n)
2 X, per ogni n
(0)
2.4
Sistemi di inferenza
02N
k+12N
7
La dimostrazione formale richiederebbe di definire rigorosamente i costruttori per cui la omettiamo: lidea
comunque resta quella esposta.
36
e il loro scopo quello di definire N come il pi piccolo insieme che soddisfa a) e b).
Una regola pu avere delle condizioni collaterali per poter essere applicata. Le condizioni
collaterali vengono scritte accanto alla regola.
Esempio 2.26. Consideriamo la definizione dellinsieme Lists(N) della Sezione 2.3.2;
utilizzando le regole di inferenza essa diventa:
1. [ ] 2 Lists(N)
2.
l 2 Lists(N)
n :: l 2 Lists(N)
n2N
k2Q
02Q
k+12Q
k/h 2 Q
h 6= 0
y se ;/y 2 R,
(D1 , . . . , Dn )/y
8
y se (x1 , . . . , xn )/y 2 R e Di
xi .
37
Diremo anche che y deriva dallinsieme di istanze R, e scriveremo, R y, se esiste una Rderivazione D di y. Quando non rilevante, o quando chiaro dal contesto, si omette di
specificare linsieme R delle istanze usato in una derivazione.
Le derivazioni (anche dette dimostrazioni) vengono rappresentate in maniera naturale
come alberi.
Esempio 2.28. Consideriamo il sistema di regole
02Q
k 2 Q, h 2 Q
k2Q
k/h 2 Q
k+12Q
h 6= 0
02Q 12Q
12Q 22Q
1/2 2 Q
Esempio 2.29. Sia DIV la pi piccola relazione binaria R che soddisfa le seguenti due
regole:
1.
2.
nR0
n2N
nRk
n R n+k
n, k 2 N
Allora,
3 DIV 0
3 DIV 3
3 DIV 6
(assioma 1)
(regola 2)
(regola 2)
2.4.1
38
P (D)
se e solo se
P (D0 ) per ogni D0
D =) P (D)
Dimostrazione. Dimostriamo solo la parte se poich laltra ovvia. Supponiamo per assurdo
che la propriet P non valga per tutte le R-derivazioni e sia D una R-derivazione di profondit
minima tra quelle per cui la propriet non vale.
La derivazione D non pu avere profondit 0 perch in tal caso D non avrebbe sottoderivazioni e quindi per ipotesi avremmo che P (D) vale. Supponiamo allora che D sia della
forma (D1 , . . . , Dn )/y. Poich D1 , . . . , Dn hanno profondit minore di D, abbiamo, per la
minimalit di D, che P (D1 ), . . . , P (Dn ) valgono, ma allora per ipotesi P (D) vale e questo
contraddice lipotesi che P (D) non vale.
2.4.2
Vi anche un principio di induzione sulle regole. Tale principio utile per dimostrare che
una propriet vera per tutti gli elementi che appartengono ad un insieme definito tramite
regole. Lidea che se una propriet preservata nel passaggio dalle premesse alla conclusione
di tutte le istanze di regole usate in una derivazione, allora la propriet resta valida anche per
la conclusione della derivazione.
Sia R un insieme di regole e sia X il pi piccolo insieme che le soddisfa. Dato un insieme
R di istanze di regole, di interesse considerare linsieme delle conclusioni che si possono
derivare usando tali istanze, pi precisamente poniamo
I(R) =
x:
x .
Si osservi che I(R) X (stiamo identificando una conclusione della forma x 2 X con
lelemento x).
Teorema 2.31 (Principio di induzione sulle regole). Sia R un insieme di istanze di regole e
sia P una propriet. Allora
P (x)
se e solo se
P (x1 ), . . . , P (xn ) =) P (x)
Dimostrazione. Dimostreremo la parte se, laltra ovvia. Procediamo per induzione sulla
profondit dellalbero di derivazione. Sia x 2 I(R) e sia D una R-derivazione di x. Se D
della forma ;/x (ossia D ha altezza 0) allora ;/x 2 R e quindi per ipotesi P (x) vale. Se
invece D della forma (D1 , . . . , Dn )/x dove D1 , . . . , Dn sono R-derivazioni di x1 , . . . , xn con
(x1 , . . . , xn )/x 2 R, allora, per induzione, P (x1 ), . . . , P (xn ) valgono e quindi, per ipotesi,
P (x) vale.
39
Vogliamo adesso mostrare che linsieme I(R) soddisfa una propriet di chiusura rispetto
alle istanze in R. Poniamo a questo scopo la seguente definizione.
Definizione 2.32. Sia R un insieme di istanze di regole. Un insieme Q si dice chiuso rispetto
a R, o semplicemente R-chiuso, se per ogni (x1 , . . . , xn )/x 2 R si ha
x1 , . . . , xn 2 Q =) x 2 Q.
In altre parole, un insieme Q R-chiuso se ogni volta che le premesse di unistanza in
R appartengono a Q anche la conclusione vi appartiene. In particolare, un insieme R-chiuso
deve contenere tutte le conclusioni delle istanze degli assiomi in R.
Dimostriamo ora che I(R) il minimo insieme chiuso rispetto ad R.
Proposizione 2.33. Sia R un insieme di istanze di regole. Allora
1. I(R) R-chiuso,
2. se Q un insieme R-chiuso allora I(R) Q.
Dimostrazione. (1.) Sia (x1 , . . . , xn )/x 2 R con xi 2 I(R). Dobbiamo provare che x 2 I(R).
Per definizione di I(R) esistono D1 , . . . , Dn tali che Di R xi per ogni i. Ne segue che
(D1 , . . . , Dn )/x una R-derivazione di x, cio x 2 I(R).
(2.) suciente considerare la propriet P (x), definita per x 2 I(R), e data da x 2 Q,
cio P (x) = {x 2 Q|x 2 I(R)} ed applicare il Teorema 2.31.
Il risultato precedente pu essere usato quando si deve provare che una propriet vale per
ogni elemento di I(R), infatti sar suciente provare che linsieme Q degli elementi per cui
la propriet vale R-chiuso per ottenere che I(R) Q e quindi che la propriet vale in tutto
I(R).
Finora abbiamo immaginato che un insieme di regole servisse a definire un unico insieme.
Nulla impedisce di generalizzare il meccanismo e considerare definizioni mutuamente ricorsive
di insiemi.
Esempio 2.34. Si considerino le regole
k2P
02P
12D
k+12D
k2D
k+12P
Esse definiscono simultaneamente linsieme P dei numeri pari e linsieme D dei numeri dispari.
Vedremo che la definizione simultanea di pi insiemi molto frequente quando si ha a che
fare con la definizione di categorie sintattiche di grammatiche.
2.5
Contesti e congruenze
Un insieme definito per induzione tramite costruttori (si veda la Sezione 2.3.2) pu essere esteso per mezzo dellaggiunta di altri costruttori. In questa sezione descriviamo una particolare
costruzione di cui avremo bisogno in seguito.
40
Sia X un insieme definito per induzione tramite una famiglia di costruttori. Sia c0 il
costruttore senza argomenti che rende la scrittura formale [ ]9 . Posto 0 = [ {c0 }, definiamo
X[ ] come il pi piccolo insieme chiuso rispetto ai costruttori di 0 . Gli elementi di X[ ] saranno
detti contesti di X.
Esempio 2.35. Abbiamo visto che linsieme Trees(N) degli alberi con foglie in N pu essere
definito per induzione tramite costruttori (si veda Sezione 2.3.2). Aggiungendo il costruttore
c0 che rende lelemento [ ], le regole diventano
a. [ ] 2 X,
b. n 2 X per ogni n 2 N,
c. t1 , . . . , tk 2 X implica (t1 , . . . , tk ) 2 X, per ogni k 2 N,
Il pi piccolo insieme che soddisfa tali regole linsieme Trees(N)[ ] dei contesti degli alberi
con foglie in N. Gli elementi di Trees(N)[ ] sono oggetti del tipo (1, ([ ], 3), (5, [ ], (8))), ossia
alberi le cui foglie sono elementi di N o lelemento speciale [ ].
Gli elementi di X[ ] vengono scritti nella forma c[ ] per indicare che possono avere al loro
interno dei buchi ossia, delle occorrenze di [ ]. Un elemento c[ ] 2 X[ ] pu essere visto come
una funzione da X in X, infatti dato x 2 X indichiamo con c[x] lelemento di X ottenuto
rimpiazzando in c[ ] ogni occorrenza del buco [ ] con x.
Tornando allesempio degli alberi, se
1
3
[]
[]
8
t = (2, 7) = 2
allora
1
3
c[t] = c[(2, 7)] = (1, ((2, 7), 3), (5, (2, 7), (8))) = 2
5
2
Non si confonda questa notazione con quella usata per indicare la lista vuota.
41
2.6 Esercizi
Definizione 2.37 (Congruenza e precongruenza). Sia X un insieme definito per induzione tramite costruttori. Una congruenza su X una relazione di equivalenza su X che sia
sostitutiva rispetto ai contesti di X.
Una precongruenza su X una relazione di preordine su X che sia sostitutiva rispetto ai
contesti di X.
2.6
Esercizi
=S
2. R (S [ T ) = R S [ R T ;
2.4 Sia X un insieme e P una propriet definita sui sottoinsiemi di X. La propriet P si dice chiusa
per unioni se
1. P (;) vale,
2. se P (Yi ) vale per certi Yi X allora P ([i2I Yi ) vale.
Si dimostri che la propriet di simmetria chiusa per unioni mentre la transitivit e la riflessivit
non lo sono.
2.5 Sia P una propriet definita sui sottoinsiemi di un certo insieme X e assumiamo che P sia
chiusa per intersezioni (vedere Esercizio 2.3). Se Y X, si definisce chiusura di Y rispetto alla
propriet P il sottoinsieme Y di X tale che
1. Y Y ,
2. P (Y ) vale,
3. se Z Y e P (Z) allora Z Y .
ossia il pi piccolo sottoinsieme di X tale che P (Y ) vale e Y Y . Si dimostri che risulta
\
Y =
Z.
P (Z), ZY
2.6 Sia P una propriet definita sui sottoinsiemi di un certo insieme X e assumiamo che P sia chiusa
per unioni (vedere Esercizio 2.4). Se Y X, si definisce nucleo di Y rispetto alla propriet P
il sottoinsieme Y di X tale che
42
1, x1 = x e xn = y}.
Capitolo 3
SOMMARIO
Questo capitolo introduce gli strumenti per definire la sintassi e la semantica operazionale dei
linguaggi che studieremo in seguito. Cominceremo con i concetti riguardanti grammatiche
e sintassi, concreta e astratta. Quindi introdurremo gli automi a stati finiti, i sistemi di
transizioni etichettate e le strutture di Kripke, che risulteranno fondamentali per definire la
semantica operazionale di vari linguaggi. In particolare, studieremo i linguaggi come insiemi
di termini ben formati, le grammatiche come strumenti per generare tali insiemi e i sistemi di
transizioni come strumenti per definire la semantica operazionale. Concludiamo il capitolo
con un esempio che illustra sintassi e semantica operazionale delle espressioni aritmetiche.
3.1
Grammatiche
44
che non sono ritenute tali. Unimportante applicazione delle grammatiche la specifica della
sintassi dei linguaggi di programmazione: le grammatiche costituiscono, infatti, una notazione
concisa per descrivere la sintassi di un tipico linguaggio di programmazione.
Definizione 3.1 (Grammatica). Una grammatica una quadrupla G , hA, V, S, P i dove:
1. A un alfabeto i cui simboli sono detti terminali,
2. V un alfabeto, i cui simboli sono detti nonterminali, e V \ A = ;,
3. S 2 V un simbolo nonterminale, detto simbolo iniziale,
4. P (A [ V ) (A [ V ) un insieme di coppie, dette produzioni, tali che se (u, v) 2 P
allora u contiene almeno un simbolo nonterminale.
Una produzione (u, v) viene generalmente scritta u ! v o anche u ::= v. Per comodit,
se diverse produzioni hanno lo stesso membro sinistro, esse possono essere raggruppate in
ununica produzione il cui membro destro costituito dalla sequenza dei membri destri delle
produzioni originarie, separati dal simbolo | . Cos, se (u, v1 ), (u, v2 ), . . . , (u, vn ) 2 P , si scrive
u ! v1 | v2 | . . . | vn
o anche
u ::= v1 | v2 | . . . | vn .
Questo modo di rappresentare un insieme di produzioni detto forma di Backus-Naur,
abbreviato in BNF.
Per convenzione, useremo lettere minuscole o sequenze di lettere minuscole per indicare
i terminali della grammatica e lettere maiuscole o stringhe inizianti con la lettera maiuscola
per indicare i nonterminali. Questo permetter di presentare una grammatica fornendo solo
linsieme delle produzioni della grammatica stessa: i simboli terminali e non terminali saranno
riconoscibili grazie alla suddetta convenzione mentre si assumer che il simbolo iniziale sia il
primo simbolo nonterminale del membro sinistro della prima produzione.
Inoltre talvolta aggiungeremo dei pedici alle varie occorrenze di uno stesso nonterminale
per poterle distinguere e nominare.
Il seguente un esempio di grammatica:
P ::= aD | "
D ::= aP
Per poter definire il linguaggio generato da una grammatica abbiamo bisogno di specificare
formalmente il meccanismo di riscrittura di una stringa in unaltra. Le prossime due definizioni
sono dedicate a questo scopo.
Definizione 3.2. Sia G , hA, V, S, P i una grammatica, e siano y, z 2 (A [ V ) .
1. Scriviamo y ! z, e diciamo che z deriva direttamente (o in un passo) da y, se z
pu essere ottenuta da y rimpiazzando in y unoccorrenza del membro sinistro di una
produzione con il membro destro di tale produzione.
45
3.1 Grammatiche
P ! aa
Vediamo, grazie ad un paio di esempi, che tipo di ragionamento utilizzare per dimostrare
che un dato linguaggio generato da una data grammatica.
Esempio 3.4. Sia G1 la grammatica le cui produzioni sono
S ::= ab
aSb.
1}.
Cominciamo col dimostrare che L1 L(G1 ), cio che una stringa an bn con n
1
qualsiasi pu essere generata da G1 . A questo proposito basta esibire una derivazione
per an bn a partire da S, come ad esempio la seguente:
S ! aSb ! aaSbb ! an
Sbn
! a n bn
46
47
3.1 Grammatiche
S
A
a
S
A
B
b
B
b
ambigua infatti gli alberi mostrati in Figura 3.2 sono due alberi distinti per la derivazione
S ! ab.
Si noti comunque che gi la grammatica
S ::= ASB | c
A ::= aA | "
B ::= bB | "
48
S
S
S
S
b
S
S
A
B
b
Si osservi che non esiste una relazione fra lambiguit di una grammatica ed il fatto che
un albero di derivazione possa essere il risultato di diverse sequenze di derivazioni.
I linguaggi generati dai simboli non terminali di una grammatica libera dal contesto possono essere visti come una famiglia di insiemi definiti in maniera mutuamente ricorsiva per
mezzo di regole, dove le regole sono date dalle produzioni della grammatica. Vale quindi per
le grammatiche il principio di induzione strutturale che nello specifico viene talvolta detto
principio di induzione sui termini . Vediamo un esempio.
Esempio 3.6. Data la grammatica
E ::= a | E1 + E2 | (E)
dove i pedici, come detto, servono a dare un nome alle diverse occorrenze del nonterminale
E, proviamo, per induzione sulla struttura2 di E, che tutti gli elementi di L(E) hanno un
numero uguale di parentesi sinistre e destre.
Caso a. Questo caso banale, non essendoci alcuna parentesi nel terminale a.
Caso E1 + E2 . Per ipotesi induttiva abbiamo che E1 ed E2 hanno un numero uguale di
parentesi destre e sinistre, diciamo n per E1 , ed m per E2 . Abbiamo che E1 + E2 ha
m + n parentesi sinistre ed m + n parentesi destre.
Caso (E). Per lipotesi induttiva E ha lo stesso numero di parentesi sinistre e destre, diciamo
n; chiaramente (E) ha n + 1 parentesi sinistre e destre.
2
Le produzioni della grammatica possono essere viste come costruttori. Per ogni simbolo terminale a
abbiamo il costruttore di ariet 0 che rende a, abbiamo poi il costruttore di ariet 2 che presi e1 ed e2 rende
la scrittura formale e1 + e2 ed infine il costruttore di ariet 1 che preso e rende la scrittura formale (e).
49
3.1 Grammatiche
Introduciamo ora lultima classe di grammatiche.
Una grammatica si dice regolare se le sue produzioni sono della forma
U ! aT
oppure
U !b
oppure
U ! ",
L1
L2
L3
Ad esempio, il linguaggio
L1 , {an bn |n
1}
libero dal contesto. Infatti, abbiamo gi visto che L1 generato dalla grammatica libera G1
data da
S ::= ab aSb.
Tuttavia L1 non regolare: infatti L3 coincide con la classe dei linguaggi riconosciuti dagli
automi a stati finiti e un tale automa, se deve riconoscere an bn con n arbitrariamente grande,
allora non pu non riconoscere anche am bn con m 6= n. Quindi L3 L2 .
Consideriamo ora il linguaggio
L2 , {an bn cn |n
1} .
50
3.2
e
e
3 + (4 5),
(while p do c1 ); c2
La sintassi concreta deve tenere conto di questi aspetti e per far questo appesantita da
notazioni estranee al significato dei singoli costrutti.
Quando si interessati alle caratteristiche semantiche di un linguaggio risulta utile pertanto ricorrere a varianti sintattiche che sono note come sintassi astratta. Tali varianti permettono
di astrarre da molti dettagli di rappresentazione delle frasi del linguaggio e di concentrarsi
solo sulla struttura dei programmi, cio su come questi possono essere composti a partire da
frasi pi elementari. Il procedimento di determinazione della sintassi astratta di un linguaggio
consiste in una semplificazione delle produzioni che porta ad unaltra grammatica, generalmente ambigua, i cui alberi di generazione possono essere messi in corrispondenza con quelli
del linguaggio originario. La sintassi astratta pu essere ottenuta dalla sintassi concreta, ad
esempio, identificando alcune frasi, ignorando delle parentesi oppure ridenominando dei simboli. In questo modo viene stabilita una corrispondenza tra gli alberi ottenuti come risultato
dellanalizzatore sintattico (alberi di derivazione) ed i programmi ottenuti tramite la sintassi
astratta (programmi astratti). In pratica, in una sintassi astratta viene considerato solo ci
che rilevante ai fini della semantica, specificando quindi per ogni costrutto sintattico solo:
1. la categoria sintattica del costrutto,
2. la costruzione sintattica applicata.
Quindi, analizzando pi in dettaglio un linguaggio di programmazione, risulta utile
distinguere quattro componenti fondamentali:
3
Contrariamente a quanto normalmente si crede, le dizioni linguaggio e linguaggio di programmazione
denotano entit molto distinte.
4
(Diz.) Sintassi: studio dei procedimenti attraverso i quali le parole di una frase sono collegate le une alle
altre, dal greco syn (insieme) e taxis (ordine).
5
(Diz.) Semantica: Studio del significato delle parole e delle frasi, dal greco sema (segno). Si pensi anche
alla parola semaforo dal greco sema phoros (che porta il segnale).
51
def inisce
?
y P arser
Sintassi
astratta
def inisce
Alberi di sintassi
astratta
?
y Esecuzione
Semantica
def inisce
Significato degli
alberi
Frase (concreta):
2 (3 + 4)
#
Albero della
sintassi astratta:
*
+
2
3
Significato (valore):
14
52
E
T
P
N
D
::=
::=
::=
::=
::=
E+T | E T | T
T P | T /P | P
N | (E)
DN | D
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
(espressioni)
(termini)
(espressioni primarie)
(numeri)
(cifre)
(Gc )
3.3
Espressioni aritmetiche
53
::=
n | E+E | E
E | E E | E/E
(Ga )
N, E N, E/N
E ! 25 6 + 1.
Facciamo ora un altro passo di astrazione da quella che la rappresentazione sequenziale delle espressioni. Per cogliere invece la natura gerarchica delle espressioni aritmetiche
suciente la grammatica mostrata in Tabella 3.3.
La grammatica (Ga ) definisce infatti la sintassi astratta delle espressioni aritmetiche.
importante sottolineare che questa grammatica viene usata per generare gli alberi del linguaggio e non le frasi del linguaggio. Se venisse usata per generare stringhe allora tale grammatica
risulterebbe ovviamente ambigua (per esempio 2 3 + 4 ammetterebbe due alberi di derivazione). Si osservi anche che la definizione di sintassi astratta non fornice informazioni sulla
struttura dei numeri: compito del parser riconoscere un numero ed assegnargli un valore
semantico.
Di fronte alla frase 2(3+4) generata dalla grammatica Gc compito del parser ricostruire
lalbero di derivazione
54
ed associare a tale albero il giusto albero della sintassi astratta, che nello specifico risulta
essere
E
*
E
E
+
3
3.4
Automi
55
3.4 Automi
on
spento
acceso
ba
o
ng
bang
rotto
Figura 3.3: Un automa a stati finiti
Definizione 3.7. Un automa a stati finiti M descritto da una quintupla
M = hQ, A, !, q0 , F i
dove:
Q un insieme finito detto insieme degli stati,
A un insieme finito detto alfabeto di input,
! Q(A[{"})Q una relazione ternaria detta relazione di transizione; scriveremo
Una transizione q ! q 0 dellautoma viene rappresentata collegando lovale che rappresenta lo stato q con quello che rappresenta q 0 tramite un arco orientato dal primo stato
al secondo ed etichettato con il simbolo .
Lo stato iniziale viene indicato con una freccia entrante che non proviene da nessun
altro stato.
Ogni stato finale viene indicato con un ovale che ha un bordo doppio.
La semplice forma delle produzioni delle grammatiche regolari consente di metterle in
corrispondenza, in maniera naturale, con gli automi a stati finiti. Data una grammatica
regolare G = (A, V, S, P ), il corrispondente automa a stati finiti
MG = hQ, A, !, S, {qf }i
dove
Q = V [ {qf } linsieme degli stati (e coincide con linsieme dei simboli nonterminali
della grammatica unito con un nuovo stato qf ),
A lalfabeto (e coincide con quello della grammatica),
! Q (A [ {"}) Q la relazione di transizione ed definita da: A
b
! B se
56
=
) =
a
"
! ,
"
"
=
) = =
) !=
) per a 2 A,
s
1
n
=
) = =)
=)
dove s 2 A ed s = a1 an con ai 2 A,
57
3.5
Storicamente i sistemi di transizioni etichettate furono introdotti da Keller (1976) come un modello formale per descrivere programmi paralleli. In seguito (Plotkin, 1979) sono stati usati per dare una semantica
operazionale ai linguaggi di programmazione.
8
(Diz.) Sistema: Aggregato di parti che dipendono le une dalle altre secondo leggi e regole fisse e che
tendono a un medesimo fine, dal greco syn (insieme) e stema (collocare).
9
In letteratura si trovano a volte definizioni leggermente dierenti. Alcuni autori definiscono gli LTS
includendo anche un insieme di stati finali.
58
q0
pla
y
q3
pla
y
q4
rk
wo
q1
"
! =
a1
an
! , se s = a1 an con ai 2 A.
dove:
Q = { q0 , q1 , q2 , q3 , q4 },
A = { play, work, },
"
=
) = ! , se q =
) q 0 si scrive anche q ) q 0 ,
"
"
=
) = =
) !=
) , se 2 Act ,
s
=
) = =) =) , se s = 1 n con i 2 Act .
s
59
Nel seguito useremo , , . . . come generici elementi di Act, come generico elemento di
Act e s come generica sequenza finita di azioni.
In alcuni casi potremmo essere interessati soltanto alla capacit da parte di uno stato di
eettuare unazione od una sequenza di azioni, indipendentemente dallo stato raggiunto, ed
useremo le seguenti notazioni:
Le notazioni q ! , q 6 ! , q =
) , q=
6),q=
) e q=
6 ) hanno significati simili. Uno stato q si
dice stabile se q 6 ! .
Useremo infine la seguente notazione
se 6= ,
=
"
se = .
Esempio 3.12. [Bill-Ben] Riprendiamo lEsempio 3.11, dove le azioni visibili sono play e
work, e lazione invisibile . Alcune derivazioni possibili sono le seguenti:
q0
play
work
! q3
q1
work
! ! q4
q2
play
! ! q4
q2 ==) q4
work
q1 ===) q4
q3 =
) q4
Strutture di Kripke. Le strutture di Kripke sono dei sistemi in cui vengono etichettati gli
stati invece degli archi. La definizione formale di una struttura di Kripke la seguente.
Definizione 3.13. Una struttura di Kripke (KS) una quadrupla hQ, !, AP, Ii, dove
Q linsieme delle stati (o configurazioni),
60
Definizione 3.14. Sia K , hQ, !, AP, I i una struttura di Kripke. Un cammino da uno
stato q0 2 Q una sequenza (finita o infinita) di stati della forma
q 0 , q 1 , q2 , q3 . . .
tale che qi ! qi+1 per ogni i 0. Per i 0, denoteremo con [i] il suo i + 1-esimo stato e con
i il cammino da [i] che susso di (cio il cammino qi qi+1 qi+2 qi+3 . . .). Indicheremo
con P aths(q) linsieme dei cammini che cominciano dallo stato q.
Nel seguito, le KS saranno principalmente utilizzate nel Capitolo 13 come modelli di interpretazione di alcune logiche temporali. In tale contesto, si assume solitamente che qualsiasi
KS hQ, !, AP, Ii soddisfa la seguente propriet
8q 2 Q, 9q 0 2 Q tale che q ! q 0 ,
cio ogni stato ha almeno un successore, quindi i cammini in una tale struttura sono infiniti.
Definizione 3.15. Per ogni KS K , hQ, !, AP, I i e per ogni stato q0 2 Q c un albero
delle computazioni infinito con radice q0 tale che hq, q 0 i un arco dellalbero se e soltanto se
q ! q 0 . Tale albero ottenuto dispiegando la KS a partire da q0 .
Si osservi che gli alberi delle computazioni sono alberi i cui nodi sono etichettati da insiemi
di proposizioni atomiche. Un albero definito nella maniera usuale. Ha ununica radice e
ogni nodo qn pu essere raggiunto dalla radice tramite un unico cammino. Se !+ indica la
chiusura transitiva di !, hq1 , q2 i 2!+ verificata se q1 un nodo che si trova nellunico
cammino che va dalla radice al nodo q2 .
3.6
In questa sezione, usiamo i sistemi di transizioni per definire una semantica operazionale per
le espressioni aritmetiche la cui sintassi astratta data dalla grammatica (Ga ) mostrata in
Tabella 3.3.
Il significato intuitivo di unespressione un numero. Diamo le regole per calcolare questo
numero definendo un sistema di transizioni10 i cui stati sono le espressioni generate dalla
grammatica in Tabella 3.3. Si noti, tra laltro, che alcuni degli stati del sistema sono finali,
nel senso che non hanno transizioni uscenti; tali stati corrispondono ai numeri. La relazione
di transizione definita tramite un sistema di regole di inferenza come la pi piccola relazione
che soddisfa gli assiomi e le regole in Tabella 3.4, dove op varia sullinsieme degli operatori
aritmetici; il sistema di inferenza quindi composto da dodici regole, ottenute istanziando op.
Una transizione quindi possibile (pu essere dedotta) se e solo se essa provabile tramite
le regole di inferenza della Tabella 3.4. La regola (op) stabilisce che lespressione m op n si
trasforma in k allorquando lapplicazione delloperazione op agli argomenti m ed n produce
come risultato k. Questa lunica regola che coinvolge eettivamente gli operatori aritmetici.
Le altre due regole consentono di ridurre ad un numero gli argomenti di un operatore. In
particolare, (redl) permette di eettuare un passo della trasformazione delloperando sinistro,
10
Si noti che i sistemi di transizioni usati in questa sezione non fanno uso di etichette. Intuitivamente, ci si
spiega col fatto che le transizioni corrispondono in ogni caso ad azioni interne, per le quali non necessario
pubblicare alcuna informazione visibile (che il ruolo tipicamente ricoperto dalle etichette delle transizioni).
61
m op n ! k
(m op n = k)
(op)
E1 ! E10
E1 op E2 ! E10 op E2
(redl)
E2 ! E20
E1 op E2 ! E1 op E20
(redr)
4
7
1) ! (4 + 21)/(6
1) ! 25/(6
1) ! 25/5 ! 5.
(6 1 = 5) (op)
1 !5
(redr)
1) ! 25/5
1).
62
!
!m
E1
!
! m1 E2 !
! m2
(m1 op m2 = k)
E1 op E2 !
!k
1)
!
!5
7 !
!7 3 !
! 3 (7 3 = 21)
!
!4
73 !
! 21 (4 + 21 = 25)
6
4 + (7 3) !
! 25
(4 + (7 3))/(6 1) !
!5
!
!6
6 1
1 !
! 1 (6 1 = 5)
!
!5
(25/5 = 5)
E ! n se e solo se E
3.7
!
! n.
Esercizi
ambigua ossia che esistono frasi del linguaggio da essa generato che ammettono due alberi di
derivazione.
63
3.7 Esercizi
3.4 Dimostrare che tutti gli elementi del linguaggio generato dalla grammatica dellesempio 2.4.4
hanno pi a che +.
3.5 Data la grammatica
S ::= aT | "
T ::= aSS
dimostrare che essa genera solo stringhe di lunghezza pari.
3.6 Data la grammatica
S
T
::= aB
::= aSS
"
1} [ {an b2n |n
3.8 Dimostrare che linsieme di tutte le stringhe formate da x, y e z che contengono un numero
dispari di x, un numero dispari di y ed un numero pari di z un linguaggio regolare sullalfabeto
{x, y, z}.
3.9 Dimostrare che il linguaggio L , {xr y s z t |s = r + t} libero (Suggerimento: si consideri la
grammatica per il linguaggio {an bn |n 1}).
3.10 Scrivere una grammatica dipendente da contesto per il linguaggio L , {an ban can |n
1}.
3.11 Dimostrare per induzione strutturale che ogni stringa generata dalla grammatica
S ::= aSbS | bSaS | "
appartiene al linguaggio
L = {w | w 2 {a, b} e w contiene tante a quante b}.
Dimostrare, per induzione sulla lunghezza delle parole, che la grammatica data genera
esattamente il linguaggio L.
3.12 La grammatica
E ::= n | E + E | (E) (E)
genera le espressioni aritmetiche con gli operatori di somma e moltiplicazione, in cui la moltiplicazione ha precedenza sulla somma. Si determini la corrispondente sintassi astratta e si
discutano le ragioni per cui lambiguit di questultima non crea problemi nella valutazione
delle espressioni.
3.13 Data la grammatica dellesercizio precedente, scrivere gli alberi di derivazione, concreti ed
astratti, per le espressioni:
1. (4 + 14) (3);
64
3.14 Fornire lespressione, derivante dalla sintassi concreta dellesercizio 5, che ha il seguente albero
di derivazione:
*
*
1
+
12
5.
E ! n se e solo se E
!
! n.
3.16 Provare che, per ogni espressione aritmetica E descritta nella Sezione 3.3,
E ! E1 , E ! E2 implica E1
!
! n, E2
!
! n.
Capitolo 4
Sintassi e denotazioni
SOMMARIO
Questo capitolo introduce alcune nozioni e definizioni preliminari di semantica denotazionale
e le illustra tramite due esempi di descrizione semantica di semplici formalismi. Cominciamo
col chiarire la dierenza fra notazioni sintattiche e denotazioni semantiche. Quindi, come
primo esempio presentiamo la semantica denotazionale di una semplice calcolatrice tascabile
e come secondo quella delle espressioni regolari. Vedremo che il principio di induzione strutturale uno strumento fondamentale per definire la semantica denotazionale e dimostrare
propriet dei linguaggi generati tramite grammatiche. Nel caso delle espressioni regolari mostreremo anche come definire semantiche coerenti usando lapproccio operazionale e quello
assiomatico.
4.1
Vogliamo ora chiarire come bisogna procedere per definire la semantica di un programma
scritto, ovviamente, in sintassi concreta utilizzando le funzioni di interpretazione semantica
che sono invece definite a partire dalla sintassi astratta del linguaggio stesso. Il procedimento
consiste di tre passi:
1. si usa la sintassi concreta per definire le frasi del linguaggio concreto e quindi lalbero
di parsing del programma;
2. si usa la corrispondenza tra sintassi concreta e sintassi astratta per ottenere lalbero
astratto;
3. si usano le funzioni di interpretazione semantica per definire il significato degli alberi
astratti.
Qualcosa di simile in realt stato gi fatto in Sezione 3.6 per definire la semantica
operazionale delle espressioni aritmetiche, dove per il punto 3. rimpiazzato come segue
30 . si usa un sistema di transizioni etichettato per definire il significato degli alberi astratti.
Per quanto riguarda il punto 3. necessario:
1. stabilire la natura degli oggetti matematici che si intendono usare come denotazioni,
66
Il primo problema sar discusso nel Capitolo 6. Il secondo problema si risolve definendo
funzioni di interpretazione tra i termini generati dalla sintassi astratta e gli opportuni domini semantici. Per fare un esempio concreto, se la sintassi del linguaggio prevede quattro
domini sintattici, e cio Programmi, Dichiarazioni, Espressioni e Comandi, avremo un modello semantico costituito da quattro domini semantici e quattro funzioni di interpretazione
semantica, ciascuna da un dominio sintattico al corrispondente dominio semantico. Queste
ultime sono definite per induzione strutturale sulla sintassi dei programmi. Quindi, ad ogni
produzione della grammatica che definisce il linguaggio corrisponder un caso della definizione della funzione di interpretazione semantica, che avr la stessa struttura ricorsiva della
corrispondente produzione. Per esempio, i linguaggi di programmazione hanno solitamente
una produzione che stabilisce che un comando pu essere ottenuto mettendo in sequenza due
comandi qualsiasi:
C ::= | C; C | . . . ;
una clausola della funzione di interpretazione semantica dei comandi avr allora la forma:
C[[C1 ; C2 ]] = C[[C1 ]] C[[C2 ]],
in modo che alloperatore sintattico ; corrisponda loperatore semantico . Questo esempio
mette in luce due propriet essenziali dellapproccio denotazionale:
1. in corrispondenza ad ogni operatore sintattico (nel nostro esempio ;) viene definito un
operatore semantico (nel nostro esempio );
2. la semantica di un comando composto definita ricorsivamente in termini della semantica dei comandi che la compongono, cos come la sintassi della sequenza di comandi
definita ricorsivamente in base alla sintassi dei comandi stessi.
La seconda propriet descritta sopra va anche sotto il nome di composizionalit con cui si
intende che il significato di un termine composto costruito in base al significato dei termini
che lo compongono.
A titolo esemplificativo, per evidenziare le caratteristiche fondamentali delle funzioni di
interpretazione semantica, definiamo qui di seguito una semantica denotazionale dei numeri
binari in termini di numeri decimali. Relativamente a tale esempio, la Tabella 4.1 mostra le
tre componenti fondamentali di una definizione denotazionale:
1. il dominio sintattico: il linguaggio dei numeri binari;
2. il dominio semantico: i naturali;
3. la funzione di interpretazione semantica, che ad ogni numero binario associa un naturale.
Dominio Sintattico:
Grammatica:
Dominio Semantico:
Operazioni:
Funzione di Interpretazione
Semantica:
67
Sintassi
Bin
B ::= 0 | 1 | B 0 | B 1
Semantica
N = {zero, uno, due, . . . }
pi`
u, per : N N ! N
M[[0]]
= zero
M[[1]]
= uno
M[[B 0]] = (M[[B]] per due) pi`
u M[[0]]
M[[B 1]] = (M[[B]] per due) pi`
u M[[1]]
68
continuando abbiamo
(((M[[1]] 2) + M[[0]]) 2) + M[[1]] = ((1 2) + 0) 2) + 1 = 5.
Lesempio riportato sopra segue un approccio top-down per cui lespressione ottenuta sulla
destra dell= pu essere semplificata solo quando, a seguito di successive riscritture, si arriva
a dover interpretare il solo simbolo iniziale del numero binario originario. Alternativamente,
possibile seguire un approccio bottom-up che, nel caso del numero 101, consiste nel determinare prima il valore di tutte le sue sottostringhe, cio 1 e 10, e quindi di utilizzarle per
definire il significato dellintera stringa. In questo caso la sequenza 101 sarebbe valutata nel
modo seguente:
M[[1]] = 1
M[[10]] = (M[[1]] 2) + M[[0]] = 2
M[[101]] = (M[[10]] 2) + M[[1]] = 5.
Chiaramente la scelta di un approccio o dellaltro dipende dai gusti di chi specifica; bisogna comunque dire che lapproccio bottom-up ha il vantaggio di garantire che la lunghezza
delle formule intermedie che si originano nel processo di valutazione semantica non cresca
proporzionalmente al termine che si sta specificando: in generale questo fatto garantisce una
maggiore leggibilit.
4.2
Per introdurre il lettore alla metodologia propria dello studio dei linguaggi di programmazione,
consideriamo il linguaggio che deve essere usato per servirsi di una semplice calcolatrice tascabile, la cui interfaccia rappresentata in Figura 4.1. Si noti che il linguaggio delle espressioni
aritmetiche introdotto in Sezione 3.3 parte del linguaggio della calcolatrice tascabile.
Lunica dicolt nella descrizione del comportamento della calcolatrice data dalla disponibilit di tasti per la memorizzazione di risultati intermedi; daltra parte questa la
caratteristica che rende il suo linguaggio simile ad un linguaggio di programmazione reale (e
lo dierenzia da quello delle espressioni aritmetiche).
La calcolatrice permette di eettuare le quattro operazioni ed fornita di un visore e
di una cella di memoria, di quattro tasti-comandi tramite i quali possibile modificare il
contenuto della memoria (MC, MR, M-, M+) e di un altro tasto-comando che permette di
rimediare a situazioni di errore e di azzerare il contenuto della cella di memoria (CE/C).
Rispetto al modo standard di interagire con la calcolatrice, che consiste nel premere tasti
in una qualsiasi sequenza, noi porremo delle restrizioni e chiederemo che i suoi programmi
seguano un particolare protocollo.
Sebbene sia fisicamente possibile premere il tasto + subito dopo quello
, premere lo
stesso tasto operazione un numero qualsiasi di volte oppure premere un qualsiasi tasto prima
di aver acceso la calcolatrice, noi lo vieteremo imponendo alcune restrizioni nella definizione
dei programmi accettabili dalla calcolatrice. Potremo allora parlare di sequenze di comandi
ben formati (corretti) ed ignorare tutti i comandi non corretti sintatticamente.
La nostra sintassi richiede che tutti i programmi comincino con laccensione della macchina
(On) e prevede che essi consistano di una sequenza di espressioni aritmetiche separate dal
simbolo uguale (per determinare risultati intermedi), inframmezzate da comandi che servono
69
On
Off
MC
MR
M-
CE
C
M+
::= On S
Tutti i programmi sono formati da una sequenza di istruzioni preceduta
dalla parola chiave On.
S ::= E = S | O | C S
Una sequenza di istruzioni pu essere costituita da:
unespressione seguita dal simbolo = e quindi ancora da una
sequenza di istruzioni;
la parola chiave O;
un comando seguito ancora da una sequenza di istruzioni.
70
::= N | MR
I numeri richiamati dalla memoria vengono qui distinti da quelli composti
premendo i tasti numerici della calcolatrice.
::= D | N D
Queste e le seguenti sono le produzioni viste in precedenza per descrivere
il meccanismo di generazione di un numero.
D ::= 0 | 1 | | 9
C ::= M+ | M- | MC | CE/C
I comandi disponibili per la gestione della cella di memoria e del visore
della calcolatrice.
Esempio 4.1. I programmi
On 5 + 37 2 = M+ O,
On 5 + 37 2 = M+ 44 + MR = O
sono sintatticamente corretti secondo le regole date sopra, mentre il programma
On 5 + 4 MR = O
non corretto perch non consentito premere il tasto MR dopo aver composto un numero.
4.3
Chiamiamo G la grammatica proposta per generare il linguaggio dei programmi accettati dalla
calcolatrice tascabile nella Sezione 4.2. L(G) il linguaggio dei programmi accettati dalla
calcolatrice. La grammatica G stata introdotta pensando alle diverse categorie sintattiche
che possono intervenire nel progetto del linguaggio, ed una grammatica libera dal contesto.
Ovviamente, G non lunica grammatica che genera L(G) ed il fatto che G sia libera dal
contesto non implica che L(G) sia un linguaggio strettamente libero dal contesto. Infatti,
L(G) pu essere generato anche a partire da unaltra grammatica G0 che risulta essere regolare,
e quindi un linguaggio regolare (si veda quanto detto in Sezione 3.1). La nuova grammatica
G0 la seguente:
P ::= On S
S ::= O | d T | MR U | c S
T ::= d T | o V | = S
(4.1)
U ::= o V | = S
V ::= MR U | d T,
71
dove d indica una qualunque cifra fra 0 e 9, c indica un comando (manipolazione della memoria
e cancellazione del visore o dellerrore), ed o indica una qualunque operazione aritmetica.
Volendo scrivere la grammatica senza considerare queste abbreviazioni dovremmo scrivere le
dieci produzioni
0 T | 1 T | | 9 T
::=
::=
::=
::=
::=
On S
E = S | O | c S
M |EoM
N | MR
d|N d
(4.2)
::=
::=
::=
::=
d T | MR U
dT |oV |"
oV |"
MR U | d T,
E
M
N
::= M | E o M
::= N | MR
::= d | N d
72
On
Off
MC
MR
M-
CE
C
M+
d
o
c
On
= 0 ,..., 9
= + ,..., /
= MC , , M- , M+
CE
C
P
c
On
Off
MR
M-
CE
C
M+
MC
STOP
Off
S
d
MR
On
Off
On
Off
MC
MC
MR
MR
M-
M-
CE
C
M+
CE
C
M+
MR
On
Off
MC
MR
M-
CE
C
M+
73
0}
dove ciascun oi uno dei quattro simboli di operazione aritmetica e gli mi sono stringhe di
cifre numeriche oppure MR. Queste dimostrazioni possono essere realizzate per induzione
sulla struttura delle grammatiche date, e vengono lasciate al lettore.
Si osservi ora che ogni derivazione di una stringa del linguaggio tramite la prima grammatica termina con una riscrittura di uno dei nonterminali T oppure U in ", quindi, fissato
un simbolo ausiliario , le due grammatiche
E0
E
T
U
V
::=
::=
::=
::=
::=
E
d T | MR U
dT |oV |"
oV |"
MR U | d T,
E
T
U
V
::=
::=
::=
::=
d T | MR U
dT |oV |
oV |
MR U | d T,
4.4
Ricordiamo innanzitutto la sintassi dei programmi accettati dalla calcolatrice tascabile descritta nella Sezione 4.2, evitando di trattare dettagliatamente la generazione delle stringhe
corrispondenti ai numeri (in maniera simile a quanto fatto nella grammatica (Ga ) per le
espressioni aritmetiche mostrata in Tabella 3.3):
P
S
E
M
C
::=
::=
::=
::=
::=
On S
E = S | O | C S
M | E + M | E M | E M | E/M
n | MR
M+ | M- | MC | CE/C
74
75
76
E[[E
77
4.5
Espressioni regolari
NellIntroduzione a queste note abbiamo descritto brevemente i tre approcci pi usati per
definire la semantica di un linguaggio di programmazione. Tali approcci vanno sotto il nome
di semantica denotazionale, semantica operazionale e semantica assiomatica. Chiudiamo
questo capitolo con un esempio in cui utilizziamo tutti e tre gli approcci definendo delle
semantiche consistenti.
Il linguaggio scelto come esempio quello delle espressioni regolari. Le espressioni regolari
sono usualmente utilizzate per rappresentare linguaggi regolari in forma sintetica oppure per
descrivere le sequenze di azioni che un sistema pu eseguire o le sequenze di caratteri che un
automa a stati finiti pu riconoscere.
Le espressioni regolari possono essere considerate anche come un piccolo linguaggio di
programmazione. I costrutti da esse usati (sequenzializzazione, scelta, iterazione, processo
nullo) saranno presenti anche nei formalismi e nei linguaggi che analizzeremo nei prossimi
capitoli, per cui usare le espressioni regolari come caso di studio risulter anche propedeutico.
La sintassi (astratta) delle espressioni regolari la seguente:
E ::= 0 | 1 | a | E + E | E; E | E
(Ge )
dove a appartiene ad un alfabeto finito A.1 Per semplicit, loperatore ; viene talvolta
indicato con la giustapposizione delle due espressioni regolari che ne costituiscono gli argometi.
Nellinterpretazione pi comune, un elemento di A inteso rappresentare unazione atomica o evento. Lelemento 1 rappresenta levento terminale e lelemento 0 rappresenta levento
vuoto. Se E ed F sono espressioni regolari E + F rappresenta lespressione che pu essere
in alternativa lespressione E o lespressione F , lespressione E; F rappresenta lespressione
ottenuta sequenzializzando le espressioni E ed F ed, infine, lespressione E rappresenta la ripetizione di un numero finito (eventualmente nullo) di volte dellespressione E, cio la ripetuta
sequenzializzazione di E con se stessa.
Osserviamo che le descrizioni precedenti costituiscono solo una semantica intuitiva per le
espressioni regolari: dicile stabilire quale possa essere linterpretazione di una espressione
composta, come ad esempio
(a + b)
oppure
(a + b ) .
Per il momento, lunica aermazione che possiamo fare riguardo a queste due espressioni
regolari che esse sono sintatticamente dierenti. Vediamo allora i vari modi di dare una
semantica formale ed esatta alle espressioni regolari.
4.5.1
Semantica denotazionale
1
Nella sintassi concreta delle espressioni regolari, loperatore unario ha precedenza sugli operatori binari
+ e ; , mentre loperatore ; ha precedenza sulloperatore +. Quando necessario useremo le parentesi.
78
L[[0]] = ;
L[[1]] = {"}
Ln+1 = L Ln ,
[
L =
Ln .
n 0
Si noti che linsieme Ln linsieme delle stringhe composte dalla concatenazione di n stringhe
di L, mentre linsieme L linsieme di tutte le stringhe composte dalla concatenazione di un
numero qualsiasi di stringhe di L (compresa la stringa vuota).
Ci detto siamo in grado di definire la funzione L di interpretazione semantica delle espressioni regolari. Linterpretazione di una espressione E sar scritta come L[[E]]. La funzione
L definita per induzione strutturale sui termini del linguaggio dalle regole mostrate nella
Tabella 4.2.2
Date due espressioni regolari E ed F diremo che esse sono semanticamente uguali e scriveremo E ' F se L[[E]] = L[[F ]]. Useremo invece la notazione E F per indicare luguaglianza
sintattica. Risulta per esempio
a+a'a
infatti
L[[a + a]] = L[[a]] [ L[[a]] = L[[a]].
Esempio 4.3. Vediamo un altro esempio di uguaglianza semantica. Vogliamo dimostrare
che
(a + b) ' (a + b ) .
Dimostriamo prima che
L[[(a + b) ]] L[[(a + b ) ]]
2
Si osservi che nellultima regola loperatore gioca due ruoli distinti: nella prima occorrenza si tratta
delloperatore sintattico delle espressioni regolari, nella seconda occorrenza si tratta delloperatore definito
in precedenza sugli insiemi di stringhe.
79
L[[(a + b)]]
= L[[a]] [ L[[b]]
(L[[a]]) [ (L[[b]])
= L[[(a + b ) ]]
= L[[a ]] [ L[[b ]]
= L[[a + b ]]
L[[a]] [ L[[b]]
da cui la tesi segue ragionando come nel caso precedente. Sfruttando il fatto che loperatore
_ idempotente, quindi che
L[[a]] [ L[[b]]
L[[a]] [ L[[b]]
L[[a]] [ L[[b]]
A tale scopo, sia s 2 L[[a]] [ L[[b]] . Ci significa che o s = e quindi s 2 L[[a]] [ L[[b]]
per definizione, oppure per un qualche n
1, si ha s = s1 s2 sn e si 2 L[[a]] oppure
si 2 L[[b]] , per ogni 1 i n. Dato che L[[a]] (L[[a]] [ L[[b]]) e L[[b]] (L[[a]] [ L[[b]]) , da
ci segue che si 2 L[[a]] [ L[[b]] , per ogni 1 i n, e quindi s 2 L[[a]] [ L[[b]]
.
Si potrebbe dimostrare che la semantica denotazionale delle espressioni regolari soddisfa
le seguenti semplici propriet:
E + (F + G) ' (E + F ) + G
E+0'E
E (F G) ' (E F ) G
E (F + G) ' E F + E G
0E ' 0
E
'1+
0 '1
E E
E+F 'F +E
E+E 'E
(E + F ) G ' E G + F G
1E ' E
E ' (1 + E)
4.5.2
Semantica operazionale
Introduciamo adesso una semantica operazionale per le espressioni regolari, vale a dire un
meccanismo di esecuzione.
Diamo prima unidea intuitiva del meccanismo. Se a 2 A unespressione atomica, possiamo immaginare che lesecuzione di a corrisponda per esempio a stampare il simbolo a.
Lesecuzione dellespressione composta E + F dovr consistere di tutte le azioni di E o, in alternativa, di tutte le azioni di F . Lesecuzione dellespressione composta E; F dovr consistere
delle azioni di E seguite dalle azioni di F .
80
(Tic)
(Atom)
"
1 !1
(Sum1 )
E ! E0
a
(Seq1 )
(Star1 )
! E0
! F0
! F0
E+F
"
E ! E0
(Seq2 )
! E0; F
E; F
(Sum2 )
E+F
a2A
a !1
E !1
"
!F
E; F
(Star2 )
"
E ! 1
E ! E0
E ! E0; E
E ! E1 ! E2 ! . . . ! En E 0 .
Tracce(E) = {s 2 A : E =
) 1},
81
a !1
(Atom)
a+b !1
(a + b)
"
1 !1
(Sum1 )
! 1; (a + b)
(T ic)
"
1; (a + b) ! (a + b)
(Star2 )
as0
s0
(Seq2 )
s0
s0
segue E =
) 1. Quindi, per ipotesi induttiva, F =
) 1. Basta allora dimostrare che F =
)F
s
a
per ottenere F =
) 1. Ora, F =
) F giustificata da
a
a !1
a
(Atom)
a ! 1; a
(Star2 )
a + b ! 1; a
"
1 !1
(Sum1 )
(a + b ) ! 1; a ; (a + b )
"
1; a ; (a + b ) ! a ; (a + b )
(Star2 )
"
a ! 1
"
"
(T ic)
(Seq2 )
(Star1 )
a ; (a + b ) ! (a + b )
(Seq2 )
"
! ! ! F.
Vediamo ora come associare ad ogni espressione regolare una macchina astratta che descrive lesecuzione dellespressione stessa. Pi precisamente, utilizzando la relazione di transizione
introdotta per le espressioni regolari, associamo ad ogni espressione regolare un automa a stati
finiti.
Definizione 4.6. Sia E unespressione regolare, definiamo lautoma a stati finiti associato
ad E come
ME = QE , A, !E , E, {1}
dove
82
QE = {F : 9s 2 A tale che E =
) F } linsieme degli stati dellautoma ed costituito
dalle espressioni raggiungibili a partire da E;
A lalfabeto dellautoma (e coincide con quello dellespressione regolare);
!E la relazione di transizione tra stati in QE ed definita da F
con 2 A [ {"};
!E F 0 se F
! F0
(a + b ) ! 1; b ; (a + b )
che serve a costruire lautoma di destra nella figura viene derivata nel modo seguente:
(Atom)
b !1
b
! 1; b
a +b
b
! 1; b
(Star2 )
(Sum2 )
(a + b ) ! 1; b ; (a + b )
(Star2 )
Vogliamo ora dimostrare che linsieme delle stringhe che unespressione E pu produrre
durante la sua esecuzione, secondo la semantica operazionale data, coincide con il linguaggio
riconosciuto dallautoma ME associato allespressione E.
83
Teorema 4.7. Sia E unespressione regolare ed ME lautoma a stati finiti ad essa associato.
Allora
Tracce(E) = L(ME )
dove L(ME ) il linguaggio riconosciuto da ME .
a
w0
E=
) E1 =) 1.
w0
Per ipotesi induttiva w0 2 L(ME1 ) ossia E1 =)E 1. La tesi segue allora osservando che,
sempre per definizione,
a
a
E=
) E1
implica
E =)E E1 .
() Procediamo di nuovo per induzione sulla lunghezza di w 2 L(ME ) e proviamo che w 2
Tracce(E). Il caso base banale. Se w = aw0 per un certo w0 , abbiamo per ipotesi
a
w0
E =)E E 0 =)E 1.
w0
w0
E1 + E2 ! F =) 1,
84
w0
w0
E1 ! F =) 1
oppure
E2 ! F =) 1.
w 2 L[[E1 ]]
oppure
w 2 L[[E2 ]]
E1 =) 1 e E2 =) 1.
Quindi, per ipotesi induttiva abbiamo che
x 2 L[[E1 ]] e y 2 L[[E2 ]],
E E1 Indichiamo con S(E1 , w) il numero di volte che la regola Star2 viene applicata nella
w
sequenza di transizioni E1 =) 1 e dimostriamo per induzione (locale) su n = S(E1 , w)
che
w 2 Ln [[E1 ]].
(Ln [[E1 ]] sta per (L[[E1 ]])n )
Se S(E1 , w) = 0, cio Star2 non viene mai usata, allora vuol dire che stata usata Star1 ,
quindi w = ". Infatti la semantica operazionale delloperatore modellata dalle due
regole Star1 e Star2 . La tesi segue dal fatto che, per definizione, si ha {"} = " 2 L0 [[E1 ]].
Se invece S(E1 , w) = n + 1, allora si ha che esistono due stringhe x, y tali che w = xy e
y
"
E1 =) E1 =) E1 ! 1,
con S(E1 , x) = n, per cui per ipotesi induttiva (locale) x 2 Ln [[E1 ]]. Dato che S(E1 , y) =
y
1, abbiamo che la regola Star2 deve essere applicata esattamente una volta in E1 =) E1
E1 ! E 0 ; E1 =) E1 .
y0
y0
E1 ==) 1
"
1
2
n
E1 =)
1; E1 =)
1; E1 =)
1; E1 ! 1
85
4.5.3
Semantica assiomatica
Vediamo infine una semantica assiomatica per le espressioni regolari. Diamo cio un insieme
di assiomi e di regole di inferenza che definiscono una relazione di binaria sullinsieme delle
espressioni regolari. Denoteremo con luguaglianza E = F il fatto che le espressioni regolari
E e F sono uguagliate da tale sistema di inferenza (ossia il fatto che esiste una derivazione di
E = F ).
Prima di introdurre il sistema di inferenza abbiamo bisogno della seguente definizione.
Definizione 4.9. Una espressioni regolare E si dice possedere la propriet di produrre la
stringa vuota se una delle seguenti tre condizioni verificata:
E E1 per un certo E1 ,
E una somma di espressioni regolari ed una di queste possiede la propriet di produrre
la stringa vuota,
E una sequenzializzazione di espressioni regolari ciascuna delle quali possiede la
propriet di produrre la stringa vuota.
La Tabella 4.4 riporta gli assiomi e le regole del sistema di inferenza (gli assiomi sono stati
divisi in gruppi e agli assiomi ed ai gruppi stessi sono stati dati dei nomi; per semplificare le
notazioni, per denotare loperatore di sequenzializzazione stata usata la giustapposizione).
Facciamo alcune osservazioni sul sistema di inferenza presentato. Innanzitutto si pu
osservare che gli assiomi e le regole risultano sensati ossia coerenti con la nostra intuizione
sul significato delle espressioni regolari. Non dicile vedere (e lo abbiamo gi osservato
nella Sezione 4.5.3) che gli assiomi sono coerenti anche con la semantica denotazionale. Per
esempio, lassioma 0E = 0 in accordo con il fatto che
L[[0E]] = L[[0]] L[[E]] = ; L[[E]] = ; = L[[0]].
Tuttavia rispetto alle semantiche viste finora, mostrare che due espressioni regolari sono
uguali risulta pi dicile. Si osservi per esempio che anche il fatto che per ogni espressione
regolare E risulta E = E, cio che = una relazione riflessiva, richiede una dimostrazione
che basata sulla sola applicazione della regola di sostituzione:
E+E =E
E=E
E+E =E
E =E+E
(regola1)
E=F
F =F
F =E
(regola1)
E=F
F =E
(regola1)
E=G
F =G
(regola1)
86
Assiomi:
E + (F + G) = (E + F ) + G
E+F =F +E
E+0=E
(assoc +)
(comm +)
(neutro +)
E (F G) = (E F ) G
1E = E
(assoc ;)
(neutro ;)
E (F + G) = E F + E G
(E + F ) G = E G + F G
0E = 0
9
=
;
E E
=1+
E = (1 + E)
0 = 1
(distribS)
(distribD)
(assorb 0)
(modulo +, ;)
(unfolding)
(assorb *)
(00 )
9
=
(regole *)
Regola 1 (Sostituzione):
E=F
G=H
G0 = H
G0 = G
(monoide ;)
9
=
E+E =E
E
(monoide+)
;
;
(idempotenza +)
(absorb0)
E0 = E0
E00 = E0
00 = 0
(regola1)
E00 + 0 = E0
(absorb0)
E0 = 00
E0 = 0
E0 + 0 = E0
(neutro+)
(regola1)
(regola2)
(regola1)
se e solo se
L[[E]] = L[[F ]].
Se diciamo che una uguaglianza E = F valida quando L[[E]] = L[[F ]], allora possiamo chiederci se il sistema di inferenza dimostra solo uguaglianze valide (correttezza) e se le dimostra
87
tutte (completezza), cio se vero che se una uguaglianza valida allora essa dimostrabile dal sistema di inferenza. La dimostrazione della correttezza immediata ed gi stata
indirettamente osservata alla fine della Sezione 4.5.1. La dimostrazione della completezza
invece delicata e in queste note ci limitiamo a dimostrare la completezza per linsieme delle
espressioni regolari che non usano loperatore .
Cominciamo con lintrodurre il concetto di forma normale per espressioni regolari senza .
Definizione 4.10. Una espressione regolare senza si dice in forma normale se o 1 oppure
della forma
X
si
i2I
Proposizione 4.11. Se E unespressione regolare senza , allora esiste unespressione regolare E 0 in forma normale tale che E = E 0 derivabile con il sistema di inferenza della
Tabella 4.4 (senza luso delle regole- e della regola 2).
Dimostrazione. Procediamo per induzione strutturale su E.
- Se E 0, 1, a non c nulla da dimostrare.
-PSe E EP
1 + E2 allora per induzione, e grazie alla regola di sostituzione, abbiamo E =
s
+
i
i2I
j2J tj e quindi, a meno di raccogliere tutti gli addendi in ununica somma per
mezzo dellassociativit e di eliminare gli addendi ripetuti per mezzo dellidempotenza, E
in forma normale.
-PSe E PE1 E2 allora per induzione, e grazie alla regola di P
sostituzione,
abbiamo E =
P
j2J tj e quindi, per la propriet distributiva, E =
i2I
j2J si tj ossia E =
Pi2I si
u
dove
K
=
I
J
ed
u
=
s
t
per
k
=
(i,
j).
Per
cui,
a
meno
di eliminare gli
i
j
k
k
k2K
addendi ripetuti per mezzo dellidempotenza, E in forma normale.
Siamo ora in grado di dimostrare la completezza del sistema di inferenza per le espressioni
regolari che non usano loperatore .
Teorema 4.12. Se E ed F sono espressioni regolari senza ed
L[[E]] = L[[F ]]
allora
E=F
della Tabella 4.4 (senza luso delle regole- e della regola 2).
Dimostrazione. Per la proposizione precedente esistono due forme normali E 0 ed F 0 tali che
le uguaglianze E = E 0 ed F = F 0 siano derivabili. Si noti che se E 0 1 allora, data
P lipotesi
L[[E]] P
= L[[F ]], segue che F 0 1 (e viceversa). Supponiamo quindi che E 0 i2I si ed
F 0 j2J tj . Basta quindi dimostrare che E 0 = F 0 , dopodiche la tesi segue applicando la
regola di sostituzione. Dalla correttezza degli assiomi segue L[[E]] = L[[E 0 ]] e L[[F ]] = L[[F 0 ]]
e quindi, data lipotesi L[[E]] = L[[F ]], segue che L[[E 0 ]] = L[[F 0 ]]. Usando la definizione di L
(Tabella 4.2) abbiamo
P
S
S
L[[E 0 ]] = L[[ i2I si ]] = i2I L[[si ]] = i2I {si } = {si : i 2 I}
88
ed analogamente
Per
applicando lassioma di commutativit della somma, abbiamo che
P cui, eventualmente
P
s
=
t
,
ossia
E0 = F 0.
i
j
i2I
j2J
4.6
Esercizi
4.1 Fornire la semantica denotazionale dei numeri in base 5, usando come dominio semantico i
naturali.
4.2 Considerare una variante della calcolatrice tascabile in cui il tasto M- sottrae il contenuto della
memoria a quello del visore.
4.3 Considerare una calcolatrice tascabile che ha una memoria con tre registri (a, b, c) a cui si accede
premendo i tasti MC, M+, M-, MR e poi il tasto On 1, 2, 3 volte, rispettivamente.
4.4 Modificare la sintassi e la semantica della calcolatrice tascabile in modo da distinguere i tasti
CE (cancellazione dopo errore) e C (cancellazione senza errore).
4.5 Descrivere in modo informale i linguaggi specificati dalle seguenti espressioni regolari:
a) (a; a) ; (b; b) ,
a) (a ; b ; c ) ,
b) (a; a; a + a; a; a; a) .
4.6 Si provi che L[[(a + b) ]] = L[[(a + b ) ]].
4.9 Siano E ed F espressioni regolari e sia s una stringa, si provi che se E; F =) 1, allora esistono
y
x
delle stringhe x e y tali che s = xy e E =) 1, F =) 1.
4.10 Si dimostrino le seguenti uguaglianze usando il sistema di inferenza della semantica assiomatica:
a) E = F =) F = E
b) E1 = E
c) E = F =) E = F
d) E + 1 = E
e) E + E = E
F ) 0 = 0
Parte II
Sistemi Sequenziali
Capitolo 5
-calculus
SOMMARIO
Questo capitolo presenta il -calculus, un sistema formale che ha un ruolo importante nello
studio dei fondamenti dei linguaggi di programmazione. Il -calculus fornisce infatti sia una
notazione semplice per la rappresentazione di funzioni nonch di altri importanti concetti di
programmazione, sia un sistema di calcolo basato su un insieme di regole di riduzione che
consente di studiare le propriet semantiche di funzioni e programmi.
Le funzioni giocano un ruolo importante nella definizione della semantica dei linguaggi di
programmazione, poich il significato di un programma sequenziale pu essere considerato una
funzione dai valori in input a quelli in output. Inoltre, le funzioni hanno un ruolo essenziale
in matematica, e infatti gran parte della teoria delle funzioni, comprese le questioni che
riguardano la computabilit, furono sviluppate come parte della logica matematica prima
ancora della nascita dei calcolatori. Tant vero che negli anni 30 del secolo scorso, il logico
americano Alonzo Church ide il -calculus [Chu41, Bar84, Bar90] come sistema formale per
definire in modo non ambiguo funzioni e manipolarle in maniera puramente sintattica.
Originariamente, quindi, il -calculus fu sviluppato come un ramo della logica matematica per definire formalmente la nozione di funzione calcolabile, in alternativa alla teoria degli
insiemi. Infatti, un modo semplice per definire le funzioni quello di vederle come insiemi di
coppie ordinate. Una funzione f : A ! B stata definita (si veda la Definizione 2.12) come
un sottoinsieme del prodotto cartesiano A B: cos (a, b) 2 f se e solo se la f assume valore
b sullargomento a. Tale definizione tuttavia non considera in alcun modo laspetto computazionale delle funzioni, vale a dire il processo che dallargomento conduce al valore. Inoltre,
essa non consente di descrivere in modo chiaro e semplice i meccanismi che permettono di costruire nuove funzioni a partire da funzioni gi definite. Un tipico esempio che illustra queste
dicolt dato dai funzionali, vale a dire funzioni che hanno funzioni fra i loro argomenti o
che producono funzioni come risultato. Al contrario, il -calculus, come altri formalismi quali
le funzioni ricorsive o le macchine di Turing, descrive come, mediante regole di riscrittura,
determinare meccanicamente i valori associati ad ogni argomento e come comporre funzioni,
risolvendo cos i problemi summenzionati in modo naturale ed elegante. Inoltre, lestrema
semplicit del sistema di calcolo lo rende interessante come modello per lo studio di propriet.
Nella teoria della computabilit il -calculus ha permesso di formalizzare una risposta
(negativa) al problema della decisione di Hilbert. Il potere espressivo del formalismo infatti
equivalente a quello delle macchine di Turing, come appunto la tesi di Church-Turing sostiene:
il -calculus (non tipato) pu esprimere e calcolare tutte le funzioni eettivamente calcolabili.
92
Capitolo 5 -calculus
Il -calculus tuttavia enfatizza luso delle regole di riscrittura pi che loperato delle macchine
che implementano le regole. Il metodo di riscrittura il calcolo.
Il -calculus ha anche avuto un ruolo importante nella teoria dei linguaggi di programmazione e ha fornito contributi importanti anche alla definizione formale della semantica dei
linguaggi di programmazione:
tutti i linguaggi di programmazione funzionali (quali Lisp, ML, Scheme, Haskell) sono sostanzialmente derivati direttamente dal -calculus che a sua volta pu essere considerato
il pi semplice linguaggio di programmazione;
sebbene sia capace di rappresentare tutte le funzioni calcolabili, la semplicit della
sua sintassi e della sua semantica forniscono uno strumento eccellente per studiare il
significato dei concetti dei linguaggi di programmazione;
la semantica denotazionale, uno degli approcci pi utilizzati per specificare formalmente
la semantica dei linguaggi, ha avuto origine dalla ricerca nel campo del -calculus e fa
largamente uso della notazione fornita dal -calculus per esprimere funzioni di ordine
superiore.
5.1
La -convenzioni semplificative
93
y,
y, possiamo quindi distinguere
y e g2 (y) = x
y,
y, g1 (5) = 5
y, g2 (3) = x
3.
Eettivamente, questa soluzione permette di evitare ambiguit e di caratterizzare univocamente quelle espressioni che rappresentano funzioni; essa, per, oltre a richiedere descrizioni
lunghe, ha lo svantaggio di richiedere che venga dato un nome ad ogni funzione definita. Inoltre, in alcune situazioni pu non essere chiaro come procedere nel definire una funzione: si
consideri ad esempio il caso in cui la funzione si ottenga come risultato dellapplicazione di
unaltra funzione ad un valore, oppure addirittura ad unulteriore funzione.
Per evitare questi problemi e per avere una notazione pi compatta, Alonzo Church ha
introdotto unoperazione che nota come -astrazione. Essa permette di specificare una
funzione ed i suoi argomenti nel modo seguente:
Sia E unespressione la cui variabile pu assumere valori in un dominio D. La
funzione
f : D ! D0
definita da
viene scritta
f x = E, 8x 2 D
x : D.E.
94
Capitolo 5 -calculus
Se consideriamo le espressioni sopra menzionate, abbiamo allora
g1 x.x y
h x. y.x y
g2 y.x y
k y. x.x y
e conseguentemente
g1 (0) ( x.x y)(0) = 0 y,
g2 (3) ( y.x y)(3) = x 3,
h(5)(3) ( x. y.x y)(5)(3) = 5
3.
x. y.x + 1
x.(x = 7) ! x
1, x + 1.
plus 2 3 = 5.
95
Una delle ragioni principali delluso della -notazione che essa permette di descrivere
naturalmente funzioni di ordine superiore, vale a dire funzioni che possono ricevere come
argomento, e produrre come risultato, altre funzioni.
Un esempio di funzione di ordine superiore il seguente:
plusc x.( y.x + y).
Abbiamo, ad esempio,
1. plusc 2 = ( x.( y.x + y)) 2 = y.2 + y
2. plusc 2 3 = ( x.( y.x + y)) 2 3 = ( y.2 + y) 3 = 2 + 3 = 5.
La funzione plusc applicata al valore 2 ha come risultato una funzione che associa naturali
a naturali, sommando 2 al suo argomento. La funzione plusc pu essere dunque applicata
anche ad un solo argomento. Il questo caso il suo valore sar una funzione, che a sua volta
potr accettare un altro argomento e produrre come risultato un intero.
Considerare le funzioni come se fossero tutte unarie e trattare funzioni di pi argomenti
come sequenze di funzioni unarie detto currificazione 1 . La currificazione fondamentale per
avere un formalismo che permetta di rappresentare in modo naturale i meccanismi con cui le
funzioni vengono combinate fra loro per ottenerne di nuove.
La -notazione risulter utile per definire funzioni e per riferirsi ad esse senza dover necessariamente dare loro un nome. Nel seguito di queste note, la notazione, arricchita con altri
costrutti derivati ad essa riconducibili, costituir il metalinguaggio (si veda Sezione 6.5) per
descrivere le funzioni di interpretazione semantica di diversi linguaggi di programmazione.
5.2
Il principio di estensionalit
Osserviamo adesso che lapplicazione di twice a succ ha fornito una nuova funzione x.(x+
1) + 1 che sommer 1 due volte consecutive al proprio argomento. Non possiamo dire tuttavia
che questa la funzione che prende un valore intero e gli somma 2, perch non vi nella
nostra notazione alcun modo di esprimere la propriet associativa della somma e trasformare
x.(x + 1) + 1
1
Loperazione di currificazione prende il nome dal logico americano Haskell Brooks Curry.
96
Capitolo 5 -calculus
in
x.x + (1 + 1)
e quindi in
x.x + 2.
Tuttavia, possiamo aermare che le due -espressioni
x.(x + 1) + 1 e
x.x + 2
sono equivalenti, perch esse forniscono evidentemente lo stesso risultato per ogni argomento.
In altre parole, gli insiemi di coppie
{(a, ( x.(x + 1) + 1) a) | a 2 N} e {(a, ( x.x + 2) a) | a 2 N}
coincidono, anche se la funzione che essi individuano viene rappresentata in due modi
dierenti.
Il principio che permette di considerare due -espressioni equivalenti se descrivono lo stesso
comportamento input-output viene detto principio di estensionalit. Esso viene espresso
formalmente come segue:
Siano e1 : D ! D0 e e2 : D ! D0 due -espressioni unarie, che rappresentano
due funzioni che associano elementi di D ad elementi di D0 . Allora diciamo che
e1 ed e2 sono estensionalmente equivalenti su D se e solo se individuano la stessa
funzione:
8d 2 D.e1 d = e2 d.
5.3
Operatori di n-upla
La -notazione uno strumento conveniente per definire funzioni composte. In questa sezione
descriviamo alcuni operatori che saranno utili allo scopo.
I primi operatori che consideriamo sono gli operatori di n-upla. Questi possono essere
utilizzati quando si desiderano formare funzioni di pi argomenti raggruppando questi ultimi
in ununica struttura.
Il costruttore di una n-upla organizza una sequenza ordinata di n espressioni in unespressione unica, in modo analogo a quanto avviene in programmazione tramite la struttura di
record. Ad esempio, date le espressioni T1 , . . . , Tn , il costruttore di n-upla fornisce la singola
espressione
hT1 , . . . , Tn i.
Ad ogni costruttore di n-ple sono associati n distruttori, detti proiettori, che consentono di
estrarre le singole componenti dalln-upla.
I costruttori ed i proiettori possono essere definiti tramite la -notazione nel modo
seguente:
Costruttori di n-ple: Dn x1 . . . xn x.xx1 . . . xn ;
97
Ne segue che lespressione x.xT1 . . . Tn rappresenta eettivamente nella -notazione lnupla hT1 , . . . , Tn i. Nel seguito, per comodit di notazione, useremo direttamente hT1 , . . . , Tn i
per rappresentare unn-upla e ni per indicare il selettore del suo i-esimo elemento (i n).
Come abbiamo gi visto, la -notazione considera tutti gli operatori come se fossero unari.
In alcuni casi tuttavia pu essere pi naturale fornire tutti gli argomenti ad una funzione n-aria
simultaneamente. In altre parole, una funzione n-aria pu essere trasformata in una funzione
unaria il cui argomento sia una n-upla. Per fare questo, si raggruppano gli argomenti della
funzione in una n-upla e si usano i proiettori per recuperare volta per volta largomento
opportuno. A partire dalla -espressione
f x1 . . . xn .E(x1 , . . . , xn ),
nella quale E(x1 , . . . , xn ) indica unespressione in cui compaiono le variabili x1 , . . . , xn ,
possibile costruire lespressione
f 0 x.E(n1 x, . . . , nn x),
rimpiazzando in E ciascuna xi con ni x. Per ogni n-upla hT1 , . . . , Tn i, si ha allora che
f 0 hT1 , . . . , Tn i = E(n1 hT1 , . . . , Tn i, . . . , nn hT1 , . . . , Tn i)
= E(T1 , . . . , Tn ) = f T1 . . . Tn .
Tramite le n-ple ed i proiettori possibile dunque ottenere le versioni non currificate delle
funzioni. Ad esempio, lespressione
somma x.(21 x) + (22 x).
tale che
somma h3, 5i ( x.(21 x) + (22 x))h3, 5i = 3 + 5 = 8.
Notazione 5.1. Per semplificare la notazione scriveremo le funzioni non currificate
semplicemente usando
(x1 , . . . , xn ).E(x1 , . . . , xn )
invece di
x.E(n1 x, . . . , nn x).
98
Capitolo 5 -calculus
5.4
Operatori di composizione
g e comp0 f g f g.
g) x = f (g x) e (f g) x = g(f x).
Inoltre, gli operatori di composizione sono entrambi associativi, per cui scriveremo
f1 f2 fn al posto di f1 (f2 ( (fn
fn ) ))
99
Allora
5.5
Il sistema di calcolo
5.5.1
Definizione 5.3. Dato un insieme numerabile Var di simboli distinti detti variabili, i cui elementi sono denotati da x, y, z, . . ., linsieme dei termini del -calculus definito attraverso
la seguente grammatica:
M ::= x | ( x.M ) | (M N )
Ad esempio, le espressioni
( x.x),
( x.( y.(x(xy)))),
( x.(xx))
100
Capitolo 5 -calculus
x. y.xy
x.( y.(xy)).
Inoltre, quando pi variabili sono astratte in successione, assumeremo di poterle scrivere tutte
dopo un unico ; ad esempio, i termini
xyz.xyz, x( uvz.uzv), x( uv.u( z.zv))
saranno considerati abbreviazioni, rispettivamente, di
x.( y.( z.xyz)), x( u.( v.( z.uzv))), x( u.( v.u( z.zv))).
La sintassi mostra che tutti i termini del -calculus sono unari. Prendiamo ad esempio il
termine T xy.yx. Esso rappresenta un operatore che, una volta applicato a due argomenti,
a e b, applica b ad a. Tuttavia i due argomenti non devono necessariamente essere passati
ambedue a T . Infatti lapplicazione T a fornisce un nuovo operatore, che potremmo chiamare
Ta , che rappresenta quella funzione che, preso ora un solo argomento, lo applica ad a. Questo
fenomeno risulta pi chiaro se si ricorda che il termine T sintatticamente equivalente a
x.( y.yx).
Osservazione 5.5. Nella sintassi non compaiono simboli di funzione di base (come gli operatori aritmetici) n costanti (come i naturali). In tal senso, essa potrebbe sembrare meno
espressiva della sintassi delle -espressioni sottintesa dalle sezioni precedenti. In eetti, possibile dimostrare che sia i naturali che linsieme di tutte le funzioni calcolabili sono codificabili
nella semplice sintassi presentata in questa sezione.
Ad esempio, il naturale n pu essere rappresentato dal termine
n xy. x(x(. . . (x y) . . .)),
| {z }
n volte
mentre i valori booleani true e false possono essere rappresentati dalle funzioni ( selettori)
true xy.x
false xy.y.
101
5.5.2
102
Capitolo 5 -calculus
103
( b.xv)z
(5.3)
xv.
necessario evitare che il passaggio dellargomento alla funzione comporti lintroduzione di legami per le variabili libere dellargomento stesso. In particolare, le variabili libere
nellargomento N devono essere dierenti da tutte le variabili legate dai in M .
Eseguendo le stesse operazioni che in (5.3) senza preoccuparsi che le variabili dellargomento restino libere dopo la sostituzione, otteniamo infatti, partendo dal termine ( uv.u)(xv)z,
che -equivalente a quello in (5.3),
( uv.u)(xv)z
( v.xv)z
xz 6= xv.
Ne segue che due termini che hanno apparentemente la stessa interpretazione vengono ad avere
due valori diversi: questo dovuto al fatto che la variabile v, libera prima della sostituzione,
viene a trovarsi nel corpo di un v: questo fenomeno si chiama collisione di variabili e deve
essere evitato durante la valutazione, ridenominando la variabile legata come di seguito
( uv.u)(xv)z ( ub.u)(xv)z
( b.xv)z
xv.
= N
= y
se x 6= y
= (M1 [N/x])(M2 [N/x])
= x.M
= y.(M [N/x])
se x 6= y
R
R
N
NZ
M
ZM
R
R
N
ZN
M
x.M
R
R
N
x.N
! , =) e = sui
104
Capitolo 5 -calculus
1.
( x.M )N ! M [N/x]
M ! N
MZ ! NZ
2.
M ! N
M =) M
3.
M ! N
ZM ! ZN
M =) N
M =) N
M =) N
M= N
M= N
N= M
M ! N
x.M !
x.N
N =) L
M =) L
M= N
N= L
M= L
105
Intuitivamente, questa regola consente di dichiarare identici due termini sulla base del principio che se essi si comportano allo stesso modo (una volta applicati ad un parametro) devono
quindi essere considerati identici. Quando diciamo che x.(M x) e M si comportano allo
stesso modo, intendiamo dire che per ogni N : ( x.(M x))N = (M x)[N/x] = M N . In pratica
la regola di -conversione giustifica una visione estensionale delle funzioni: cio due funzioni
sono uguali se producono gli stessi valori quando vengono passati loro gli stessi argomenti.
La regola di -conversione non strettamente necessaria per valutare -termini; noi la
menzioniamo per completezza.
Un termine della forma ( x.M )N chiamato -redesso, terminologia derivata da reduction expression che significa espressione che pu essere -ridotta. Il termine M [N/x]
risultante dalla -riduzione chiamato contratto. Lo scopo della valutazione di un -termine
quindi quello di ridurlo finch non contiene pi -redessi. Il termine cos ottenuto viene
detto forma normale e rappresenta la valutazione del -termine originario.
Definizione 5.15 (Forma normale). Diciamo che P una -forma normale se P non contiene
alcun -redesso. Un termine M si riduce a -forma normale (o ha -forma normale) se esiste
un termine N in -forma normale tale che M =) N .
Nel -calculus una funzione calcolabile (rappresentata da) una qualche -espressione in
grado di riscriversi fino a raggiungere una -forma normale. Esistono per anche termini che
generano una successione infinita di riscritture senza mai raggiungere una -forma normale,
che perci rappresentano funzioni non calcolabili. Un tipico esempio dato dallapplicazione
del duplicatore x.xx a se stesso
( x.xx)( x.xx).
Infatti, durante il processo di riduzione, il termine non fa altro che riprodurre se stesso:
( x.xx)( x.xx) =) ( x.xx)( x.xx) =) ( x.xx)( x.xx) =) . . .
La caratteristica di poter definire funzioni calcolabili e non calcolabili insieme alla ricorsione, rende il -calculus del tutto equivalente alle macchine di Turing ma con un approccio
completamente a-temporale.
Vale la pena notare che un termine potrebbe contenere pi di un redesso e potrebbe quindi
ridursi in diversi modi; ad esempio, i redessi presenti in
( x.x)(( u.uv)t)
sono stati sottolineati. Abbiamo allora
( x.x)(( u.uv)t) =) ( u.uv)t
ma anche
( x.x)(( u.uv)t) =) ( x.x)(tv).
Il criterio con cui viene scelto il redesso successivo da ridurre viene detto strategia di
riduzione. Ci sono varie strategie, come ad esempio quella detta normal order, che sceglie
sempre il redesso pi a sinistra tra quelli pi esterni, o quella detta applicative order che
invece sceglie il redesso pi a sinistra tra quelli pi interni.
Bench ci siano varie strategie di riduzione, vale tuttavia la seguente propriet di
confluenza o Church-Rosser :
106
Capitolo 5 -calculus
Se P =) Q e P =) R, allora esiste un termine S tale che Q =) S e R =) S.
5.6
-termine
Esercizi
5.3 I due termini (( yz.z(yz))( a.a) e ( yz.yzz)( ab.ba) possono essere considerati uguali?
Perch?
5.4 Si ponga
S xyz.xz(yz)
B xyz.x(yz)
K xy.x
C xyz.xzy
I x.x
W xy.xyy.
107
5.6 Esercizi
5.10 Esibire un termine
K = y.
Esibire:
Capitolo 6
SOMMARIO
Questo capitolo introduce le basi matematiche per la semantica denotazionale dei linguaggi
di programmazione. Introdurremo i concetti di insieme parzialmente ordinato completo,
funzione continua, minimo punto fisso e soluzione di un sistema di equazioni mutuamente
ricorsive. Presenteremo quindi i concetti di base della teoria dei domini ed alcuni operatori
che permettono di costruire domini a partire da domini pi semplici. Infine, definiremo un
metalinguaggio per esprimere le funzioni utilizzate per descrivere la semantica denotazionale di una vasta classe di linguaggi di programmazione e mostreremo che i costrutti del
metalinguaggio preservano la continuit.
Per studiare la semantica dei linguaggi di programmazione importante definire una teoria
matematica che permetta di parlare di significati. A tale scopo, la semantica denotazionale usa
la teoria dei domini e le funzioni sui domini. Dana Scott svilupp la teoria dei domini [Sco76]
per fornire un modello per il -calculus cos da gettare delle basi consistenti per la semantica
denotazionale. Senza un tale fondamento, non avremmo motivo di credere che le definizioni
denotazionali hanno realmente un significato matematico. Allo stesso tempo, la teoria dei
domini fornisce una valida interpretazione per funzioni e tipi definiti ricorsivamente.
La nozione centrale della teoria dei domini quella di dominio semantico, un insieme di
elementi, raggruppati perch condividono importanti propriet, strutturato da una relazione
di ordinamento parziale, v, basata sulla quantit di informazione associata ai singoli elementi.
Ogni dominio fornisce un insieme di operazioni che ben si comportano rispetto alla struttura
e che permettono di assemblare e disassemblare gli elementi del dominio stesso.
I domini permettono quindi di parlare di quantit di informazione contenuta in un elemento e, soprattutto, di elementi infiniti in termini delle loro approssimazioni finite. Infatti, i
domini garantiscono che tutte le sequenze, anche infinite, di elementi sempre pi definiti hanno un limite di cui gli elementi della sequenza sono approssimazioni via via migliori. Questa
propriet, che permette di rappresentare informazione infinita come limite di sequenze di elementi con informazione finita, essenziale per costruire una teoria delle funzioni, perch una
funzione ha un carattere intrinsecamente infinito, dovendo essere in generale definita per una
quantit infinita di argomenti. Analogo discorso vale per i programmi scritti in un linguaggio.
Quindi, il concetto di approssimazione connesso alla relazione di ordinamento parziale riveste
un ruolo fondamentale.
110
I domini sono anche dotati di un elemento minimo, ?, che rappresenta assenza di informazione. In pratica esso un elemento totalmente indefinito, che la peggiore approssimazione
di un qualsiasi elemento. La presenza di un elemento minimo nei domini permette di poter
considerare totali tutte le funzioni usate nella nostra indagine sulla semantica denotazionale.
Infatti, piuttosto che dire che una funzione f non definita su un elemento d del suo dominio,
scriveremo f (d) =?, dove ? lelemento minimo del codominio di f . Lelemento minimo
inoltre fondamentale per la semantica dei linguaggi di programmazione. Infatti, qualsiasi linguaggio che fornisce la possibilit di usare iterazione indefinita e funzioni ricorsive consente di
scrivere programmi che non terminano. Perci, per definire la semantica serve un meccanismo
per rappresentare la non terminazione e lelemento minimo pu essere visto come il risultato
di una computazione che non termina.
Definiremo vari operatori che permettono di costruire nuovi domini a partire da domini
pi semplici e mostreremo che le funzioni associate a tali costruzioni sono continue. Infatti,
quando si ha a che fare con insiemi strutturati, piuttosto che con insiemi senza alcuna struttura associata, di solito utile considerare funzioni che preservano la struttura, invece che
funzioni arbitrarie. Ci porta alla richiesta di monotonia, nel caso di insiemi parzialmente
ordinati (o poset), ed a quella di continuit, nel caso di insiemi parzialmente ordinati completi
(o cpo o domini). Le funzioni in questione costituiscono una sorta di -calculus esteso, un
metalinguaggio che nei capitoli successivi sar usato come formalismo matematico per definire la semantica denotazionale dei vari linguaggi considerati. Il fatto che il metalinguaggio
permetta di descrivere solo funzioni continue, ci consentir di assumere la continuit delle
funzioni che via via introdurremo, evitando di intercalare la loro presentazione con le relative
prove di continuit.
6.1
Definizioni ricorsive vengono utilizzate sia nei linguaggi di programmazione, che solitamente
permettono per esempio la definizione di funzioni o strutture dati (es. liste, alberi) ricorsive,
che nelle specifiche dei linguaggi stessi (le grammatiche che generano i termini di un linguaggio
sono solitamente ricorsive). Costrutti familiari nella pratica della programmazione vengono
altrettanto spesso spiegati intuitivamente tramite equazioni ricorsive. Si pensi ad esempio
al costrutto while ed allequazione
while e do c = if e then begin c; while e do c end,
con la quale si indica che lesecuzione di un ciclo while consiste nella valutazione dellespressione booleana e seguita, nel caso in cui essa sia vera, dallesecuzione della sequenza di
comandi c e da una nuova esecuzione del ciclo while.
Normalmente lutente di un linguaggio di programmazione non si cura dei fondamenti logici
delle definizioni ricorsive, tuttavia necessario garantire la validit delle definizioni ricorsive. Lattribuzione di un significato ad unequazione ricorsiva non per sempre immediato.
Consideriamo ad esempio la seguente equazione ricorsiva:
f x.(x = 0) ! 1, f (x + 1).
(6.1)
In eetti, si potrebbe obiettare che questa non una vera e propria definizione di funzione,
in quanto f definito in termini di se stesso. La (6.1) deve essere vista piuttosto come una
111
specifica di funzione, vale a dire la descrizione di vincoli che la funzione f deve soddisfare. Tale
specifica indica che una qualsiasi funzione che la rispetti deve dare risultato 1 quando riceve
0 come argomento. Tuttavia il suo comportamento sugli altri argomenti non univocamente
determinato. Infatti lunico altro vincolo che viene richiesto quello di dare sempre lo stesso
risultato per tutti gli argomenti maggiori di 0. Da un punto di vista computazionale il
significato intuitivo della specifica daltra parte ovvio:
per calcolare la f su un argomento x, si controlli innanzitutto se x = 0, nel qual
caso f (x) = 1; altrimenti si richiami la f sullargomento x + 1.
Seguendo questo procedimento di calcolo, ed indicando con ? la non definizione (lassenza
di informazione), chiaro che la specifica (6.1) individua la funzione
g x.(x = 0) ! 1, ?,
cio la funzione che d risultato 1 per argomento 0 e che non definita per gli altri argomenti
perch il procedimento di calcolo procede allinfinito per essi.
In generale, diciamo che una funzione soddisfa una specifica se e solo se essa una sua
soluzione. In eetti, una specifica come la (6.1) pu essere vista come unequazione nellincognita f . Una soluzione allora una qualunque funzione che, sostituita al posto di f , renda
lequazione unidentit.
Ci si pu facilmente rendere conto che la funzione g una soluzione dellequazione (6.1).
Sostituendo la definizione di g nella parte destra dellequazione (6.1) otteniamo:
x.(x = 0) ! 1, ( x.(x = 0) ! 1, ?)(x + 1)
|
{z
}
g
= x.(x = 0) ! 1, (x + 1 = 0) ! 1, ?
= x.(x = 0) ! 1, ?
(dato che non esiste un naturale x tale che x + 1 = 0)
g.
Daltra parte importante notare come la g non sia lunica soluzione possibile; infatti, per
ogni k 2 N, ogni funzione della forma
gk x.(x = 0) ! 1, k
soddisfa la specifica, vale a dire soluzione dellequazione.
Tra tutte le possibili soluzioni, la g ha comunque un ruolo particolare; essa corrisponde ai
risultati che si ottengono interpretando la specifica in modo meccanico, cos che, per valutare
la f per un generico x > 0, si espande il corpo della f per scoprire che necessario valutarla
per x + 1, quindi per x + 2, e cos via.
Si noti che la funzione g meno definita di ciascuna delle gk . Infatti, sullunico argomento
su cui g definita, le gk sono anchesse definite ed assumono lo stesso valore:
8k. g(0) = gk (0).
La discussione precedente evidenzia la necessit di individuare un metodo per risolvere
equazioni ricorsive, nonch per poter scegliere fra eventuali soluzioni multiple. Allo scopo di
caratterizzare le soluzioni di unequazione ricorsiva, diamo innanzitutto una definizione che
useremo spesso nel seguito.
112
f act f. x.(x = 0) ! 1, x f (x
1)
che corrisponde evidentemente alla definizione della funzione fattoriale. Infatti, se poniamo
f act = x.(x = 0) ! 1, x f act(x
1)
113
1) = x.(x = 0) ! 1, ? .
(6.2)
F act1 non ovviamente un punto fisso di f act , per una funzione pi definita di ,
ed assume sullargomento su cui definita lo stesso valore che su di esso assume la funzione
fattoriale. F act1 unapprossimazione della funzione fattoriale migliore di . Inoltre, F act1
ha, sullunico argomento per cui definita, un comportamento operazionalmente corrispondente alla specifica della funzione fattoriale, perch stata ottenuta interpretando la specifica
come un programma e sostituendo, al posto del richiamo ricorsivo della funzione, una sua
approssimazione. Il lettore potr ora verificare che, considerando la sequenza
F act2 f act F act1 , F act3 f act F act2 , . . .
si ottengono approssimazioni della funzione fattoriale via via migliori, e che il limite di questa
sequenza di funzioni la funzione fattoriale stessa. In altre parole, il minimo punto fisso della
specifica della funzione fattoriale pu essere ottenuto per approssimazioni successive. Inoltre,
ciascuna di queste approssimazioni pu essere rappresentata in modo finito e, ovviamente,
non ricorsivo.
6.2
Cominciamo col definire le propriet strutturali degli insiemi che costituiscono i domini. A
questo proposito, si ricordi che una relazione binaria R su un insieme A una relazione di
ordine se riflessiva, antisimmetrica e transitiva (Definizione 2.7).
Definizione 6.1.
1. Un insieme parzialmente ordinato (poset) una coppia (D, v), dove D un insieme e
v una relazione di ordine parziale su D.
2. Un poset D totalmente ordinato se per ogni coppia d, d0 2 D abbiamo che d v d0 o
d0 v d.
3. Un insieme totalmente ordinato finito o numerabile viene chiamato catena.
Abbiamo gi detto, nellintroduzione di questo capitolo, che intuitivamente la relazione
di ordine parziale v basata sulla quantit di informazione associata ai singoli elementi
dellinsieme D. Qui facciamo notare che in un insieme totalmente ordinato la quantit di informazione di due elementi qualsiasi sempre confrontabile. In una catena, poi, ogni elemento
deve contenere informazione che consistente con quella contenuta dal suo predecessore; pu
essere uguale al suo predecessore o pu contenere informazione aggiuntiva.
Esempio 6.2.
1. Gli interi con la relazione di minore o uguale sono una catena.
114
{a, c}
{b, c}
{a}
{b}
{c}
{}
I naturali con il tradizionale ordinamento di minore o uguale possono essere rappresentati
come segue:
Si noti che se (D, v) un poset, allora per ogni A D si ha che (A, vA ), dove vA la
restrizione di v su A, un poset.
Le definizioni riportate di seguito servono come preparazione alla nozione di approssimazione di informazione e fissano le propriet di alcuni elementi di un ordinamento
parziale.
Definizione 6.3. Sia (D, v) un poset ed S un sottoinsieme di D; un elemento a 2 D
chiamato:
1. un maggiorante di S se d v a, 8d 2 S;
2. un minorante di S se a v d, 8d 2 S;
3. il massimo di S se a un maggiorante di S ed a 2 S;
115
Per denotare lestremo superiore (inferiore) utilizzeremo soltanto sup (inf) omettendo in
D tutte le volte che il dominio in questione risulti evidente dal contesto. Alcune volte, per
far capire in quale dominio viene determinato lestremo superiore verr utilizzato un apice od
un indice che suggerisca il dominio (ad esempio scriveremo sup0 S invece di sup S in D0 ).
Naturalmente, lunicit del massimo (minimo) di un poset, implica quella dellestremo
inferiore (superiore).
Esempio 6.5.
1. Linsieme dei naturali ha minimo, ma non ha maggioranti; talvolta il maggiorante viene
aggiunto e viene denotato da !.
2. Linsieme dei sottoinsiemi di un insieme ordinato per inclusione ha per minimo linsieme
vuoto e per massimo linsieme originario.
3. Consideriamo il seguente poset D:
g
f
d
c
a
116
Proposizione 6.6.
Dato un insieme parzialmente ordinato, abbiamo che:
1. Se un sottoinsieme ha massimo, questo anche lestremo superiore.
2. Ogni catena finita ha un massimo.
3. Ogni sottoinsieme di una catena una catena.
Proposizione 6.7.
Sia (D, v) un cpo, {xi | i 2 I} una catena su D e d 2 D un elemento qualsiasi. Se xi v d,
per ogni i 2 I, allora sup{xi | i 2 I} v d.
Dimostrazione. Per definizione di estremo superiore, se d un maggiorante della catena, il
minimo degli maggioranti sup{xi | i 2 I} devessere non pi grande di d.
Proposizione 6.8.
Sia (D, v) un cpo e {xi | i 2 I} e {yi | i 2 I} due catene su D. Se xi v yi , per ogni i 2 I,
allora sup{xi | i 2 I} v sup{yi | i 2 I}.
Dimostrazione. Dallipotesi, e per definizione di estremo superiore, segue che per ogni i 2 I,
xi v yi v sup{yi | i 2 I}. Perci, per la Proposizione 6.7 (prendendo d = sup{yi | i 2 I}), si
ha sup{xi | i 2 I} v sup{yi | i 2 I}.
I domini utilizzati per definire la semantica di linguaggi di programmazione sono insiemi
parzialmente ordinati (poset), che hanno sempre un elemento minimo e sono tali che lestremo
superiore delle loro catene esista sempre. Essi sono chiamati ordinamenti parziali completi,
abbreviati in cpo, dallinglese complete partially ordered set.
Definizione 6.9. Un poset (D, v) completo ( cpo set, cpo o dominio) se e solo se
1. D ha il minimo, indicato con ?;
2. ogni catena in (D, v) ha estremo superiore in D.
I poset descritti negli esempi precedenti sono tutti cpo tranne i naturali, che hanno minimo
ma non hanno estremo superiore della catena costituita da tutto linsieme, e gli interi, che
non hanno n massimo n minimo.
In un cpo dunque lestremo superiore di una catena riassume linformazione che stata
accumulata in maniera consistente lungo la catena stessa. Poich una catena pu avere un
numero infinito di elementi distinti, lestremo superiore agisce come elemento limite per la
sequenza infinita. Daltro canto, una catena pu avere elementi duplicati, poich v include
anche luguaglianza, e pu anche assumere un valore costante da un certo punto in poi. Nel
qual caso, lestremo superiore proprio quel valore.
6.3
117
118
In pratica, una funzione tra due cpo monotona quando preserva la relazione dordine
ed continua quando preserva e rispetta gli estremi superiori delle catene del dominio.
Si noti che la nozione di funzione continua introduce in matematica discreta il concetto di
limite, solitamente utilizzato in matematica del continuo.
Il teorema che segue chiarisce la relazione tra funzioni monotone e funzioni continue.
Teorema 6.11. Siano (D, v) e (D0 , v0 ) due cpo. Se f : D ! D0 una funzione continua
allora f anche monotona.
Dimostrazione. Se consideriamo x, y 2 D con x v y e la corrispondente catena {x, y}, abbiamo che sup{x, y} = y. Siccome f continua, abbiamo anche che f (sup{x, y}) = f y =
sup{f x, f y} e quindi che f x v0 f y per definizione di estremo superiore.
In generale il viceversa di questo teorema non vero; esistono funzioni che sono monotone
ma non continue. Come esempio consideriamo il cpo N! , costituito dai naturali con il tradizionale ordinamento di minore o uguale (0 1 2 . . . ), ed esteso con un nuovo elemento
! tale che ! ! e, per ogni naturale n, n !. facile dimostrare che N! = (N [ {!}, )
un cpo. Consideriamo ora la funzione f : N! ! N! definita come segue:
f x.(x = !) ! !, 1.
facile verificare che f monotona. Essa non per continua: infatti se consideriamo
la catena {i | i 2 N} ottenuta prendendo tutti i naturali senza ! abbiamo che f (sup{i | i 2
N}) = f ! = ! 6= sup{f i | i 2 N} = 1.
Monotonia e continuit si implicano a vicenda soltanto quando gli argomenti della funzione
appartengono a cpo che contengono solo catene finite.
Teorema 6.12. Sia f : D ! D0 una funzione monotona e D contenga solo catene finite.
Allora f continua.
Dimostrazione. Sia {x0 , . . . , xn }, n 2 N, una catena su D. Siccome la catena finita, abbiamo
che sup{x0 , . . . , xn } = xn e quindi che f (sup{x1 , . . . , xn }) = f xn . Daltra parte, siccome f
monotona abbiamo anche che {f x1 , . . . , f xn } una catena di D0 il cui estremo superiore
f xn . Questo basta per concludere che sup0 (f {x1 , . . . , xn }) = f (sup{x1 , . . . , xn }) e quindi
che f continua.
Dalla definizione di funzione continua su un cpo segue banalmente la continuit della
funzione identit.
Lemma 6.13. Se D un cpo, la funzione identit su D continua.
Nel seguito, faremo uso di questa propriet di base della composizione di funzioni continue.
Lemma 6.14. Se D1 , D2 e D3 sono cpo e f : D1 ! D2 e g : D2 ! D3 sono due funzioni
continue, allora
g f : D1 ! D3
continua.
119
per
per
per
per
definizione
la continuit di f
la continuit di g
definizione.
1. La funzione f x.(x =?) !?, x monotona e quindi continua (NAT ha solo catene
finite). Tutti gli elementi di NAT sono suoi punti fissi e il minimo punto fisso ?.
2. Invece la funzione g x.(x =?) ! 1, ? non monotona. Infatti per ogni numero
naturale n abbiamo che ? n ma g ?= 1 6 ?= g n e quindi la funzione g non ha punti
fissi.
3. Un altro esempio di funzione non monotona h x.(x =?) ! 1, x. La funzione h ha
infiniti punti fissi (tutti i naturali diversi da ?) ma non ha minimo punto fisso.
In Sezione 6.1 abbiamo visto come i concetti di approssimazione finita di una funzione e
quello di minimo punto fisso contribuiscano a fornire un modo eettivo per determinare una
soluzione di una specifica ricorsiva. Il prossimo teorema, dovuto al matematico americano
Stephen Cole Kleene, mostra che, nel caso di funzioni continue, il minimo punto fisso
ottenibile come estremo superiore di una catena ed quindi approssimabile in maniera finita
con gli stessi elementi della catena.
Nel seguito, se f : D ! D una funzione, useremo la seguente notazione
f 0x = x
f i+1 x = f (f i x)
120
Teorema 6.17 (Teorema di Kleene per il minimo punto fisso). Sia (D, v) un cpo. Ogni
funzione continua f : D ! D ha il minimo punto fisso (indicato con fix f ) che uguale a
sup f i ?| i 2 N .
Dimostrazione. La prova si svolge in tre passi. Prima (passo 1) proviamo che {f i ?| i 2 N}
una catena e che sup{f i ?| i 2 N} il suo estremo superiore, quindi (passo 2) che sup{f i ?|
i 2 N} un punto fisso di f , infine (passo 3) che esso il minimo tra tutti i punti fissi di f .
1. Per induzione su N dimostriamo prima che {f i ?| i 2 N} una catena, cio che 8i :
f i ?v f i+1 ?.
Base dellinduzione. f 0 ?=?v f ?= f 1 ?, perch ?v d, 8d 2 D.
Passo induttivo. f i ?= f (f i 1 ?) v f (f i ?) = f i+1 ?, per la monotonia di f e lipotesi
induttiva (f i 1 ?v f i ?).
Ora, siccome D un cpo, questa catena ha estremo superiore sup{f i ?} (per abbreviare,
anche nel seguito, scriviamo {f i ?} anzicch {f i ?| i 2 N}).
2. Dimostriamo ora che sup{f i ?| i 2 N} un punto fisso di f :
f (sup{f i ?}) =
=
=
=
=
sup{f (f i ?)}
sup{f i+1 ?}
sup({f i+1 ?} [ {?})
sup({f i+1 ?} [ {f 0 ?})
sup{f i ?}
per la continuit di f
per la definizione di f i
il sup non varia aggiungendo ?
perch ?= f 0 ?
3. Dimostriamo ora che ogni punto fisso della funzione f un maggiorante della catena
{f i ?} e quindi che ogni punto fisso maggiore o uguale dellestremo superiore della
catena. La dimostrazione procede per induzione su N. Sia x un punto fisso, cio tale
che f x = x.
Base dellinduzione. f 0 ? = ?v x, perch ?v x, 8x 2 D.
Passo induttivo. Supponiamo che f i ?v x; dobbiamo dimostrare che f i+1 ? v x.
Abbiamo
f i+1 ? = f (f i ?)
v fx
= x
per definizione
per ipotesi induttiva e per la monotonia di f
perch x un punto fisso di f .
Questo basta per concludere che per ogni i 2 N abbiamo f i ?v x. Poich lestremo superiore di una catena per definizione il minimo dei maggioranti, abbiamo che
sup{f i ?} v x, e quindi che sup{f i ?} il minimo punto fisso di f .
Come immediata applicazione del teorema del punto fisso abbiamo il seguente corollario.
Corollario 6.18. Siano (D, v) e (D0 , v0 ) due cpo. Ogni funzionale continuo F : (D !
D0 ) ! (D ! D0 ) ha minimo punto fisso fix F , che pu essere assunto come il significato della
definizione (ricorsiva) corrispondente a F .
Osservazione 6.19 (Cpo e funzioni continue). Soermiamoci ora brevemente sullidea intuitiva alla base dei cpo e delle funzioni continue. Gli ordinamenti parziali completi corrispondono ai tipi di dati, dati che possono essere utilizzati come input o come output di una
121
v
v
f (zmax ) e
zmax .
Ci serviremo inoltre
122
Componendo le due relazioni delle quali appena stata dimostrata la validit si ottiene
zmax v f (zmax ) v zmax
Per lantisimmetria di v deve valere zmax = f (zmax ), quindi zmax un punto fisso di f .
2. Vediamo ora che zmax il massimo punto fisso di f . Sia r un qualsiasi punto fisso di
f . Allora in particolare avremo che r v f (r). Questo implica che r 2 A e quindi che
r v sup A = zmax . Perci tutti i punti fissi di f appartengono ad A e quindi zmax ,
che lestremo superiore di A, il massimo punto fisso di f .
6.4
Costruzioni di domini
Come i linguaggi di programmazione forniscono primitive per costruire nuovi dati a partire
da dati preesistenti, cos la teoria dei domini fornisce alcuni operatori che permettono di
costruire nuovi domini a partire da domini esistenti. Questa ricchezza importante in quanto
garantisce che i cpo possano essere utilizzati come domini per dare significato ai vari tipi di
costrutti dei linguaggi di programmazione. Di seguito illustriamo alcuni di questi operatori
insieme a particolari funzioni continue associate alle costruzioni.
6.4.1
Domini elementari
123
banale verificare che ogni D definito come sopra soddisfa le condizioni richieste ai domini.
Il pi semplice esempio di dominio piatto quello dei booleani estesi con ?:
BOOL = (true, false, ?)
in cui i due valori di verit true e false sono incomparabili ed entrambi pi definiti di ?.
true
false
?
Un altro esempio di dominio piatto che sar frequentemente usato in queste note NAT,
il dominio piatto dei naturali (introdotto nellEsempio 6.16).
6.4.2
Prodotti finiti
124
1.
Nel caso
0 : ( D 0 D 1 ) ! D 0
1 : ( D 0 D 1 ) ! D 1
definite come segue:
i (x0 , x1 ) = xi
i = 0, 1.
per i = 0, 1
125
126
Dimostrazione. La prova semplice e si basa sul fatto che gli insiemi A = {ai,j | i 2 I, j 2 I},
B = {sup{ai,j | i 2 I} | j 2 I}, C = {sup{ai,j | j 2 I} | i 2 I} e D = {ai,i | i 2 I} hanno
gli stessi maggioranti, e quindi lo stesso minimo dei maggioranti, cio estremo superiore. Per
esempio, facile vedere che A e D hanno gli stessi maggioranti perch qualsiasi elemento ai,j
minore o uguale di un elemento della forma ai,i , e viceversa. Certamente lestremo superiore
della catena D esiste e quindi lestremo superiore di A esiste e i due valori coincidono. Inoltre,
sfruttando la commutativit di quantificatori omogenei, in questo caso del quantificatore
universale, abbiamo
x un maggiorante per B
,
,
,
,
,
8j. sup{ai,j | i 2 I} v x
8j8i. ai,j v x
x un maggiorante per A
8i. sup{ai,j | j 2 I} v x
x un maggiorante per C.
Dimostrazione. ) Questa parte semplice. Basta fissare uno dei due argomenti e dimostrare che se soltanto uno degli argomenti contribuisce al crescere della catena, allora
lipotesi di continuit della funzione suciente per derivare la tesi. In pratica, bisogna
dimostrare che se {ai | ai 2 D1 , i 2 I} una catena e b 2 D2 allora
f (sup{ai | i 2 I}, b) = sup{f (ai , b) | i 2 I}.
Dallipotesi che A una catena segue che anche gli insiemi {(ai , bj ) | bj 2 D2 , j 2 I},
per ogni ai 2 D1 con i 2 I, sono catene. In particolare, lipotesi di continuit, seppure
sui singoli argomenti, implica la monotonia di f e quindi sono catene anche gli insiemi
{f (ai , bj ) | bj 2 D2 , j 2 I}, per ogni ai 2 D1 e i 2 I. Inoltre, sempre dallipotesi di
continuit, segue che tali insiemi hanno estremo superiore. Quindi abbiamo
f (sup{(ai , bi ) | i 2 I}) = f (sup{ai | i 2 I}, sup{bj | j 2 I})
per la definizione di sup di un prodotto,
= sup{f (ai , sup{bj | j 2 I}) | i 2 I}
per la continuit di f nel primo argomento
= sup{sup{f (ai , bj ) | j 2 I} | i 2 I}
per la continuit di f nel secondo argomento
= sup{f (ai , bi ) | i 2 I}
per la Proposizione 6.28.
127
6.4.3
Somma disgiunta
spesso utile creare unioni di domini, per esempio per aggiungere valori di errore ai valori
normali delle computazioni. Un modo per unire due o pi domini ed ottenere un nuovo
dominio quello di fare lunione disgiunta dei loro elementi. Questa costruzione, indicata
dalloperatore +, simile alloperazione di unione disgiunta tra insiemi; essa strutturata in
modo tale che possibile esaminare un elemento del risultato e decidere a quale degli insiemi di
partenza esso appartiene. Dati due domini D0 e D1 , loperazione di somma disgiunta costruisce
un dominio i cui elementi sono copie degli elementi dei domini di origine contrassegnate con
il nome di tale dominio (o con qualcosa che permetta di identificarlo univocamente), pi un
nuovo elemento minimo. Anche in questo caso definiremo soltanto la somma disgiunta di due
domini, in quanto la sua estensione al caso generale di n domini ovvia.
Definizione 6.30. Siano D0 = (D0 , v0 ) e D1 = (D1 , v1 ) due domini. Chiamiamo somma
disgiunta, denotata da D0 + D1 , la coppia (D0 + D1 , v) con
1. D0 + D1 = {inD0 (x) | x 2 D0 } [ {inD1 (y) | y 2 D1 } [ {?},
2. v definita come segue:
(a) ?v d, per ogni d 2 D0 + D1 ,
?i se x =? o x = inDi+2 1 (y)
y
se x = inDi (y)
128
8
se x = inDi (y)
< true
false
se x = inDi+2 1 (y)
isDi (x) =
:
?BOOL se x =?D0 +D1
dove i = 0, 1.
Possiamo dimostrare la continuit delle operazioni associate alla somma disgiunta, come
enunciato dal seguente risultato.
Lemma 6.32. Le immersioni inDi , i selettori outDi e i predicati isDi sono continui.
La costruzione di somma disgiunta di cpo pu essere estesa alle funzioni. Siano f0 : D0 ! D
e f1 : D1 ! D due funzioni continue sui cpo D0 , D1 e D. Si definisce la funzione combinazione
[f0 , f1 ] : D0 + D1 ! D
nel modo seguente:
[f0 , f1 ](inDi (di )) = fi (di )
[f0 , f1 ](?)
= ?D
8di 2 Di e i = 0, 1
6.4.4
Il prossimo costruttore di domini risulta essenziale per le definizioni semantiche dei linguaggi
di programmazione. Il costruttore di spazi di funzione, indicato con !, crea il dominio (D0 !
D1 , v) a partire dai domini D0 e D1 . Gli elementi di questo dominio sono tutte le funzioni
continue da D0 a D1 e lordinamento v richiede che una funzione pi definita di unaltra
fornisca, per uguale argomento, un risultato uguale o pi definito. Tale ordinamento, quando
i domini D0 e D1 sono piatti, coincide con quello presentato informalmente in Sezione 6.1.
Per esprimere gli elementi del dominio (D0 ! D1 , v) useremo la -notazione (introdotta nel
Capitolo 5); in pratica, la -astrazione funge da costruttore e lapplicazione di funzione da
distruttore.
Definizione 6.34. Siano D0 = (D0 , v0 ) e D1 = (D1 , v1 ) due domini. Chiamiamo spazio
delle funzioni continue da D0 a D1 , denotato da [D0 ! D1 ], la coppia (D0 ! D1 , v) dove
1. D0 ! D1 linsieme delle funzioni continue da D0 a D1 ,
2. v cos definito: f v g , 8x. f x v1 gx.
129
Di seguito dimostriamo che lo spazio delle funzioni continue tra due cpo ancora un cpo.
Teorema 6.35. [D0 ! D1 ] un cpo.
sup{fi sup{xj | j 2 J} | i 2 I}
sup{sup{fi xj | j 2 J} | i 2 I}
sup{sup{fi xj | i 2 I} | j 2 J}
sup{g xj | j 2 J}
definizione di g
continuit delle fi
Proposizione 6.28
definizione di g.
Questo basta per concludere che h x un maggiorante della catena {fi x | i 2 I}. Poich
g x per definizione il sup di tale catena, dalle definizioni di sup e di v abbiamo
8x 2 D0 . g x v1 h x, dunque g v h
e questo basta per concludere che g il sup di {fi | i 2 I}.
130
In particolare, dal teorema precedente segue che lestremo superiore di una catena di
funzioni continue definito in maniera puntuale, cio corrisponde alla funzione che su ogni
elemento del dominio restituisce lestremo superiore della catena di elementi formata dai valori
restituiti dalle singole funzioni della catena quando invocate su quellelemento.
Ci sono due operazioni chiave associate alla costruzione dello spazio delle funzioni,
lapplicazione e la currificazione (introdotta alla fine della Sezione 5.1). La prima corrisponde
alla funzione apply : [D1 ! D2 ] D1 ! D2 definita da
apply (f, x).f (x) .
La seconda ()c :: [(D1 D2 ) ! D3 ] ! [D1 ! D2 ! D3 ], data una funzione continua f :
(D1 D2 ) ! D3 , corrisponde alla versione currificata di f , cio f c : D1 ! D2 ! D3 , definita
da
()c f. x. y.f (x, y) .
Sotto ipotesi opportune, entrambe le funzioni risultano essere continue, come sostenuto dai
due lemmi seguenti.
Lemma 6.36. La funzione apply continua se il suo primo argomento una funzione
continua.
Dimostrazione. Sfruttando il Lemma 6.29 sar suciente dimostrare che apply continua nel
primo e secondo argomento separatamente.
1. Dimostriamo prima che apply(f, sup{xi | i 2 I}) = sup{apply(f, xi ) | i 2 I}.
apply(f, sup{xi | i 2 I}) = f (sup{xi | i 2 I})
per definizione di apply,
= sup{f xi | i 2 I}
per la continuit di f ,
= sup{apply(f, xi ) | i 2 I} per definizione di apply.
2. Dimostriamo ora che apply(sup{fi | i 2 I}, x) = sup{apply(fi , x) | i 2 I}.
per definizione di apply,
perch lestremo superiore di una catena di
funzioni continue definito in modo puntuale,
= sup{apply(fi , x) | i 2 I} per definizione di apply.
131
f (sup{xi | i 2 I}, d)
sup{f (xi , d) | i 2 I}
sup{(f c (xi ))d | i 2 I}
sup(f c {xi | i 2 I})d
per definizione di f c ,
perch f continua,
per definizione di f c ,
perch lestremo superiore di una catena di
funzioni continue definito in modo puntuale.
8d1 2 D1 , d2 2 D2 .
Un operatore utile nel seguito () :: [D1 ! D2 ] ! [D1 ! D2 ], il quale data una funzione
continua f : [D1 ! D2 ] ne restituisce la sua versione stretta; questa coincide con la funzione
originale a parte che indefinita quando tale largomento. Sia f : [D1 ! D2 ] una funzione
continua tra due cpo. La funzione f : [D1 ! D2 ] definita nel modo seguente
f (d) se d 6=?D1
f (d) =
?D2 se d =?D1
Lemma 6.38. Loperatore () continuo.
Dimostrazione. Sia d un elemento qualsiasi di D1 e sia {fi | i 2 I} una generica catena di
funzioni continue in [D1 ! D2 ]. Nel caso in cui d =?D1 , dalla definizione delloperatore () , si
ottiene immediatamente che (sup{fi | i 2 I}) (d) =?D2 = (sup{fi | i 2 I})(d). Altrimenti,
cio se d 6=?D1 , abbiamo
per definizione di f ,
perch lestremo superiore di una catena di
funzioni continue definito in modo puntuale.
= sup{fi (d) | i 2 I}
per definizione di f ,
132
6.5
Nel Capitolo 4 abbiamo visto che la semantica denotazionale di un linguaggio di programmazione consiste nellassociare elementi di opportuni domini semantici a termini della sintassi
astratta del linguaggio. Nellintroduzione a questo capitolo abbiamo visto che, per le dicolt
matematiche che intervengono quando si vogliono catturare propriet e descrivere costrutti
dei linguaggi di programmazione, necessario utilizzare come domini speciali tipi di insiemi
con struttura conosciuti come ordinamenti parziali completi ed necessario richiedere che le
funzioni su tali oggetti matematici siano continue.
In questa sezione introdurremo un linguaggio per descrivere elementi dei domini semantici,
cio elementi dei cpo che utilizzeremo per denotare i costrutti dei linguaggi di programmazione
che studieremo nei capitoli successivi. Siccome il linguaggio che proporremo verr utilizzato
per descrivere altri linguaggi, esso verr chiamato metalinguaggio. Assumeremo che il significato dei suoi costrutti sia noto; se cos non fosse dovremmo utilizzare un meta-metalinguaggio
pi semplice per descrivere il metalinguaggio stesso ed assumere o che la semantica del metametalinguaggio sia nota oppure andare avanti fino ad un linguaggio (ad esempio quello dei
numeri naturali) che riterremo sucientemente semplice per poter essere utilizzato come base
delle nostre descrizioni semantiche.
6.5.1
133
134
D = {nil} + D + D2 + D3 + . . .
se n > 1
135
con D0 ! D1 ! D2 ! ! Dn .
La -astrazione il modo pi comune per costruire elementi di [D0 ! D1 ], cos come lapplicazione di una funzione elemento di [D0 ! D1 ] ad un elemento di D0 permette di riottenere
un elemento di D1 .
6.5.2
Il metalinguaggio
Nella descrizione della semantica denotazionale di un linguaggio di programmazione necessario avere a disposizione strumenti che permettano di ottenere nuove funzioni a partire da
funzioni esistenti. Per quanto visto finora (si veda in particolare i risultati in Sezione 6.3),
importante che le funzioni utilizzate siano continue. Risulta essenziale quindi che le operazioni
per la manipolazione di funzioni preservino la continuit. Il principale scopo di questa sezione quello di rassicurare il lettore che le funzioni di interpretazione semantica che saranno
utilizzate nel seguito per descrivere i costrutti dei linguaggi di programmazione sono tutte
definite su cpo e sono tutte continue.
Il metalinguaggio proposto basato sulla -notazione introdotta nel Capitolo 5 e la sua
semantica operazionale quindi basata sulla -riduzione. Ricordiamo che invece di scrivere
x. y.f spesso scriveremo semplicemente xy.f . importante non confondere questa notazione con (x, y).f . Infatti, xy.f un funzionale di un solo argomento, mentre (x, y).f
una funzione di due argomenti raggruppati in una coppia. Approfittiamo di questa occasione
anche per ricordare che la -astrazione associa a destra, cio lega il pi possibile alla sua
destra: pertanto x.x + y va letto come x.(x + y) e non come ( x.x) + y.
Tuttavia, per denotare funzioni utilizzeremo non soltanto -espressioni, ma anche una
sintassi pi mnemonica. Questa pu comunque essere sempre vista come unabbreviazione
di una qualche -espressione, come sar chiaro alla fine della sezione. Si vorrebbe imporre il
minor numero possibile di vincoli sulla -notazione e tuttavia essere sicuri che, cos facendo,
si definiscono funzioni continue.
Le principali componenti delle funzioni di interpretazione che utilizzeremo nei capitoli
successivi saranno:
le variabili,
le costanti, tra cui loperatore di minimo punto fisso,
le n-uple,
lapplicazione di funzione,
la -astrazione,
i costrutti derivati Condizionale, Let e Case.
136
Queste, ed alcune altre costruzioni esprimibili utilizzando solo quelle elencate sopra, costituiscono le espressioni del metalinguaggio. Tipicamente, tali espressioni rappresentano elementi
di un qualche cpo D1 e dipendono da variabili ciascuna delle quali assume valori in qualche
altro cpo. quindi necessario stabilire la continuit di queste espressioni. Unespressione e
detta continua nella variabile x 2 D0 se e solo se la funzione x.e (con tipo D0 ! D1 )
continua. Si dice che e continua nelle sue variabili se e solo se e continua in ciascuna
delle sue variabili. In particolare, se la variabile x non occorre in e, allora la funzione x.e
costante e quindi continua.
I risultati di questa sezione, insieme a quelli della sezione precedente, ci permettono di
dimostrare che i costrutti fondamentali del metalinguaggio usato per descrivere le funzioni di
interpretazione semantica preservano la continuit e quindi garantiscono che le espressioni del
metalinguaggio sono continue nelle loro variabili.
Variabili. Unespressione e, che assume valori in un cpo D1 , costituita da una singola variabile x continua nelle sue variabili perch, presa y 2 D0 , la funzione y.e risulta infatti
essere o lidentit x.x (quando y = x) oppure la funzione costante y.x.
Costanti. Oltre ai valori base (interi, booleani, ?, . . . ), abbiamo gi introdotto altri
elementi particolari dei cpo, quali
le proiezioni i 2 (D0 . . . Dn ) ! Di , le operazioni su funzioni hf0 , . . . , fn i : D !
D0 . . . Dn e f0 . . . fn : D0 . . . Dn ! D00 . . . D0n associate al prodotto di
cpo;
le immersioni inDi 2 Di ! (D0 + . . . + Dn ), i selettori outDi 2 (D0 + . . . + Dn ) ! Di ,
i predicati isDi 2 (D0 + . . . + Dn ) ! BOOL e loperazione di combinazione di funzioni
[f0 , . . . , fn ] 2 D0 + . . . + Dn ! D, tutti associati alla somma disgiunta;
il costruttore :: 2 (D D ) ! D , i selettori hd() 2 D ! D e tl() 2 D ! D ed il
predicato null 2 D ! BOOL, tutti associati al dominio delle sequenze;
gli operatori apply 2 (D1 ! D2 ) D1 ! D2 , ()c 2 [(D1 D2 ) ! D3 ] ! [D1 ! D2 ! D3 ]
e () :: [D1 ! D2 ] ! [D1 ! D2 ] associate allo spazio delle funzioni;
il condizionale ! , : BOOL D D ! D.
Queste espressioni costanti (non dipendenti da variabili), di cui abbiamo provato la continuit
nelle Sezioni 6.3, 6.4 e 6.5.1, costituiscono pertanto elementi prestabiliti di un cpo di funzioni
continue perci sono continue nelle loro variabili.
Introduciamo ora un importante operatore che riguarda le funzioni continue da un cpo a
se stesso. Ad ogni cpo D infatti associato un operatore di punto fisso fix : [D ! D] ! D che
mappa una qualsiasi funzione continua f : [D ! D] nel suo minimo punto fisso, ed definito
da
fix f.sup f i ?| i 2 I .
Il Lemma 6.41, la cui dimostrazione rimandata a dopo aver trattato lapplicazione di funzione
e la -astrazione, ci dice che loperatore fix continuo.
137
138
[D ! D]. A questo punto, per il Teorema 6.35, segue che sup{fixi | i 2 I} esiste ed una
funzione continua. Infine, poich lestremo superiore di una catena di funzioni definito in
modo puntuale, abbiamo che sup{fixi | i 2 I} = f.sup{f i ?| i 2 I} che appunto fix.
Costrutti derivati. Riassumendo, unespressione costruita a partire da elementi prestabiliti e funzioni continue tramite i metodi descritti nei paragrafi precedenti continua nelle sue
variabili. Vediamo ora come esprimere alcuni costrutti utili in termini di quelli gi esaminati
in modo da ottenere una sintassi pi mnemonica.
Condizionale. Useremo
p ! e 1 , e2
false 1 : (D D) ! D
definite da:
true (x, y).x
Difatti queste definizioni corrispondono a quelle introdotte nellOsservazione 5.5 riguardo (le modalit per esprimere) le costanti nel -calculus. A questo punto, indicando
genericamente con p una qualsiasi delle funzioni true, false o 2 (x, y). ?, e con e1
ed e2 espressioni a valori in D, abbiamo che il condizionale esprimibile con lespressione apply(p, (e1 , e2 )). Quindi, se e1 e e2 sono continue nelle loro variabili, allora anche
anche il condizionale lo , perch esprimibile usando unicamente le costruzioni descritte in precedenza, in particolare apply e i , di cui abbiamo gi mostrato la continuit
(Lemmi 6.36 e 6.24).
Let. Useremo
let x be e1 in e2
al posto di ( x.e2 ) e1 . In pratica, il costrutto let vuole evidenziare che soltanto se
e1 2 D1 un valore diverso da ?D1 allora la funzione x.e2 utilizza tale valore per
determinare il risultato tramite lespressione e2 , altrimenti il risultato ?D2 . Dalla sua
definizione segue immediatamente che il costrutto let continuo nelle sue variabili se
e1 2 D1 e e2 2 D2 lo sono, perch in tal caso continua lespressione ( x.e2 ) e1 , la
quale infatti si pu ottenere da e1 e e2 usando unicamente le costruzioni descritte in
precedenza.
139
T ::= D | hT1 , . . . , Tn i | i (T )
| inD(T ) | outD(T ) | isD(T )
| T1 :: T2 | hd(T ) | tl(T ) | null(T )
| x | x.T | T1 T2
| fix(T ) | T ! T1 , T2 | let x be T1 in T2
6.6
In questa sezione applichiamo la teoria vista in precedenza al dominio piatto dei naturali NAT
e alle funzioni continue che coinvolgono i naturali.
Cominciamo col dare una struttura di dominio alle funzioni dai naturali ai naturali. Consideriamo il dominio NAT ed il dominio prodotto NAT NAT = NATn . Il dominio
140
FUNn = ({f : NATn ! NAT | f continua} , v) delle funzioni continue di n argomenti definito
come segue:
1)
1).
Essendo il funzionale continuo, per il Teorema 6.17, esso ha minimo punto fisso, che dato
da
sup{ i }
dove x. ? il minimo di FUN1 .
0 = =
x. ?
1 = ( f. x.(x = 0) ! 1, x f (x 1))()
= x.(x = 0) ! 1, x (x 1)
= x.(x = 0) ! 1, x ?
= x.(x = 0) ! 1, ? (perch come vedremo pi avanti x ?=?)
2 = ( f. x.(x = 0) ! 1, x f (x 1))( x.(x = 0) ! 1, ?)
= x.(x = 0) ! 1, x (( x.(x = 0) ! 1, ?)(x 1))
= x.(x = 0) ! 1, x ((x 1 = 0) ! 1, x 1 ?)
= x.(x = 0) ! 1, (x 1 = 0) ! x, ?
= x.(x = 0) ! 1, ((x = 1) ! x, ?).
In generale si pu dimostrare che per ogni i 2 N
i = x.(x < i) ! x!, ?
e quindi lestremo superiore della catena la funzione fattoriale x.x!.
Lesempio appena visto ci permette di capire come la continuit permetta di ragionare su
oggetti infiniti non considerandoli globalmente (cosa peraltro impossibile), ma considerando le
loro approssimazioni finite. Infatti per conoscere, ad esempio, il risultato della funzione che
la semantica del funzionale succitato sullargomento 5 non necessario sapere che tale funzione
141
la funzione fattoriale, basta considerare la sesta funzione nella catena che la approssima e
valutarla con argomento 5.
Se un funzionale non continuo, il comportamento dellestremo superiore della catena
pu non avere nulla a che vedere col comportamento degli elementi della catena. Di seguito
riportiamo due esempi di funzionali non continui. Ricordiamo che su domini piatti continuit
e monotonia si equivalgono (vedi 6.11).
Esempio 6.43. Il funzionale
1 = f. x.(f x =?) ! 0, ?
non monotono. Infatti, se consideriamo le funzioni
= x. ? e Z = x.0;
abbiamo che v Z secondo il normale ordinamento di funzioni, ma
1 Z v 1 e 1 Z 6= 1
essendo 1 = Z e 1 Z = .
Esempio 6.44. Consideriamo la funzione Id x.x ed il funzionale
2 = f. x.(f = Id) ! x, ? .
Il risultato di 2 per qualsiasi argomento diverso dalla funzione identit vale sempre , mentre
2 ( x.x) = x.x. Sia f v g. Se nessuna delle due funzioni la funzione identit, abbiamo
che 2 f = 2 g = . Nel caso g x.x allora possiamo avere due sottocasi: 2 f = oppure
2 f = x.x; in entrambi i casi abbiamo sempre che 2 f v 2 g. Per esaurire i casi e concludere
che 2 monotono ci basta ora notare che se f lidentit allora f = g, perch non esistono
funzioni monotone pi definite dellidentit, che una funzione totale.
Mostriamo ora che il funzionale 2 non continuo. Si consideri la catena di funzioni
continue
{ x.(x < i) ! x, ?| i 2 N}
il cui estremo superiore la funzione identit. Abbiamo
2 (sup{ x.(x < i) ! x, ?| i
mentre
Si noti che la non continuit di 2 dovuta sostanzialmente al fatto che in esso viene eettuato
un test di uguaglianza fra funzioni, che ovviamente non pu essere determinato confrontando
un numero finito di approssimanti.
Per concludere questa sezione, analizziamo un problema posto dal fatto che, per garantire
la continuit, i domini delle funzioni sono stati ottenuti estendendo linsieme dei numeri
naturali con ?. La presenza di ? pone la necessit di associare un significato allapplicazione di
funzione ad argomenti indefiniti. Questo permetter daltra parte di trattare la composizione
di funzioni f g anche quando g non sia definita su qualche argomento.
142
Definizione 6.45. Data una funzione f : Nn ! NAT diciamo che la funzione fext la sua
estensione naturale su NATn se e solo se definita come segue:
143
6.7
La teoria del punto fisso per le definizioni ricorsive di funzione pu essere estesa senza dicolt
a sistemi di equazioni mutuamente ricorsive.
Consideriamo un insieme di n equazioni:
8
>
< f1 = x1 . . . xm1 .e1
..
.
>
:
fn = x1 . . . xmn .en
Ognuna di esse individua un funzionale di mi argomenti
144
145
6.8 Esercizi
6.8
Esercizi
6.1 Si dimostri che se un cpo ha un numero finito di elementi, allora ogni funzione monotona su di
esso anche continua.
6.2 Un ordinamento parziale su un insieme finito sempre completo? E quello su un insieme
infinito?
6.3 Si considerino due cpo (D1 , v1 ) e (D2 , v2 ) tali che D1 D e D2 D, per qualche D.
1. La struttura (D1 [D2 , v), dove x v y se e solo se x v1 y _x v2 y sempre un ordinamento
parziale?
2. La struttura (D1 \ D2 , v), dove x v y se e solo se x v1 y ^ x v2 y
(a) sempre un ordinamento parziale?
(b) sempre un ordinamento parziale completo?
6.4 Si consideri linsieme T di tutti i termini costruiti con un simbolo f di funzione binaria e con
due simboli di costante c e ?. Si consideri la relazione v ( T T ) definita informalmente da
t v t0 se il termine t0 ottenuto da t sostituendo alcune occorrenze di ? con generici termini in
T.
1. Si definisca formalmente la relazione v.
6.5 Si studino gli insiemi V e V [ V 1 delle stringhe finite e delle stringhe finite ed infinite
sullalfabeto V = {a, b, c}, con lordinamento v , dove indica la concatenazione delle
stringhe e e inoltre = se infinita.
1. La struttura (V [ V 1 , v) un ordinamento parziale?
2. Esiste lelemento minimo?
3. completo?
6.6 Si considerino le stesse domande dellesercizio precedente per la struttura (V , v).
6.7 Risolvere le equazioni fra linguaggi:
X = {a} X,
6.8 Si dimostri che, per ogni f, g, funzioni continue tra gli opportuni cpo, vale
fix(f
g) = f (fix(g f )).
6.9 Dimostrare se, per ogni cpo, esiste sempre il minimo dei maggioranti di ogni suo sottoinsieme.
6.10 Sia D un cpo. Una funzione r : D ! D si dice idempotente se r(r(x)) = r(x), per ogni x 2 D.
Dimostrare che linsieme di tutte le funzioni continue idempotenti da D in D un cpo.
Capitolo 7
SOMMARIO
In questo capitolo definiamo la semantica denotazionale di un semplice linguaggio funzionale. La semantica ottenuta viene paragonata ad una semantica operazionale, basata su
regole di riscrittura semplici ed intuitive. La prova che semantica operazionale e semantica
denotazionale coincidono fornisce unulteriore giustificazione dellapproccio alla semantica
basato su di una teoria che garantisce lesistenza di punti fissi e, in molti casi, di un minimo
punto fisso per le funzioni definite ricorsivamente.
In questo capitolo analizziamo sintassi e semantica di un semplice linguaggio funzionale,
che chiameremo SLF. Il linguaggio detto funzionale in quanto i costrutti principali che lo
caratterizzano sono la definizione e lapplicazione di funzioni (per questo motivo tali linguaggi
sono anche detti applicativi ). Esso ha un costrutto letrec D in T , che permette di definire
insiemi di funzioni, anche mutuamente ricorsive, a partire da funzioni base, numeri naturali,
e variabili. Il calcolo avviene solo attraverso applicazioni di funzioni. Lassociazione variabilevalore non modellata attraverso una nozione esplicita di stato, ma semplicemente tramite la
sostituzione dei parametri formali con quelli attuali. Il linguaggio sucientemente espressivo
per permettere di definire tutte le funzioni calcolabili.
Per definire la semantica di SLF utilizzeremo due tecniche diverse, una basata sullapproccio operazionale ed unaltra su quello denotazionale, quindi studieremo le relazioni tra questi
due approcci. Inoltre, delle due semantiche forniremo versioni che permettono di descrivere il
passaggio degli argomenti alle funzioni con meccanismi per nome e per valore.
7.1
148
P ::= letrec D in T
T ::= xi | n | bj (T1 , . . . , Tm ) | fr (T1 , . . . , T(r) ) | if T then T1 else T2
D ::= f1 (x1 , . . . , x(1) ) ( T1 , . . . , fn (x1 , . . . , x(n) ) ( Tn
dove (j) uguale allarit di fj , 1 j n.
Tabella 7.1: Sintassi di SLF
Esempi tipici di funzioni di base sono +, , succ, pred. Per semplicit, tra i valori di base
sono assenti i booleani; codificheremo true con 0, false con tutti gli altri naturali. Cambiando
gli insiemi delle funzioni e dei valori di base possibile ottenere linguaggi leggermente diversi.
Per descrivere linsieme delle funzioni di base si presenta un problema analogo a quello
incontrato studiando la semantica dei numeri naturali. necessario distinguere oggetti appartenenti ad un dominio sintattico dalle loro denotazioni, anche quando la loro corrispondenza
diretta. In questo capitolo utilizzeremo le stesse lettere per rappresentare i nomi delle funzioni
di base e le funzioni di base stesse, evidenziando la dierenza fra sintassi e semantica tramite
caratteri tipografici leggermente diversi. Il nome della funzione di base b sar scritto b.
I termini del linguaggio sono definiti tramite la grammatica descritta in Tabella 7.1. Indichiamo con Prog, Term, Decl i linguaggi generati da tale grammatica con simboli iniziali
rispettivamente P, T, D.
Nelle varie clausole si utilizzano per comodit degli indici per denotare elementi della stessa
categoria sintattica: ad esempio, nel caso della categoria sintattica Term, i vari Ti denotano
un qualsiasi termine di SLF. Un programma P 2 Prog scritto nel linguaggio SLF consiste di
un termine T 2 Term e di un insieme di dichiarazioni D 2 Decl; queste ultime determinano
il contesto in cui T dovr essere valutato. Nella definizione di programma il termine T deve
essere un termine chiuso, cio un termine in cui non compaiono variabili di dati.
Le dichiarazioni sono semplicemente una n-upla di associazioni di termini a nomi di
funzioni e possono essere mutuamente ricorsive.
Gli esempi che seguono sono programmi, scritti nel linguaggio SLF, che calcolano il fattoriale di 2. Mentre nel primo esempio moltiplicazione e sottrazione sono considerate funzioni
base (ed espresse in notazione infissa), nel secondo esempio la moltiplicazione viene definita
in base alla somma e alla sottrazione.
Esempio 7.1.
1. letrec
in
2. letrec
in
7.2
1)
1, x2 )
Semantica operazionale
149
bj (n1 , . . . , nm ) = n
bj (n1 , . . . , nm ) !D n
Ti
bj (. . . , Ti , . . . )
(Bas1 )
!D Ti0
!D bj (. . . , Ti0 , . . . )
if 0 then T1 else T2
!D T1
if n + 1 then T1 else T2
T
if T then T1 else T2
!D T2
!D T 0
!D if T 0 then T1 else T2
fr (T1 , . . . , T(r) )
(Bas2 )
(Cond1 )
(Cond2 )
(Cond3 )
(Fun)
150
inferenza.
(Bas1 ) se, valutando la funzione base bj con m naturali come argomenti, si ottiene come
risultato un naturale n, allora il termine ottenuto applicando il simbolo di funzione
bj (che corrisponde a bj ) ai simboli che rappresentano gli argomenti stessi, pu essere
riscritto nella rappresentazione di n.
(Bas2 ) quando il termine attuale un simbolo di funzione base applicato a termini che non
sono ancora riscritti come rappresentazioni di naturali, necessario trasformare tutti gli
argomenti in rappresentazioni di naturali, per poter essere nella condizione di applicare
la regola (Bas1 ).
(Cond1 ) e (Cond2 ) questi due assiomi definiscono le possibili trasformazioni di un termine
condizionale in cui il predicato gi il rappresentante di un naturale. Le riscritture sono
dovute alla scelta di considerare 0 come il valore booleano true e tutti gli altri numeri
come il valore false.
(Cond3 ) nel caso in cui il termine di controllo non rappresenti un naturale, necessario
trasformarlo, per poter essere nella condizione di applicare la regola (Cond1 ) oppure la
(Cond2 ).
(Fun) descrive il comportamento di una chiamata di funzione quando a questa vengono passati
altri termini come argomenti: si deve sostituire al nome della funzione il suo corpo
come specificato nelle dichiarazioni in D e sostituire i parametri attuali ai parametri
formali. importante notare che, siccome nella regola non si fa alcun riferimento alla
valutazione dei parametri prima di legarli allinterno del corpo della funzione, questa
semantica realizza la cosiddetta chiamata per nome o call-by-name. In seguito vedremo
i cambiamenti necessari per modellare un diverso meccanismo di passaggio di parametri
noto come call-by-value.
A partire dalle regole di riscrittura per !D possibile definire una nuova relazione
!D
che semplicemente la chiusura riflessiva e transitiva di !D e che necessaria per definire
il valore prodotto dalla valutazione operazionale di un programma. Si noti che !D una
relazione e non una funzione, nel senso che un programma pu evolvere in modi dierenti.
Ad esempio abbiamo che
ma anche
+(succ(0), succ(0))
!D +(1, succ(0))
+(succ(0), succ(0))
!D +(succ(0), 1)
151
In questo caso, esiste la possibilit di scegliere quale dei termini Ti riscrivere. Tuttavia,
! n.
D
f(f(1))
(Fun)
!D 0.
Daltra parte, per determinare il valore di P tramite la call-by-value, abbiamo bisogno di due
passi:
f(f(1))
(Fun00 )
!D f(0)
(Fun0 )
!D 0.
152
bj (n1 , . . . , nm ) = n
bj (n1 , . . . , nm ) !D n
(Bas1 )
Ti !D Ti0
(Bas2 )
bj (. . . , Ti , . . . ) !D bj (. . . , Ti0 , . . . )
if 0 then T1 else T2 !D T1
(Cond1 )
if n + 1 then T1 else T2 !D T2
(Cond2 )
T !D T 0
(Cond3 )
(Fun0 )
(Fun00 )
(Fun0 )
1, f(x1 , x2 )) in f(1, 2)
abbiamo che, mentre il suo valore operazionale basato sulla call-by-name 0, quello basato
sulla call-by-value non d alcun risultato, nel senso che le regole richiedono sempre nuove
riscritture. Infatti, nel caso della call-by-value necessario valutare tutti gli argomenti della
funzione f prima di cercare di determinarne il valore e questo fa s che dopo ogni riscrittura
sia sempre necessario valutare il termine f(x1 , x2 ):
f(1, 2)
(Fun0 )
!D
(Cond2 )
!D
1, f(1, 2))
()
1, f(1, 2))
!D .
7.3
!D n, allora T
!D n.
Semantica denotazionale
Come abbiamo gi visto, lapproccio denotazionale descrive in termini matematici il significato di ogni costrutto del linguaggio, in generale associando ad esso una funzione che permette
153
154
~ i X
~
T [[xi ]] = F~ . X.
(Var)
~ n
T [[n]] = F~ . X.
(Nat)
~ bj (T [[T1 ]] F~ X,
~ . . . , T [[Tm ]] F~ X)
~
T [[bj (T1 , . . . , Tm )]] = F~ . X.
(Bas)
~ [[T ]] F~ X
~ ! T [[T1 ]] F~ X,
~ T [[T2 ]] F~ X
~ (Cond)
T [[if T then T1 else T2 ]] = F~ . X.T
~ r (F~ )(T [[T1 ]] F~ X,
~ . . . , T [[Tm ]] F~ X)
~
T [[fr (T1 , . . . , Tm )]] = F~ . X.
(Fun)
(Prg)
155
n-ple. Per provare la continuit di T suciente seguire il percorso tracciato nella Sezione 6.5. Osserviamo che nelle clausole relative a T in Tabella 7.4 compaiono solo variabili,
naturali oppure operazioni che abbiamo gi dimostrato preservare la continuit. Siccome anche la composizione di funzioni preserva la continuit, abbiamo che la propriet desiderata
garantita.
Teorema 7.5 (Continuit). Per ogni termine T del linguaggio SLF, il funzionale T [[T ]]
continuo.
Dimostrazione. Per induzione sulla struttura di T. Per la base dellinduzione suciente
notare che
~ i
T [[xi ]] = F~ . X.x
e
~
T [[n]] = F~ . X.n
sono banalmente funzionali continui; ad esempio, data una catena di n-uple di funzioni
{F~i | i 2 I},
si ha che
e
~
T [[n]]( sup {F~i | i 2 I}) = X.n
~
8i T [[n]]F~i = X.n.
Per il passo induttivo consideriamo innanzitutto il caso delle funzioni base e, supponendo che
T [[T1 ]], . . . , T [[Tm ]]
siano continui, dimostriamo che
T [[bj (T1 , . . . , Tm )]]
continuo. Sia {F~i | i 2 I} una catena di n-uple di funzioni. Per ogni m-upla d~ di naturali
abbiamo
sup {(T [[bj (T1 , . . . , Tm )]]F~i }d~
~ . . . , T [[Tm ]]F~i d)}
~
= sup {bj (T [[T1 ]]F~i d,
~ . . . , sup {T [[Tm ]]F~i d})
~
= bj ( sup 0 {T [[T1 ]]F~i d},
~ . . . , sup {T [[Tm ]]F~i }d)
~
= bj ( sup {T [[T1 ]]F~i }d,
~ . . . , T [[Tm ]] sup {F~i }d)
~
= bj (T [[T1 ]] sup {F~i }d,
~
~
= T [[bj (T1 , . . . , Tm )]] sup {Fi }d
156
7.4
~ . . . , T [[Tm ]] (D[[D]])Xi.
~
T [[T ]] (D[[D]])hT [[T1 ]] (D[[D]])X,
157
per
per
per
per
per
la regola (Dec),
il Lemma 7.8,
lOsservazione 7.7,
la regola (Fun),
la regola (Prg).
completa rispetto a
!D , cio per tutti i programmi del linguaggio SLF abbiamo
!D n implica P[[letrec D in T ]] = n.
Dimostrazione. La tesi viene provata per induzione sulla lunghezza k della derivazione
k
T
!D n (che indichiamo T
!D n).
Base dellinduzione. Se T va in zero passi in n allora lunica possibilit che sia T n.
Esaminando la denotazione che abbiamo associato alle costanti, otteniamo che questa coincide
con n:
P[[letrec D in n]] = T [[n]] (D[[D]])h0, . . . , 0i
~
= ( F~ X.n)(D[[D]])h0,
. . . , 0i
= n.
Passo induttivo. Supponiamo che, se T
P[[letrec D in T ]] = n.
Dobbiamo provare che T
cui T
i+1
i+1
!D n possibile.
T bj (T1 , . . . , Tm ) : Se bj (T1 , . . . , Tm )
m, e quindi abbiamo
i+1
!D n, allora Th
!D nh con k i e 1 h
per
per
per
per
per
def. di P,
def. di T ,
def. di P,
lipotesi induttiva,
la definizione delle funzioni base.
158
!D n.
Come abbiamo dimostrato che P completa rispetto alla semantica operazionale con callby-name, cos possiamo dimostrare che lo anche rispetto alla semantica operazionale con
call-by-value. In eetti, questo risultato una immediata conseguenza di alcuni risultati gi
dimostrati.
Teorema 7.11 (Completezza rispetto alla semantica operazionale con call-by-value). P
completa rispetto a !D , cio per tutti i programmi del linguaggio SLF abbiamo
T
!D n implica P[[letrec D in T ]] = n.
Dimostrazione. Questo risultato una diretta conseguenza del Lemma 7.4 e del Teorema 7.10.
Per la semantica operazionale basata sulla chiamata per nome, dimostriamo anche il
seguente teorema, che risulter non valido per la semantica basata su call-by-value.
Teorema 7.12 (Consistenza rispetto alla semantica operazionale con call-by-name). P
consistente rispetto a
!D , cio per tutti i programmi del linguaggio SLF abbiamo
P[[letrec D in T ]] = n implica T
!D n.
159
Dimostriamo ora un risultato pi generale, da cui la tesi seguir come corollario. Sia T un
termine non necessariamente chiuso; assumiamo solo che le sue variabili libere appartengano
allinsieme {y1 , . . . , ym }. Presi m termini chiusi {V1 , . . . , Vm } qualsiasi, dimostriamo che:
T [[T ]]F~ (r) (res(V1 ), . . . , res(Vm )) = n implica T [V1 /y1 , . . . , Vm /ym ]
dove, per ogni termine chiuso V , poniamo
(
res(V ) =
!D n,
(7.2)
n se V
!D n
? altrimenti.
In pratica, res(V ) indica il risultato della valutazione operazionale del termine chiuso V .
Si noti che la propriet (7.2) pu essere equivalentemente espressa come:
T [[T ]]F~ (r) (res(V1 ), . . . , res(Vm )) v res(T [V1 /y1 , . . . , Vm /ym ]).
(7.3)
Infatti, se vale la propriet (7.2) allora abbiamo o che T [[T ]]F~ (r) (res(V1 ), . . . , res(Vm )) =?,
quindi la propriet (7.3) banalmente vera, oppure che T [[T ]]F~ (r) (res(V1 ), . . . , res(Vm )) =
n; in questultimo caso, dalla definizione di res(), segue res(T [V1 /y1 , . . . , Vm /ym ]) = n
per cui si ha nuovamente che la propriet (7.3) vale. Al contrario, cio se vale la propriet (7.3), e se T [[T ]]F~ (r) (res(V1 ), . . . , res(Vm )) = n, allora, dalla definizione di v,
segue che res(T [V1 /y1 , . . . , Vm /ym ]) = n; quindi, dalla definizione di res(), abbiamo
che Vj
!D n. La tesi deriva allora dal fatto che yj [V1 /y1 , . . . , Vm /ym ] Vj . Gli altri casi
della base dellinduzione sono altrettanto semplici e lasciati al lettore.
Consideriamo ora il caso r > 0. Procediamo ancora per induzione sulla struttura di T .
Lunico caso interessante quando T fh (T1 , . . . , Tm ), poich gli altri casi procedono in
modo simile al caso r = 0. In tal caso, abbiamo
~
T [[fh (T1 , . . . , Tm )]]F~ (r) V
160
1)
1)
hres(T1 [V1 /y1 , . . . , Vm /ym ]), . . . , res(Tm [V1 /y1 , . . . , Vm /ym ])i = n
implica Th [T1 [V1 /y1 , . . . , Vm /ym ]/y1 , . . . , Tm [V1 /y1 , . . . , Vm /ym ]/ym ]
!D n.
1)
hres(T1 [V1 /y1 , . . . , Vm /ym ]), . . . , res(Tm [V1 /y1 , . . . , Vm /ym ])i
v res(Th [T1 [V1 /y1 , . . . , Vm /ym ]/y1 , . . . , Tm [V1 /y1 , . . . , Vm /ym ]/ym ]).
!D
!D n.
161
7.5 Esercizi
Esempio 7.13. Sia P il programma
letrec
in
f2 (f1 (1))
perch si ha
f1 (1)
!D f2 (f1 (1))
(Cond2 )
(Fun00 )
!D . . .
!D f1 (1)
Per concludere, osserviamo che certamente possibile definire una semantica denotazionale
per il linguaggio SLF che sia equivalente (consistente e completa rispetto) alla semantica
operazionale definita dalle regole per la chiamata per valore. Per far ci suciente modificare
leggermente la semantica denotazionale descritta in Tabella 7.4. Lapplicazione di funzione
va modificata, per richiedere che anche tutte le funzioni non di base siano strette, cio che
siano indefinite se alcuni dei loro argomenti non sono definiti.
7.5
Esercizi
162
12. possibile specificare la sintassi di SLF senza usare i puntini (. . .)? Motivare la risposta.
Capitolo 8
SOMMARIO
Questo capitolo presenta alcuni concetti comuni a vari linguaggi di programmazione e le
tecniche utilizzate per la loro descrizione formale. Considereremo TINY, un semplice linguaggio di programmazione imperativo, di cui presenteremo una semantica operazionale ed
una semantica denotazionale e ne dimostreremo lequivalenza.
8.1
Il linguaggio TINY
164
un file di input. Per quanto riguarda i comandi, i costrutti sintattici rappresentano, nellordine, il comando nullo, lassegnamento, la sequenzializzazione, il condizionale, literazione e
loperazione di scrittura su un file di output. Infine, un programma TINY una sequenza di
comandi.
8.2
: Id ! Val} [ { : Id ! Val},
165
htrue, i
!
! [true/res]
(True)
hfalse, i
!
! [false/res]
(False)
hn, i
!
! [n/res]
(Nat)
hx, i
!
! [ (x)/res]
(Ide)
he, i !
!
hnot e, i
0 (res)
!
!
0 [v/res]
=v
he1 , i !
! 0
he2 , 0 i !
! 00
he1 bop e2 , i !
!
= v1
= v2
00 [v bop v /res]
1
2
he1 , i !
! 0
0
he2 , i !
! 00
he1 nop e2 , i !
!
= v1
= v2
00 [v nop v /res]
1
2
hread, i
(Not)
0 (res)
00 (res)
(Bop)
0 (res)
00 (res)
(Nop)
!
! [hd( (in))/res, tl( (in))/in] (Read)
166
0 (res) = v
he, i !
! 0
(Ass)
hx := e, i ! hnoaction, 0 [v/x]i
hnoaction; c2 , i ! hc2 , i
(Seq1 )
hc1 , i ! hc01 , 0 i
(Seq2 )
hc1 ; c2 , i ! hc01 ; c2 , 0 i
0 (res) = true
he, i !
! 0
(Cond1 )
hif e then c1 else c2 , i ! hc1 , 0 i
0 (res) = false
he, i !
! 0
(Cond2 )
hif e then c1 else c2 , i ! hc2 , 0 i
0 (res) = true
he, i !
! 0
hwhile e do c, i ! hc; while e do c,
0i
(While1 )
0 (res) = false
he, i !
! 0
(While2 )
hwhile e do c, i ! hnoaction, 0 i
0 (res) = v
he, i !
! 0
(Out)
houtput e, i ! hnoaction, 0 [v :: ( (out))/out]i
: Id ! Val},
: Id ! Val}.
167
comporta la valutazione di e
Osserviamo che la Tabella 8.3 non contiene alcuna regola per la riscrittura di noaction.
Questo basta per concludere che noaction viene interpretato come il comando nullo. Un
esempio dellesecuzione di un semplice programma TINY, ottenuta utilizzando il sistema di
transizioni appena descritto, riportato in Tabella 8.4.
Analizziamo ora alcune propriet della semantica operazionale di TINY. Per fare questo,
abbiamo bisogno di introdurre alcuni concetti.
Definizione 8.1. Una computazione di un comando c a partire da uno stato
hc, i hc0 ,
0i
! hc1 ,
1i
! ! hcn ,
ni
una sequenza
che infinita, oppure tale che lultima configurazione della forma hnoaction,
0 i.
Informalmente, diremo che uno stato appropriato per un comando c se tutte le variabili
di c sono definite in . Il fatto che una variabile x sia definita in uno stato indica o che
associa esplicitamente un valore a x o che la sequenza dei valori di input associati a in
sucientemente lunga da permettere di leggere, tramite espressioni read, i valori di base
necessari per poi inizializzare x.
Vale il seguente teorema, che pu essere dimostrato per induzione utilizzando la semantica
operazionale ed eettuando unanalisi della struttura di tutti i possibili programmi TINY.
Teorema 8.2. Siano c un programma TINY e
8.3
0i
tale che
168
while x < y do
output (y
x); x := x + 1
#
x); x := x + 1
in 7! [2, 5]
out 7! [ ]
8
res 7! 4
>
>
<
in 7! [5]
,
out 7! [ ]
>
>
:
x 7! 4
9
>
+
>
=
>
>
;
8
9 +
< res 7! 5
=
in 7! [ ] x 7! 4
,
:
;
out 7! [ ] y !
7
5
#
8
9 +
* output (y x); x := x + 1;
< res 7! true
=
while x < y do
in 7! [ ]
x 7! 4
,
:
;
output (y x); x := x + 1
out 7! [ ]
y 7! 5
#
8
9 +
* x := x + 1;
7
1
< res !
=
while x < y do
in 7! [ ]
x 7! 4
,
:
;
output (y x); x := x + 1
out 7! [1] y 7! 5
#
8
9 +
*
< res 7! 5
=
while x < y do
in 7! [ ]
x 7! 5
,
output (y x); x := x + 1
:
;
out 7! [1] y 7! 5
#
8
9 +
*
< res 7! false
=
noaction ,
in 7! [ ]
x 7! 5
:
;
out 7! [1]
y 7! 5
Tabella 8.4: Un esempio di computazione in TINY
dati che permettano di descrivere passo passo il comportamento dei vari programmi scritti
in TINY e che siano comunque sucientemente astratte da evitare la descrizione di inutili
dettagli implementativi. Tali strutture dati, analogamente a quanto gi visto nel caso della
calcolatrice tascabile, dipenderanno dallinput, dalloutput e dalla memoria. La memoria non
sar, come nel caso della calcolatrice tascabile, semplicemente un intero, ma una funzione
che associa valori booleani o naturali ad identificatori. Questa scelta ci permetter di determinare i valori delle variabili usate allinterno dei programmi e di modificare lassociazione
variabili-valori per tener conto di eventuali comandi di assegnamento.
La struttura dati, che utilizzeremo per descrivere il comportamento dei vari programmi,
non esplicitamente menzionata allinterno della sintassi del linguaggio, ma gioca un ruolo
fondamentale per la descrizione della semantica; come per la semantica operazionale, questa
struttura viene chiamata stato. Tutte le possibili frasi del linguaggio verranno descritte in
termini delle modifiche che esse inducono sullo stato. Oltre a definire lassociazione variabili-
169
valori, esso servir a modellare la comunicazione tra parti separate di uno stesso programma:
i valori calcolati da una frase sono depositati nello stato ed altre frasi useranno il nuovo stato
aggiornato. Essenzialmente lo stato rappresenta un argomento implicito durante lesecuzione
di tutti i programmi e non altro che un modello della memoria del calcolatore.
In generale leetto dellesecuzione di un comando di un linguaggio imperativo quello di cambiare il contenuto delle celle di memoria, dellinput o delloutput. La descrizione
denotazionale rende esplicito questo fatto modellando lo stato come una tripla che contiene
informazioni su input, output e memoria e la semantica dei vari comandi come funzioni che
trasformano uno stato in un altro, in generale diverso dal precedente.
I domini semantici che utilizzeremo per descrivere le funzioni di interpretazione del
linguaggio TINY sono riportati di seguito.
VAL
MEM
STATO
= NAT + BOOL
= ID ! (VAL + {unbound})
= VAL VAL MEM.
VAL indica linsieme dei possibili valori che le diverse espressioni possono assumere.
MEM invece una funzione che viene utilizzata per rappresentare la corrispondenza tra
170
Osservazione 8.3. Poich le espressioni producono valori, si potrebbe pensare di prendere come denotazione delle espressioni gli elementi del dominio VAL, e quindi di porre semplicemente
E : Exp ! VAL.
Questo potrebbe andar bene per i valori (costanti) di base, ma non permetterebbe di modellare la semantica di espressioni che causano errori, quali ad esempio 1 + true. Per trattare
adeguatamente tali situazioni dovremmo definire E : Exp ! (VAL + {error}).
Ci per non sarebbe ancora suciente per esprimere la dipendenza dei valori di alcune
espressioni dallo stato, come per esempio nel caso di x+1, il cui valore dipende dal valore legato
ad x nella memoria, o di 1+read, il cui valore dipende dallinput. Per trattare adeguatamente
anche tali situazioni dovremmo definire E : Exp ! STATO ! (VAL + {error}).
Infine, dobbiamo tener conto anche del fatto che la valutazione di unespressione potrebbe
modificare lo stato, come capita per esempio per lespressione read, la cui valutazione comporta la rimozione del primo valore dalla sequenza dei valori in input. Per trattare adeguatamente
anche tali situazioni dobbiamo definire E : Exp ! STATO ! ((VAL STATO) + {error}).
Leetto di eseguire un comando a partire da uno stato qualsiasi quello di produrre un
nuovo stato o di generare un errore; questo viene espresso nella seguente funzionalit di C:
C : Com ! STATO ! (STATO + {error}).
La funzione di valutazione di un comando prende il comando stesso come argomento e fornisce
come risultato una funzione che, dato uno stato, produce errore oppure un nuovo stato.
Nelle due sezioni successive riportiamo tutte le clausole di interpretazione semantica per
TINY. Il valore delle funzioni di interpretazione E e C sar definito in termini del metalinguaggio visto in precedenza in Sezione 6.5; avremo unequazione per ciascuna delle opzioni
delle categorie sintattiche Exp e Com. Ogni equazione sar seguita da brevi commenti sul suo
significato.
importante notare che le clausole di interpretazione semantica che riportiamo sono
sucienti per definire completamente la semantica di TINY e cio di tutti i programmi e di
tutte le espressioni che si possono costruire a partire dalla grammatica del linguaggio. Daremo
una clausola per ogni costrutto di TINY e definiremo E e C sui termini composti in funzione dei
risultati della loro applicazione ai sottotermini. Il principio di induzione strutturale garantisce
che questo suciente per specificare la semantica di qualsiasi programma TINY. Come
vedremo, le definizioni di E e di C sono mutuamente ricorsive nel senso che si richiamano a
vicenda. Esse vanno viste come un unico sistema ricorsivo la cui soluzione garantita dal
fatto che tutte le funzioni sono continue (vedi Capitolo 6) e quindi dallesistenza del minimo
punto fisso.
8.4
In questa sezione riportiamo le equazioni semantiche relative alla categoria sintattica Exp.
Sostanzialmente esse associano ad ogni espressione una funzione che preso uno stato produce un valore (il valore dellespressione) ed uno stato eventualmente modificato durante la
valutazione dellespressione.
171
E[[true]] =
E[[false]] =
. < true,
. < false,
>
>
La denotazione dellespressione true (risp. false) una funzione che riceve come input
uno stato e costruisce la coppia < true, > (risp. < false, >) dove true (false) il valore
di verit costante che fa parte del dominio semantico dei booleani assunto noto; lo stato
esattamente lo stesso stato ricevuto in ingresso dal momento che la valutazione di una costante
non comporta alcuna modifica alla memoria. Vale la pena notare che la denotazione scelta
per true e false non completamente appropriata. Per tener conto esattamente del tipo delle
funzioni di interpretazione semantica avremmo dovuto scrivere
E[[true]] =
>)
E[[false]] =
>).
Comunque, nel resto delle note ometteremo questi dettagli per non appesantire
ulteriormente la notazione.
E[[not e]] =
. cases (E[[e]] ) of
< v, 0 >: isbool(v) !< (v),
error : error
endcases
>, error;
La denotazione dellespressione not e una funzione che ricevuto uno stato lo usa per
valutare lespressione e, quindi produce come risultato intermedio una coppia <valore, nuovo
stato>. Successivamente la funzione controlla che la prima componente del risultato sia un
valore di verit e costruisce la coppia formata dal negato del valore risultato e dal nuovo stato
( rappresenta il simbolo di negazione del metalinguaggio). Nel caso in cui la valutazione
dellespressione e dia luogo ad errore oppure il valore risultato non sia un booleano, il risultato
della funzione error. A voler essere pi precisi si potrebbe distinguere anche fra i due tipi
di errore, ma, per semplicit, preferiamo ignorare anche questo tipo di problematica.
E[[n]] =
. < n,
>
La denotazione dellespressione n una funzione che quando riceve come input uno stato
costruisce la coppia < n, > dove ora n un elemento del dominio degli interi e lo stato
ricevuto in ingresso.
E[[read]] = (in, out, mem). cases in of
nil : error;
v :: in0 :< v, < in0 , out, mem >>
endcases
La funzione associata a read riceve in input uno stato, che viene visto in questo caso
come una tripla ottenuta dal prodotto di elementi di tre domini1 . Questo modo esplicito di
1
Ricordiamo che, in base alla notazione descritta nel Capitolo 5, (in, out, mem).E(in, out, mem) sta per
.E(21 , 22 , 23 ).
172
vedere lo stato ci permette di selezionare la sue componenti ed assegnare loro un nome; grazie
a questa possibilit, la funzione associata a read pu verificare se la componente dello stato
corrispondente allinput una lista (diciamo l) non vuota ed in caso aermativo produrre
come risultato il primo elemento di l insieme ad un nuovo stato del tutto simile al precedente
a parte la lista di input che viene modificata rimuovendo da essa il primo elemento. Se la lista
di input risulta vuota la funzione corrispondente a read vale error.
E[[e1 nop e2 ]] =
. cases (E[[e1 ]] ) of
< v1 , 1 >: isnat(v1 ) !
cases (E[[e2 ]] 1 ) of
< v2 , 2 >: isnat(v2 ) !
< v1 nop v2 ,
error;
error : error
endcases,
error;
error : error
endcases
>,
>.
. cases (E[[e1 ]] ) of
< v1 , 1 >: isbool(v1 ) !
cases (E[[e2 ]] 1 ) of
< v2 , 2 >: isbool(v2 ) !
< v1 bop v2 ,
error;
error : error
endcases,
error;
error : error
endcases
>,
173
La semantica di un identificatore una funzione dello stato che restituisce il vecchio stato
ed il valore associato ad x allinterno di esso, se x non unbound; in caso contrario restituisce
semplicemente error.
8.5
La funzione di interpretazione dei comandi una funzione che dato uno stato lo trasforma
in un nuovo stato che il risultato delle modifiche apportate allo stato originario durante
lesecuzione del comando. Se si verificano situazioni di errore allora invece che uno stato il
risultato della valutazione la stringa error.
C[[noaction]] =
Il significato del comando noaction la funzione identit sullo stato, cio la funzione che
non modifica il suo argomento.
C[[x := e]] =
. cases (E[[e]] ) of
< v, < in, out, mem >>:< in, out, mem[v/x] >;
error : error
endcases
La semantica di un comando di assegnamento prevede la valutazione dellespressione coinvolta nel comando, la verifica che questa valutazione non dia luogo ad errori e quindi la
creazione di un nuovo legame allinterno della memoria (tramite [v/x]) tra lidentificatore a
sinistra dellassegnamento ed il risultato della valutazione. Chiaramente, se x in precedenza
era legato ad un altro valore, il vecchio legame viene perso.
C[[c1 ; c2 ]] =
. cases (C[[c1 ]] ) of
0 : C[[c ]] 0 ;
2
error : error
endcases
La semantica delloperatore di sequenzializzazione prevede la valutazione del primo comando usando lo stato che viene passato come argomento alla funzione di valutazione. Il secondo
comando viene quindi interpretato utilizzando lo stato risultante della prima valutazione.
Questo succede solo quando non si verificano situazioni di errore.
C[[if e then c1 else c2 ]] =
. cases (E[[e]] ) of
< v, 0 >: isbool(v) !
v ! C[[c1 ]] 0 , C[[c2 ]]
error;
error : error
endcases
0,
174
La semantica del condizionale basata sul condizionale del metalinguaggio. Essa prevede
di valutare prima la condizione e, poi il comando c1 o il comando c2 a seconda che il valore
dellespressione e sia vero o falso. Quando la valutazione di e non un valore booleano, il
risultato della valutazione del condizionale error.
C[[output e]] =
. cases (E[[e]] ) of
< v, < in, out, mem >>:< in, v :: out, mem >;
error : error
endcases
La funzione associata ad output e riceve in input uno stato che essa usa per valutare
lespressione e; il risultato della valutazione, se diverso da error, viene inserito in testa alla
lista degli output del programma di cui il comando fa parte. Come risultato complessivo la
funzione produce un nuovo stato che contiene la stessa lista di input, la nuova lista di output
e la memoria risultante dalla valutazione di e.
La funzione di interpretazione semantica del comando while la pi complicata tra quelle
prese in considerazione finora. Il suo significato intuitivo ed i motivi dellintroduzione delloperatore di punto fisso possono essere spiegati utilizzando la semantica di tre dei comandi gi
descritti. Infatti, abbiamo che
while e do c
ha lo stesso significato di
if e then ( c; while e do c ) else noaction.
Pertanto, se si ignorano alcune verifiche di assenza di errore, che in questo caso avrebbero il
solo risultato di appesantire la notazione, si ha che la funzione di interpretazione semantica
del while pu essere descritta in termini della semantica delloperatore condizionale come:
C[[while e do c]] =
0,
endcases.
0 ),
>: v ! w (C[[c]]
),
endcases.
175
>: v ! w (C[[c]]
),
endcases.
Possiamo quindi concludere che la funzione di interpretazione del while il punto fisso del
funzionale suddetto (ove si siano considerate le tre possibili sorgenti di errore: E[[e]] , isbool(v)
e C[[c]] 0 ).
C[[while e do c]] = fix( w .
. cases (E[[e]] ) of
< v, 0 >: isbool(v) !
v!
cases C[[c]]
of
: w 00 ;
error : error
endcases,
0,
error;
error : error
endcases)
00
8.6
176
queste due sequenze di valori. La variabile riservata res sar utile nellanalisi della semantica
delle espressioni, ma avr scarsa rilevanza nello studio della semantica dei comandi.
Innanzitutto, consideriamo lequivalenza tra le semantiche delle espressioni.
Lemma 8.4. La semantica operazionale e la semantica denotazionale definite per le
espressioni del linguaggio TINY sono equivalenti:
E[[e]]
=< v,
> , he,
res i
!
!
[ {res 7! v}.
res [true/res].
La tesi segue
res (x)}.
hread,
res i
!
!
not e : Si ha
E[[not e]] =< v, 0 >
, E[[e]] =< v, 0 >
per la definizione di E[[]]
0
, he, res i !
! [ {res 7! v}
per ipotesi induttiva
, hnot e, res i !
! 0 [ {res 7! v}. per la regola operazionale (Not)
e1 nop e2 : Per ipotesi induttiva abbiamo che
E[[e1 ]] =< v1 ,
E[[e2 ]] 0 =< v2 ,
00
> , he1 ,
> , he2 ,
res i
0
res i
!
!
!
!
00
[ {res 7! v1 },
[ {res 7! v2 }.
Utilizziamo ora il risultato precedente per stabilire lequivalenza fra le semantiche dei
comandi.
177
, hc,
res i
! hnoaction,
0
res i.
Dimostrazione. Consideriamo innanzitutto limplicazione ) (cio la consistenza della semantica denotazionale rispetto alla semantica operazionale). La dimostrazione procede per
induzione sulla struttura di c. Il caso pi interessante quando si considera il comando while.
In questo caso, abbiamo
C[[while e do c]] = fix F
dove F il funzionale descritto nella sezione precedente, cio
F =
w .
. let < v,
> be E[[e]]
in v ! w (C[[c]]
),
F n+1
> be E[[e]]
in v ! (F n )(C[[c]]
0 ),
Considerando che fix F una funzione da stati in stati, conviene in questo contesto rappresentarla come un insieme di coppie di stati. Analogamente, tutte le sue approssimazioni finite
possono essere descritte come insiemi di coppie di stati. Infatti, applicando la funzione F n+1
and uno stato , si ottiene
0
E[[e]] =< false, 0 >
n+1
(F
) =
0 E[[e]] =< true, 00 > e (F n )(C[[c]] 00 ) = 0
Per cui abbiamo
F 0 = ;
= {( ,
{( ,
F n+1
0)
0)
| E[[e]]
| E[[e]]
=< false,
=< true,
00
>} [
> e (C[[c]]
00 ,
0)
2 F n }.
,
,
,
,
,
,
,
,
,
,
>}
>} [
>
000
Dimostriamo ora, per induzione matematica (interna), che per ogni n, abbiamo
8( ,
) 2 F n ) hwhile e do c,
res i
! hnoaction,
0
res i.
178
res i
! hnoaction,
0
res i.
Passo induttivo. Siano e 0 tali che ( , 0 ) 2 F n+1 . Data la definizione di F n+1 ci sono
due possibilit. Se E[[e]] =< false, 0 >, allora la tesi segue dal Lemma 8.4 e dalla regola
(While2 ) della semantica operazionale dei comandi. Altrimenti, sia E[[e]] =< true, 00 >.
Per il Lemma 8.4, segue che he, res i !
! 00 [ {res 7! true}. Allora, applicando la regola
operazionale (While1 ), otteniamo
hwhile e do c,
res i
! hc; while e do c,
00
dove res
indica lo stato 00 [ {res 7! true}. Se ora poniamo
strutturale (esterna), abbiamo che
hc,
00
res i
! hnoaction,
00
res i
000
= C[[c]]
00 ,
per induzione
000
res i.
00
res i
! hwhile e do c,
000
res i.
Ora, dalla definizione di F n+1 , da E[[e]] =< true, 00 > e 000 = C[[c]]
F n e quindi, per induzione matematica (interna), segue che
hwhile e do c,
000
res i
! hnoaction,
0
res i,
res i
! hnoaction,
0
res i.
00 ,
segue che (
000 ,
0)
Dimostriamo ora limplicazione ( (cio la completezza della semantica denotazionale rispetto alla semantica operazionale). La dimostrazione procede, come nel caso precedente,
per induzione sulla struttura dei comandi, considerando i diversi modi in cui possono essere
applicate le regole della semantica operazionale. Per semplicit, considereremo solo il caso pi interessante, relativo al comando while e do c. Consideriamo allora la transizione,
eventualmente in pi passi,
hwhile e do c,
res i
! hnoaction,
0
res i.
In questo caso, la dimostrazione procede per induzione sul numero n di volte che nella
transizione viene applicata la regola (While1 ).
Se n = 0, allora la transizione in esame ottenuta in un solo passo attraverso la re0
0 (res) = f alse.
gola (While2 ), quindi he, res i !
! res
con res
Dal Lemma 8.4 si ha
0
0
E[[e]] =< false, >. Quindi, la tesi, cio C[[while e do c]] = , segue immediatamente
dalla definizione di C[[while e do c]].
Altrimenti, cio n > 0, esistono 00 e 000 tali che
179
8.7 Esercizi
00
00 (res) = true, quindi, per la regola operazionale (While ),
1. he, res i !! res
e res
1
00 i,
ricaviamo che hwhile e do c, res i ! hc; while e do c, res
2. hc,
00
res i
! hnoaction,
3. hwhile e do c,
volte.
000
res i
000
res i,
! hnoaction,
Quindi abbiamo
E[[e]]
0
res i,
00
=< true,
C[[c ]]
00
000
>,
000
per ipotesi induttiva interna (numero di applicazioni della regola (While1 )). La tesi, cio
C[[while e do c]] = 0 , allora segue dalla definizione di C[[while e do c]], dato che si ha
E[[e]] =< true, 00 > e C[[while e do c]] (C[[c ]] 00 ) = 0 .
Come detto allinizio di questa dimostrazione, gli unici casi interessante nellinduzione
strutturale su cui si basano la due prove sono quelli appena completati. Inoltre il caso del
comando while richiede due prove sostanzialmente dierenti per le due implicazioni, mentre
i casi degli altri comandi possono essere arontati seguendo uno stesso schema. Vediamo
infatti come si dimostra uno degli altri casi, relativo al comando di assegnamento, lasciando
il resto della dimostrazione per esercizio al lettore. Abbiamo
C[[x := e]] = {( ,
) | E[[e]] =< v,
00
> e
00
[v/x]}.
8.7
Esercizi
180
c1 then when e do c2 ,
con la seguente semantica informale: nello stato ottenuto eseguendo c1 viene valutata la condizione e; se questa risulta vera, il comando c2 viene valutato nello stato precedente lesecuzione
di c1 , altrimenti lintero comando non ha eetto sullo stato. Fornire la semantica operazionale
e denotazionale del comando sopra descritto.
8.6 Si calcoli formalmente, usando la semantica denotazionale di TINY, linsieme degli stati a partire
dai quali eseguendo il comando seguente si ha divergenza:
while x > 0 do
if x < 3 then x := x
1 else noaction.
8.8 Fornire una semantica non standard di TINY, che ad ogni programma associa linsieme degli
identificatori utilizzati.
8.9 Fornire una semantica non standard di TINY, che associa ad ogni programma il valore corretto,
se tutti gli identificatori, prima di comparire a sinistra di un assegnamento, compaiono a destra,
ed il valore sbagliato altrimenti.
8.10 La semantica operazionale presentata per il linguaggio TINY una semantica di valutazione
oppure di computazione? Specificare laltra alternativa.
8.11 Si aggiunga al linguaggio TINY un comando stop con la semantica informale di far terminare il
programma. Se ne dia la semantica e si dimostri che c1 ; stop e c1 ; stop; c2 sono semanticamente
equivalenti.
Capitolo 9
SOMMARIO
Questo capitolo introduce un altro linguaggio di programmazione, SMALL, che una semplice estensione del linguaggio TINY considerato nel capitolo precedente. Rispetto a TINY, il
linguaggio SMALL prevede la dichiarazione esplicita di variabili e costanti usate allinterno di
un programma e la strutturazione in blocchi dei programmi stessi; inoltre SMALL permette
la dichiarazione e luso di funzioni e procedure. Pertanto, SMALL si avvicina notevolmente
al linguaggio Pascal.
9.1
Il linguaggio SMALL
SMALL, anchesso ripreso da [Gor79], ha quattro categorie sintattiche. Una categoria Dec per
le dichiarazioni, una categoria, Prog per i programmi e le categorie Exp e Com, come il TINY,
per le espressioni ed i comandi. Qui e nel resto della sezione utilizzeremo
prog
d, d1 , d2 , . . .
e, e1 , e2 , . . .
c, c1 , c2 , . . .
per
per
per
per
indicare
indicare
indicare
indicare
elementi
elementi
elementi
elementi
di
di
di
di
Prog,
Dec,
Exp, ed infine
Com.
182
9.2
Ambienti e locazioni
Lintroduzione dei blocchi porta con s la nozione di contesto allinterno del quale valutare le
espressioni ed i comandi e quindi il problema di decidere quale significato assegnare alle loro
variabili. Si pu infatti verificare il caso in cui un unico identificatore abbia due significati
diversi che dipendono dal contesto in cui esso viene usato. Ci accade ad esempio quando in
un programma ci sono due blocchi che usano lo stesso identificatore; ovvio che in questo
caso, in un qualsiasi punto di un programma, si pone il problema di determinare lassociazione
attiva.
Esempio 9.1. Consideriamo il programma
program
begin
var x = 100;
var y = 0;
y := x;
begin
var x = 1;
y := x
end;
y := x
end
In esso appaiono due diverse dichiarazioni per x e di conseguenza due diversi valori per y.
Infatti, nel blocco pi esterno, x vale 100, mentre nel blocco pi interno x una variabile
inizializzata ad 1. Conseguentemente nel blocco pi esterno y vale 100 sia prima che dopo la
valutazione del blocco pi interno; dentro questultimo y vale 1.
183
Oltre al problema di utilizzare lo stesso nome per indicare valori diversi, evidenziato dal
frammento di programma SMALL riportato nellEsempio 9.1, pu anche succedere che vengano utilizzati due identificatori per far riferimento allo stesso valore; ci si verifica ad esempio
quando i corpi di due diverse procedure usano una stessa variabile globale. In tal caso il problema che si pone quello di mantenere la consistenza tra i valori associati ai due identificatori:
in un qualsiasi istante la valutazione di entrambi deve dar luogo allo stesso valore.
importante notare come sia sempre possibile determinare, in ogni punto di un programma, il contesto attivo e quindi lesatta associazione tra variabili e valori. Nel nostro caso,
avendo scelto per SMALL uno scoping statico, lassociazione potr essere determinata anche
senza eseguire i programmi. Altri linguaggi, che qui non prenderemo in considerazione, sono
basati sullo scoping dinamico: in questi casi la determinazione esatta dei contesti attivi
possibile solo durante lesecuzione.
La descrizione della semantica di un qualsiasi linguaggio a blocchi richiede una gestione
appropriata dei contesti. Con lapproccio denotazionale questi vengono modellati tramite
funzioni chiamate ambienti . Gli ambienti stabiliscono una corrispondenza tra identificatori
e locazioni della memoria, le quali contengono invece dei valori. Lassociazione completa
identificatore-valore viene quindi ottenuta applicando in sequenza due funzioni: lambiente e
la memoria. Questultima una funzione simile alla funzione mem vista per TINY e che in
questo caso mappa locazioni (invece che identificatori) in valori. Abbiamo quindi la doppia
corrispondenza rappresentata in Figura 9.1.
xO
identificatore
/l
O
O
locazione
ambiente
/v
O
valore
memoria
184
/v
Cl
y
Figura 9.2: Nomi diversi per una stessa locazione
xO
O
identificatore
/v
O
valore
memoria
9.3
Di seguito studieremo le funzioni di interpretazione semantica per Prog, Dec, Exp e Com,
che chiameremo rispettivamente P, D, E e C. Queste funzioni associano elementi dei domini
semantici ai relativi costrutti sintattici. Per definirle essenziale quindi specificare i domini
semantici che abbiamo intenzione di utilizzare. Come nel caso di TINY, questi domini saranno
dei cpo. Tutti saranno costruiti a partire da domini elementari quali NAT, BOOL, LOC (il
dominio piatto delle locazioni), ID (il dominio piatto degli identificatori) e dai singoletti
error, unused e unbound. I domini pi complicati saranno costruiti utilizzando operatori tra
domini quali +, , !.
Per descrivere i domini delle varie funzioni che vengono associate ai frammenti di
programmi SMALL, risulta conveniente individuare dierenti classi di valori. Avremo pertanto:
185
BVAL il dominio che contiene i valori che possono essere dati in input ai programmi e ottenuti
NVAL il dominio dei valori che possono essere denotati da identificatori (valori nominabili),
EVAL il dominio dei valori che le espressioni possono assumere (valori esprimibili); un esempio
MVAL il dominio dei valori che possono essere associati alle locazioni nella memoria (valori
Non pu essere deciso una volta per tutte, a prescindere dal linguaggio che si intende
descrivere, quali debbano essere gli elementi dei domini di interpretazione. Ad esempio, pu
essere o meno necessario avere le procedure tra i valori esprimibili, avere i reali tra i valori di
base, avere le locazioni tra i valori memorizzabili, e cos via.
Nel caso di SMALL i domini precedentemente menzionati sono quelli specificati dalle
seguenti equazioni:
BVAL =
NVAL
EVAL =
MVAL
NAT + BOOL
NVAL
= BVAL + BVAL
Dalle formule riportate sopra possiamo vedere che i valori di base necessari per descrivere la
semantica di SMALL sono i naturali ed i booleani, mentre i valori nominabili sono quelli di base
pi le locazioni, le funzioni e le procedure. Ancora, per SMALL abbiamo che i valori esprimibili
coincidono con quelli nominabili; anche questo fatto pu non essere vero per tutti i linguaggi:
ad esempio, in alcuni linguaggi le procedure sono valori nominabili ma non esprimibili. I
valori memorizzabili necessari per SMALL sono i valori di base oppure loro sequenze; queste
ultime verranno essenzialmente utilizzate per rappresentare possibili input ed output.
Insieme ai domini semantici visti sopra, per descrivere la semantica di SMALL utilizzeremo
un ambiente ed una memori il cui scopo stato gi discusso in precedenza. Ambiente e
memoria sono funzioni che associano valori nominabili e valori memorizzabili ad identificatori
e locazioni, rispettivamente. Pi formalmente abbiamo:
AMB
MEM
= ID ! (NVAL + {unbound})
Come suggerito dai loro tipi, le equazioni sopra riportate prevedono anche la possibilit
che lambiente definisca unbound un identificatore e che la memoria definisca unused una
locazione.
Un ambiente fornisce il risultato unbound quando il suo argomento non stato dichiarato
prima del suo uso. Gli elementi di AMB saranno nel seguito indicati con , 0 , 00 , etc. e
saranno funzioni inizialmente uguali a x.unbound, che verranno successivamente aggiornate
in base alle dichiarazioni presenti allinterno dei programmi.
Per descrivere la modifica di un ambiente utilizzeremo due diverse notazioni:
186
La prima notazione verr utilizzata per descrivere laggiornamento dellambiente relativamente ad un solo identificatore, mentre la seconda indicher che tutte le associazioni
dellambiente 0 in cui il valore diverso da unbound vengono utilizzate per aggiornare .
Come detto in precedenza, anche per la memoria abbiamo la possibilit di segnalare situazioni anomale che si verificano durante la valutazione di un frammento di programma.
La memoria infatti rappresentata da una funzione che pu produrre il valore associato alla
locazione che gli viene passata come argomento, oppure la stringa unused quando alla locazione argomento non stato ancora associato alcun valore. Gli elementi di MEM, che saranno
indicati con , 0 , 00 , etc., saranno funzioni inizialmente uguali a x.unused, che verranno
poi aggiornate dalla valutazione delle dichiarazioni o degli assegnamenti presenti allinterno
dei programmi.
In modo simile alle funzioni ambiente, possibile aggiornare i valori associati ad una
locazione. Nel seguito useremo la seguente notazione:
[val/loc] che sta per x. (x = loc) ! val, (x).
Prima di concludere questa discussione, necessario stabilire quali sono gli elementi del
dominio base LOC; infatti la memoria definita in termini di questi. Una possibile soluzione
quella di assumere LOC uguale al dominio dei naturali NAT; per modellare le locazioni serve
soltanto un insieme sucientemente grande ed un meccanismo per verificare se ci sono o meno
valori associati ai suoi elementi. Tutte le volte che avremo bisogno di far riferimento ad una
locazione per la prima volta allinterno di una memoria, utilizzeremo la funzione:
new : MEM ! LOC
che, quando applicata ad una memoria , restituisce il minimo intero n a cui non si mai
fatto riferimento precedentemente, e cio un n tale che (n) = unused e (m) 6= unused, per
ogni m < n.
Va detto che questa soluzione non tiene conto n dei problemi indotti dalle limitazioni
della memoria, n del comportamento del programma in caso di overflow. In caso contrario
bisognerebbe assumere che la memoria sia una funzione che mappa gli interi fino a k (opportunamente scelto) in unused e gli interi maggiori di k in error. Se facessimo questa scelta la
funzione new dovrebbe essere del tipo
new : MEM ! (LOC + {error})
e restituire il minimo intero m a cui non si mai fatto riferimento precedentemente, cio un
m tale che (m) = unused, se m minore od uguale a k, ed error altrimenti.
In tutto questo capitolo, per evitare ulteriori controlli ed appesantimenti notazionali, assumeremo memoria illimitata. Inoltre, assumeremo come date due locazioni che chiameremo
lin e lout; ad esse saranno associate le stringhe di valori di input e di output dei programmi.
Una volta definiti ambiente e memoria, siamo in grado di definire i domini delle funzioni e delle procedure che ci permettono di completare la definizione dellinsieme dei valori
nominabili NVAL:
FUN = NVAL ! MEM ! ((EVAL MEM) + {error})
PROC = NVAL ! MEM ! (MEM + {error})
187
Queste equazioni prevedono che le funzioni programmabili in SMALL prendano come argomento un valore nominabile (il parametro attuale) e diano come risultato una funzione che
prende come argomento la memoria e produce un valore esprimibile (il risultato della funzione) ed una nuova memoria; questo ovviamente se non si verificano situazioni di errore. Una
procedura SMALL si comporta in modo analogo alle funzioni, ma ha come risultato semplicemente una nuova memoria; il risultato della procedura potr essere fornito al programma
chiamante tramite assegnamenti a variabili globali e quindi tramite il nuovo stato.
Osservazione 9.2. Poich non immediatamente evidente, vale la pena notare che le definizioni di questi domini semantici sono ricorsive. Per esempio, abbiamo che PROC un valore
nominabile (cio appartenente a NVAL), ma anche che NVAL viene usato nella definizione del
dominio PROC. Questa caratteristica dei domini semantici aumenta notevolmente il potere
espressivo dei linguaggi di programmazione. Grazie ad essa, siamo ad esempio in grado di
scrivere il seguente programma SMALL che calcola la funzione fattoriale senza utilizzare alcun
costrutto per la ricorsione, o per literazione.
program
begin
fun f (< g, x >);
if x = 0 then 1 else g(< g, x
output f (< f, read >)
end
1 >) x;
9.4
Semantica di SMALL
188
f ? g = x. cases f x of
< d2 , d3 >: (g d2 ) d3 ;
error : error
endcases
. cases C[[c1 ]] of
0 : C[[c ]] 0 ;
2
error : error
endcases
189
per un generico dominio D, ma non c alcuna dicolt ad istanziarla sui domini di nostro
interesse; la sua definizione la seguente:
checkD : D ! MEM ! ((D MEM) + {error})
checkD = v . isD(v) !< v,
>, error.
Essenzialmente checkD si comporta come un filtro tra una funzione e laltra, che lascia
passare soltanto quei risultati dellapplicazione della prima funzione che risultano essere di
tipo D. Utilizzando sia ? che checkD abbiamo che la semantica delloperatore not di TINY,
che prima era
E[[not e]] =
. cases E[[e]] of
< v, 0 >: isbool(v) !< v,
error : error
endcases
>, error;
diventa semplicemente:
E[[not e]] = E[[e]] ? checkBOOL ? v . < v,
>
In alcuni casi per descrivere le funzioni di interpretazione semantica troveremo pi conveniente mostrare il loro comportamento quando sono applicate ad alcuni dei loro parametri;
questo giustificato dal principio di estensionalit, che permette di identificare due funzioni
quando i loro valori sono gli stessi per tutti i possibili argomenti (si veda a tale proposito la
Sezione 5.2). Nel seguito pertanto, invece di scrivere
C[[c1 ; c2 ]] = . (
. C[[c1 ]] ) ?
. C[[c2 ]]
scriveremo
C[[c1 ; c2 ]] =
. C[[c1 ]] ?
. C[[c2 ]]
. C[[c2 ]]
190
9.5
Un programma SMALL una funzione della sequenza di input (in); il suo valore dipende
dalla semantica del corpo del programma, valutato in un ambiente vuoto 0 (indica lambiente
x.unbound) ed utilizzando una memoria in cui le uniche locazioni inizialmente definite sono
la locazione lin inizializzata con la sequenza di input e la locazione lout inizializzata con la
sequenza vuota. Il risultato del programma il contenuto della locazione lout allinterno della
memoria che risultata dalla valutazione del programma stesso.
9.6
Nel seguito, lambiente vuoto 0 sar utilizzato come base per costruire il piccolo ambiente
che viene fornito come risultato della valutazione di una o pi dichiarazioni. Nel piccolo
ambiente tutte le locazioni, a parte quelle appena dichiarate, sono legate ad unbound.
D[[const x = e]] = R[[e]] ? v . < 0 [v/x],
>
>
>
191
Le valutazioni delle dichiarazioni di funzione e di procedura danno come risultato la memoria ricevuta come argomento ed un piccolo ambiente in cui lunica associazione quella tra
il nome della funzione, o della procedura, e la semantica del loro corpo. Questultima una
funzione che, ricevuti come argomento il parametro attuale ed una memoria, valuta i costrutti
che costituiscono il corpo utilizzando la memoria passatale come argomento e lambiente in
cui ha avuto luogo la dichiarazione, aggiornato per dallassociazione tra il parametro formale
ed il parametro attuale.
D[[d1 ; d2 ]] = D[[d1 ]] ? 1 . D[[d2 ]] [1 ] ? 2 . < 1 [2 ],
>
9.7
192
>;
. < true,
. < false,
. < n,
>
>
>
La semantica delle costanti di base di SMALL una funzione costante che lascia inalterati
ambiente e memoria e d come risultato la vecchia memoria ed il valore semantico associato
ai simboli di costante.
E[[not e]] = R[[e]] ? checkBOOL ? b . < b,
>
>
>
Le valutazioni delle varie operazioni tra espressioni sono funzioni che, dopo aver ricevuto
come argomenti un ambiente ed una memoria, valutano il primo operando, quindi verificano
che il risultato della valutazione del tipo appropriato rispetto alloperazione che si deve
eseguire. Successivamente, se il tipo del primo operando appropriato e se loperazione
ha un altro argomento, valutano anche questo utilizzando il vecchio ambiente e la memoria
risultante dalla prima valutazione. Infine, se anche il risultato della seconda valutazione
del tipo appropriato, applicano loperazione, corrispondente alloperatore sintattico, ai valori
ottenuti dalla valutazione degli operandi. Per valutare gli operandi viene utilizzata la funzione
R e non la E, in quanto le operazioni not, nop e bop sono definite soltanto su valori di
base.
E[[if e then e1 else e2 ]] = R[[e]] ? checkBOOL
? b. b ! E[[e1 ]] , E[[e2 ]]
Linterpretazione del condizionale valuta la condizione e, verifica che il valore risultante
sia un booleano, quindi a seconda che esso sia il booleano true o false, valuta il secondo o
il terzo argomento utilizzando il vecchio ambiente e la memoria risultante dalla valutazione
dellespressione e.
193
. cases (lin) of
v :: in :< v, [in/lin] >;
nil : error
endcases
Se la lista associata alla locazione lin non vuota, lespressione read produce come risultato il suo primo elemento insieme ad una nuova memoria che dierisce da quella originaria
solo per la locazione lin. A questa verr associata una nuova sequenza ottenuta rimuovendo
lelemento di testa dalla vecchia.
E[[x]] =
>
La valutazione di un identificatore ha come risultato il valore nominabile (cio un valore di base intero o booleano, una locazione, una procedura o una funzione) associato
allidentificatore allinterno dellambiente ed insieme ad esso la vecchia memoria.
E[[e(e0 )]] = E[[e]] ? checkF U N ? f. E[[e0 ]] ? v . f v
La valutazione di unapplicazione di funzione ha come risultato, se non si verificano situazioni di errore, lapplicazione del risultato della valutazione della prima espressione al risultato
della valutazione della seconda espressione. I punti importantiche caratterizzano il tipo di passaggio di parametri ed il tipo di scoping modellati con la chiamata di funzione qui descritta
sono due:
1. Per valutare largomento viene utilizzata la funzione E e non la funzione R, quindi si
pu passare come parametro un qualunque valore esprimibile; e cio non solo valori di
base ma anche locazioni, procedure od altre funzioni.
2. Lambiente in cui viene eettuata la chiamata non viene utilizzato al momento della
valutazione dellapplicazione della funzione. Vengono utilizzati a questo punto soltanto
largomento e la memoria come definita al momento della chiamata; lambiente in cui la
valutazione dellapplicazione ha luogo quello che era attivo quando la funzione era stata
dichiarata e che stato associato al corpo della funzione al momento della valutazione
della dichiarazione della funzione stessa.
9.8
194
9.9
Considerazioni conclusive
195
196
9.10
Esercizi
9.1 Informalmente, un programma genera aliasing se durante una sua esecuzione due identificatori
vengono legati alla stessa locazione. Definire formalmente tale concetto e dire quali costrutti
SMALL possono dar luogo ad aliasing.
9.2 Si modifichi la semantica di SMALL in modo che le locazioni liberate alluscita dei blocchi
possano essere riutilizzate.
9.3 Mostrare, usando le clausole semantiche, che in SMALL possibile lautoapplicazione, vale a
dire il passaggio di una procedura come parametro a se stessa.
9.4 Utilizzando la propriet vista nellesercizio precedente, scrivere un programma che, ricevendo
in input una stringa u appartenente al linguaggio descritto dallespressione
(a + b) c(a + b)
decide se u appartiene al linguaggio delle stringhe palindrome sullalfabeto {a, b}.
9.5 Il linguaggio SMALL valuta le espressioni da sinistra a destra o viceversa? Modificare la semantica in modo tale che venga scelta laltra alternativa e mostrare un semplice programma che ha
una semantica diversa nei due casi, calcolando la semantica in entrambi i casi.
9.6 Si aggiunga al linguaggio SMALL un comando stop con la semantica informale di far terminare il
programma. Se ne dia la semantica e si dimostri che c1 ; stop e c1 ; stop; c2 sono semanticamente
equivalenti.
9.7 Estendere il linguaggio SMALL introducendo i comandi restart ed exit, il cui significato di
saltare rispettivamente allinizio ed alla fine del blocco pi interno.
9.8 Fornire una semantica non standard di SMALL, che ad ogni programma associa il numero
corrispondente alle volte che un assegnamento appare nel programma.
9.9 Fornire una semantica non standard di SMALL, che ad ogni programma associa il numero
corrispondente alle volte che un assegnamento viene eettuato dal programma.
9.10 Ridefinire la semantica di SMALL in modo che si abbia error se una variabile viene usata senza
essere dichiarata.
9.11 Ridefinire la semantica di SMALL in modo che si abbia warning se una variabile viene dichiarata,
ma mai usata.
Parte III
Sistemi Concorrenti
Capitolo 10
SOMMARIO
Questo capitolo introduce alcuni degli operatori utilizzati dai calcoli di processo pi conosciuti. Vedremo come tali operatori possono essere impiegati per costruire processi complessi
a partire da azioni elementari e processi pi semplici. Grazie alla semantica definita in stile SOS, il comportamento di un processo composto verr quindi definito per mezzo della
semantica dei processi che lo compongono.
10.1
200
10.2
In questo capitolo esamineremo gli operatori pi frequentemente utilizzati dai calcoli di processo. Non considereremo operatori che modellano caratteristiche sofisticate dei sistemi concorrenti quali priorit, tempo, probabilit, ecc. Ci limiteremo invece a considerare gli operatori
di base e ad alcuni operatori che manipolano valori.
201
1
Ei 1 !
Ei01 Eim
! Ei0m
10.3
Processi di base
I processi di base sono costanti (cio, operatori senza argomenti) e rappresentano i processi
elementari.
202
Processo inattivo. Il processo pi elementare di tutti quello inattivo ossia quel processo
che non esegue alcuna attivit. Esso viene solitamente indicato con i simboli nil, 0, o stop.
La sua semantica definita dal fatto di non avere regole di transizione. Per semplificare la
notazione si omette spesso il processo inattivo quando preceduto da almeno unazione.
Il processo
nil
pu quindi rappresentare un distributore automatico rotto: esso non accetta monete e non
ore bevande.
Terminazione. La terminazione a volte esplicitamente denotata dalla costante di procesp
so exit (o, skip) che pu solo eseguire lazione speciale (pronunciato tick) per indicare la
terminazione e trasformarsi in un processo inattivo, come formalizzato dal seguente assioma
p
exit ! stop
chaos ! chaos
10.4
chaos ! stop
Operatori di sequenzializzazione
203
.E ! E
che descrive un distributore automatico (un po limitato) che in cambio di una moneta fornisce
una barretta di cioccolato e poi si ferma.
Composizione sequenziale o enabling. Loperatore binario composizione sequenziale
tra processi si indica con ; . A volte, con la la stessa semantica, si usa il simbolo
che
chiamato enabling o il simbolo che chiamato prodotto. Intuitivamente, se E ed F
sono processi, la semantica del processo E; F prevede che inizialmente venga eseguito E e che,
p
quando E segnala la sua terminazione (indicata dallazione ), cominci lesecuzione di F . Le
regole di inferenza che definiscono la semantica delloperatore composizione sequenziale sono
le seguenti
p
p
E ! E0
E ! E0
( 6= )
E; F ! E 0 ; F
E; F ! F
Con loperatore di sequenzializzazione un distributore automatico limitato ma onesto pu
essere descritto, considerando le azioni come processi, da
coin; choc
esso prende una moneta e, dopo che il processo di acquisizione della moneta terminato, ore
una barretta di cioccolato.
Disabling. Loperatore binario disabling, indicato con [>, viene di solito usato in congiunzione con lenabling. Intuitivamente, se E ed F sono processi, il processo E [> F inizialmente
si comporta come E ma pu essere interrotto in qualsiasi momento da F , anche prima della
sua terminazione. Se invece E segnala la sua terminazione, F viene eliminato perch venuto
meno il suo ruolo.
E ! E0
E [> F ! E 0 [> F
( 6=
E ! E0
E [> F ! E 0
F ! F0
E [> F ! F 0
che descrive un distributore automatico che in cambio di un colpo ben assestato fornisce la
barretta di cioccolato anche quando non stata inserita alcuna moneta.
204
10.5
Operatori di scelta
Gli operatori di scelta permettono di esprimere scelte tra comportamenti alternativi. Si tratta
di operatori dinamici (perch scompaiono quando la scelta viene eettuata) e, naturalmente,
non deterministici. Con essi, e con gli operatori visti in precedenza, possiamo gi modellare
LTS ed automi a stati finiti.
Scelta (mista) o somma. Loperatore binario scelta, scritto +, permette di esprimere
una scelta tra due possibili comportamenti. Cominciamo col vedere le semplici regole che
definiscono loperatore
E ! E0
F ! F0
E + F ! E0
E + F ! F0
Osserviamo che loperatore non-deterministico, infatti il processo
Ej ! Ej0
X
Ei ! Ej
(j 2 I)
i2I
Esempio 10.1. [Bill-Ben] Utilizzando gli operatori visti fino a qui possiamo scrivere un
processo che ha come grafo delle transizioni quello della Figura 10.1. Infatti, se allo stato q0
associamo il processo
play. work. . nil + work. play. . nil
abbiamo che, grazie alla semantica degli operatori, dallo stato q0 escono due archi distinti
(transizioni (q0 , play, q1 ) e (q0 , work, q2 ) ) che raggiungono due stati dierenti q1 e q2 , associati rispettivamente ai processi work. . nil e play. . nil. Da questi, tramite altri due archi
205
q0
pla
y
q3
pla
y
q4
rk
wo
q1
F !E
F !F
water ! stop)
206
E ! E0
E F ! E0
( 6= )
F ! F0
E F ! F0
( 6= )
E ! E0
F ! F0
E F ! E0 F
E F ! E F0
Con questo operatore possibile limitare larbitrio del nostro distributore automatico. Ad
esempio, il termine
water ! stop) water ! stop
descrive un distributore automatico che non pu rifiutarsi di orire lacqua. Infatti, se dopo
aver ricevuto la moneta la componente a sinistra di decidesse di orire solo una barretta
di cioccolato, allora la componente a destra di continuerebbe a garantire la possibilit di
scegliere lacqua. Levoluzione sarebbe la seguente:
coin ! (choc ! stop
water ! stop) water ! stop
(choc ! stop
water ! stop) water ! stop
(choc ! stop water ! stop)
coin
!
!
water ! stop )
water ! stop
10.6
coin
!
!
choc
Operatori di parallelismo
Gli operatori di parallelismo permettono di ottenere processi complessi tramite la composizione parallela di processi pi semplici. Si tratta in generale di operatori statici che modellizzano
la strutturazione di processi in sottoprocessi.
Composizione parallela ( la Milner). Loperatore binario | permette sia linterleaving
delle azioni eseguibili dalle componenti parallele sia linterazione tra due processi che eseguono
azioni complementari. Informalmente, nel processo E|F le azioni di E e di F sono considerate
indipendenti le une dalle altre e qualsiasi interleaving tra loro possibile; inoltre, azioni visibili
complementari e possono dare origine a sincronizzazioni. Quando vi una sincronizzazione
207
essa viene percepita dallesterno come unazione . Le regole di inferenza che definiscono la
semantica delloperatore sono
E ! E0
F ! F0
E|F ! E 0 |F
E|F ! E|F 0
E ! E0
F ! F0
E|F ! E 0 |F 0
( 6= )
Per mezzo delloperatore composizione parallela possiamo modellare non solo il nostro
distributore automatico ma anche le sue interazioni con un utente ipotetico. Il termine
coin ! (choc ! stop
water ! stop)
Va detto che questo sistema prevede anche altre computazioni in cui le sincronizzazioni non
avvengono, come in
coin ! (choc ! stop
(choc ! stop
(choc ! stop
water ! stop)
coin
coin
che sostanzialmente cattura il fatto che il distributore ore la possibilit di inserire la moneta
anche ad altri utenti e che lutente pu inserire la sua moneta anche in altri distributori.
Nel seguito, vedremo come forzare le sincronizzazioni quando discuteremo gli operatori di
astrazione.
Merge. Alcuni calcoli, quali ad esempio ACP, utilizzano, per la composizione parallela tra
due processi, loperatore k . Anche questo operatore permette sia linterleaving che linterazione tra i due processi. La dierenza rispetto alloperatore | sta nel modo in cui viene espressa
linterazione. Come abbiamo visto, nel caso delloperatore | , si usa la nozione di complementarit tra azioni. Nel caso delloperatore k , si usa invece un meccanismo pi generale e si
modella il fatto che lesecuzione simultanea di due azioni qualunque pu originare una sincronizzazione. A questo scopo viene introdotta una funzione di comunicazione : !
(dove linsieme delle azioni) avente la propriet di essere commutativa (cio tale che
(a, b) = (b, a)) e associativa (cio tale che ( (a, b), c) = (a, (b, c))). Dati due elementi
a, b 2 , lelemento (a, b) viene interpretato come lazione risultante dalla sincronizzazione di
un processo che esegue lazione a con uno che esegue lazione b. In generale si ammette che la
funzione sia una funzione parziale e talvolta, come ad esempio nei calcoli di processi TCSP
e LOTOS, si impone (a, a) = a. Inoltre, poich (a, b) visibile, essa pu essere usata per
ulteriori sincronizzazioni con altre azioni. Quindi, mentre | permette solo la sincronizzazione
208
F ! F0
E k F ! E0 k F
E ! E0
E ! E0
E k F ! E k F0
EkF
F ! F0
(a,b)
! E0 k F 0
dove 2 [ { }.
Il sistema costituito da un distributore automatico e da un utente potrebbe essere cos
descritto (dove usiamo loperatore . per le azioni prefisse):
getCoin.(giveChoc.nil + giveW ater.nil) k putCoin.getChoc.nil
dove si pone (getCoin, putCoin) = ok e (giveChoc, getChoc) = ok. Anche in questo caso,
come per loperatore | , le sincronizzazioni non sono obbligatorie; vedremo in seguito come
forzare le sincronizzazioni a cui siamo interessati.
Loperatore k pu essere espresso in termini di operatori di parallelismo pi basilari come
specificato dallequazione E k F = ETF +F TE+E|c F , dove T e |c sono gli operatori left-merge
e communication-merge che illustriamo adesso.
Left-merge e communication-merge. Loperatore T noto come left-merge e la sua
semantica dice che lazione iniziale deve essere eseguita dal processo di sinistra dopodich il
comportamento del sistema regolato da k. Lunica regola semantica
E ! E0
ETF ! E 0 k F
Loperatore |c noto come communication-merge e la sua semantica dice che lazione
iniziale deve essere uninterazione tra i due processi dopodich il comportamento del sistema
regolato da k. Lunica regola semantica
a
E ! E0
E|c F
F ! F0
(a,b)
! E0 k F 0
Interleaving Gli operatori di parallelismo che abbiamo visto finora permettono ai processi
in parallelo di sincronizzarsi nellesecuzione di certe azioni. Al contrario, loperatore binario
interleaving ||| permette esclusivamente lesecuzione indipendente dei due processi argomento.
Le regole semantiche sono
E ! E0
E ||| F ! E 0 ||| F
F ! F0
E ||| F ! E ||| F 0
Consideriamo il processo
a.b.nil ||| c.d.nil
esso ammette le seguenti computazioni che lo fanno evolvere in nil ||| nil
abcd,
acdb,
cdba,
acbd,
cadb,
cabd
209
E ! E0
E |[L]| F ! E 0 |[L]| F
F ! F0
( 62 L)
E |[L]| F ! E |[L]| F 0
E ! E0
( 62 L)
F ! F0
E |[L]| F ! E 0 |[L]| F 0
(a 2 L)
Loperatore |[L]| in relazione con alcuni degli operatori visti in precedenza. In particolare,
se si definisce (a, a) = a per ogni a 2 L, gli operatori |[L]| e k hanno semantiche equivalenti.
Se invece si prende L = ;, gli operatori |[L]| e ||| risultano equivalenti.
Prodotto (o parallelo con esecuzione sincrona). Se E ed F sono processi, loperatore
binario permette di formare il processo E F in grado di eseguire unazione solo se questa
il risultato del prodotto di unazione iniziale di E ed una azione iniziale di F . In pratica, le
componenti E e F di E F devono procedere in maniera sincrona; cio, non possibile che
una componente resti ferma mentre laltra eettua unazione.
Perch la definizione abbia senso richiesto che sullinsieme delle azioni sia definita unoperazione di prodotto, denotata anchessa con , che rende tale insieme un gruppo abeliano.
Ricordiamo che un gruppo abeliano costituito da un insieme A e da unoperazione binaria
su A tale che
associativa e commutativa,
esiste un elemento speciale 1 2 A, detto elemento neutro, tale che 1 = 1 = ,
per ogni 2 A,
per ogni 2 A esiste un elemento, detto opposto di e denotato con
, tale che
=
= 1.
La semantica operazionale delloperatore sui processi definita dalla seguente regola
dinferenza
E ! E0
EF
F ! F0
! E0 F 0
210
00
1
b.0 1.0
10.7
00
Operatori di astrazione
Spesso utile vedere un processo come una black-box e modificarne il comportamento restringendo o ridenominando le azioni che pu eettuare. Gli operatori di astrazione permettono
questo tipo di modifiche sui processi e si rendono quindi utili per modificare il livello di
astrazione a cui un sistema descritto facilitando cos la composizionalit dei processi stessi.
Restrizione. Loperatore unario \L , dove L , permette di restringere le azioni visibili
del processo a cui applicato. Il processo E\L potr eseguire solo le azioni non incluse in
L ed il cui complementare non incluso in L. Ovviamente non ha senso impedire che un
processo esegua unazione interna e perci non permesso che appartenga ad L. Quando
L contiene una sola azione, cio L = {a}, scriveremo, per semplicit, E\a invece di E\{a}.
La semantica operazionale definita dalla regola dinferenza
E ! E0
E \L ! E 0 \L
( , 62 L)
!
(ok.nil) | ok.(choc.nil + water.nil) \ ok | choc.nil
!
nil | (choc.nil + water.nil) \ ok | choc.nil
!
nil | nil \ ok | nil
Si osservi che un utente malizioso che tentasse di eseguire la sequenza di azioni ok.choc.nil
per ottenere il cioccolato senza inserire una moneta non riuscirebbe ad interagire con il
distributore.
211
Osserviamo infine che c una certa corrispondenza tra i processi (E|F )\L e E |[L]| F : in
entrambi i casi i processi E ed F devono necessariamente sincronizzarsi se vogliono eseguire
azioni di L, nel secondo caso per lazione risultante dalla sincronizzazione visibile anche
allesterno.
Esempio 10.2. [Bill-Ben] Abbiamo visto che il grafo delle transizioni associato al processo
play.work..nil + work.play..nil
quello della Figura 10.1. Vediamo adesso che vi sono altri processi che hanno lo stesso grafo
delle transizioni. Si consideri il processo
(play.meet.nil | work.meet.nil) \ meet
Non dicile rendersi conto che il grafo delle transizioni ad esso associato ancora quello di
Figura 10.1.
E ! E0
( 2 L _ 2 L _ = )
E L ! E0 L
Encapsulation. Loperatore unario H , dove H , ha leetto di rinominare le azioni
appartenenti ad H in bloccandone cos lesecuzione. In pratica, il processo H (E) si
comporta come E eccettuato il fatto che esso non pu eseguire le azioni che compaiono in H
e le loro complementari (e, di conseguenza, ci che li segue sintatticamente). La semantica
operazionale definita dalla regola di inferenza (ove si assume che lazione invisibile non
appartenga a H)
E ! E0
H (E)
H (E
( 62 H)
Si noti la stretta corrispondenza con (la regola che definisce) la semantica operazionale
delloperatore di restrizione (in pratica, E \H e H (E) si comportano allo stesso modo).
212
E ! E0
E/L ! E 0 /L
E ! E0
( 62 L)
E/L ! E 0 /L
( 2 L)
E ! E0
E[f ]
f ()
! E 0 [f ]
dove sintende f ( ) = e f (a) = f (a). Come si vede si tratta di un operatore statico. Esso
usato per gestire meglio la sincronizzazione e per facilitare il compito di costruire processi
complessi a partire da altri pi semplici.
Se la funzione f non si comporta come lidentit solo su un insieme finito di punti a1 , , an
allora essa viene scritta per semplicit come [b1 /a1 , , bn /an ] dove b1 = f (a1 ), , bn =
f (an ). Per esempio [c/a, d/b] la funzione che rinomina a con c e b con d.
213
e un utente italiano che voglia usufruire del distributore per prendere un bicchiere di acqua
soldo. acqua. nil
Lutente pu interagire col distributore se gli applichiamo un operatore di rietichettatura
coin. (choc. nil + water. nil) | ( soldo. acqua. nil ) [coin/soldo, water/acqua]
10.8
Gli operatori che abbiamo visto finora permettono di definire solo processi il cui comportamento finito, cio processi che possono eettuare solo computazioni di lunghezza finita.
Introduciamo adesso i meccanismi che possono essere utilizzati per definire processi in grado
di eettuare sequenze infinite di transizioni.
Costanti di processo. Una costante di processo un processo il cui significato dato da
unequazione di definizione. Se A una costante di processo si assume quindi che vi sia anche
una definizione della forma A , E che definisce A per mezzo del processo E. La semantica
operazionale per le costanti di processo ovvia
E ! E0
A ! E0
(A , E)
Il potere espressivo di quella che sembra essere una definizione banale sta nel fatto che nulla impedisce che la costante di processo A venga usata anche nel processo che la definisce
permettendo cos definizioni ricorsive o mutuamente ricorsive.
Per convenzione, le costanti di processo sono solitamente indicate con stringhe che
cominciamo con una lettera maiuscola.
Finalmente siamo in grado di migliorare il nostro distributore automatico e fare in modo
che esso sia sempre pronto a servire un nuovo cliente dopo aver finito di servirne un altro. A
questo scopo definiamo la costante di processo D (distributore) come
D , coin. (choc. D + water. D)
Una possibile computazione del distributore in parallelo con un utente la seguente
D | coin. choc. nil
(choc. D + water. D) | choc. nil
D | nil
che mostra che, dopo aver interagito con lutente, il distributore tornato nel suo stato iniziale
ed attende il prossimo cliente.
214
toss
! tail.Coin
tail
! Coin
toss
! head.Coin
head
! Coin
toss
! ...
Ricorsione. Processi ricorsivi possono essere ottenuti anche per mezzo delloperatore unario rec X. . Se E un processo (o, pi precisamente, unespressione di processo) in cui
compare la variabile X allora, intuitivamente, il processo rec X.E (talvolta scritto anche come f ix(X = E)) definito come il processo che si comporta come E in cui le occorrenze
di X sono sostituite con rec X.E stesso. Informalmente possiamo anche dire che rec X.E
equivalente a una definizione della forma X , E. Per definire formalmente la semantica
delloperatore di ricorsione bisogna definire il concetto di occorrenza libera di una variabile.
Se E unespressione di processo, ossia un processo in cui compaiono delle variabili, allora
diremo che una certa occorrenza di X in E libera se essa non appartiene al corpo di un operatore della forma rec X. Con E{F/X} si denota il processo ottenuto sostituendo (a livello
sintattico) le occorrenze libere di X in E con il processo F .
La semantica data dalla seguente regola dinferenza
E{rec X.E/X} ! E 0
rec X.E ! E 0
La regola dice che il processo rec X.E pu fare qualsiasi azione che pu fare il processo
E{rec X.E/X} e proseguire nello stesso modo.
Per mezzo di questo operatore il distributore automatico pu essere definito come il
processo
rec D. coin. (choc. D + water. D)
Una possibile computazione di questo processo la seguente
coin
9
=
;
choc
coin
...
215
toss
tail
!
!
toss
...
f ixj (X
ed ha la seguente semantica
Ej
= E)/X
f ixi (X
i | i2I
= E)
!
f ixj (X
E0
! E0
= E)/X
dove Ej f ixi (X
rappresenta il processo ottenuto sostituendo, per ogni i,
i | i2I
= E).
E ! E0
! E ! E0| ! E
oppure
E| ! E ! E 0
! E ! E0
Come si vede, si tratta di un operatore statico. Il suo potere espressivo equivalente a quello
delle definizioni di processo ed a quello delloperatore di ricorsione. Infatti, ! E pu essere
definito dalla seguente equazione
A , E|A
oppure pu essere espresso in termini delloperatore rec dal processo
recX.(E|X)
Al contrario, ! pu essere utilizzato per codificare equazioni di processo ricorsive e processi
ricorsivi in modo tale che, se si ignorano le azioni invisibili, i processi risultanti dalle codifiche si
comportino come quelli originali. Per esempio, supponiamo che il processo E usi la costante di
216
coin
coin
choc
!
!
choc
!
!
Si pu quindi osservare che, una volta ricevuta una moneta, il distributore non obbligato a
dare la barretta di cioccolato prima di ricevere una seconda moneta. Se invece si vuole fare in
modo che le azioni di ricezione della moneta e di erogazione della barretta siano strettamente
sequenziali, si potrebbe utilizzare il seguente processo ricorsivo
recX. coin. choc.X
Tale processo, codificato usando loperatore ! , diventa
(a. nil | ! a. coin. choc. a. nil) \ a
Le sue possibili computazioni sono della forma
(a. nil | ! a. coin. choc. a. nil) \ a
coin
choc
!
...
e quindi il processo ottenuto si comporta sostanzialmente (cio, come sar formalizzato nel
Capitolo 11, a meno di azioni interne) come volevamo.
10.9
217
Sincronia ed asincronia
218
0
0
0
0
0
0
0
..
.
0 0 0 0 0 0 0
a
a
b
b
..
.
a
a
b
b
..
.
0
0
0
0
0
..
.
a
a
0
0
0
0
..
.
0
0
0
..
.
b
b
0
0
0
0
..
.
a a = a, a = 0, a
= 0,
ossia
per ogni ,
=
a 0
0
0
0
0 0
a
0
0
a
0
0
0
0
0
0
6= a
6= a
0
0
0
0
0
0
Come ultimo esempio consideriamo unalgebra di sincronizzazione che assicura che tutte
le azioni dei processi composti in parallelo occorrono in maniera asincrona.
0
0
0
0
0
0
E ! E0
EF
F ! F0
! E F
6= 0)
219
10.10
Finora abbiamo introdotto azioni ed operatori che non manipolano valori. Consideriamo ora
un sistema in cui vi scambio di informazioni tra le varie componenti e in cui il comportamento
delle varie componenti dipende dalle informazioni ricevute. Si potrebbe pensare che un tale
sistema non possa essere espresso con gli operatori visti. Le cose non stanno cos. Si pu infatti
mostrare, e lo faremo in seguito per CCS, che sotto opportune ipotesi possibile tradurre un
sistema in cui c scambio di valori in uno in cui tale scambio non c.
I calcoli di processo che supportano il passaggio di valori tra le varie componenti sono
detti calcoli con value-passing. Tali calcoli risultano pi espressivi e comodi da usare ma, dal
punto di vista teorico, equivalenti a quelli senza value-passing. Quando si tratta di studiare
le propriet di un calcolo di processi conviene quindi riferirsi alla versione senza value-passing
che risulta sicuramente pi facile da trattare avendo meno costrutti.
In questa sezione presentiamo gli operatori standard per la manipolazione di valori. Le
operazioni pi comuni per trattare valori sono:
Output di valori. Per inviare il valore dellespressione e sul canale a si usa la sintassi
a e. Tale sintassi viene vista come una sorta di azione e la si usa perci come prefisso: se
E un processo, a e.E il processo che spedisce il valore dellespressione e sul canale a
per poi comportarsi come E. Per esempio: a 1.nil spedisce 1 sul canale a e poi termina.
Input di valori. Per ricevere un valore su un canale a si usa la sintassi a(x). Se E un
processo in cui compare la variabile x, allora a(x).E rappresenta il processo che riceve
un valore v sul canale a e poi si comporta come E in cui le occorrenze libere di x sono
sostituite dal valore v. Vedremo tra breve linterazione tra un processo che spedisce un
valore ed uno che lo riceve.
Comportamento condizionale. Se un processo riceve un valore si potrebbe volere
che il suo comportamento dipenda dal valore ricevuto. A questo scopo si usa loperatore
if . Se E ed F sono processi, il processo if e then E else F si comporta come E se
la valutazione (che supponiamo gestita da qualche altro meccanismo) dellespressione e
restituisce true e si comporta come F se la valutazione di e f alse.
Costanti di processo parametriche. Se i processi sono in grado di gestire valori
pu risultare utile permettere che le costanti di processo abbiano dei parametri. Una
costante di processo parametrica A un processo definito da una equazione della forma
A(x1 , . . . , xn ) , E
dove E un processo che pu contenere le variabili x1 , . . . , xn (oltre che A o altre
costanti di processo). Per esempio: il processo a(x).A(x), dove
A(x) , if x = 0 then nil else b x.nil
220
(v valore)
a(v)
! E{v/x}
a val(e)
!E
a e.E
a v
! E0
a(v)
! F0
a(v)
! E0
E|F ! E 0 |F 0
a v
! F0
E|F ! E 0 |F 0
val(e) = true E ! E 0
val(e) = f alse
F ! F0
if e then E else F ! E 0
if e then E else F ! F 0
Come esempio descriviamo un distributore automatico che accetta una moneta da 20 centesimi
(o pi) ed ore una barretta di cioccolato
coin(x). if x
!
20 then choc.nil else nil | choc.nil
!
nil | nil
Ovviamente, cos com descritto, il distributore non d il resto e non restituisce la moneta
se questa inferiore a 20 centesimi (oltre al problema di funzionare per una volta sola). Si
osservi anche che ci siamo permessi di usare in modo promiscuo gli operatori per il passaggio
di valori e quelli senza passaggio di valori.
Diamo infine la semantica per le costanti di processo parametriche
A(e1 , . . . , en ) ! E 0
(A(x1 , . . . , xn ) , E)
Vediamo ora un altro semplice esempio di processo che utilizza il passaggio di valori con
lo scopo di mostrare come esso possa essere simulato senza luso del passaggio di valori.
1
Si noti che il prefisso di input a(x). legante nel senso che nel processo a(x).E le occorrenze libere della
variabile x in E sono legate allinput a(x). Le definizioni di costanti di processo parametriche si comportano
in maniera simile, cio in A(x1 , . . . , xn ) , E le occorrenze libere delle variabili xi in E sono legate dalla
definizione.
221
Consideriamo il seguente processo forwarder che riceve un valore sul canale in e quindi lo
spedisce sul canale out
F , in(x). out(x). F
Le computazioni del processo risultano quindi essere della forma
F
in(v)
! out(v). F
out(v)
! F
Indichiamo con V linsieme dei valori che possono essere trasmessi. Per esprimere nel calcolo
senza passaggio di valori un processo che si comporta come F associamo a ogni canale a
del calcolo con value-passing tanti canali del calcolo senza value-passing quanti sono i valori
di V . In altre parole, ad ogni canale a del calcolo con value-passing associamo un insieme
{av | v 2 V } i cui elementi sono canali indicizzati dagli elementi di V . In questo modo, per
esempio, un processo della forma in(x). E corrisponde al processo
X
inv . E {v/x}.
v2V
Lazione P
in(v) corrisponde allazione inv e lazione out(v) corrisponde allazione outv . Loperatore
esprime la possibilit da parte del processo tradotto di scegliere uno qualunque
degli elementi di V . Ovviamente, se linsieme V dei valori infinito la scelta espressa da
una somma con infiniti termini per cui la traduzione che abbiamo eettuato ha senso se V
finito o se si ammettono le somme di infiniti termini.
Il processo risultante dalla traduzione di F il seguente
X
Fb ,
inv . outv . Fb
v2V
Vediamo ora come pu essere tradotto il costrutto if e then E else F in un calcolo senza
value-passing. Nella definizione della traduzione, non c un costrutto corrispondente a questo
operatore, piuttosto, la guardia e utilizzata per scomporre linsieme degli indici di ciascuna
delle somme risultanti dalla traduzione delle azioni di input in due insiemi: quello degli indici
che rendono vera e, e quello degli indici che la rendono falsa. Per esempio, se V linsieme
dei numeri naturali, il processo
in(x). if x > 0 then out(x
tradotto nel processo
(
inv .outv
1 .nil)
v>0
222
Altri operatori che subiscono modifiche nella traduzione sono la restrizione e il relabelling.
Nel primo caso, \L diventa \{v | 2 L, v 2 V } mentre [f ] diventa [f] dove, per definizione,
si pone f(v ) = f ()v .
Esempio 10.8. Facendo uso delle costanti di processo parametriche si pu definire un
processo Countdown(x) che esegue un conto alla rovescia a partire dal valore x:
Countdown(x) , if x > 0 then tick. Countdown(x
Osservazione 10.9. Sono stati definiti in letteratura calcoli in cui i processi possono scambiarsi altri tipi di informazioni, quali ad esempio record di dati, processi (comunicazione
higher-order) o canali di comunicazione ( link mobility). Le teorie matematiche sviluppate
per questi calcoli sono basate su idee simili a quelle utilizzate per i calcoli di base ma sono
sensibilmente pi complicate. Per questo motivo tali calcoli di processo non saranno presi in
considerazione in queste note.
10.11
Esercizi
10.1 Si disegnino i grafi di transizione associati ai seguenti termini (i nil finali sono stati omessi):
a)
b)
c)
e)
f)
g)
a+a
a|a
(a.b | a
.c) \ a
a.b + a.c
a.b a.c
.a.b + .a.c
h)
i)
l)
m)
n)
o)
.a.b .a.c
a.b | a
.b
a.b ||| a
.b
rec x.a.b.x
rec x.(a + b).x
A|a
, dove A , a.b.A
10.2 Si scriva un termine che descriva un distributore automatico in grado di orire acqua o cioccolato
un numero illimitato di volte senza accettare monete fino a che non stato servito lutente
precedente. Si risolva lesercizio in tre modi: con loperatore di ricorsione, con la definizione di
costanti di processo e con loperatore di replicazione.
10.3 Si descriva il comportamento del termine D(0) dove D una costante di processo parametrica
definita nel modo seguente
223
10.11 Esercizi
D(q)
change (q).D(0)
+ if(q < 40) then coin(x). D(x + q) else nil
+ if(q 40)
then chock. change (q 40). D(0)
else if(q 20) then water. change (q 20). D(0) else nil
Capitolo 11
Equivalenze comportamentali e
preordini di ranamento
SOMMARIO
Questo capitolo presenta diversi criteri per confrontare sistemi di transizioni etichettate.
Alcuni di questi criteri costituiscono delle relazioni di equivalenza sullinsieme dei sistemi di
transizioni, altri invece costituiscono dei preordini su tale insieme. In particolare introdurremo lequivalenza a tracce, la bisimilarit e lequivalenza testing. Di ciascuna di esse daremo
una versione forte che considera le azioni invisibili alla stessa stregua delle altre azioni ed
una versione debole che tratta le azioni invisibili in maniera speciale. Presenteremo inoltre
alcune varianti, quali lequivalenza a tracce complete, la doppia simulazione e la bisimilarit
di branching. Concluderemo esaminando il comportamento delle relazioni introdotte nei
confronti della divergenza e la gerarchie a cui danno origine.
11.1
Come detto nellintroduzione, stabilire se due processi sono equivalenti interessante ed utile
sia al fine di assegnare una semantica formale ai processi sia al fine di dimostrare che limplementazione di un sistema (come realizzato) corretta rispetto ad una data specifica (cosa
gli si chiede di fare), quando implementazione e specifica sono entrambe espresse utilizzando
lo stesso formalismo.
La nozione di equivalenza da utilizzare dipende fondamentalmente dalluso previsto per
i sistemi in considerazione. In eetti, il tipo di uso di un sistema determina gli aspetti
comportamentali che devono essere presi in considerazione e quelli che possono essere ignorati.
Perci, per ciascuna equivalenza, importante conoscere le propriet dei sistemi che essa
preserva. Non quindi sorprendente che in letteratura siano state proposte molte teorie di
equivalenza per via dei molti aspetti di un sistema concorrente che potrebbe valere la pena di
considerare.
Le equivalenze che vedremo sono tutte basate sullidea che due processi sono equivalenti
se nessun osservatore (utente) esterno li pu distinguere, cio se i due processi hanno lo stesso
insieme di osservazioni. Le semantiche indotte da questo tipo di equivalenze sono anche dette
osservazionali. Ci che interessa, infatti, non la struttura interna di un processo, ma il
suo comportamento in relazione allambiente esterno. Pertanto, unequivalenza ragionevole
tra processi non pu essere basata sulluguaglianza delle loro semantiche operazionali, cio
226
dei corrispondenti LTS, perch risulterebbe eccessivamente discriminante in quanto considererebbe dettagli dei processi, quali la struttura, non osservabili dallesterno. Perci, bisogna
definire dei meccanismi di astrazione che, a partire dalla semantica operazionale, cio dagli
LTS, permettano di ignorare dettagli ritenuti irrilevanti.
Non c per ancora completo accordo su quale sia la nozione corretta di osservazione e
su come gli esiti di unosservazione debbano essere usati per distinguere o identificare sistemi.
Per questo, in letteratura sono state definite molte equivalenze osservazionali, ciascuna basata
su una specifica e ragionevole nozione di osservabile. Difatti, esiste unintera gamma di equivalenze che possono essere organizzate in una gerarchia che va dallequivalenza pi restrittiva,
che lisomorfismo tra i grafi di transizione degli LTS, a quella pi debole, che lequivalenza
a tracce. Va tenuto conto che ci che dierenzia le equivalenze osservazionali il modo in cui
esse trattano il nondeterminismo. Infatti, se si considerano solo LTS deterministici, tutte le
equivalenze coincidono.
Le equivalenze che considereremo possono essere raggruppate in due grandi categorie: le
equivalenze forti che considerano lazione interna alla stessa stregua delle altre azioni e le
equivalenze deboli che invece trattano lazione interna in maniera speciale, nel senso che la
considerano non osservabile e, ad esempio, astraggono dal fatto che un processo la possa
eettuare o no.
Quanto detto relativamente alle equivalenze comportamentali, si applica anche ai preordini
di ranamento. Questi sono relazioni di (pre)ordinamento e quindi si prestano in maniera
naturale a descrivere le relazioni tra descrizioni di uno stesso sistema a vari livelli di astrazione.
Infatti, le equivalenze talvolta impongono restrizioni troppo severe ed in particolare richiedono
che i comportamenti di un sistema a vari livelli di astrazione siano identici. I preordini di
ranamento costituiscono quindi unalternativa ragionevole alle relazioni di equivalenza.
I calcoli di processo utilizzano spesso le nozioni di congruenza e precongruenza (introdotte
in Sezione 2.5) comportamentale sia per lanalisi dei sistemi che per sviluppare una metodologia di stepwise-development che permette di passare dalla specifica allimplementazione
di un sistema complesso eettuando una serie di sostituzioni di componenti con altre componenti equivalenti o pi ranate. Per, mentre equivalenze comportamentali e preordini
di ranamento possono essere definiti direttamente sugli LTS in maniera indipendente dagli
operatori di uno specifico calcolo di processi, non altrettanto possiamo fare per congruenze e
precongruenze. Come abbiamo visto, infatti, una congruenza una relazione di equivalenza
che soddisfa anche la propriet di sostituzione: sistemi equivalenti possono essere usati in
modo intercambiabile allinterno di sistemi pi grandi. Pi formalmente, un contesto c[ ] lo
si pu definire come una descrizione di un processo con un buco, [ ], eettuata usando gli
operatori di un determinato linguaggio. Dato un processo E scritto nello stesso linguaggio,
c[E] rappresenta il processo ottenuto riempiendo il buco con E. Unequivalenza t una congruenza per il linguaggio in considerazione se da E t F , deriva c[E] t c[F ] per ogni contesto
c[ ] costruito usando gli operatori del linguaggio. Il problema di determinare se le equivalenze
ed i preordini introdotti in questo capitolo sono rispettivamente congruenze e precongruenze
sar arontato nel Capitolo 12 relativamente allo specifico calcolo di processi CCS.
In questo capitolo introdurremo alcune semantiche osservazionali che permettono di confrontare stati di un LTS. Le definizioni delle semantiche quindi saranno date senza fare riferimento ad un insieme specifico di operatori. Nel capitolo successivo vedremo che tali definizioni
si possono riportare senza alcuna modifica in un calcolo di processi specifico come CCS. Ci
reso possibile dal fatto che lo stesso calcolo pu essere visto come un unico LTS, dove gli
227
r
a
a
q1
p1
b
p2
c
p3
p4
q2
q3
c
q5
r2
r1
b
r4
d
q4
r3
d
r6
r5
Figura 11.1: Tre LTS con cui evidenziare le dierenze tra equivalenza a tracce, equivalenza
testing e bisimilarit forte
stati corrispondono ai processi CCS.
Definiremo le semantiche osservazionali come relazioni tra stati di uno stesso LTS, piuttosto che tra stati di due LTS diversi, questo perch a volte ci servir confrontare stati di uno
stesso LTS. Ovviamente, le definizioni si applicano facilmente a stati di due LTS in quanto
lunione disgiunta di due LTS ancora un LTS.
11.2
Relazioni forti
In questa sezione introdurremo alcune relazioni tra stati di LTS che trattano le azioni degli
LTS tutte allo stesso modo, senza distinguere tra azioni esterne, ossia visibili, ed azioni interne.
Pertanto, tali relazioni saranno definite su un LTS hQ, A, ! i generico il cui insieme di azioni
A non contiene azioni trattate in modo speciale.
Cominceremo con lintrodurre le seguenti tre equivalenze: a tracce, bisimilarit e testing.
Esse ci forniranno dei criteri che ci permetteranno di eguagliare e/o distinguere, ad esempio,
gli stati p, q ed r degli LTS della Figura 11.1. Vedremo infatti che i tre stati sono indistinguibili per lequivalenza a tracce, in quanto tutti in grado di eseguire le stesse sequenze di
azioni, mentre sono distinti per la bisimilarit che basata su un gioco di sfide reciproche
in cui i sistemi procedono sfidandosi a vicenda sulla capacit di eseguire una determinata
azione; lequivalenza testing, invece, che considera le capacit di interazione e le potenzialit
di deadlock dei sistemi, eguaglia q ed r e li dierenzia da p.
Concluderemo con la definizione di alcuni preordini di ranamento e con lintroduzione di altre equivalenze (tracce complete e doppia simulazione) ottenute come varianti delle
equivalenze viste.
11.2.1
Nella teoria dei linguaggi formali, esiste una ben precisa nozione di equivalenza per gli automi
a stati finiti. Si tratta dellequivalenza dei linguaggi accettati che stabilisce che due automi
sono in relazione tra loro se accettano le stesse sequenze di simboli (si veda Sezione 3.4). Nel
Capitolo 3 abbiamo visto che, dierentemente dagli automi, gli LTS non contengono stati
228
di accettazione, quindi lequivalenza dei linguaggi accettati non pu essere applicata direttamente. Tuttavia, se supponiamo che ogni stato di un LTS uno stato di accettazione,
allora il linguaggio accettato da un LTS formato dalle sequenze di etichette, dette tracce,
di tutte le sequenze di transizioni che pu eseguire. Quindi, nel caso dellequivalenza a tracce, unosservazione di un processo una sequenza finita di azioni eseguita dal processo in
successione.
Definizione 11.1 (Traccia). Siano hQ, A, ! i un LTS, q 2 Q e s 2 A . La sequenza s
s
una traccia di q se esiste q 0 2 Q tale che q ! q 0 . Denoteremo con T (q) linsieme di tutte le
tracce di q.
Definizione 11.2 (Equivalenza a tracce). Siano hQ, A, ! i un LTS, p 2 Q e q 2 Q. Gli
stati p e q sono detti equivalenti a tracce, scritto p =T q, se T (p) = T (q).
Si pu notare che nelle definizioni precedenti non c distinzione tra azioni interne ed esterne;
tutte possono apparire in una traccia e sono trattate allo stesso modo.
Sebbene semplice da definire, lequivalenza a tracce =T risulta essere inadeguata per LTS
non deterministici, in cui cio esiste perlomeno uno stato che ha due transizioni etichettate
con la stessa etichetta verso stati dierenti tra loro, com illustrato dal seguente esempio.
Esempio 11.3. [Macchina distributrice di t e ca] Consideriamo una macchina
distributrice di t e ca il cui grafo delle transizioni sia il seguente:
20
20
tea
p0
cof f ee
A partire dallo stato p0 , dopo aver inserito 20, si pu ottenere un t oppure si possono inserire
altri 20 e quindi ottenere un ca; e cos via. Consideriamo ora una variante della macchina
il cui grafo delle transizioni sia il seguente:
20
tea
q0
cof f ee
20
20
229
Malgrado il fatto che i due stati p0 e q0 siano equivalenti a tracce, chiaro che essi, e quindi
le macchine corrispondenti, non sono equivalenti per un utente esterno. Questo perch la
seconda macchina non deterministica: dopo che ha ricevuto 20, si pu trovare in uno stato
in cui solo possibile emettere tea (e non pu pi ricevere 20), oppure pu essere in uno
stato in cui pu solo accettare 20 (e non pu emettere tea) per emettere cof f ee. chiaro
che un utente non sar contento di avere a che fare con una macchina che si comporta in
questo modo dal momento che lutente non avrebbe alcuna garanzia di ottenere la bevanda
eettivamente desiderata.
Il problema sta quindi nel considerare equivalenti una macchina deterministica e una non
deterministica e, quindi, meno adabile.
In conclusione, se siamo interessati al comportamento interattivo degli LTS, allora un LTS
non deterministico non pu essere considerato equivalente ad uno deterministico. Il problema
con lequivalenza a tracce e gli LTS non deterministici che, anche quando due stati hanno
le stesse tracce, durante lesecuzione delle stesse si possono incontrare stati non equivalenti,
ossia stati con tracce diverse (come si vede nel caso degli LTS dellesempio precedente). Ci
non succede per gli LTS deterministici.
Considerando sistemi che interagiscono con lambiente esterno, diventa importante sapere, ad esempio, se certe interazioni avranno sempre luogo, oppure se esiste la possibilit di
raggiungere uno stato di deadlock , cio uno stato da cui non possibile eettuare azioni.
Il comportamento riguardo al deadlock in eetti unaltra propriet dei sistemi concorrenti
che non catturabile soddisfacentemente dallequivalenza a tracce, come mostra il seguente
esempio.
Esempio 11.4. Si vede facilmente che gli stati p0 e q0 dei due LTS
q3
a
p0
p1
p2
q0
a
q1
q2
sono in relazione =T , per p0 pu sempre eseguire lazione visibile b dopo aver eettuato
lazione a, mentre q0 dopo aver eettuato lazione a pu raggiungere uno stato in cui non
possibile eettuare alcuna azione.
Esempio 11.5. Consideriamo lesempio dei tre LTS della Figura 11.1 di pagina 227. facile
vedere che tutti e tre gli LTS hanno il seguente insieme di tracce a partire, rispettivamente,
dagli stati p, q ed r:
{, a, ab, abc, abd}
Pertanto, si ha p =T q =T r, come gi anticipato.
230
11.2.2
Bisimilarit forte
Le considerazioni della sezione precedente ci suggeriscono un modo per arricchire le osservazioni fatte sul comportamento degli LTS non deterministici: le sequenze di esecuzione dovrebbero
attraversare stati equivalenti. Il forte potere discriminante delle relazioni ottenute in questo
modo dovuto proprio a questo loro carattere ricorsivo. In pratica, rispetto alla semantica
a tracce, nel caso della bisimilarit forte losservatore esterno, in qualsiasi momento durante
una computazione del sistema osservato, pu eettuare quante copie1 vuole del sistema nel
suo stato corrente ed osservarle indipendentemente in modo da osservare tutte le possibili
computazioni a partire da quello stato. Quindi, il risultato di unosservazione ora un albero
anzicch una traccia.
Definizione 11.6 (Bisimulazione forte). Sia hQ, A, ! i un LTS. Una relazione R QQ
una bisimulazione forte se, dati p e q tali che hp, qi 2 R, le seguenti condizioni sono soddisfatte:
a
Intuitivamente, se due stati sono in relazione di bisimulazione forte, possibile per ognuno
dei due simulare il comportamento dellaltro: da qui il termine bisimulazione. Pi specificamente, perch una relazione sia una bisimulazione forte, gli stati in relazione fra loro devono
essere in grado di eseguire le stesse transizioni, muovendosi verso stati che sono ancora in
relazione fra loro. In pratica, ci significa che una bisimulazione forte una relazione chiusa
per transizioni. Diremo che due stati sono equivalenti secondo la bisimulazione forte, o che
sono bisimili, se esiste una bisimulazione forte fra di loro.
Definizione 11.7 (Bisimilarit). Sia hQ, A, ! i un LTS. Due stati p, q 2 Q sono fortemente
bisimili, scritto p q, se esiste una bisimulazione forte R che contiene hp, qi.
q3
p2
q0
p0
a
p1
c
q2
q4
p3
Gli stati p0 e q0 non sono fortemente bisimili. Se lo fossero anche gli stati p1 e q1 , in cui p0 e
q0 si trasformano dopo aver eettuato una transizione etichettata con a, dovrebbero esserlo,
ma non c alcuna bisimulazione forte R che contiene la coppia hp1 , q1 i. Infatti, la transizione
di p1 etichettata c non pu essere simulata da q1 che non in grado di eettuare transizioni
etichettate c.
1
In realt questa solo unapprossimazione del reale potere di osservazione richiesto, che va sotto il nome
di global testing e che non esploreremo oltre.
231
a
b
Esempio 11.11. Vediamo ora un esempio pi articolato. Consideriamo i due LTS seguenti.
p1
q1
a
b
p0
q0
a
b
p2
q2
232
q1
a
b
p0
q0
a
b
p2
q2
Le bisimulazioni e la bisimilarit hanno diverse propriet interessanti. Dimostriamo dapprima che la propriet di essere una bisimulazione forte preservata da alcune operazioni sulle
relazioni (si rivedano eventualmente le definizioni di inversa e di composizione di relazioni
binarie viste nella Sezione 2.2).
Proposizione 11.12. Si assuma che ogni Si , con i 2 I, sia una bisimulazione forte e che Id
sia la funzione identit su Q. Allora le seguenti relazioni sono bisimulazioni forti.
1. Id
2. Si
3. S1 S2
4. [i2I Si
Dimostrazione. Dimostreremo solo la 3, le altre sono altrettanto semplici. Supponiamo duna
que che hp, ri 2 S1 S2 . Supponiamo inoltre che p ! p0 e facciamo vedere che ci implica che,
a
per qualche r0 , r ! r0 e hp0 , r0 i 2 S1 S2 .
Per definizione di composizione tra relazioni binarie, per qualche q, si ha che
hp, qi 2 S1
hq, ri 2 S2
Allora, dal momento che hp, qi 2 S1 che una bisimulazione, per qualche q 0 abbiamo che
a
q ! q0
hp0 , q 0 i 2 S1
r ! r0
hq 0 , r0 i 2 S2
Da ci segue anche che (p0 , r0 ) 2 S1 S2 . In modo del tutto simile si dimostra che se supponiamo
a
a
che r ! r0 , allora possiamo trovare un p0 tale che p ! p0 e hp0 , r0 i 2 S1 S2 .
Dimostriamo ora che la bisimilarit la pi grande tra le bisimulazioni e che una
equivalenza.
Proposizione 11.13.
1. la pi grande bisimulazione forte;
2. una relazione di equivalenza.
Dimostrazione. Dimostriamo i due asserti separatamente.
233
1. Dalla Proposizione 11.12(4) si vede che lunione di bisimulazioni forti ancora una
bisimulazione forte: dunque, anche lo e include tutte le altre bisimulazioni.
2. Per dimostrare che una relazione di equivalenza, cio che riflessiva, simmetrica e
transitiva, ragioniamo come segue.
Riflessivit. Dalla Proposizione 11.12(1) segue che 8p 2 Q p p.
Simmetria. Se p q allora hp, qi 2 S per qualche bisimulazione forte S. Allora
hq, pi 2 S 1 e, per la Proposizione 11.12(2), S 1 una bisimulazione forte; quindi
q p.
Transitivit. Se p q e q r allora hp, qi 2 S1 e hq, ri 2 S2 per qualche bisimulazione
forte S1 ed S2 . Dunque hp, ri 2 S1 S2 e quindi p r per la Proposizione 11.12(3).
Infine, dimostriamo una propriet di che nel seguito sar talvolta usata al posto della
sua definizione per dimostrare che due stati sono fortemente bisimili.
Proposizione 11.14. Siano hQ, A, ! i un LTS, p, q 2 Q. Si ha p q se e solo se 8a 2 A
a
allora
9q 0 2 Q : q ! q 0
allora
9p0 2 Q : p ! p0
i) 8p0 2 Q : p ! p0
ii) 8q 0 2 Q : q ! q 0
p0 q 0 ;
p0 q 0 .
1. 8p 2 Q : p ! p0
a
2. 8q 2 Q : q ! q 0
allora 9q 0 2 Q : q ! q 0
a
allora 9p0 2 Q : p ! p0
^
^
p0 q 0 ;
p0 q 0 .
Dalla Proposizione 11.13(1), sappiamo che una bisimulazione forte; dalle definizioni di
bisimulazione forte e di 0 , possiamo allora dedurre che
p q
implica p 0 q
(11.1)
234
dove get e put corrispondono alle tipiche operazioni P e V sui semafori originariamente usate
da Dijkstra. Un tale semaforo quindi una risorsa che pu essere alternativamente acquisita
e rilasciata.
Definiamo ora un semaforo pi generale, cio un semaforo n-ario (con n 1), che ammette
una qualsiasi sequenza di get e put purch il numero di get meno il numero di put rimanga
nellintervallo tra 0 e n, estremi inclusi.
Semn (0) , get.Semn (1)
Semn (k) , get.Semn (k + 1) + put.Semn (k
Semn (n) , put.Semn (n 1)
1)
(0 < k < n)
ci sono ben quattro coppie su otto che sono ridondanti! Le definizioni e le proposizioni che
seguono formalizzano tale idea.
Introduciamo allora la nozione di bisimulazione forte up to che ci permetter di rendere
pi eciente la tecnica di prova della bisimulazione forte. Ricordiamo che se R una relazione
binaria tra stati, la notazione R indica la composizione delle relazioni binarie e R e
poi di nuovo ; pi specificamente, p R q significa che per qualche p0 e q 0 abbiamo che
p p0 , p0 Rq 0 , q 0 q.
235
11.2.3
Sebbene sistemi fortemente bisimili abbiano lo stesso potenziale di deadlock, il contrario non
vero, cio, in generale, sistemi aventi lo stesso comportamento riguardo al deadlock possono
non essere bisimili. Si pu quindi dire che la bisimilarit forte eccessivamente sensibile alle
dierenze non osservabili della struttura ramificata (branching) dei sistemi. Ci testimoniato
dal fatto che gli stati q e r dellesempio di Figura 11.1 non sono bisimili. Sostanzialmente
ci succede perch r non sempre in grado, dopo aver fatto a, di eettuare la sequenza b c,
mentre q lo . Tuttavia, non sarebbe necessario doverli distinguere, perch per entrambi la
scelta tra le azioni c e d nondeterministica, cio non controllabile, mentre il potenziale di
236
deadlock lo stesso. La dierenza tra i due LTS risiede nel momento in cui la scelta viene
fatta. Ci si riflette sulla diversa struttura branching dei due LTS ma non di interesse
da parte di un osservatore esterno che pu solo interagire con gli LTS (quindi, controllare il
comportamento riguardo il deadlock) e non pu invece osservarne la struttura interna.
In questa sezione, definiremo una equivalenza che tiene conto di queste considerazioni (e
quindi eguaglia gli stati q ed r). A questo scopo utilizzeremo lapproccio testing che basato
su una nozione esplicita di osservatore che esegue dei test sui sistemi sotto osservazione e ne
esamina lesito. In questo scenario, risulta importante non soltanto sapere se, dato un particolare test, un processo risponde positivamente oppure no, ma anche se il processo risponde
in maniera consistente ogni volta che il test viene eseguito. Pi specificamente, possiamo
pensare ad un insieme di sistemi e ad un insieme di test; due sistemi saranno equivalenti
(rispetto a questo insieme di test) se superano esattamente gli stessi test. Questa naturale
equivalenza pu essere espressa tramite altre due equivalenze tra sistemi: la prima formulata
in termini dellabilit di rispondere positivamente ad un particolare test, la seconda in termini
dellincapacit di non rispondere positivamente ad un particolare test; nellultimo caso vedremo come un processo p sia equivalente ad un processo q se, per ogni test a cui p risponde
positivamente, anche q risponde positivamente, e viceversa. Attraverso la congiunzione di
queste due equivalenze se ne otterr una terza.
Supponiamo di dover confrontare LTS le cui azioni appartengono ad uno stesso insieme A
(dati degli LTS qualsiasi, semplice ricondursi a questa situazione, basta prendere lunione
degli insiemi di azioni degli LTS in considerazione). Un osservatore un LTS il cui insieme
di azioni Aw , A [ {w}, con w 62 A; in pratica, un osservatore esegue dei test su un LTS ed
eettua lazione visibile w quando il LTS sotto esame passa con successo un test. Nel seguito,
indichiamo con O linsieme degli osservatori. Per determinare se uno stato q soddisfa o no un
osservatore o si considera linsieme Comp(q, o) delle computazioni dalla configurazione iniziale
hq, oi e si determina lesito di ogni computazione c.
Definizione 11.19 (Computazione). Dati due LTS hQ, A, ! i e hO, Aw , ! i e presi due
stati q 2 Q e o 2 O, una computazione c dalla configurazione iniziale hq, oi una sequenza
di configurazioni hqi , oi i, con i 0, cio di coppie di stati, tale che
1. hq0 , o0 i coincide con hq, oi;
2. tra due configurazioni consecutive, diciamo hqi , oi i e hqi+1 , oi+1 i, si pu derivare una
a
transizione hqi , oi i ! hqi+1 , oi+1 i usando la seguente regola dinferenza
a
E ! E0
F ! F0
hE, F i ! hE 0 , F 0 i
a2A
3. se la sequenza finita allora lultimo elemento, diciamo hqk , ok i, tale che per nessun
a 2 A e per nessuna configurazione hq 0 , o0 i, con q 0 2 Q e o0 2 O, sia possibile derivare
a
una transizione hqk , ok i ! hq 0 , o0 i usando la regola precedente.
237
11.2.4
Preordini di ranamento
238
239
11.2.5
240
Si noti che se non si richiedesse anche T (p) = T (q) nella definizione di p =CT q, cio se si
definisse p =CT q se CT (p) = CT (q), =CT non sarebbe un ranamento di =T . Infatti, ad
esempio, gli LTS seguenti hanno le stesse tracce complete ma non hanno le stesse tracce.
b
b
a
a
Dalla definizione di =CT si ottiene banalmente che se due stati sono in relazione =CT
allora essi sono sicuramente equivalenti a tracce. Per il contrario non sempre vero, come
testimonia lEsempio 11.4 di pagina 229: si ha infatti p0 =T q0 e p0 6=CT q0 poich gli stati
p0 e q0 hanno le tracce ", a e ab, ma q0 ha la traccia completa a che non appartiene a p0 (il
quale dopo a pu sempre fare b).
Tuttavia, anche questa equivalenza non del tutto soddisfacente da un punto di vista
dellinterazione con lambiente esterno. Difatti, si ha p0 =CT q0 dove p0 e q0 sono gli stati iniziali delle due descrizioni della macchina distributrice di t e ca dellEsempio 11.3 di pagina
228 (infatti abbiamo CT (p0 ) = CT (q0 ) = ;). Questo perch, come nel caso dellequivalenza
basata sulle tracce, vale ancora il fatto che stati di un LTS non deterministico che hanno
le stesse tracce complete possono passare, durante lesecuzione delle stesse, attraverso stati
aventi tracce dierenti (come lo stesso esempio testimonia).
Doppia simulazione
Introduciamo ora il nucleo della relazione di simulazione.
Definizione 11.37 (Doppia simulazione). La doppia simulazione, denotata con ', il nucleo
del preordine di simulazione (quindi, ' , v \ v 1 ).
Dato che la bisimilarit lunione di tutte le bisimulazioni e che una relazione una bisimulazione se essa stessa e la sua inversa sono simulazioni (vedere Proposizione 11.31), risulta
naturale chiedersi quale sia la relazione tra e '. In eetti si ha che implica ', cio p
bisimile a q implica p simula q e q simula p (perch ovviamente ogni bisimulazione
una simulazione ed inoltre simmetrica). Il contrario per non vale! Per esempio, consideriamo gli LTS dellEsempio 11.4 di pagina 229. Non dicile dimostrare che la relazione
R1 = {hp0 , q0 i, hp1 , q1 i, hp2 , q2 i} una simulazione, e quindi q0 simula p0 , e che la relazione
R2 = {hq0 , p0 i, hq1 , p1 i, hq2 , p2 i, hq3 , p1 i} una simulazione, e quindi p0 simula q0 . Perci,
p0 ' q0 . Daltro canto, q0 meno adabile di p0 perch ha pi possibilit di andare in
deadlock, quindi, per quanto detto sulla bisimulazione, ci aspettiamo che p0 6 q0 . In eetti,
una ipotetica relazione di bisimulazione R che contenga la coppia hp0 , q0 i, dovrebbe anche
a
contenere la coppia hp1 , q3 i, dato che alla transizione q0 ! q3 , p0 pu solo replicare con la
a
11.3
Relazioni deboli
In questa sezione introdurremo le seguenti equivalenze di tipo debole: a tracce deboli, bisimulazione debole, bisimulazione di branching, testing ed equivalenza basata sui fallimenti.
241
Ricordiamo che tali equivalenze trattano in maniera speciale lazione interna degli LTS e
saranno quindi definite su un LTS del tipo hQ, A , ! i con A , A [ { }. La sezione conclusiva esaminer, in particolare, il trattamento dei processi con comportamento divergente
(cio capaci di eseguire sequenze infinite di azioni interne) da parte delle equivalenze deboli
ed introdurr alcune semplici varianti delle relazioni viste (quali, ad esempio, fair testing).
Esempio 11.38. Consideriamo la seguente specifica di una macchina distributrice di ca,
la quale, dopo linserimento di una moneta, e prima della produzione del ca, si occupa di
macinarne i grani.
p0
cof f ee
grinding
coin
Le azioni interne necessarie alla macchina per produrre il ca non dovrebbero tuttavia essere
osservabili da un utente esterno. Quindi, il comportamento della macchina da un punto di
vista delle interazioni con lambiente esterno dovrebbe essere quello specificato dal seguente
LTS.
q0
cof f ee
coin
coin
cof f ee
Per, gli stati p0 e q0 dei due LTS non sono equivalenti rispetto a nessuna delle nozioni
esaminate nella sezione precedente, anche se, osservandone il comportamento dallesterno, e
mettendosi nellottica che non osservabile, non possibile individuare delle dierenze. Il
problema che nessuna delle equivalenze forti viste nella sezione precedente tiene conto della
particolare natura delle azioni interne.
11.3.1
Definiamo ora la variante debole dellequivalenza a tracce. Si ricordi, dal Capitolo 10, che
s
q=
) q 0 indica che lo stato q pu trasformarsi nello stato q 0 tramite lesecuzione di una sequenza
s di azioni visibili ciascuna delle quali pu essere preceduta e seguita da un qualsiasi numero
di azioni interne .
Definizione 11.39 (Traccia debole). Siano hQ, A , ! i un LTS, q 2 Q e s 2 A . La
s
sequenza s una traccia debole di q se esiste q 0 tale che q =
) q 0 . Denoteremo con L(q)
linsieme di tutte le tracce deboli di q.
Definizione 11.40 (Equivalenza a tracce deboli). Siano hQ, A , ! i un LTS, p 2 Q e q 2 Q.
Gli stati p e q si dicono equivalenti a tracce deboli, scritto p tL q, se L(p) = L(q).
242
11.3.2
Bisimulazione debole
Per diminuire la sensibilit alle azioni interne rispetto alla bisimulazione forte, la bisimulazione
debole considera lazione interna in modo speciale per cui, quando un sistema eettua unazione interna, laltro sistema pu rispondere eettuando un numero qualsiasi (anche nullo) di
azioni interne. Introduciamo prima una notazione tecnica.
Definizione 11.41. Sia hQ, A , ! i un LTS. Se s 2 (A ) allora con s 2 A indichiamo la
sequenza (eventualmente vuota) di azioni visibili ottenuta cancellando tutte le occorrenze di
da s.
Intuitivamente, s rappresenta il contenuto visibile (cio gli elementi diversi da ) della
sequenza s e pu essere definita induttivamente sulla lunghezza di s. In particolare, data
2 A , abbiamo
se =
=
se 6=
Adesso possibile definire la bisimulazione debole come segue.
3. S1 S2
243
risultato: se hq, ri 2 S2 e q =
) q 0 allora, per qualche r0 , r =
) r0 e (q 0 , r0 ) 2 S2 .
Proposizione 11.45.
1. la pi grande bisimulazione debole;
2. una relazione di equivalenza.
Dimostrazione. La dimostrazione segue le argomentazioni usate nella Proposizione 11.13,
utilizzando per la Proposizione 11.44 anzicch la Proposizione 11.12.
Proposizione 11.46. Siano hQ, A , ! i un LTS, p, q 2 Q. Si ha p q se, e solo se,
8 2 A
allora
9q 0 2 Q : q =
) q0
allora
9p0 2 Q : p =
) p0
i) 8p0 2 Q : p ! p0
ii) 8q 0 2 Q : q ! q 0
p0 q 0 ;
p0 q 0 .
Dimostrazione. Cominciamo col definire una nuova relazione, 0 , in termini di nel modo
seguente
p 0 q se per ogni 2 A risulta:
1. 8p0 2 Q : p ! p0
allora
9q 0 2 Q : q =
) q0
p0 q 0 ;
2. 8q 0 2 Q : q ! q 0
allora
9p0 2 Q : p =
) p0
p0 q 0 .
Dalla Proposizione 11.45(1) sappiamo che una bisimulazione debole. Dalle definizioni di
bisimulazione debole e di 0 , possiamo allora dedurre che
p q
implica p 0 q
(11.2)
244
.p =
) p0 , e ovviamente p0 p0 . Consideriamo ora la sola transizione che .p pu fare, ossia
"
.p ! p: questa chiaramente corrisposta dalla transizione nulla p =
) p di p (dato che = ").
Abbiamo dunque che p 0 .p e di conseguenza p .p.
Dimostriamo ora una propriet che fornisce un criterio alternativo per poter stabilire che
una data relazione una bisimulazione debole.
Proposizione 11.48. Sia hQ, A , ! i un LTS. Una relazione R QQ una bisimulazione
debole se, e solo se, dati p, q 2 Q tali che hp, qi 2 R ed s 2 A , le seguenti condizioni sono
soddisfatte:
s
1. per ogni p0 2 Q, se p =
) p0 allora q =
) q 0 per qualche q 0 2 Q tale che hp0 , q 0 i 2 R;
2. per ogni q 0 2 Q, se q =
) q 0 allora p =
) p0 per qualche p0 2 Q tale che hq 0 , p0 i 2 R.
s
t
n
1
2
p ! p0 dove t = (1 . . . n ) 2 A e t = s. Allora p ! p1 ! ! p0 e dal momento che
p0 R q 0 . Da ci segue che q =
) q 0 , e quindi q =
) q 0 . La tesi segue allora per simmetria.
"
"
0
(() Supponiamo che p ! p . Se = allora p =
) p0 e cos dal punto 1 si ha q =
) q 0 con
p0 Rq 0 ; ma
= ", quindi q =
) q 0 come richiesto. Se 6= allora p =
) p0 , e grazie al punto 1
q =
) q 0 con p0 Rq 0 ; ma
= e quindi q =
) q 0 come richiesto. Anche in questo caso, la tesi
segue allora per simmetria.
245
q0
q1
q2
e definiamo la relazione R , {hp0 , q0 i}. In base alla definizione precedente, R una bisimulazione debole up to . Infatti, p0 non ha transizioni, quindi non c bisogno che q0
faccia alcuna transizione. Invece, q0 ha una transizione etichettata nello stato q1 a cui p0
risponde senza muoversi; per cui otteniamo la coppia hp0 , q1 i. Ora, poich stiamo ragionando
up to , e poich q1 q0 , possiamo richiedere che hp0 , q0 i sia in R (che, per definizione,
vero), anzicch chiedere che lo sia hp0 , q1 i. Quindi, R una bisimulazione debole up to , ma
chiaramente p0 e q0 non sono bisimili.
Il problema in eetti dovuto al fatto che le transizioni possono essere ignorate, come nellesempio precedente. La definizione naturale presentata in precedenza pu essere modificata
imponendo condizioni pi restrittive che considerino -discendenti anzicch -derivate.
Definizione 11.49 (Bisimulazione debole up to ). Sia hQ, A , ! i un LTS. Una relazione
R Q Q una bisimulazione debole up to se, dati p e q tali che hp, qi 2 R, le seguenti
condizioni sono soddisfatte
1. per ogni 2 A e p0 2 Q, se p =
) p0 allora q =
) q 0 per qualche q 0 2 Q tale che
0
0
hp , q i 2 R ;
2. per ogni 2 A e q 0 2 Q, se q =
) q 0 allora p =
) p0 per qualche p0 2 Q tale che
0
0
hp , q i 2 R .
Analogamente a quanto fatto per la bisimulazione forte up to si possono dimostrare
(con tecniche simili) le seguenti propriet, che ci autorizzano, dovendo dimostrare che p q,
a dimostrare pi semplicemente lesistenza di una bisimulazione debole up to R tale che
hp, qi 2 R.
Proposizione 11.50. Se R una bisimulazione debole up to allora R una
bisimulazione debole.
Proposizione 11.51. Se R una bisimulazione debole up to allora R .
posto di ! . Questo comporta la necessit di considerare non solo -derivate ma anche discendenti: i -discendenti potrebbero essere molto pi numerosi delle -derivate e, talvolta,
potrebbero addirittura essere infiniti. La seguente proposizione fornisce un criterio alternativo
per stabilire se una relazione R una bisimulazione debole up to che permette di considerare
solo -derivate a patto di raorzare alcuni vincoli (richiedendo al posto di , sebbene questa
richiesta pu a volte essere eccessiva [SM92]).
Proposizione 11.52. Sia hQ, A , ! i un LTS ed R Q Q. Se hp, qi 2 R implica che per
ogni 2 A le seguenti condizioni sono soddisfatte
246
11.3.3
Bisimulazione di branching
Questa equivalenza si pone tra la bisimulazione forte e quella debole, in quanto da una parte
tratta le azioni interne in modo speciale (come fa la bisimulazione debole), dallaltra cerca
di preservare la struttura di branching dei sistemi (come fa la bisimulazione forte) non ignorando del tutto gli stati intermedi attraversati eettuando azioni interne. Lidea quindi di
indebolire le richieste fatte dalla bisimulazione forte, considerando il ruolo speciale rivestito
dalle azioni interne, in modo da uguagliare LTS quali
a
che sono invece dierenziati da , ed al contempo esaminare gli stati attraversati durante
lesecuzione di una sequenza di azioni interne, per dierenziare LTS quali i seguenti
p2
c
a
p0
p1
q0
p4
q6
q2
q5
q1
p3
q3
q4
2. q =
) q 00 ! q 0 per qualche q 0 , q 00 2 Q tali che hp, q 00 i 2 R e hp0 , q 0 i 2 R.
247
Gli stati p e q sono branching bisimili, scritto p b q, se esiste una bisimulazione di branching
R contenente hp, qi. La bisimilarit di branching, b , lunione di tutte le bisimulazioni di
branching. In modo equivalente, possiamo scrivere:
[
b ,
{R | R una bisimulazione di branching}
Si noti che nel caso 2 della definizione, pu anche essere . Quindi, se = , suciente
che una delle due condizioni sia soddisfatta, mentre se 6= , deve necessariamente essere
soddisfatta la seconda condizione.
Esempio 11.55. Consideriamo gli LTS precedenti e dimostriamo che p0 e q0 non sono
branching bisimili. Il problema dovuto alla transizione etichettata a da q0 in q5 . Infatti, p0
pu rispondere soltanto eettuando a e andando in p1 (e non in p3 come invece permette la
), ma p1 e q5 non sono chiaramente branching bisimili poich p1 ha una transizione c che q5
non ha.
La condizione 2 della Definizione 11.54, pu essere espressa in vari modi alternativi tutti
equivalenti tra loro. In particolare, avremmo ottenuto la stessa relazione raorzando (apparentemente) la condizione 2 richiedendo che tutti gli stati intermedi in q =
) q 00 siano in
a
00
0
0
000
relazione con p e permettendo che dopo q ! q si possa avere q =
) q con q 000 , e tutti gli
0
stati intermedi, in relazione con p . Formalmente, la condizione la seguente
q1
q2
...
qn
q1
q2
...
qm
Quindi, riassumendo possiamo dire che la bisimulazione di branching considera due stati
equivalenti soltanto se hanno la stessa capacit di eseguire azioni e se gli stati intermedi,
anche quelli raggiunti attraverso azioni interne, hanno comportamento equivalente.
Si pu dimostrare che lunione di tutte le bisimulazioni di branching la pi grande
bisimulazione di branching e che essa una equivalenza.
Proposizione 11.56.
1. b la pi grande bisimulazione di branching;
2. b una relazione di equivalenza.
La dimostrazione lasciata come esercizio.
248
11.3.4
Per definire le varianti deboli delle relazioni basate sul testing, dobbiamo modificare la nozione di computazione per permettere che una configurazione possa evolvere anche quando,
in maniera asincrona, losservatore od il processo osservato eseguono una azione interna. Al
solito, supponiamo che w 62 A sia unazione speciale usata per indicare il successo di un
esperimento. Indicheremo con A w linsieme A [ {w}.
Definizione 11.57 (Computazione). Siano hQ, A , ! i e hO, A w , ! i due LTS e siano
q 2 Q e o 2 O. Una computazione c dalla configurazione iniziale hq, oi una sequenza di
configurazioni hqi , oi i (con i 0), cio una sequenza di coppie di stati, tale che
1. hq0 , o0 i coincide con hq, oi;
2. tra due configurazioni consecutive, diciamo hqi , oi i e hqi+1 , oi+1 i, si pu derivare una
transizione hqi , oi i ! hqi+1 , oi+1 i usando una delle seguenti regole dinferenza
E ! E0
hE, F i ! hE 0 , F i
F ! F0
E ! E0
hE, F i ! hE, F 0 i
F ! F0
hE, F i ! hE 0 , F 0 i
a2A
3. se la sequenza finita allora lultimo elemento, diciamo hqk , ok i, tale che per nessuna configurazione hq 0 , o0 i, con q 0 2 Q e o0 2 O, sia possibile derivare una transizione
q3
test
p1
q1
q2
p2
p4
q6
q5
q4
249
satisfy o. Ragionando in maniera simile possiamo convincerci che q1 may satisfy o implica
p1 may satisfy o, per ogni osservatore o.
Dimostriamo ora che p1 'M q1 . Supponiamo che per un qualche osservatore o si abbia
w
p1 must satisfy o. Se o ! allora abbiamo anche q1 must satisfy o. Altrimenti, cio se
w
o 6 ! , p1 must satisfy o implica che per ogni o1 tale che o =
) o1 dobbiamo avere che o
w
b
0
0
esiste uno stato intermedio o tale che o ! , oppure o1 =
) o2 ed esiste uno stato intermedio
w
a
w
o0 tale che o0 ! , oppure o1 ! o2 ed esiste uno stato intermedio o0 tale che o0 ! . facile
vedere che in tutti i casi q1 si comporta come p1 relativamente allosservatore o. Ragionando
in maniera simile possiamo dimostrare limplicazione inversa.
Quindi la tesi dimostrata.
q2
test
...
abbiamo che p2 must satisfy o ma non vero che q2 must satisfy o (per via della computazione formata dalla sequenza infinita di azioni interne che q2 pu eettuare), quindi la tesi
dimostrata.
Abbiamo gi detto, nel caso delle varianti forti delle relazioni testing, che esse sono dicili
da verificare, ci anche testimoniato dai due esempi precedenti. Possiamo per definire una
caratterizzazione alternativa delle relazioni in modo da ovviare a questo inconveniente. Tale
caratterizzazione indipendente dalla nozione di osservatore ed definita in termini delle
sequenze di azioni che un LTS pu eseguire e dellinsieme di azioni che un LTS deve accettare.
Per esempio, per lequivalenza testing, si tratter di controllare che due LTS possano eseguire
le stesse sequenze di azioni e che, dopo ogni sequenza lungo la quale non c divergenza (cio
possibilit di eseguire sequenze infinite di azioni interne), possano scegliere la loro prossima
250
azione dallo stesso insieme di azioni. Un ulteriore vantaggio della caratterizzazione alternativa
che essa permette un confronto pi agevole con le altre equivalenze studiate.
In eetti, la caratterizzazione alternativa del preordine may data dal preordine vL
definito in termini di inclusione dei linguaggi.
Definizione 11.60. Siano hQ, A , ! i un LTS, p, q 2 Q. Si dice che p minore rispetto
alle tracce deboli di q, scritto p vL q, se L(p) L(q).
Teorema 11.61 (Caratterizzazione alternativa di vm ). Sia hQ, A , ! i un LTS e siano
p, q 2 Q. Si ha p vm q se e solo se p vL q.
Dimostrazione. Caso se. Supponiamo che p vL q e che p may satisfy o, dove o un
s
osservatore generico. Lipotesi p may satisfy o significa che esiste s 2 A tale che p =
) e
sw
o ==) ; in particolare ci significa che s 2 L(p). Pertanto, se per assurdo q may satisfy o
sw
s
non valesse, dato che comunque o ==) , avremmo che q =
6 ) , cio s 62 L(q), che contradirebbe
lipotesi p vL q. Quindi devessere q may satisfy o, da cui segue che p vm q.
Caso solo se. Cominciamo col definire, per ogni sequenza s 2 A , diciamo s = a1 an
(n 0), il seguente osservatore canonico o(s):
o(s) ,
{oi | 0 i n + 1},
{ai | 1 i n} [ {w},
{oi
ai+1
! oi+1 | 0 i n
1} [ {on ! on+1 }
a1
o1
a2
o2
on1
an
on
on+1
(11.3)
Supponiamo ora che p vm q e s 2 L(p). Dallipotesi che s 2 L(p) e dalla propriet precedente
segue che p may satisfy o0 . Dallaltra ipotesi, segue allora che q may satisfy o0 . Applicando
nuovamente la Propriet (11.3) si ha che s 2 L(q) e, quindi, la tesi.
Una banale conseguenza del teorema precedente che lequivalenza may 'm coincide con
quella a tracce deboli, cio tL (se veda Definizione 11.40).
La caratterizzazione alternativa del preordine must non cos diretta come la precedente
e fa uso delle seguenti definizioni ausiliarie.
Definizione 11.62. Siano hQ, A , ! i un LTS, q 2 Q, s 2 A , Q0 Q e L f A (cio L
sottoinsieme finito di azioni visibili).
q diverge, scritto q *, se esiste una sequenza infinita di stati q0 , q1 , . . . tale che q = q0 e
251
(q after s) , {q 0 2 Q | q =
) q 0 } linsieme degli stati che q pu raggiungere dopo aver
o , {oi | 0 i n} [ {of , ow },
{ai | 1 i n} [ {, w},
ai+1
w
{oi ! ow , oi
! oi+1 | 0 i n 1} [ {on ! ow , ow ! of }
che possiamo visualizzare graficamente nel modo seguente
w
ow
of
o0
a1
o1
a2
o2
on1
an
on
252
o0 ,
{oi | 0 i n} [ {of , ow },
{ai | 1 i n} [ {, w},
{oi ! ow , oi
ai+1
! oi+1 | 0 i n
1} [ {ow ! of }
ow
of
o0
a1
o1
a2
o2
on1
an
on
Si pu anche dimostrare che per ogni sequenza s che non una traccia per uno stato q si
ha che (q after s) = ; e viceversa; da ci segue banalmente che se s 62 L(q) allora (q after
s) must L vero, per ogni insieme di azioni L. Quindi, per verificare se p vM q, suciente
limitarsi a considerare le sequenze s lungo le quali p non diverge e che sono anche tracce di p.
Lemma 11.65. (q after s) must ; se e solo se s 62 L(q).
Dimostrazione. (() banale, in quanto se s 62 L(q) questo implica che (q after s) = ;.
s
()) Ragioniamo per assurdo e supponiamo che s 2 L(q). Allora esiste un q 0 tale che q =
) q0
quindi linsieme (q after s) non vuoto (contiene almeno q 0 ). Evidentemente, non c un
a
a 2 ; tale che q 0 =
) e quindi dovremmo concludere che (q after s) must ; falso, che
sarebbe in contraddizione con lipotesi.
Sfruttando la propriet precedente, si pu dimostrare che se p 4M q e se p non diverge
lungo s, allora se s una traccia di q lo anche di p.
Lemma 11.66. Se p 4M q e p + s allora s 2 L(q) implica s 2 L(p).
Dimostrazione. Ragioniamo per assurdo, supponiamo cio che essendo vere le ipotesi vale
anche che s 62 L(p). Allora, per il Lemma 11.65 abbiamo che (p after s) must ;. Per via
delle ipotesi, ci implica che (q after s) must ;. Quindi, ancora per il Lemma 11.65, si ha
che s 62 L(q), che contraddice lipotesi. Quindi, devessere s 2 L(p).
Nel seguito, per qualsiasi stato r 2 Q di un LTS hQ, A , ! i, indicheremo con Init(r)
a
linsieme {a 2 A | r =
) }, cio linsieme delle azioni visibili che r pu immediatamente eseguire
(eventualmente precedute da una sequenza di azioni invisibili).
253
o,
{oi | 0 i n} [ {of , ow },
{ai | 1 i n} [ {, w},
bj
ai+1
w
{oi ! ow , oi
! oi+1 | 0 i n 1} [ {on ! ow | bj 2 L} [ {ow ! of }
che possiamo visualizzare graficamente nel modo seguente
w
ow
of
o0
a1
o1
a2
b1 bm
o2
on1
an
on
facile verificare che (p after s) must L implica p must satisfy o che a sua volta, per via
dellipotesi, implica che q must satisfy o. Questo implica che (q after s) must L; infatti,
per come fatto losservatore o, abbiamo o che s 62 L(q) o che per tutti gli stati q 0 tali che
s
bj
q=
) q 0 , vero che q 0 =) per qualche bj 2 L.
Ora, dimostriamo che p 4M q implica p vM q. Dimostreremo una aermazione equivalente cio che preso un osservatore o qualsiasi abbiamo che se q must satisfy o falso
allora anche p must satisfy o falso. In altri termini, dimostreremo che se esiste una
computazione senza successo c1 2 Comp(q, o) allora esiste una computazione senza successo
c2 2 Comp(p, o). Se una tale c1 esiste allora il fatto che c1 non ha successo pu dipendere da
una delle seguenti ragioni:
254
Esempio 11.68. Riconsideriamo i due LTS presentati nellEsempio 11.58 di pagina 248.
Vogliamo vedere il tipo di ragionamento che bisogna seguire per dimostrare che p1 'test q1
utilizzando le caratterizzazioni alternative; quindi vogliamo dimostrare che p1 tL q1 , che
p1 4M q1 e che q1 4M p1 . La validit della relazione p1 tL q1 ovvia dato che p1 e q1
hanno le stesse tracce deboli. Per dimostrare che p1 4M q1 consideriamo solo le sequenze
di azioni visibili s 2 L(p) perch altrimenti avremmo p after s = q after s = ; (dato
che L(p) = L(q)) e quindi, per qualsiasi L, (p after s) must L e (q after s) must L
valgono. Se prendiamo s = allora p after = {p1 , p2 }; quindi, anch (p after ) must
L devessere b 2 L. Dato che q after = {q1 , q2 , q3 }, segue allora che (q after ) must L.
Se s = a allora p after a = {p3 }. Quindi, (p after a) must L falso per qualsiasi insieme
L: se L = ;, ci segue dal Lemma 11.65; altrimenti, cio se L 6= ;, segue dal fatto che p3 6 !
per qualsiasi 2 A. Quindi, non c bisogno di fare alcuna verifica su (q after s) must L.
Analogo ragionamento pu essere ripetuto nel caso s = b. Con un ragionamento simile si pu
dimostrare che q1 4M p1 , e quindi la tesi.
11.3.5
255
Quindi, un rifiuto consiste in un insieme finito di azioni visibili che uno stato incapace di
eseguire, non tenendo conto del numero di azioni interne eseguite. Un fallimento una coppia
data da una sequenza di azioni e da un insieme di azioni oerte dallambiente; uno stato pu
fallire divergendo durante lesecuzione della sequenza oppure completandola ma arrivando in
uno stato incapace di rispondere alle azioni oerte. Quindi, un fallimento pu anche essere il
risultato di non determinismo o divergenza; pi un sistema non deterministico o divergente,
pi fallimenti ha.
Consideriamo un paio di esempi.
Esempio 11.70. Consideriamo i seguenti tre LTS.
b
p1
p2
p3
a
c
a
c
La coppia ha, {b}i un fallimento per p1 e per p2 ma non per p3 . Infatti, i primi due stati
a
hanno transizioni =
) che portano in uno stato che non pu eseguire b, cio che rifiuta {b};
lo stato p3 non ha una tale transizione. In eetti, si potrebbe dimostrare che p1 e p2 hanno
gli stessi fallimenti, i quali sono un sovrainsieme di quelli di p3 .
256
11.4
Le equivalenze viste hanno comportamenti piuttosto dierenti riguardo le computazioni divergenti , cio le computazioni formate da sequenze infinite di transizioni interne senza alcuna
interazione con lambiente esterno. Per esempio, lequivalenza a tracce deboli tL incapace
di distinguere il deadlock dalla divergenza, come mostra il fatto che
p0
q0
p1
q1
sono bisimili debolmente. Questa propriet cruciale per poter usare come criterio di
correttezza per la verifica di sistemi quali i protocolli di comunicazione. Daltro canto, come
si visto, essa comporta che sistemi alcuni dei quali divergono ed altri no possano essere
considerati equivalenti.
Al contrario, lequivalenza must (e, quindi, anche lequivalenza test) pi sensibile al
problema della divergenza, come si pu anche intuire dalla definizione alternativa del preordine
must (Definizione 11.63). Se infatti prendiamo come osservatore lo stato o del seguente LTS
o
abbiamo che p0 must satisfy o mentre non vero che q0 must satisfy o; quindi, p0 6vM q0
e p0 6vtest q0 , e di conseguenza i due stati non sono n must n test equivalenti.
Esercizio 11.74. Dimostrare che q0 vM p0 e q0 vtest p0 .
Tra le varianti dei preordini testing che sono state studiate in letteratura, ne sono state
introdotte anche alcune che trattano la divergenza in maniera simile a quanto appena detto
per la bisimulazione debole. Di seguito ne presentiamo una. A tale scopo, modifichiamo la
nozione di successo di una computazione (Definizione 11.20) in modo da ignorare lesistenza
di eventuali computazioni divergenti.
Definizione 11.75 (Esito di una computazione).
Siano hQ, A, ! i e hO, Aw , ! i due LTS, q 2 Q e o 2 O. Una computazione c 2 Comp(q, o)
della forma hq0 , o0 i, hq1 , o1 i, hq2 , o2 i, . . . ha successo se per ogni configurazione hqi , oi i 2 c, con
w
i 0, si ha hqi , oi i =) .
257
=CT
F M
=T
L m
Figura 11.2: Gerarchie tra le equivalenze presentate in questo capitolo nel caso di processi
totalmente convergenti: R1 ! R2 significa R2 R1 . I simboli hanno il seguente significato: =T equivalenza a tracce forti, =CT equivalenza a tracce (forti) complete, ' doppia
simulazione, bisimilarit forte, tL equivalenza a tracce deboli, 'm equivalenza may, 'F
equivalenza basata sui fallimenti, 'M equivalenza must, bisimilarit debole, b bisimilarit
di branching.
Si noti che di fatto la definizione appena data indebolisce la richiesta posta dalla Definizione 11.20 anch una computazione abbia successo cosicch anche una computazione
divergente pu avere successo.
Definizione 11.76 (Soddisfacimento di un osservatore).
Siano hQ, A, ! i e hO, Aw , ! i due LTS, q 2 Q e o 2 O. Si dice che q fair-must satisfy
o se ogni computazione c 2 Comp(q, o) ha successo.
11.5
Innanzitutto, va ricordato che nel caso di LTS deterministici tutte le equivalenze coincidono.
Consideriamo allora il caso pi generale dgli LTS non deterministici.
Se ci limitiamo al caso di LTS totalmente convergenti, le relazioni che abbiamo definito
in questo capitolo possono essere raggruppate, a seconda che si tratti di equivalenze forti
o deboli, nelle due gerarchie mostrate in Figura 11.2 (gerarchie simili valgono anche per i
corrispondenti preordini). Di seguito, commentiamo alcuni dei risultati riassunti nella figura.
Nel caso che tutti gli LTS considerati siano totalmente convergenti si ha:
258
se p =
) p0 si ha che Init(p0 ) \ L 6= ;, 9q 0 : q =
) q 0 ^ Init(q 0 ) \ L = ;
s
In generale invece, cio nel caso di LTS non convergenti, le equivalenze 'm e 'M non
sono confrontabili. Per convincerci di ci, suciente individuare coppie di stati che sono in
una relazione ma non nellaltra, e viceversa. Per esempio, abbiamo che p1 'm q1 e p1 6'M q1
dove p1 e q1 sono cos definiti:
b
a
p1
q1
a
c
p2
q2
259
11.6 Esercizi
11.6
Esercizi
11.1 Sia hQ, A, ! i un LTS. Dimostrare che una relazione R Q Q una simulazione forte se e
solo se
a
a
R 1 ! !R 1
per ogni a 2 A.
11.2 Sia hQ, A, ! i un LTS. Dimostrare che una relazione R Q Q una bisimulazione forte se
e solo se
a
a
a
a
R 1 ! !R 1
e
R ! !R
per ogni a 2 A.
11.3 Utilizzando la caratterizzazione delle simulazioni forti vista nellEsercizio 11.1, si provi che Id
una simulazione e che se R ed S sono simulazioni allora R [ S ed RS sono simulazioni.
11.4 Sia hQ, A, ! i un LTS e sia v lunione di tutte le simulazioni forti. Si provi che v un
preordine, ossia che Id v e vv v.
11.5 Si provi con un esempio che lintersezione di bisimulazioni forti non necessariamente una
bisimulazione forte.
11.6 Si considerino le seguenti costanti di processo:
Impl
Spec
,
,
Si provi che Impl e Spec sono equivalenti a tracce deboli ma non sono equivalenti a tracce (si
ricordi che / loperatore di hiding).
11.7 Si considerino le seguenti costanti di processo:
R
W
S
,
,
,
p. beginRead. endRead. v. R
p. beginW rite. endW rite. v. W
p. v. S
,
,
Si provi che Impl e Spec sono debolmente bisimili e che non sono fortemente bisimili.
260
11.8 Dimostrare che lunione di tutte le bisimulazioni di branching una bisimulazione di branching
e che essa una equivalenza.
11.9 Si dimostri che se la coppia hs, Bi un fallimento per q e B 0 B allora anche la coppia hs, B 0 i
un fallimento per q.
Capitolo 12
Calculus of Communicating
Systems (CCS)
SOMMARIO
Questo capitolo presenta CCS (Calculus of Communicating Systems, Milner 1980), uno dei
calcoli di processo pi conosciuti ed utilizzati, ed alcune teorie della concorrenza sviluppate
specificamente per esso. Cominceremo con la sintassi e la semantica operazionale di CCS.
Quindi vedremo una variante di CCS con passaggio di valori e la sua traduzione nel calcolo
con pura sincronizzazione. Successivamente presenteremo specificamente per CCS alcune
delle equivalenze e dei preordini comportamentali visti nel capitolo precedente. Studieremo
anche quali relazioni sono preservate da tutti gli operatori del linguaggio. Infine, introdurremo un altro approccio alla definizione della semantica dei sistemi concorrenti, quello
algebrico (o assiomatico), tramite caratterizzazioni (dis)equazionali alternative di alcune
delle relazioni osservazionali introdotte.
In questo capitolo rivedremo in maniera omogenea alcuni concetti gi introdotti, ma il
fatto di aver fissato la sintassi per il linguaggio ci permetter di concentrarci su due aspetti
importanti che finora erano stati volutamente tralasciati: (pre)congruenze e assiomatizzazioni.
12.1
Sintassi di CCS
CCS [Mil80, Mil89] basato su un insieme minimale di operatori che possono essere usati
per costruire descrizioni di sistemi a partire da descrizioni di sottosistemi. Gli elementi fondamentali su cui si basano queste descrizioni, come in ogni altro calcolo di processo, sono le
azioni.
Azioni in CCS. Le azioni rappresentano operazioni elementari eseguite in maniera atomica
e non interrompibile. In pratica le azioni corrispondono sia ad operazioni di input/output sulle
porte di comunicazione, sia a passi computazionali interni di un sistema. Le prime vengono
dette esterne, o visibili, dato che permettono linterazione di un sistema con lambiente.
Per formalizzare queste intuizioni, sia un insieme infinito numerabile di etichette, o
porte, non contenente il simbolo . Unazione in CCS ha una delle seguenti tre forme:
a 2 , rappresenta lazione di ricevere un segnale sulla porta a;
262
La capacit di un sistema di interagire con lesterno dipende dalle porte che il sistema
utilizza e dalle operazioni di input/output che eettua. Quindi, importante distinguere le
diverse porte di comunicazione, mentre non c alcuna necessit di distinguere tra loro i passi
computazionali interni, dal momento che essi corrispondono ad operazioni che non possono
influenzare lambiente di esecuzione o essere da questo influenzate. Perci, ununica azione
suciente per modellare le operazioni interne dei sistemi in questione.
Linsieme ACCS di tutte le azioni CCS quindi:
ACCS , [ {a | a 2 } [ { }
Poniamo inoltre , , dove 2 [ {a | a 2 }. Si noti che non unazione valida.
Le azioni e sono dette complementari, ovvero rappresentano azioni di input e di output
su uno stesso canale. Essendo lunica azione interna, linsieme di tutte le azioni esterne
ACCS \ { }. Nel seguito, quando non diversamente specificato, utilizzeremo come elemento
generico di ACCS \ { } e come elemento generico di ACCS .
Operatori di CCS. Dopo aver definito linsieme ACCS delle azioni CCS introduciamo gli
operatori che il calcolo mette a disposizione per la descrizione di sistemi interattivi.
Sia C un insieme infinito numerabile di costanti di processo, i cui generici elementi sono
denotati con A, B, C, . . . . Di seguito utilizzeremo p, p1 , q, q 0 per denotare processi CCS.
CCS fornisce i seguenti operatori per costruire processi.
Processo inattivo: nil rappresenta il processo che non esegue alcuna attivit.
Azione prefissa: ., con 2 ACCS , permette di preporre lazione ad un processo. Intuitivamente, .p capace di eseguire prima lazione e poi di comportarsi come il
processo p.
Scelta o somma: + rappresenta una scelta tra due comportamenti possibili. Il processo
p1 + p2 ha la possibilit di comportarsi come p1 o come p2 , a seconda dellinterazione
oerta dallambiente.
Composizione parallela: | permette lesecuzione concorrente dei due processi argomento.
Il processo p1 | p2 esegue p1 e p2 simultaneamente permettendo anche azioni complementari per la loro sincronizzazione; in questo caso lazione composta risultante unazione
interna .
Restrizione: \L, dove L , permette di localizzare delle azioni allinterno di un processo.
Intuitivamente, p\L si comporta come p eccettuato il fatto che esso non pu interagire
con lambiente usando azioni, o complementari di azioni, che compaiono in L.
Relabelling: [f ], dove f : ! , permette di ridenominare le azioni di un processo in
modo da facilitare la costruzione di processi complessi a partire da altri pi semplici.
Il processo p[f ] si comporta come p, eccetto che ogni azione che p pu eseguire viene
ridenominata applicandole f .
263
::=
nil
.p
p1 |p2
p1 + p 2
p\L
p[f ]
Nellesempio precedente abbiamo assunto che , lalfabeto delle azioni atomiche, contenga
play, work e meet. Nei tre esempi che seguono assumeremo che contenga send, recv, msg,
ack, get, put, get_ack e put_ack.
Esempio 12.2. Il termine
send.recv.nil
rappresenta un sistema che esegue una sequenza di due azioni: un input sul canale send,
seguito da un output sul canale recv.
264
265
12.2
Vediamo adesso le regole dinferenza che definiscono la semantica operazionale in stile SOS di
ogni singolo operatore CCS. Va detto che tutti sono stati gi definiti nel Capitolo 10, riteniamo
tuttavia opportuno riportare qui la loro semantica per facilit di consultazione.
Processo inattivo. Il processo nil non ha regole; di conseguenza, non capace di eettuare
alcuna transizione.
Azione prefissa. Loperatore di azione prefissa ha una sola regola. Per questo operatore
la regola di inferenza non ha premesse e viene anche detta assioma.
.p ! p
La regola aerma che un processo della forma .p pu eseguire e poi comportarsi come p.
Scelta o somma. Loperatore di scelta ha due regole simmetriche.
p ! p0
q ! q0
p + q ! p0
p + q ! q0
Tali regole ci dicono che un processo della forma p + q pu comportarsi come uno dei due
(sotto)processi p e q, a seconda dellinterazione oerta dallambiente. Va detto che se uno
dei due sottoprocessi eettua unazione interna, lambiente pu non riuscire a controllare la
scelta.
Composizione parallela. La semantica delloperatore di composizione parallela definita
da tre regole, le prime due sono simmetriche ed indicano che | intercala le azioni dei due
processi argomento.
p ! p0
q ! q0
p|q ! p0 |q
p|q ! p|q 0
La terza regola permette ai processi argomento di sincronizzarsi fra di loro eettuando azioni
complementari (cio input ed output sulla stessa porta); in questo caso lazione risultante
unazione interna .
p ! p0 , q ! q 0
p|q ! p0 |q 0
266
(pref)
.p ! p
p ! p0
(sum1)
p + q ! p0
(par1)
p ! p0
p|q ! p0 |q
(sum2)
q ! q0
(par2)
p|q ! p|q 0
q ! q0
p + q ! q0
(sincr)
p|q ! p0 |q 0
p ! p0
(res)
p ! p0
p\L ! p0 \L
p ! p0 q ! q 0
(rel)
(, 2
/ L)
p[f ]
f()
! p0 [f ]
(def)
p ! p0
C ! p0
(C , p)
p ! p0
p\L ! p0 \L
(, 2
/ L)
La regola dice che il processo p\L pu eseguire solo azioni tali che n loro n le loro complementari appartengono allinsieme L . La restrizione in eetti localizza le azioni
dellinsieme L, dato che loperatore proibisce allambiente di interagire con il processo usando
quelle azioni. Si noti che lazione interna non pu mai essere ristretta.
Relabelling. Anche loperazione di relabelling ha una sola regola.
p ! p0
p[f ]
f()
! p0 [f ]
p ! p0
C ! p0
(C , p)
267
saranno talvolta detti operatori statici in quanto, esaminando le conclusioni delle corrispondenti regole operazionali, si pu notare che essi sono presenti sia a sinistra che a destra del
simbolo di transizione. Ci dierente dal caso dei restanti operatori che invece saranno detti
dinamici.
Esempio 12.5. Consideriamo il processo M dellesempio 12.3 e vediamo le sue possibili
transizioni. Usando la regola per il prefisso (pref), si deriva la seguente transizione:
put.get.M
put
! get.M
put
! get.M
Quindi, usando la regola (def) per le costanti di processo, possibile determinare che:
M
put
! get.M
send
Si noti che questa lunica azione inizialmente possibile per P , dato che le azioni iniziali di
M e R[] sono tutte ristrette.
La definizione della semantica operazionale mostra che in realt lo stesso calcolo di processo
CCS pu essere visto come un unico LTS. Infatti, abbiamo che la tripla
hPCCS , ACCS , ! i
costituisce un LTS, dove:
PCCS linsieme di tutti i processi CCS sintatticamente corretti,
ACCS linsieme di tutte le azioni CCS,
! indica la relazione di transizione definita dalle regole in Tabella 12.2.
Questa osservazione vale anche per altri calcoli di processo ed ha due conseguenze importanti.
La prima che alcune definizioni, come quelle di equivalenze comportamentali e ordinamenti per ranamento, possono essere date in modo indipendente dal linguaggio, definendole
direttamente su LTS generici.
La seconda conseguenza che ad ogni descrizione in CCS di un sistema, pu essere associato un LTS con uno stato iniziale che rappresenta il sistema. In pratica ci vuol dire che ad
ogni termine sintattico corrisponde semanticamente un LTS con stato iniziale. Formalmente,
ad ogni processo p associata la quadrupla
hPCCS , ACCS , ! , pi
268
12.3
269
nil
a(x)., a
e., .
P
i2I
|
\L
[f ]
if be then
A(e1 , . . . , en )
270
Fb
nil
P
\
av .p{v/x}
aval(e) .b
p
.b
p
P
bi
i2I p
pb1 | pb2
pb\{av : a 2 L, v 2 V}
pb[fb], dove fb(av ) = f (a)v
pb
se val(be) = true
nil altrimenti
Aval(e1 ),...,val(en )
v2V
Tabella 12.4: Semantica di CCS con passaggio di valori per traduzione in CCS puro
P
di b riportata in Tabella 12.4. Si noti che, per semplicit, usiamo loperatore
al posto
delloperatore + anche in CCS puro. A questo proposito, per evitare di dover introdurre
somme infinite essenziale far uso dellipotesi che linsieme dei valori V sia finito. Cos, il
P
\ dove le azioni av rappresentano tutti i
termine a(x).p tradotto nel termine v2V av .p{v/x},
valori che x pu assumere. Similmente, il termine A(e1 , . . . , en ) tradotto in Aval(e1 ),...,val(en )
dove al contempo si definiscono tante costanti Av1 ,...,vn per ogni possibile n-upla di valori
v1 , . . . , vn .
12.4
12.4.1
271
Nel capitolo precedente abbiamo enunciato e dimostrato alcune propriet generali della
relazione di bisimulazione forte su LTS generici. Dimostriamo ora che la bisimilarit ()
una relazione di congruenza per CCS, cio sostituitiva per tutti gli operatori sui processi
ed anche per le definizioni ricorsive di costanti di processo. Quindi, se due processi CCS
sono fortemente bisimili, allora possono essere inter-scambiati in un qualunque contesto CCS.
Dimostriamo prima la propriet per tutti gli operatori CCS.
Proposizione 12.8. Siano p, q, r 2 PCCS , L ed f : ! . Allora p q implica
1. .p .q
2. p + r q + r
3. p|r q|r
4. p \ L q \ L
5. p[f ] q[f ]
Dimostrazione. Per dimostrare il punto 1. suciente esibire una bisimulazione forte R0 che
contiene la coppia h.p, .qi. Definiamo R0 a partire da una (qualsiasi) bisimulazione forte R
che contiene la coppia hp, qi, la quale esiste per ipotesi. La definizione la seguente:
R0 , {h.p, .qi} [ R
R0 una bisimulazione forte. Infatti, essa ovviamente chiusa per transizioni perch R lo
e perch le uniche transizioni di .p e .q portano in p e q, rispettivamente.
Per il punto 2., si pu procedere in maniera simile. Cos, se R una bisimulazione forte
che contiene la coppia hp, qi, allora la bisimulazione forte cercata R0 la seguente:
R0 , {hp + r, q + ri} [ R [ Id
Mostriamo che R0 chiusa rispetto alle transizioni (gi sappiamo che R e Id lo sono). Sia
Caso 1 p ! p0 e t p0 .
Allora, poich R una bisimulazione forte e hp, qi 2 R, esiste q 0 2 PCCS tale che q ! q 0
e hp0 , q 0 i 2 R. Dato che R R0 , abbiamo hp0 , q 0 i 2 R0 .
272
Caso 2 r ! r0 e t r0 .
Allora, poich hr1 , r2 i 2 R, abbiamo che r2 ! r20 con hr10 , r20 i 2 R; da questo si ha
Allora, poich hr1 , r2 i 2 R, abbiamo che r2 ! r20 con hr10 , r20 i 2 R; da questo si ha
Tale propriet una semplificazione di una propriet pi generale in cui si ha a che fare con singole
definizioni di costanti piuttosto che con sistemi di equazioni di definizione per pi costanti (rimandiamo il
lettore interessato a Milner [Mil89], pag. 99).
273
con uninferenza pi breve, C[A] ! p0 . Allora, per induzione, possiamo assumere che
00
C[B] ! q q 0 con hp0 , q 0 i 2 S. Poich C[] D[], abbiamo allora che D[B] ! q 000 q 0
E[A] E1 [A] + E2 [A]; ci sono quindi due casi per cui E[A] ! p0 :
E1 [A] ! p0 ;
E2 [A] ! p0 .
Esaminiamo il primo caso in quanto il secondo analogo. Poich la derivazione di
Quindi E[A] E1 [A]|E2 [A]. Consideriamo la transizione E[A] ! p0 ; abbiamo tre casi
possibili
E1 [A] compie lazione e E2 [A] sta fermo;
E2 [A] compie lazione e E1 [A] sta fermo;
E1 [A] compie unazione e E2 [A] compie lazione complementare .
Esaminiamo il terzo caso che il pi complesso; gli altri due procedono in maniera
simile. In questo caso, abbiamo = , E1 [A] ! p01 , E2 [A] ! p02 e p0 p01 |p02 . Poich
le transizioni da E1 [A] e E2 [A] hanno uninferenza pi corta, per induzione possiamo
assumere che E1 [B] ! q100 q10 con hp01 , q10 i 2 S e E1 [B] ! q200 q20 con hp02 , q20 i 2 S.
274
Quindi, prendendo q 0 q10 |q20 e q 00 q100 |q200 abbiamo che E[B] E1 [B]|E1 [B] ! q 00
q 0 . Rimane da stabilire se hp0 , q 0 i 2 S. Ora, poich hp0i , qi0 i 2 S con i = 1, 2, per
definizione di S, per qualche contesto Hi [] si ha p0i Hi [A] e qi0 Hi [B], sempre per
i = 1, 2. Prendiamo allora il contesto H[] H1 []|H2 []. Abbiamo H[A] H1 [A]|H2 [A]
e H[B] H1 [B]|H2 [B] e, quindi, hp0 , q 0 i hH[A], H[B]i 2 S come richiesto.
Caso 5 E[] E1 []\L oppure E1 [][R]
Questo caso pi semplice del caso precedente e la prova lasciata per esercizio al
lettore.
Caso 6 E[] C con C , r
Quindi, E un contesto costante (cio senza buchi). Ne deriva che E[A] C e
E[B] C ed entrambi hanno la stessa -derivata p0 ; essendo il processo p0 un contesto
senza buchi si ha hp0 , p0 i hp0 [A], p0 [B]i e, quindi, hp0 , p0 i 2 S come richiesto.
12.4.2
Per comodit, riportiamo su CCS la definizione di bisimulazione debole data nel Capitolo 11.
Definizione 12.11 (Bisimulazione debole per CCS).
Una relazione R PCCS PCCS una bisimulazione debole se, dati p e q tali che hp, qi 2 R,
allora le seguenti condizioni sono soddisfatte:
275
Dimostrazione. La dimostrazione in tutti e tre i casi simile alla corrispondente per la bisimilarit forte. Cominciamo a considerare il caso 1. Supponiamo che R una bisimulazione
debole che contiene la coppia hp, qi. suciente allora dimostrare che la relazione
R0 = {hr1 | t, r2 | ti : t 2 PCCS ^ hr1 , r2 i 2 R}
una bisimulazione debole. A quel punto, infatti, la tesi segue dal fatto che per costruzione
la coppia hp | r, q| ri 2 R0 . Per dimostrare che R0 una bisimulazione debole, prendiamo una
R. Quindi r2 | t =
) r20 | t e, per definizione di R0 , hr10 | t, r20 | ti 2 R0 come richiesto.
R. Quindi r2 | t =
) r20 | t00 e, per definizione di R0 , hr10 | t00 , r20 | t00 i 2 R0 come richiesto.
Da questo, tramite un argomento simmetrico, segue che R0 una bisimulazione debole.
La dimostrazione per 2. simile e, data una bisimulazione debole R che contiene la coppia
hp, qi, utilizza la bisimulazione debole
R0 , {hr1 \ L, r2 \ Li : hr1 , r2 i 2 R}
La dimostrazione per 3. simile e, data una bisimulazione debole R che contiene la coppia
hp, qi, utilizza la bisimulazione debole
R0 , {hr1 [f ], r2 [f ]i : hr1 , r2 i 2 R}
Abbiamo quindi dimostrato che la bisimilarit debole preservata da tutti gli operatori ad
eccezione della scelta. Purtroppo, come gi accennato in precedenza, la bisimulazione debole
non completamente sostitutiva perch non preservata dalloperatore di scelta. Abbiamo
infatti che p q non implica p + r q + r, per qualsiasi processo r.
Per mostrare che non una congruenza, suciente esibire due processi p e q e un
contesto C[] tali che p q e C[p] 6 C[q]. Prendiamo i processi a.nil e .a.nil ed il contesto []+
b.nil. Ora, dalla Proposizione 11.47, segue che .a.nil a.nil. Tuttavia, abbiamo C[.a.nil] 6
C[a.nil]. Infatti, la transizione C[.a.nil] ! a.nil deve essere messa in corrispondenza con
una discendenza etichettata con del processo C[a.nil]; lunica discendenza possibile quindi
quella che lascia il processo C[a.nil] invariato. Daltra parte, si ha a.nil 6 C[a.nil], dato che
276
C[a.nil] pu eseguire una transizione b che non pu essere eseguita da a.nil; ci quindi mostra
che C[.a.nil] 6 C[a.nil]. Concludendo, non una congruenza, e la causa linterazione
delloperatore di scelta con le azioni interne iniziali di un processo.
Data limportanza che riveste la possibilit di sostituire un termine con uno equivalente in
qualsiasi contesto, si pone quindi il problema di determinare quale sia la pi grande congruenza
contenuta in . Indichiamo tale relazione con il simbolo c . Formalmente la si pu definire
come una relazione di congruenza tale che c e per ogni altra congruenza R tale che
R si ha R c . Per definizione, tale congruenza esiste (Id una congruenza ed inoltre
Id ); per la precedente definizione di c poco utile in pratica, per cui sarebbe meglio
trovare una caratterizzazione alternativa. A tale scopo introduciamo la relazione congruenza
osservazionale, denotata col simbolo
=.
Definizione 12.15. Due processi p, q 2 PCCS sono osservazionalmente congruenti, scritto
p
= q, se per ogni 2 ACCS
Si noti la somiglianza con la propriet di data dalla Proposizione 11.46 di pagina 243.
al posto di =
) , che si usa invece nella definizione di , e la definizione di
= non ricorsiva.
Il primo punto implica che ogni azione di p o q deve essere corrisposta da almeno unazione
dellaltro processo. Questo comunque vale solo per lazione iniziale, in quanto successivamente
si richiede p0 q 0 e non p0
= q 0 (infatti, come si detto, la definizione di
= non ricorsiva).
Vogliamo innanzitutto dare una caratterizzazione di = che mostri quanto questa sia vicina
alla bisimilarit debole . Introduciamo allora la nozione di sorta di un processo p per indicare
linsieme delle porte usate da p. Formalmente possiamo dare la seguente definizione.
Definizione 12.16. Sia L ACCS \ { }. Se le azioni di un processo p e di tutte le sue
derivate sono elementi di L [ { } allora diremo che L una sorta di p, o anche che p ha
sorta L, e scriveremo p : L.
Chiaramente ogni processo ha una sorta minima, data dallintersezione di tutte le sue
sorte, ma non sempre facile determinarla (data una porta che compare nella sintassi del
processo, bisogna fare unanalisi semantica per capire se il processo pu eettivamente eettuare unazione su quella porta). Un modo piuttosto naturale per assegnare una sorta ad
ogni processo p per induzione sulla sintassi; questa viene chiamata sorta sintattica di p ed
indicata con L(p).
Definizione 12.17. La sorta (sintattica) L(p) di un processo p definita come segue (per
induzione sulla sintassi di p):
L(nil)
L(.p)
L(.p)
L(p + q)
L(p|q)
L(p\L)
L(p[f ])
,
,
,
,
,
,
,
;
{} [ L(p)
L(p)
L(p) [ L(q)
L(p) [ L(q)
L(p) \ (L [ L)
{f ()| 2 L(p)}
277
dove si suppongono assegnate le sorte L(A) alle costanti di processo A 2 C in modo tale che
per ogni equazione di definizione A , p si abbia L(p) L(A).
La nozione di sorta sintattica ci sar utile in seguito quando sar necessario poter scegliere
porte nuove rispetto a quelle utilizzate dai processi presi in considerazione. Sar infatti
suciente supporre che sia sempre possibile scegliere una porta che non appartiene alle sorte
(sintattiche) di tali processi. Una prima applicazione nella dimostrazione della proposizione
successiva.
Proposizione 12.18. Siano p, q 2 PCCS tali che L(p) [ L(q) ACCS . Allora p
= q se, e
solo se, per ogni r 2 PCCS , p + r q + r.
e dimostriamo che una bisimulazione debole. Sia p + r ! t; questo pu essere dovuto a due
situazioni:
Caso 1 p ! p0 e t p0 .
Allora, poich hp, qi 2 R ed R una bisimulazione debole, abbiamo che, per qualche q 0 ,
q=
) q 0 e hp0 , q 0 i 2 R. Quindi, dato che R R0 , abbiamo che hp0 , q 0 i 2 R0 .
Caso 2 r ! r0 e t r0 .
che q + r =
6 ) ; se invece = , abbiamo p0 6 q + r dato che q + r ! e p0 6 ! . Perci in ogni
278
p 2 PCCS stabile se p 6 ! .
Proposizione 12.21. Se p e q sono stabili, allora p q implica p
= q.
Dimostrazione. Sia p ! p0 . Per ipotesi, e per la Proposizione 11.46 di pagina 243, esiste q 0
tale che q =
) q 0 e p0 q 0 . Per via dellipotesi di stabilit, 6= e, quindi, =
) e =
)
0
p 2 PCCS si ha che p ! p0 e p0 q allora, dalla definizione di
=, segue che p
= .q.
0
0
0
Secondo, se per qualche q 2 PCCS si ha che q ! q e p q allora, ragionando come prima,
segue che .p
= q. Se nessuno dei due casi precedenti si verifica, allora si pu mostrare che
p = q nel modo seguente. Supponiamo dapprima che p ! p0 con 6= ; dal momento che
279
Dimostrazione. .p
= .q discende direttamente dalla proposizione precedente e dalla Proposizione 12.20. Le rimanenti uguaglianze si possono dimostrare applicando direttamente la
definizione di
=.
Per dimostrare che
= preservata dalloperatore di scelta, supponiamo che p
= q e che
q=
) q 0 e t q 0 . La tesi per questo caso segue allora dal fatto che q + r =
) q 0 . Se r ! t allora,
ovviamente, q + r =
) t. La tesi segue tramite un argomento simmetrico.
Per dimostrare che
= preservata dalloperatore di composizione parallela, supponiamo
tale che q =
) q 0 e p0 q 0 . Poich preservata dalloperatore di composizione parallela,
che f : ! e facciamo vedere che p[f ] = q[f ]. Supponiamo che p[f ] ! t. Ci vuol dire che,
0
280
(12.1)
La dimostrazione procede per induzione sulla profondit della derivazione con la quale la
transizione E[A] ! p0 inferita (il caso della transizione E[B] ! q 0 analogo). I dettagli sono
simili a quelli della dimostrazione della Proposizione 12.10. Ora, per la Proposizione 11.52 di
pagina 245, il fatto che S soddisfa la propriet precedente implica che S una bisimulazione
! di .a.nil non pu
3. Svc
= P , dove Svc , send.recv.Svc e P il processo (corrispondente ad un semplice
protocollo di comunicazione) definito in Sezione 12.2.
12.4.3
281
(riflessivit)
t1 = t 1
(sostitutivit)
(simmetria)
t1 = t2
t2 = t1
(transitivit)
t1 = t01 . . . tk = t0k
C(t1 , . . . , tk ) = C(t01 , . . . , t0k )
t 1 = t2
t2 = t 3
t1 = t3
C operatore di arit k
12.5
Come abbiamo detto nellIntroduzione esistono vari approcci per definire semantiche formali
per calcoli di processo. Finora abbiamo esaminato lapproccio operazionale; in questa sezione
esamineremo lapproccio equazionale. Tale approccio permette di stabilire la validit o meno
di una relazione tra processi attraverso semplici manipolazioni sintattiche dei processi stessi,
quindi senza utilizzare la semantica operazionale.
Lapproccio equazionale consiste nellindividuare un certo numero di regole dinferenza che
costituiscono quello che si chiama sistema di prova. Ci che distingue un sistema di prova da
un altro linsieme degli assiomi, che pu essere visto come unalgebra di processi. Linguaggi
di processi dierenti ed equivalenze dierenti conducono ad algebre di processi dierenti.
Come vedremo infatti, gli assiomi sono specifici della relazione che si intende catturare (per
esempio, bisimilarit o testing).
Oltre agli assiomi, un sistema di prova contiene di solito le regole dinferenza presentate
nella Tabella 12.5. Esse riflettono il fatto che ogni termine uguale a se stesso (riflessivit),
che se un termine uguale ad un altro allora vero anche il contrario (simmetria), che
termini uguali ad uno stesso termine sono uguali tra loro (transitivit), e che allinterno di
certi contesti termini uguali possono essere sostituiti gli uni agli altri (sostitutivit). In pratica
ci vuol dire che la relazione risultante dal sistema di inferenza una equivalenza e, talvolta,
una congruenza (quando la sostituzione si pu applicare a tutti i contesti del linguaggio). Le
regole nella Tabella 12.5 vengono di solito usate implicitamente per la costruzione di prove
per cui nel seguito menzioneremo solo gli assiomi dei vari sistemi. Quando esiste una prova
per i termini t1 e t2 usando le regole suddette e gli assiomi di un certo insieme E, scriveremo
E ` t1 = t2 .
Data una certa assiomatizzazione, cio un certo insieme di assiomi, ed una relazione di
equivalenza, ad esempio, comportamentale importante stabilire la relazione esistente tra le
uguaglianze che lassiomatizzazione ci permette di dimostrare e la relazione in questione. In
particolare, importante garantire che:
1. lassiomatizzazione corretta: ovvero, tutte le uguaglianze che riusciamo a dimostrare nel sistema di prova valgono per lequivalenza comportamentale che stiamo
282
p+q
p + (q + r)
p + nil
p+p
=
=
=
=
q+p
(p + q) + r
p
p
12.5.1
Assiomatizzazione di
283
i2I
i .pi |
j2J
0j .qj
P
P
P
i2I
j2J
i . pi |
0j . (
j2J
i2I
0j .qj +
i .pi ) | qj
da (A3)
da (A1)
da (A2)
= a.b.nil + a.nil
da (A4)
Questa prova stabilisce che a.(b.nil + nil) + (a.nil + a.b.nil) = a.b.nil + a.nil in quattro passi,
dove ogni passo rappresenta una applicazione di un assioma ad un sottotermine, in modo
da produrne un altro, facendo uso delle regole dinferenza di Tabella 12.5 di cui si detto
allinizio di questa sezione. Quindi, possiamo scrivere
E1 ` a.(b.nil + nil) + (a.nil + a.b.nil) = a.b.nil + a.nil
possibile dimostrare che E1 unassiomatizzazione corretta e completa di per CCS
di base.
Assiomatizzazione per CCS di base con parallelo. Analizziamo adesso il sottolinguaggio ottenuto aggiungendo a CCS di base loperatore di composizione parallela. Per questo
motivo, lo chiameremo CCS di base con parallelo. Come si pu intuire, gli assiomi (A1)-(A4)
rimangono corretti per CCS di base con parallelo, ma non sono ovviamente completi, dato
che nessun assioma menziona il parallelo; quindi, per esempio, non possiamo uguagliare p|q
e q|p. Per definire unassiomatizzazione completa per questo nuovo sottoinsieme di CCS, occorre aggiungere degli assiomi per il parallelo. La nuova assiomatizzazione presentata in
Tabella 12.7.
Lunico nuovo assioma, (Exp), conosciuto come legge di espansione, dato che mostra come
un termine costruito usando il parallelo come operatore principale (cio, al livello pi alto),
pu essere espanso in un altro che invece utilizza la somma come operatore al livello pi alto.
In questo modo, tramite applicazioni ripetute di (Exp), possibile eliminare completamente
loperatore di composizione parallela da un termine.
In eetti, (Exp) il pi complicato assioma
Pdi CCS, e merita ulteriori commenti. In primo
luogo, si ricordi la definizione delloperatore i2I data nella SezioneP10.5: dato un indice I
e un insieme di termini della forma pi , indicizzato da I, si definisce i2I pi come nil se I
vuoto e come la somma di tutti i pi altrimenti. Si noti allora che (Exp) pu essere applicato
a un termine p1 |p2 solo se p1 e p2 hanno una certa forma: ognuno deve essere una somma
284
di termini il cui operatore pi esterno quello di azione prefissa. Ancora, bisogna dire che
(Exp) uno schema di assiomi; al variare di I e J si ottengono assiomi diversi. Infine, la parte
destra di (Exp) consiste di tre sommandi, ognuno dei quali corrisponde ad una diversa regola
SOS per loperatore di composizione parallela: il primo sommando permette al sottotermine
a sinistra del parallelo di muoversi in modo autonomo; il secondo fa la stessa cosa con quello
di destra; il terzo sommando gestisce le possibili sincronizzazioni.
Per vedere come (Exp) pu essere usato nelle prove, presentiamo un paio di esempi.
Esempio 12.31. Vediamo un semplice esempio di applicazione della legge di espansione.
p , . p0 + . p00
def
q = . q 0 + . q 00
def
r = p|q
Esempio
12.32. Mostriamo che E2 ` nil|b.nil = b.nil; ricordiamo che nil sta per il termine
P
i2; pi , con pi qualsiasi.
nil|b.nil = nil + b.(nil|nil) + nil
da (Exp)
= b.(nil|nil)
da (Exp)
= b.nil
Pi in generale, per ogni processo CCS di base con parallelo p si pu dimostrare che
E2 ` nil|p = p; quindi, | ha nil come elemento neutro. possibile inoltre dimostrare che per
ogni p1 , p2 e p3 , E2 ` p1 |p2 = p2 |p1 e E2 ` p1 |(p2 |p3 ) = (p1 |p2 )|p3 ; conseguentemente, |
commutativo e associativo.
possibile dimostrare che E2 unassiomatizzazione corretta e completa di per CCS
di base con parallelo.
Assiomatizzazione per CCS finito. Consideriamo ora il sottolinguaggio di CCS che comprende tutti gli operatori a parte le costanti di processo; in letteratura questo sottolinguaggio
noto col nome di CCS finito. In altre parole, CCS finito estende CCS di base con parallelo
con gli operatori di restrizione e relabelling; gli assiomi per questo linguaggio sono presentati
in Tabella 12.8.
Gli assiomi per \L e [f ] esprimono solo come questi operatori interagiscono con nil, azione
prefissa e somma. Il fatto che non ci siano regole che descrivono linterazione tra | e \L oppure
tra \L e [f ], una conseguenza del fatto che le occorrenze pi interne di ciascun operatore
statico possono essere eliminate con luso ripetuto degli assiomi per loperatore in questione
in aggiunta agli assiomi (A1)-(A4).
285
nil\L
(Res2)
(.p)\L
(Res3)
(Rel1)
(Rel2)
(Rel3)
(p + q)\L
nil[f ]
(.p)[f ]
(p + q)[f ]
=
=
=
=
nil
nil
se , 2 L
.(p\L) altrimenti
p\L + q\L
nil
f ().(p[f ])
p[f ] + q[f ]
p ! t oppure q ! t oppure r ! t. In ognuno dei casi, usando ancora le regole della semantica
286
corretta rispetto a .
j2J
0j . (
i2I
i .pi ) | qj
Dimostrazione. suciente dimostrare che i termini CCS coinvolti nella legge di espansione
hanno le stesse -derivate per ogni 2 ACCS ; a questo puntoP
la tesi deriva P
dalla propriet di
0
espressa dalla Proposizione 11.14. Supponiamo allora che
.p
|
i2I i i
j2J j .qj ! t.
Dalle regole della semantica operazionale per la composizione parallela, otteniamo che si deve
presentare una delle seguenti tre situazioni:
P
P
k
Caso 1 = k per qualche k 2 I, i2I i .pi !
pk e t pk |( j2J 0j .qj );
Caso 2 = 0l per qualche l 2 J,
j2J
l
j .pj !
ql e t (
i2I
i .pi )|ql ;
k
i2I i .pi ! pk ,
l
0
j2J j .qj ! ql e
In ognuno dei casi, usando le regole della semantica operazionale per la somma, possiamo
facilmente inferire che il termine a destra del simbolo di = nella legge di espansione ha t come derivata. Infatti, per ciascuna delle tre situazioni precedenti, abbiamo un caso corrispondente
P
P
P
k
0
Caso 1
! pk |( j2J 0j .qj ) per qualche k 2 I;
i2I i . pi |
j2J j .qj
P
0l
0 .
Caso 3
.(p
|
q
)
!
p
|q
per
qualche
(k,
l)
2
(i,
j)
|
0
i
j
k
l
i
j
{(i,j) | = }
Caso 2
0
j2J j . (
i2I i .pi ) | qj
!(
i2I
In maniera simile si pu dimostrare il contrario, cio che ogni -derivata del termine a destra
del simbolo di = anche una -derivata del termine a sinistra. Per quanto detto prima, ci
suciente per ricavare la tesi.
Proposizione 12.35 (Leggi per restrizione e relabelling). Le leggi della Tabella 12.8, cio
1. nil\L = nil
nil
se , 2 L
2. (.p)\L =
.(p\L) altrimenti
3. (p + q)\L = p\L + q\L
4. nil[f ] = nil
5. (.p)[f ] = f ().(p[f ])
287
m
X
i .pi
i=1
288
Facendo uso delle s.f. possiamo dimostrare la completezza dellinsieme di leggi E3 rispetto
a per CCS finito.
Proposizione 12.39 (Completezza). p q implica E3 ` p = q.
Dimostrazione. Assumiamo cheP
p q ed inoltre,Pper via del lemma precedente, che p e q
n
sono entrambi in s.f., cio p m
i=1 i .pi e q
j=1 j .qj . La dimostrazione procede per
induzione sulla massima tra le profondit di p e di q, che indichiamo con k.
Se k = 0, allora entrambi i processi (essendo in s.f.) sono il processo nil e la regola
dinferenza (riflessivit) in Tabella 12.5 ci permette di inferire che E1 ` nil = nil.
Se k > 0, allora almeno uno tra p e q diverso dal processo nil; supponiamo sia p. Sia
.p0 un sommando di p. Allora p ! p0 ; inoltre, dal fatto che p q, sappiamo che esiste
p = t[p/X]
q = t[q/X]
(X = t ha soluzione unica)
p=q
Questa regola ci permette di concludere che due termini sono uguali se possibile dimostrare (i) che sono entrambi soluzioni della stessa equazione e (ii) che lequazione ha una sola
soluzione (a meno di ).
Si possono fare alcune osservazioni su questa ultima regola. In primo luogo, ogni equazione
X = t ha una soluzione: posto infatti X , t, facile vedere che il processo X soluzione
di X = t. In eetti, (UFI) utile solo nel caso in cui siamo in grado di capire quando
289
Dimostrazione. La dimostrazione procede per induzione sulla profondit della derivazione con
p0 t01 [p/X] e t[q/X] ! t01 [q/X] per ogni q 2 PCCS . Nel secondo caso, sempre per
induzione, possiamo assumere che per qualche termine CCS t02 si ha p0 t02 [p/X] e
In questo caso, abbiamo = , t1 [p/X] ! p01 , t2 [p/X] ! p02 e p0 p01 |p02 . Poich le
transizioni da t1 [p/X] e t2 [p/X] hanno uninferenza pi breve, per induzione, possiamo
assumere che esistono due termini CCS t01 e t02 tali che p01 t01 [p/X], p02 t02 [p/X],
t1 [q/X] ! t01 [q/X] e t2 [q/X] ! t02 [q/X] per ogni q 2 PCCS . La tesi segue allora
prendendo t0 t01 |t02 .
3
La propriet che dimostreremo si potrebbero generalizzare a sistemi di equazioni di definizione con pi
variabili, ma rimandiamo il lettore interessato a Milner [Mil89], pag. 103.
290
Caso 5 t t1 \L oppure t1 [f ].
Questi casi sono pi semplici del caso precedente e la loro prova lasciata per esercizio
al lettore.
Caso 6 t C con C , r.
Quindi X[p/X] p ! p0 , perci, dato che p t[p/X], abbiamo che t[p/X] ! p00 p0 .
Poich X guardata in t, per la Proposizione 12.41, p00 t00 [p/X] e t[q/X] ! t00 [q/X].
Dato che t0 [q/X] X[q/X] q t[q/X], allora abbiamo t0 [q/X] ! q 0 t00 [q/X].
Riassumendo abbiamo p0 t00 [p/X] S t00 [q/X] q 0 come richiesto.
Caso 2 t0 0 .t1 .
Quindi dobbiamo avere 0 e p0 t1 [p/X]. Ovviamente abbiamo anche t0 [q/X]
.t1 [q/X] ! t1 [q/X]. La tesi segue dal fatto che per costruzione ht1 [p/X], t1 [q/X]i 2 S.
Caso 3 t0 t1 + t2 .
primo caso, per induzione, abbiamo che, per qualche q10 2 PCCS , t0 [q/X] ! q10 con
hp0 , q10 i 2 S . Nel secondo caso, sempre per induzione, abbiamo che, per qualche
291
Esaminiamo il terzo caso che il pi complesso; gli altri due procedono in maniera simile.
In questo caso, abbiamo = , t1 [p/X] ! p01 , t2 [p/X] ! p02 e p0 p01 |p02 . Poich le
transizioni da t1 [p/X] e t2 [p/X] hanno uninferenza pi breve, per induzione, possiamo
assumere che esistono q10 , q20 2 PCCS , tali che t1 [q/X] ! q10 , t2 [q/X] ! q20 , hp01 , q10 i 2
S e hp02 , q20 i 2 S . Rimane da stabilire se hp01 |p02 , q10 |q20 i 2 S . Ora, poich
hp0i , qi0 i 2 S con i = 1, 2, per definizione di S, per qualche termine t0i si ha p0i t0i [p/X]
e qi0 t0i [q/X], sempre per i = 1, 2. Prendiamo allora il termine t00 t01 |t02 . Abbiamo
t00 [p/X] t01 [p/X]|t02 [p/X] e t00 [q/X] t01 [q/X]|t02 [q/X] e, quindi, poich preservata
dalloperatore di composizione parallela, abbiamo p01 |p02 t00 [p/X] S t00 [q/X] q10 |q20
come richiesto.
Caso 5 t0 t1 \L oppure t0 t1 [f ] oppure t C con C , r.
Questi casi sono pi semplici del caso precedente e la loro prova lasciata per esercizio
al lettore.
Ora, prendiamo t0 X. Ne deriva che hX[p/X], X[q/X]i hp, qi 2 S e, quindi, che p q,
che ci che volevamo dimostrare.
Esempio 12.43. Come esempio di applicazione di (Unr) e (UFI), supponiamo di voler
dimostrare che A e B sono bisimili, dove A , a.A e B , a.a.B. Consideriamo lequazione
X = a.a.X. Dimostriamo dapprima che sia A che B sono soluzione di questa equazione:
A = a.A
da (Unr)
= a.a.A
da (Unr)
B = a.a.B
da (Unr)
C ,C +p
D , p[D/C]
C=D
dove p[D/C] indica il processo p in cui le occorrenze della costante di processo C sono
rimpiazzate con D. Si pu allora enunciare il seguente risultato (che non dimostreremo).
Proposizione 12.44 (Correttezza e completezza). Siano p, q 2 PCCS processi sequenziali.
p q se e solo se E1 [ {(Unr), (UFI), (Seq1)} ` p = q.
292
..p
p + .p
.(p + .q)
=
=
=
.p
.p
.(p + .q) + .q
12.5.2
Assiomatizzazione di
=
unassiomatizzazione completa per =, occorre aggiungere degli assiomi che riflettano la natura
speciale dellazione interna . Tali assiomi, noti come leggi , sono illustrati in Tabella 12.9.
La legge ( 1) serve per lassorbimento delle azioni che seguono immediatamente operatori
di azione prefissa. La legge ( 2) pu essere spiegata come segue. Primo, ogni transizione forte
di .p anche una transizione forte di p+.p. Secondo, ogni transizione forte di p+.p, incluse
le transizioni , pu essere messa in corrispondenza con una appropriata transizione debole
di .p. La legge finale, ( 3) forse la pi dicile da interpretare; si noti che la derivazione
.(p + .q) + .q ! q
della parte destra della regola, pu essere messa in corrispondenza con la discendenza
.(p + .q) =
)q
della parte sinistra. Lutilit di queste leggi la si apprezzer nella dimostrazione di completezza
ed in particolare in quella del Lemma 12.47.
Dimostriamo adesso la correttezza delle leggi .
Proposizione 12.45 (Leggi ). Le leggi della Tabella 12.9, cio
1. ..p = .p
2. p + .p = .p
3. .(p + .q) + .q = .(p + .q)
sono corrette rispetto a
=.
Dimostrazione. La correttezza delle leggi segue direttamente dalla definizione di congruenza
osservazionale. Nel punto 1. si usa anche la Proposizione 11.47.
Si osservi anche che tutte le leggi corrette per e
= lo sono anche per , mentre non vale
il viceversa: infatti, abbiamo che p .p mentre in generale p
6 .p.
=
Possiamo infine dimostrare che linsieme di leggi E4 definito in Tabella 12.9 completo per
= su CCS finito. Anche in questo caso faremo uso di alcune forme particolari per i processi.
293
Definizione 12.46 (Full standard form). Un processo p 2 PCCS in full standard form
(f.s.f.) se
P
1. p m
i=1 i .pi , dove ogni pi anchesso in full standard form;
2. se p =
) p0 allora p ! p0 .
Possiamo pensare alla f.s.f. come ad una s.f. saturata nel seguente senso: per ogni p =
) p0
allora .p0 appare come sommando di p. Vediamo ora come ogni s.f. pu essere saturata
utilizzando le leggi (Tabella 12.9).
Dimostrazione. La prova procede per induzione su prof (p). Dato che p una s.f., se p =
) p0
allora si deve presentare uno dei seguenti tre casi.
Caso 1 .p0 un sommando di p. La tesi segue dallassioma (A4).
Caso 2 .q un sommando di p e q =
) p0 . Allora per induzione E4 ` q = q + .p0 , quindi
E4 ` p =
=
=
=
=
p + .q
p + .(q + .p0 )
p + .(q + .p0 ) + .p0
p + .q + .p0
p + .p0
Caso 3 .q un sommando di p
quindi
E4 ` p =
=
=
=
=
da
da
da
da
da
(A4)
E4 ` q = q + .p0
( 3)
E4 ` q = q + .p0
(A4)
e q =
) p0 . Allora per induzione si ha E4 ` q = q + .p0 ,
p + .q
p + .q + q
p + .q + q + .p0
p + .q + .p0
p + .p0
da
da
da
da
da
(A4)
( 2)
E4 ` q = q + .p0
( 2)
(A4)
294
=. In particolare, .a.nil
= ..a.nil e .b.nil
= ..b.nil, ma ovviamente .a.nil 6
= .b.nil.
Comunque, possibile individuare una classe di equazioni che hanno soluzione unica rispetto
a
=.
Nel resto di questa sezione4 , supporremo per semplicit che tutti i termini considerati
contengano al pi la stessa variabile di processo X.
Definizione 12.50. Sia X una variabile e t un termine CCS. X fortemente guardata in t
se ogni sottotermine di t che contiene X, a parte X stesso, della forma .t0 , con 6= .
Ci significa che X fortemente guardata in t se almeno un operatore di azione prefissa
che coinvolge unazione visibile precede ogni occorrenza di X in t. Ovviamente X non
4
La propriet che dimostreremo si potrebbero generalizzare a sistemi di equazioni di definizione con pi
variabili, ma rimandiamo il lettore interessato a Milner [Mil89], pag. 158.
295
fortemente guardata in .X. Comunque, il fatto che X sia fortemente guardata in t non
implica che X = t abbia soluzione unica a meno di
=. Infatti, consideriamo lequazione
X = (a.X|a.nil)\ {a} .
X fortemente guardata nella parte destra dellequazione, tuttavia si pu vedere che, per
esempio, .b.nil e .c.nil sono entrambe soluzioni. possibile risolvere questo problema
richiedendo quanto segue.
Definizione 12.51. Sia X una variabile e t un termine CCS. X sequenziale in t se ogni
sottotermine di t che contiene X, a parte X stesso, della forma .t0 oppure t1 + t2 .
Per esempio, X sequenziale in a.X e .X +(b.nil|c.nil) ma non sequenziale in a.X|b.nil
(bench il termine sia fortemente guardato). In pratica, se X sequenziale in t allora nessuna
occorrenza di X in t ricade nello scopo di un operatore statico.
Analogamente al caso della bisimilarit forte, dimostriamo prima che se un termine t contiene solo occorrenze fortemente guardate e sequenziali di una variabile di processo X, allora il
comportamento di t, fino ed incluso lesecuzione della prima azione visibile, completamente
indipendente dal processo sostituito al posto di X.
per qualche termine CCS t0 , abbiamo p0 t0 [p/X] e t[q/X] ! t0 [q/X] per ogni q 2 PCCS .
Inoltre, X sequenziale in t0 e, se = , allora anche fortemente guardata.
Dimostrazione. La dimostrazione procede per induzione sulla struttura di t. Innanzitutto si
noti che t X non pu verificarsi, poich per ipotesi X fortemente guardata in t. Ora, se
t C (C costante di processo), oppure t t1 |t2 , oppure t t1 \ L (L ), oppure t t1 [f ]
(f : ! ), allora, poich per ipotesi X sequenziale in t, la variabile X non occorre in t
se t0 [p/X] =
) p0 allora, per qualche q 0 2 PCCS , t0 [q/X] =
) q 0 e hp0 , q 0 i 2 S .
se t0 [q/X] =
) q 0 allora, per qualche p0 2 PCCS , t0 [p/X] =
) p0 e hp0 , q 0 i 2 S .
(12.2)
Vediamo prima perch ci ci permette di arrivare alla tesi. Ora, per ogni processo CCS r
296
implica che S una bisimulazione debole up to (Definizione 11.49). Perci, per la Proposizione 11.50, abbiamo che hp0 , q 0 i 2 S implica p0 q 0 . Inoltre, poich per ogni processo
(12.3)
t0 [t[q/X]/X] =
) ! t00 [q/X]. A questo punto, per la propriet (12.3), otteniamo t00 [q/X] =
) q 00
00
00
00
0
0
t0 [q/X] =
) q 0 q 00 . Perci p0 p00 S q 00 q 0 , da cui, per transitivit di , abbiamo
p0 S q 0 . Ci, per simmetria, suciente a concludere che la propriet (12.2) vale.
Esempio 12.54. Per concludere, presentiamo un esempio per esteso, riguardo lutilizzo
degli assiomi introdotti. Riprendiamo il semplice protocollo di comunicazione P definito in
Sezione 12.1 di pagina 261 e la sua specifica Svc definita nellEsempio 12.27 di pagina 280.
possibile stabilire che E4 [ {(Unr), (UFI)} ` P = Svc nel modo seguente. Si noti prima
di tutto che X fortemente guardata e sequenziale in send.recv.X e quindi lequazione X =
send.recv.X ha soluzione unica a meno di
=. Quello che resta da fare mostrare che sia P
che Svc sono soluzioni di questa equazione, dopodich, utilizzando la regola (UFI), si ha che
P = Svc. Per fare ci vediamo subito che
Svc = send.recv.Svc
da (Unr)
297
usando (Unr), quindi suciente dimostrare che la parte destra una soluzione dellequazione
data, cio che
(S[put/msg, get_ack/ack] | M | R[get/msg, put_ack/ack])
\ {get, put, get_ack, put_ack} =
per ( 1)
per ( 1)
per ( 1)
298
.p + .q
p + .q
.p + .(.q + r)
.p
=
v
=
v
.(.p + .q)
.(p + q)
.(.p + .q + r)
p
C , .C + p
D , .p[D/C]
C=D
(Seq3)
C , .(C + p) + q
D , .D + p[D/C] + q[D/C]
C=D
(si ricordi che r[D/C] indica il processo r in cui le occorrenze di C sono rimpiazzate con D).
Si pu allora enunciare il seguente risultato (che non dimostreremo).
Proposizione 12.55 (Correttezza e completezza). Siano p, q 2 PCCS processi sequenziali.
p
= q se e solo se E1 [ {( 1), ( 2), ( 3), (Unr), (UFI), (Seq1), (Seq2), (Seq3)} ` p = q.
12.5.3
Come per e
=, cominciamo con lintrodurre le assiomatizzazioni corrette e complete dei
preordini per CCS finito e quindi presentiamo brevemente alcune euristiche per gestire le
definizioni di processo ricorsive.
Assiomatizzazione per CCS finito. Lassiomatizzazione di vctest per CCS finito data dallinsieme E5 ed presentata in Tabella 12.10. A dierenza di quanto abbiamo visto
finora, questa unassiomatizzazione disequazionale: essa usata per dimostrare asserzioni
della forma p v q invece che p = q. Come si pu vedere, gli assiomi includono disuguaglianze; le uguaglianze come nella regola (F1) vanno interpretate come abbreviazioni per due
disuguaglianze, nelle due direzioni.
Lassiomatizzazione per vcM si ottiene aggiungendo allinsieme E5 il seguente assioma
(F5)
.p + .q v p
299
p v .p + .q
Per vedere come queste regole possono essere usate per derivare dei risultati, mostriamo
che E5 [ {(F5)} ` a.b.nil + a.c.nil v a.b.nil.
a.b.nil + a.c.nil = a.(.b.nil + .c.nil)
v a.b.nil
da (F1)
da (F5)
300
Assiomatizzazione dei preordini per tutto CCS. Per trattare i processi ricorsivi, si
possono usare le regole (Unr) e (UFI) viste nella Sezione 12.5.1. Una condizione suciente
anch unequazione X = t abbia soluzione unica rispetto a 'ctest che X sia fortemente
guardata e sequenziale in t e che t sia totalmente convergente (si veda la Definizione 11.62).
12.6
Esercizi
12.1 Dimostrare la proposizione seguente che introduce alcune leggi per gli operatori statici derivabili
a partire da quelle nelle Tabelle 12.7, 12.8 e 12.9.
Proposizione 12.62 (Leggi derivabili). Le seguenti leggi
1. p|q q|p
2. p|(q|r) (p|q)|r
3. p|nil p
4. p \ L p
se L(p) \ (L [ L) = ;
5. p \ K \ L p \ (K [ L)
6. p[f ] \ L p \ f
(L)[f ]
7. (p|q) \ L p \ L|q \ L
8. p[Id] p
9. p[f ] p[f 0 ]
se f
0
f]
se L(p) \ L(q) \ (L [ L) = ;
L(p) = f 0
se f
L(p)
(L [ L)
p + .(p + q) = .(p + q)
Capitolo 13
SOMMARIO
Questo capitolo presenta alcune logiche modali e temporali e mostra come utilizzarle per
specificare propriet dei sistemi concorrenti. Dopo aver introdotto in generale le caratteristiche delle logiche modali e temporali, descriveremo in dettaglio la logica HML, la logica
ACTL ed il -calculus modale. Infine, esamineremo la corrispondenza tra le equivalenze
indotte dalle logiche e le equivalenze comportamentali presentate nel Capitolo 11.
13.1
I linguaggi per la specifica di processi, come il CCS, consentono di definire sia un sistema
concorrente che la sua specifica. Inoltre, forniscono tecniche di equivalence checking che
studiano la relazione che lega le due definizioni formali del sistema e permettono di verificare
se il sistema rispetta i requisiti richiesti della sua specifica.
Questo tipo di tecniche non sono per utilizzabili nel caso in cui si intenda verificare se
un dato sistema verifica una propriet del tipo in ogni momento il sistema pu eettuare
lazione a. I formalismi che vedremo in questo capitolo, chiamati logiche modali e temporali,
permettono di esprimere propriet di sistemi concorrenti e reattivi, quali deadlock e livelock.
Certamente sarebbe desiderabile disporre di una logica che consenta di formalizzare propriet allo stesso modo in cui queste vengono formulate dal pensiero umano. Purtroppo non
facile catturare in ununica logica tutti gli aspetti che possono descrivere le caratteristiche di
un sistema, per questo esistono logiche diverse che dieriscono tra loro proprio per il genere
di propriet che sono in grado di descrivere. La maggior parte delle propriet dei sistemi
concorrenti si possono suddividere in due categorie di base: propriet di safety e propriet di
liveness.
Safety. In questa categoria rientrano tutte quelle propriet del tipo niente di indesiderato
accadr nel prosieguo dellesecuzione del sistema. Per soddisfare una tale propriet il
sistema non dovr mai eettuare lattivit proibita. Per esempio, una propriet di
safety per una macchina distributrice di te e ca vista nellEsempio 11.3, che la macchina non distribuir un te se stato richiesto un ca. Normalmente, le propriet di
safety intendono esprimere invarianze, cio se una condizione vale nello stato iniziale,
allora essa resta vera per tutta lesecuzione del programma. Una di queste propriet
lassenza di stati di deadlock che assicura che il sistema non pu raggiungere una situazione in cui tutte le componenti sono bloccate. Oltre ai deadlock, possono esistere anche
302
Liveness. In questa categoria rientrano tutte quelle propriet del tipo qualcosa di positivo
accadr prima o poi nel prosieguo dellesecuzione del sistema. Per soddisfare una tale
propriet il sistema dovr eettuare una qualche attivit desiderata. Per esempio, una
propriet di liveness per una macchina distributrice di te e ca vista nellEsempio 11.3,
che la macchina distribuir un ca una volta che lutente ha inserito la giusta quantit
di denaro. Le propriet di liveness esprimono il fatto che, nel futuro, una data condizione
debba essere soddisfatta almeno una volta, infinite volte o continuamente da un certo
punto in poi. Le propriet che esprimono il progresso di un sistema sono una classe
di propriet di liveness. Dato un insieme di azioni L = {1 , , n }, un sistema ha
la propriet di progresso rispetto a L se, in qualunque stato si trovi, esso prima o poi
esegue una azione i 2 L.
Molte altre propriet possono essere descritte come combinazione delle due categorie di base.
Tra queste abbiamo alcune propriet di tipo infinitario quali quelle di fairness che esprimono
il fatto che qualcosa di buono accadr infinite volte. Ad esempio, desiderabile che se un
sistema operativo serve due utenti, il controllo passi dalluno allaltro infinite volte. In altri
termini, non succede mai che uno dei due utenti monopolizzi il sistema indefinitamente, poich
questo non sarebbe equo (fair ).
Una caratteristica importante di una logica per sistemi concorrenti il tipo di modello di
sistema su cui una formula interpretata. Sostanzialmente questo o un LTS o una Struttura
di Kripke (KS). Come abbiamo visto nel Capitolo 3, LTS e KS si dierenziano per quelle che
sono le informazioni associate ai nodi e agli archi dei grafi sui quali entrambi sono basati.
Lapproccio logico introdotto in questo capitolo costituisce un approccio alternativo a
quelli operazionale (comportamentale) ed assiomatico introdotti nei capitoli precedenti, per
lo studio del comportamento dei sistemi concorrenti e distribuiti e delle loro propriet. Infatti,
dati un modello a stati finiti di un sistema ed una formula che descrive una propriet in un
qualche formalismo logico appropriato (quale ad esempio una logica modale o temporale),
tramite una tecnica automatica chiamata model checking possibile verificare (tramite una
esplorazione dello spazio degli stati) se il sistema soddisfa la propriet. Il model checking
una tecnica alquanto generale che applicata in varie aree, quali la verifica di sistemi hardware
e lingegneria del software.
Uno dei vantaggi del model checking, che lo distingue dalle altre tecniche di verifica,
consiste nel fatto che gli algoritmi, attraverso i quali questa tecnica viene realizzata, sono
completamente automatici e raggiungono un esito senza richiedere nessun tipo di intervento
da parte dellutente che sta svolgendo la verifica. Questo aspetto rende possibile anche ad
utenti meno esperti lutilizzo di queste tecniche di verifica; le uniche conoscenze richieste sono
quelle minime relative ai formalismi di specifica del sistema e delle propriet da verificare.
Lapproccio logico pu comunque essere messo in relazione con gli approcci operazionale e
assiomatico. Una logica induce una naturale relazione di equivalenza sui sistemi: due sistemi
sono equivalenti se (e solo se) essi soddisfano le stesse formule. Supponiamo che L sia una
logica, allora possiamo definire la seguente equivalenza tra due sistemi p e q:
p L q
()
8' 2 L :
303
Il fatto che due sistemi equivalenti soddisfano esattamente le stesse formule della logica L non
vuol dire che le soddisfano tutte (ovviamente, se L = ; allora qualunque coppia di sistemi
in relazione ; ). Spesso risulta che la nozione di equivalenza indotta da una logica coincide
con una nozione di equivalenza tra sistemi definita usando la semantica operazionale od un
insieme di assiomi. Difatti, naturale che due processi che si comportano allo stesso modo
soddisfino le stesse classi di propriet. In quel caso, si pu aermare che la logica espressiva
rispetto allequivalenza considerata. Per le logiche presentate in questo capitolo esamineremo
le relazioni con le semantiche basate sul concetto di bisimulazione.
Le logiche pi utilizzate per esprimere propriet di sistemi concorrenti sono quelle modali
e temporali. Le formule di una logica modale, come la Hennessy-Milner Logic, esprimono
capacit e necessit locali di (uno stato di) un sistema, ma non hanno la capacit di esprimere
propriet riguardanti levoluzione nel tempo del sistema. Ad esempio, non possono dire che
una certa propriet sempre vera (in ogni stato di una computazione) o inizier a valere in
uno stato futuro (non conosciuto). Tali propriet sono invece esprimibili tramite le logiche
temporali.
Le logiche temporali si possono raggruppare in due categorie sulla base del modello del
tempo sottostante. Le logiche temporali linear time (o lineari) hanno un modello del tempo
lineare per cui in ogni istante di tempo esiste un unico futuro che si potr concretizzare. Tali
logiche considerano un sistema come linsieme di tutte le sue possibili computazioni (sequenze
di esecuzione) distinte e permettono di esprimere propriet delle singole computazioni di un
sistema. Le logiche temporali branching time hanno un modello del tempo ad albero (cio
ramificato) per cui il futuro non univocamente determinato; esistono pi futuri possibili
ciascuno dei quali potrebbe essere quello che eettivamente si realizzer. Sono dotate di operatori che permettono di esprimere propriet che si riferiscono al futuro e di quantificare sulle
possibili computazioni dierenti. Tali logiche considerano un sistema come lalbero delle sue
computazioni. Infatti, lesecuzione di un sistema concorrente non un qualcosa di lineare,
di preconfezionato, ma caratterizzata da diverse scelte che vengono compiute in base al
valore assunto a runtime da particolari fattori, che possono essere i dati in input o le variabili
dambiente, o da eventi indesiderati che possono causare eccezioni. Lalbero delle computazioni rappresenta in maniera compatta lesecuzione di un sistema. I nodi interni dellalbero,
da cui partono rami diversi, rappresentano stati in cui viene eettuata una scelta. Ogni cammino nellalbero rappresenta una singola computazione possibile o, a seconda di come lo si
interpreta, un diverso futuro nel quale il sistema pu evolvere. Perci le logiche temporali
branching time permettono di esprimere propriet che riguardano le scelte che un sistema pu
fare durante la sua evoluzione e le possibili computazioni da un certo stato. Questi due tipi
di logiche, tuttavia, non sono in generale confrontabili in termini di espressivit.
13.2
Il nostro interesse per le logiche motivato dallintento di utilizzarle per esprimere propriet
dei sistemi concorrenti. A questo scopo, di fondamentale importanza la relazione di soddisfazione per stabilire se un sistema un modello di una formula. In questa sezione, per illustrare
le tecniche di interpretazione di formule basate su modelli, introduciamo una presentazione
delle logiche proposizionali diversa da quella classica.
304
Nel panorama che introdurremo, le logiche proposizionali si collocano alla base di quelle
modali e temporali, in quanto definiscono un insieme di operatori comuni a queste diverse
categorie. Il loro nome deriva dal fatto che sono definite a partire da un insieme di proposizioni
atomiche ciascuna delle quali pu assumere valore true o f alse. Sia AP = {p0 , p1 , . . . , }
linsieme delle proposizioni atomiche. I suoi elementi esprimono propriet di base che il
sistema in esame garantisce nello stato in cui si trova, come ad esempio file_eliminato, che
indica il fatto che un certo file stato eliminato, o ca_pronto, che indica il fatto che il
ca pronto (si consideri il distributore automatico di bevande dei capitoli precedenti).
La sintassi delle formule della logica proposizionale definita dalla grammatica seguente:
' ::= AP
'
'1 _ '2
Ossia:
ogni proposizione atomica di AP una formula proposizionale;
la negazione di una formula proposizionale ancora una formula proposizionale;
la disgiunzione (_) di due formule proposizionali ancora una formula proposizionale.
Usando gli operatori della sintassi di base della logica proposizionale possiamo derivare
molti altri operatori, tra i quali i principali sono i seguenti:
le costanti booleane: true , p _ p e f alse , true, con p 2 AP ;
loperatore ^ (congiunzione): '1 ^ '2 , ('1 _ '2 );
loperatore ! (implica): '1 ! '2 , '1 _ '2 ;
loperatore $ (se e soltanto se): '1 $ '2 , ('1 ! '2 ) ^ ('2 ! '1 ).
Per definire la semantica della logica proposizionale dobbiamo introdurre il concetto di modello. A questo scopo, indichiamo con U il dominio dei valori booleani, cio U , {true, f alse}.
Una interpretazione I una funzione che associa ad ogni proposizione atomica p 2 AP un
valore booleano, cio:
I : AP ! U.
Il concetto di interpretazione importante in quanto ci consente di valutare le stesse proposizioni atomiche in situazioni dierenti a ciascuna delle quali associata una diversa interpretazione. Un modello per la logica proposizionale costituito allora da una coppia
M , hU , Ii.
La semantica della logica proposizionale formalizzata mediante una relazione binaria di
soddisfazione, indicata con il simbolo |=, tra un modello M , hU , Ii e una formula proposizionale '. Tale relazione definita per induzione sulla sintassi delle formule dalle regole
seguenti:
M |= p sse I(p) = true;
M |= ' sse non vero che M |= ';
M |= '1 _ '2 sse M |= '1 oppure M |= '2 .
305
Nel seguito, talvolta scriveremo M 6|= ' se non vero che M |= '.
Diremo che una formula ' soddisfacibile se esiste un modello M tale che M |= '. In tal
caso, diremo anche che M un modello per '. Diremo che una formula ' valida, scritto
|= ', se ogni modello M tale che M |= '. Si noti che se ' valida, allora ' non
soddisfacibile. Ad esempio abbiamo che true valida mentre f alse non soddisfacibile.
Le formule della logica proposizionale, se da un lato consentono di specificare diverse
propriet che lo stato di un sistema pu soddisfare, dallaltro non sono particolarmente adatte
per descrivere il cambiamento di queste propriet nel tempo quando il sistema transisce da
uno stato ad un altro. Non per esempio possibile esprimere, attraverso formule delle logiche
proposizionali, propriet del tipo dopo aver eettuato una certa azione lo stato del sistema
verifica la propriet '.
Per trattare propriet di questo tipo si possono usare le logiche modali.
13.3
Nelle logiche proposizionali ogni evento si intende riferito allistante presente del tempo. Proposizioni come file_eliminato vengono interpretate secondo il significato il file stato eliminato
adesso. Per poter introdurre il concetto di tempo e disporre degli strumenti per definire un
ordinamento tra gli istanti di tempo considerati, nelle logiche modali1 si introduce un insieme
R di relazioni binarie i cui elementi R 2 R sono relazioni di transizione tra stati. Ogni relazione R pu essere etichettata associando ad ogni suo elemento lazione che causa il passaggio da
uno stato allaltro. Nel caso in cui R sia etichettata, linsieme AP delle proposizioni atomiche
pu non esserci; questo il caso della logica HML che vedremo nella sezione successiva.
Loperatore principale delle logiche modali che consente di riferirsi ad istanti successivi
del tempo diamond, scritto hRi'. Il significato di hRi' che esiste un qualche stato in
relazione R con quello attuale nel quale la propriet ' verificata. Loperatore duale di
diamond, che prende il nome di box, scritto [R]', significa che in qualunque stato in relazione
R con quello attuale la propriet ' verificata. In pratica, loperatore diamond consente
di definire propriet di possibilit ( possibile arrivare in uno stato nel quale verificata la
propriet espressa dalla formula '), mentre loperatore box consente di definire propriet di
necessit (tutti gli stati in relazione R con quello attuale soddisfano la propriet ').
Se aggiungiamo alla logica proposizionale le due modalit di cui sopra, otteniamo la logica
modale proposizionale la cui sintassi delle formule definita dalla grammatica seguente:
' ::= true
AP
'
' 1 _ '2
'1 ^ '2
hRi'
[R]'
Per formalizzare la semantica della logica modale nel corso del tempo sono stati proposti
molti modelli dierenti. A noi qui interessa la semantica basata su strutture di Kripke. La
relazione di soddisfazione, indicata con il simbolo |=, in questo caso una relazione ternaria
tra una struttura di Kripke K , hQ, R, AP, I i, uno stato q 2 Q e una formula modale '. Per
convenienza notazionale, ometteremo K quando chiaro dal contesto. Quindi, la relazione |=
definita per induzione sulla sintassi delle formule dalle regole seguenti:
q |= true;
1
q |= p sse q 2 I(p);
La logica modale risale ad Aristotele, che la utilizz per studiare i concetti di possibilit e necessit.
306
Alcuni degli operatori sono derivati nel senso che potrebbero essere eliminati senza che
ci influisca sul potere espressivo della logica (li abbiamo posti nella sintassi di base per
comodit). Potremmo porre per definizione
'1 ^ '2 , ('1 _ '2 )
[R]' , hRi'
e derivare la semantica delle formule '1 ^ '2 e [R]' da quella degli altri operatori della logica.
Nel caso del secondo operatore, possiamo procedere come mostrato di seguito:
q |= [R]'
, q |= hRi'
per definizione di [R]
, (9q 0 2 Q tale che hq, q 0 i 2 R e q 0 |= ') per la semantica di hRi
, 8q 0 2 Q tale che hq, q 0 i 2 R vale q 0 |= '
per la semantica di
Le logiche modali hanno una espressivit limitata, puramente locale. Infatti, la verit
di una formula modale di lunghezza n in un modello dipende solo dagli stati a distanza
al pi n dallo stato inizialmente considerato per interpretare la formula. Pertanto, la logica
modale troppo debole per esprimere molte delle propriet desiderabili dei sistemi informatici
che abbiamo accennato nellintroduzione di questo capitolo. Per ottenere la possibilit di
esprimere propriet globali, sono necessarie logiche pi potenti, quali quelle temporali.
13.4
La logica HML
HML (Hennessy-Milner Logic [HM85]) una logica modale e quindi permette di descrivere
capacit locali dei sistemi. La principale caratteristica che distingue HML dalle logiche modali
proposizionali presentate nella sezione precedente risiede nel fatto che le relazioni di transizione
R 2 R sono etichettate con le azioni, appartenenti ad un certo insieme A, che causano il
passaggio da uno stato allaltro. Questo comporta che possiamo fare a meno di AP e di
conseguenza il dominio di interpretazione delle formule della logica passa da KS a LTS. Nel
seguito, supporremo che i LTS hQ, A, !i usati per interpretare le formule HML (ma anche
quelle di ACTL in Sezione 13.6) soddisfano la seguente propriet
a
8q 2 Q, 9q 0 2 Q, 9a 2 A tali che q ! q 0 ,
cio ogni stato ha almeno un successore, quindi i cammini in una tale struttura sono infiniti.
Dato un insieme A di azioni (con , 2 A), la sintassi delle formule HML definita dalla
grammatica seguente:
' ::= true
'
'1 _ '2
' 1 ^ '2
<> '
[]'
307
m>
Uno stato soddisfa questa formula se pu eseguire la sequenza 1 . . . m e arrivare in uno stato
che rifiuta le oerte di interazione che coinvolgono le azioni 1 . . . n . Quindi, in un ambiente
capace prima di eseguire la sequenza 1 . . . m e poi di richiedere uninterazione che coinvolge
unazione tra le 1 . . . n , lo stato considerato potrebbe andare in deadlock.
Come abbiamo gi detto nella sezione precedente, alcuni degli operatori sono derivati
nel senso che potrebbero essere eliminati senza che ci influisca sul potere espressivo della
logica (li abbiamo posti nella sintassi di base per comodit). Potremmo porre per definizione
'1 ^ '2 , ('1 _ '2 )
308
309
I due operatori modali diamond e box possono essere indeboliti in modo da poter analizzare solo le azioni osservabili, ignorando le azioni interne. Si ottiene cos la variante weak
di HML. Quindi, prendendo un insieme di azioni qualsiasi ma contenente lazione interna ,
cio A [ { }, la sintassi delle formule di weak HML definita dalla grammatica seguente:
' ::= true
'
'1 _ '2
'1 ^ '2
'
'
[[]]'
[[ ]]'
dove 2 A (cio 6= ).
Intuitivamente, il significato dei nuovi operatori modali il seguente.
' (weak-diamond -): esiste un -discendente dello stato corrente che soddisfa '.
' (weak-diamond ): esiste una computazione dallo stato corrente formata da sole
azioni interne che porta in uno stato che soddisfa '.
310
Formalmente, poich weak HML astrae dalle azioni interne che un sistema pu eettuare,
la sua interpretazione va definita su un LTS il cui insieme di azioni contiene lazione interna ,
cio un LTS della forma hQ, A[{ } , !i. Quindi, la relazione di soddisfazione |= che determina
la semantica delle formule definita per induzione sulla loro sintassi dalle regole seguenti
(mostriamo solo la semantica dei nuovi operatori, poich quella degli altri non cambia):
q |=
[[]]
Si possono anche utilizzare abbreviazioni simili a quelle definite per HML. A dierenza del
caso di HML, K denota il complemento di K rispetto allinsieme A (che non contiene lazione
).
Weak HML pi debole di HML poich, ad esempio, non in alcun modo capace di
esprimere loperatore <> , cosicch una formula non pu in alcun modo far riferimento alle
azioni interne (al contrario, tutti gli operatori di weak HML possono essere espressi in HML).
Per quanto riguarda i rapporti con le equivalenze comportamentali, possibile dimostrare che
lequivalenza indotta da weak HML coincide con la bisimilarit debole (sempre a condizione
che i LTS considerati siano image-finite), cio vale un teorema di corrispondenza simile a
quello tra HML e bisimilarit forte (anche questo non lo dimostreremo).
Teorema 13.5. Sia hQ, A, !i un LTS image-finite. Allora, per ogni p, q 2 Q, p W HM L q
se e solo se p q.
Dimostrazione.
Ci quindi implica che anche se ignora le computazioni interne, la bisimilarit debole (e
quindi anche lequivalenza osservazionale) gode ancora di un grado di sensibilit al deadlock
simile a quello della bisimilarit forte. A questo proposito consideriamo i due processi CCS
A , a.b.c.nil + a.b.d.nil e B , a.(b.c.nil + b.d.nil). Sappiamo gi che questi due processi non
sono in relazione tra loro; infatti, la formula [[a]]b c true soddisfatta da B e non
da A.
311
13.5
Logiche temporali
Le logiche temporali sono pi espressive delle logiche modali ma non richiedono il background
matematico necessario per capire ed apprezzare le definizioni ricorsive che sono alla base
dellespressivit del -calculus modale (che vedremo nella Sezione 13.8). Le logiche temporali
si occupano di concetti come sempre, mai, qualche volta, . . . . Costituiscono una branca
della logica di origine antica, ma solo negli anni 50 sono state studiate matematicamente,
a cominciare dal lavoro di Prior [Pri57]. Negli anni 70 sono state applicate alla verifica di
correttezza dei sistemi informatici, a cominciare dal lavoro di Pnueli [Pnu77].
Esistono vari aspetti da considerare per definire un modello matematico del tempo: lineare o ramificato, discreto o continuo, finito o infinito, unidirezionale o bidirezionale, . . . .
Come abbiamo visto nella prima sezione di questo capitolo, lalternativa tra tempo lineare e
ramificato genera due possibilit egualmente interessanti. Il tempo si dice lineare se in ogni
istante il sistema pu evolvere in un solo modo nellistante successivo; levoluzione si ragura
quindi su una linea retta. Invece, il tempo si dice ramificato se in ogni istante, il sistema
pu evolvere in molti modi, in questo caso levoluzione si rappresenta con un albero. Per
quanto riguarda gli altri aspetti, le scelte sono dettate dal fatto che lo scopo fare previsioni
sul comportamento futuro di un sistema. Pertanto, le logiche temporali specializzate per la
verifica di sistemi che presenteremo fanno tutte le seguenti assunzioni:
il tempo discreto: tra un istante e laltro, si hanno solo un numero finito di istanti
intermedi;
il tempo infinito nel futuro e finito nel passato: c un primo istante ma non un ultimo;
il tempo fluisce dal passato al futuro: siamo interessati a cosa accadr nel futuro.
Infine, si tenga presente che lespressivit di molte logiche temporali linear e branching
time non confrontabile. Ci significa che ci sono propriet esprimibili in una logica lineare
che non possono essere espresse in una branching, e viceversa. Inoltre, anche le tecniche per
il model checking di queste due classi di logiche sono solitamente piuttosto dierenti.
312
...
AP
'
'1 _ '2
'1 ^ '2
'1 U+ '2
La relazione di soddisfazione, indicata con il simbolo |=, in questo caso una relazione
ternaria tra una struttura di Kripke K , hQ, R, AP, I i, un cammino in K (si veda la
Definizione 3.14) e una formula LTL '. Per convenienza notazionale, ometteremo K quando
chiaro dal contesto. Quindi, la relazione |= definita per induzione sulla sintassi delle formule
di LTL dalle regole seguenti:
|= true;
|= p sse q0 0 e q0 2 I(p);
|= ' sse non vero che |= ';
|= '1 _ '2 sse |= '1 oppure |= '2 ;
|= '1 ^ '2 sse |= '1 e |= '2 ;
|= '1 U+ '2 sse 9i > 0 tale che i |= '2 e per ogni 0 < j < i vale j |= '1 .
In LTL, alcuni importanti operatori temporali, quali neXt X, Future F e Global G, possono
essere derivati utilizzando loperatore U+ come mostrato di seguito. possibile innanzitutto
definire un operatore, detto Until riflessivo, che tenga anche conto dello stato attuale. Tale
operatore, indicato con U , definito come segue:
'1 U '2 , '2 _ ('1 ^ ('1 U+ '2 )).
La dierenza sostanziale con la formula '1 U+ '2 , che anch '1 U '2 sia vera, '1 deve
valere anche nello stato attuale oppure '2 devessere subito vera. Graficamente loperatore
illustrato in Figura 13.2. Utilizzando gli operatori Until possiamo porre:
X ' , f alse U+ ';
F+ ' , true U+ ';
F ' , true U ';
G' , (true U ').
X detto neXt in quanto, anch la formula X ' sia verificata, ' deve valere in uno stato
immediatamente successivo a quello attuale, cio raggiunto con un solo passo di transizione.
F invece viene chiamato Future in quanto ci consente di esprimere il fatto che la formula
' varr prima o poi in qualcuno degli stati successivi, cio raggiunti nel futuro: un futuro
313
...
AP
'
'1 _ ' 2
'1 ^ '2
E ('1 U+ '2 )
A ('1 U+ '2 )
Come si pu notare, i quantificatori possono solo essere seguiti da formule che utilizzano
loperatore Until.
La relazione di soddisfazione, indicata con il simbolo |=, in questo caso una relazione
ternaria tra una struttura di Kripke K , hQ, R, AP, I i, un albero delle computazioni in
K (si veda la Definizione 3.15) e una formula CTL '. Se per semplicit omettiamo K ed
identifichiamo un albero con la sua radice, le clausole che definiscono la semantica delle formule
con i quantificatori la seguente:
314
315
non possibile esprimere il fatto che in qualche cammino una certa propriet ' vale in tutti
gli stati in posizione pari. I limiti del potere espressivo di CTL motivano lintroduzione di
logiche pi potenti quali il -calculus modale, che sar presentato nella Sezione 13.8.
13.6
La logica ACTL
ACTL (Action-based Computation Tree Logic [DV90]) una logica temporale di tipo branching time derivata da CTL. Il nome della logica dovuto al fatto che le formule fanno
specifico riferimento alle azioni che il sistema in esame pu compiere. Grazie a questa sua
caratteristica ACTL consente di descrivere in maniera semplice ed intuitiva le propriet di un
sistema. Le formule di ACTL sono costruite usando i quantificatori di cammino 8 ed 9 (per
descrivere la struttura ramificata dellalbero delle computazioni) e gli operatori temporali X
ed U (per descrivere le propriet di un cammino nellalbero).
8 corrisponde allespressione per tutti i cammini di computazione, quindi la propriet
che segue questo quantificatore deve valere in ogni sequenza di azioni a partire dallo
stato corrente.
9 corrisponde allespressione per qualche cammino di computazione, quindi la propriet
che segue questo quantificatore deve valere almeno in una sequenza di azioni a partire
dallo stato corrente.
X loperatore neXt: corrisponde allespressione next time, quindi la formula che
segue questo operatore deve valere nello stato successivo del cammino che si sta
analizzando.
U loperatore Until : prende in input due formule e indica che esiste uno stato q nel
cammino che si sta analizzando in cui vale la seconda formula, ma in tutti gli stati che
precedono q vale la prima formula.
Formalizziamo ora la struttura della logica ACTL. Per rendere pi comprensibile la sintassi delle formule ACTL scomponiamo la sua definizione distinguendo tre categorie sintattiche:
formule di stato, formule di cammino e formule di azione. Come si detto la logica parametrizzata rispetto ad un insieme di azioni A [ { }; nel seguito, supporremo che 2 A. La
sintassi delle formule di ACTL quindi definita dalla grammatica seguente:
formule di stato ' ::= true
formule di cammino
formule di azione
::= X '
::=
'
X '
' _ '0
' U
0
0'
' U '0
Si noti che nelle formule di stato ogni operatore temporale preceduto da un quantificatore
di cammino.
Una formula di azione individua un insieme di azioni visibili, che sono appunto quelle che
la soddisfano. A volte useremo le formule derivate true, che sta per _ , per indicare
linsieme di tutte le azioni visibili, e f alse, che sta per true, per indicare linsieme vuoto di
azioni visibili.
Una novit importante che distingue la logica ACTL dalla logica CTL che, sebbene
anche questultima avesse delle formule di cammino, in ACTL ad ognuna di queste viene
316
b1
b2
...
bn
...
b1
b2
...
bn
...
dove b1 |= , . . . , bn |= e a |=
Per formalizzare la semantica della logica ACTL, definiamo tre relazioni di soddisfazione,
indicate con il simbolo |=, una per ogni diversa tipologia di formule. Infatti, dato un LTS
S = hQ, A [ { } , !i avente lo stesso insieme di azioni visibili A assunto per ACTL, le formule
di stato vanno interpretate rispetto ad uno stato q 2 Q, quelle di cammino rispetto ad un
cammino 2 P ath(q) (si veda anche la Definizione 3.10), e quelle di azione rispetto ad
unazione 2 A. Le relazioni |= sono definite come al solito per induzione sulla sintassi delle
formule ACTL dalle regole seguenti:
q |= true;
q |= ' sse non vero che q |= ';
q |= ' _ '0 sse q |= ' oppure q |= '0 ;
q |= 9 sse 9 2 P ath(q) tale che |= ;
q |= 8 sse 8 2 P ath(q) si ha |= ;
|= X ' sse = (q, , q 0 ), q 0 |= ' e |= ;
|= X ' sse = (q, , q 0 ) e q 0 |= ';
317
|= ' U 0 '0 sse 9i > 0 tale che [i + 1] |= '0 , [i] |= ' e i |= 0 , dove i
([i], i , [i + 1])i+1 , e 8j : 0 j < i abbiamo [j] |= ' e j |= oppure j , dove
j ([j], j , [j + 1])j+1 ;
|= ' U '0 sse 9i > 0 tale che [i] |= '0 e 8j : 0 j < i abbiamo [j] |= ' e j |=
oppure j , dove j ([j], j , [j + 1])j+1 ;
|=
sse ;
sse |=
_ |=
0.
I due operatori temporali standard Future e Global in ACTL possono essere derivati come
mostrato di seguito.
F ' , truetrue U ' (prima o poi nel futuro) asserisce che ' varr in qualche stato
successivo del cammino considerato. Infatti, qualsiasi stato soddisfa true e qualsiasi
azione visibile soddisfa true.
G' , F ' (sempre) asserisce che ' vale in ogni stato del cammino considerato
(infatti, letteralmente la formula asserisce che non possibile che prima o poi lungo il
cammino analizzato si arrivi in uno stato che non soddisfa ').
Vediamo ora alcuni esempi di formule ACTL.
9X true: esiste un cammino la cui prima azione silente.
8X true: tutti i cammini dallo stato corrente iniziano con lazione .
9(true U f alse): esiste un cammino infinito di sole azioni e .
Saf ety(') , 8G': non si arriva mai in uno stato in cui vale la condizione '.
Liveness(') , 8F ': in ogni cammino, prima o poi si arriva in uno stato in cui vale '.
318
Si potrebbe dimostrare che la formula caratteristica del sistema implica ciascuna delle
propriet suddette.
13.7
Come abbiamo accennato alla fine della Sezione 13.3, lespressivit delle formule modali
assai limitata. Queste infatti consentono di esprimere propriet che descrivono comportamenti
finiti di un sistema sistema, mentre si visto che una delle caratteristiche principali dei sistemi
reattivi quella di avere comportamenti infiniti. Tale limitazione deriva del fatto che ogni
operatore delle logiche modali consente di studiare le evoluzioni del sistema limitatamente ad
un passo di esecuzione, per questo, e per il fatto che si possono prendere in considerazione
solamente formule di lunghezza finita, gli unici comportamenti analizzabili sono quelli con
un numero finito di azioni. Una misura per esprimere quanto a fondo il comportamento di
un sistema pu essere studiato utilizzando delle formule modali costituita dalla cos detta
profondit modale (modal depth) della formula. Questa definita come il massimo livello di
annidamento degli operatori modali allinterno di una formula. Ad esempio, se si considera
la formula hai[b]true _ hcitrue la profondit modale pari a due; verificare se un processo
soddisfa o meno la formula comporta dunque lanalisi di comportamenti del sistema costituiti
da sequenze di azioni che possono avere una lunghezza massima pari a due.
Per poter esprimere propriet legate al tempo, quali il sistema pu sempre eettuare una
certa azione, abbiamo introdotto le logiche temporali. Una prima alternativa per rendere le
logiche modali capaci di esprimere propriet infinitarie potrebbe essere quella di introdurre
la possibilit di definire congiunzioni e disgiunzioni infinite. Per esempio, consideriamo il
processo CCS C , a.C. C pu sempre (in ogni punto della computazione) eseguire unazione
a, cio la formula <a> true uninvariante. Chiamiamo questa propriet Inv(<a> true);
potremmo esprimerla in HML nel modo seguente:
Inv(<a> true) , <a> true ^ [a] <a> true ^ [a][a] <a> true ^ . . .
1
^
=
[a]i <a> true
i=0
La formula pu essere interpretata cos: anch un processo sia sempre capace di eseguire
unazione a, tale azione devessere possibile subito (come espresso dalla sottoformula <a>
true) e, per ogni i 0, in ogni stato che il processo pu raggiungere eseguendo una sequenza
di i azioni (come espresso dalla sottoformula [a]i <a> true, dal momento che a lunica
azione del nostro sistema).
Come altro esempio, consideriamo il processo CCS D , a.D + a.nil. D pu terminare
in qualsiasi momento o, equivalentemente, sempre possibile transire in uno stato in cui la
319
formula [a]f alse vera. Chiamiamo questa propriet P os([a]f alse); potremmo esprimerla in
HML nel modo seguente:
P os([a]f alse) , [a]f alse _ <a> [a]f alse _ <a><a> [a]f alse _ . . .
1
_
=
<a>i [a]f alse
i=0
[[']] = Q \ [[']]
[['1 ^ '2 ]] = [['1 ]] \ [['2 ]]
[[[]']] = [][[']]
<> E = q 2 Q | 9q 0 2 Q : q ! q 0 e q 0 2 E
n
o
[]E = q 2 Q | 8q 0 2 Q : q ! q 0 si ha q 0 2 E
Quindi, formalmente, la notazione ' '0 indica che [[']] = [['0 ]].
naturale allora aspettarsi che un insieme E di stati che soddisfa la formula (13.1)
dovrebbe essere tale che
E <> Q \ []E
320
(13.2)
321
Until debole: '1 vale in tutti gli stati di una computazione finch non si raggiunge uno
stato in cui vale '2 (ma ci potrebbe non succedere mai):
X.('2 _ ('1 ^ [ ]X))
Questi sono esempi di propriet temporali; quindi la logica che si ottiene in questo modo
temporale. Difatti HML con ricorsione ha un potere espressivo simile al -calculus modale (si
consulti [AILS07] per approfondimenti), il quale in grado di descrivere qualsiasi operatore
standard delle logiche temporali.
13.8
Il -calculus modale
Il -calculus modale [Koz83] si ottiene aggiungendo alla logica modale gli operatori di massimo
e minimo punto fisso, ovviamente insieme a variabili di punto fisso. Nella nostra presentazione
la logica modale di base ottenuta prendendo alcuni operatori di HML e di weak HML su un
insieme A [ { } di azioni. Lutilit degli operatori di minimo e massimo punto fisso deriva
dal fatto che molti concetti della logica temporale possono essere descritti come punti fissi
di certe funzioni su insiemi di stati dei modelli usati per le formule. Perci, nel -calculus
modale si possono esprimere anche propriet temporali. Ad esempio, stato dimostrato che
ogni formula di CTL , e quindi di CTL, ha una formula corrispondente nel -calculus.
La sintassi delle formule del -calculus modale definita dalla grammatica seguente:
' ::= true
'
' _ '0
<> '
'
Z.'
Una formula si dice ben-formata se ogni sottoformula della forma Z.' tale che la variabile
Z positiva (cio ogni occorrenza di Z compare sotto un numero pari di simboli di negazione)
in '. Tale restrizione garantisce la monotonia ed necessaria perch le formule non positive
possono dare luogo a funzioni insiemistiche senza punti fissi (ad esempio, la funzione negazione
F definita da F (X) = X non ha punti fissi nellinsieme potenza di un qualunque insieme
non vuoto). Una formula si dice chiusa se non contiene variabili libere, dove lunico operatore
legante Z..
Altri operatori ed abbreviazioni possono essere definiti come abbiamo gi fatto per HML
e weak HML.
Per definire la semantica delle formule chiuse e ben-formate conviene usare un approccio
basato sulla semantica denotazionale ed associare ad ogni formula ben-formata ' il sottoinsieme [[']] degli stati che soddisfano '. Le formule del -calculus sono interpretate sugli stati di
un generico LTS S = hQ, A [ { } , !i. Questa semantica, che pu essere definita al solito per
induzione sulla sintassi delle formule, in eetti non molto diversa da quella presentata per
HML con ricorsione nella sezione precedente. Tutti i casi sono semplici; lunica dicolt sta
nel definire la semantica di una formula ricorsiva del tipo Z.'. Nello specifico, una formula '
(che pu contenere una variabile Z) interpretata come una funzione [[']] : 2Q ! 2Q che, dato
un insieme E Q che si suppone soddisfi Z, restituisce linsieme degli stati che soddisfano '.
[[true]](E) = Q
[['1 _ '2 ]](E) = [['1 ]](E) [ [['2 ]](E)
[[<> ']](E) =<> [[']](E)
[[Z]](E) = E
[[']](E) = Q \ [[']](E)
[['1 ^ '2 ]](E) = [['1 ]](E) \ [['2 ]](E)
[[ ']](E)
T = [[']](E)
[[Z.']] = {E Q | [[']](E) E}
322
<> E 0 = q 2 Q | 9q 0 2 Q : q ! q 0 e q 0 2 E 0
n
o
E 0 = q 2 Q | 9q 0 2 Q : q =
) q0 e q0 2 E 0
che Z implicitamente dato da una equazione ricorsiva in Z della forma Z = '. Come
abbiamo visto nella sezione precedente, una tale equazione pu essere interpretata come une Ora, poich [[']] una funzione monotona su un cpo,
quazione su insiemi di stati Z = [[']](Z).
ha soluzione, cio ammette punti fissi. In particolare,
sappiamo che lequazione Z = [[']](Z)
il teorema del punto fisso ci dice che
1. [[']]
T ha minimo punto fisso dato dallintersezione dei punti pre-fissi:
{E Q | [[']](E) E};
2. [[']]
S ha massimo punto fisso dato dallunione dei punti post-fissi:
{E Q | E [[']](E)}.
La semantica di Z.', che per definizione il minimo punto fisso della funzione [[']], pertanto
ben definita.
La teoria del punto fisso dice inoltre che se la funzione associata a ' monotna, la
seguente una catena di approssimanti del minimo punto fisso:
'0 = f alse
Inoltre, in generale
lestremo superiore della catena strettamente minore del minimo
S1
S1 punto
fisso (cio, i=0 'i Z.'); ma se la funzione associata a ' continua si ha che i=0 'i =
Z.'. In pratica, ci vuol dire che la formula Z.' pu essere interpretata nel modo seguente
Z.' '0 _ '1 _ '2 _
Per dualit possiamo porre Z.' , Z.'[Z/Z]. Come conseguenza di questa definizione, si pu dimostrare che la semantica della formula Z.' il massimo punto fisso della
funzione corrispondente a ', cio
[
{E Q | E [[']](E)} .
La teoria del punto fisso dice inoltre che se la funzione associata a ' monotna, la seguente
una catena di approssimanti del massimo punto fisso:
'0 = true
323
i=0 '
i.
seguente
In pratica, ci vuol dire che la formula Z.' pu essere interpretata nel modo
Z.' '0 ^ '1 ^ '2 ^
Si osservi infine che se Q finito, diciamo che formato da k elementi, ogni funzione
monotna continua ed inoltre ogni catena dopo al pi k elementi si stabilizza, cio diventa
costante. Di conseguenza, il k-esimo elemento di una catena di approssimanti coincide con il
punto fisso corrispondente.
Con gli operatori di minimo e massimo punto fisso si pu esprimere la capacit di svolgere
un comportamento nel futuro o di ripeterlo continuamente. In particolare, il costruttore di
minimo punto fisso utile per esprimere propriet di eventualit forte (prima o poi avviene
una data condizione), mentre quello di massimo punto fisso utile per esprimere propriet di
invarianza nel tempo (un certo comportamento si verifica in ogni stato indicato). Le formule
del -calculus possono diventare dicili da comprendere al crescere della loro lunghezza;
una euristica che pu aiutare a comprenderne il significato consiste nel vedere le formule
dinamicamente, come ricerche di stati con certe propriet svolte muovendosi lungo gli archi
del grafo delle transizioni che rappresenta il modello. Loperatore dice che la ricerca deve
terminare, mentre loperatore dice che la ricerca non deve necessariamente terminare.
Esempi di questa euristica sono i seguenti.
Z.(' _ < > Z) indica che la propriet ' vale inizialmente oppure dopo aver fatto
qualunque altra sequenza di azioni. In altri termini la formula dice che deve esistere uno
stato accessibile da quello iniziale che gode della propriet '. In pratica corrisponde
alla formula temporale EF'. Infatti, partendo dallo stato in cui la formula valutata,
iteriamo la seguente verifica: se il punto corrente verifica ', abbiamo finito; altrimenti,
selezioniamo una direzione (infatti, il diamond modale significa che si sceglie una direzione) e continuiamo la ricerca in quella direzione. Il allinizio della formula dice che
la ricerca deve terminare, e lunico modo per terminare la ricerca trovare uno stato
in cui ' vale. Notiamo che la formula esprime una propriet di liveness: qualcosa di
buono, prima o poi, accadr.
Z.(' ^ [ ]Z) indica che la propriet ' vale inizialmente e dopo aver fatto qualunque
altra sequenza di azioni. In altri termini la formula dice che tutti gli stati accessibili
godono della propriet '. In pratica corrisponde alla formula temporale AG'. Infatti,
partendo dallo stato in cui la formula valutata, iteriamo la seguente verifica: se lo
stato corrente verifica ', abbiamo un fallimento; altrimenti, continuiamo la ricerca in
tutte le direzioni (infatti il box modale significa prendere tutte le direzioni). Notiamo
che la formula precedente esprime una propriet di safety: se la negazione ' di '
una propriet indesiderata, abbiamo che qualcosa di indesiderato non accadr mai.
Vediamo alcuni altri esempi di formule del -calculus.
[[ ]] <> true significa che ogni volta che si esegue una sequenza di azioni si va in uno
stato dove possibile eseguire .
[[]] < > ( true ^ [, ]f alse) significa che in ogni cammino che comincia con un
-discendente, c poi la possibilit di eseguire unazione per arrivare in uno stato in
cui esiste un -discendente e non si possono eseguire le azioni e .
324
Bibliografia
[AB84]
[AILS07]
Luca Aceto, Anna Ingolfsdottir, Kim G. Larsen, and Jiri Srba. Reactive Systems:
Modelling, Specification and Verification. Cambridge University Press, 2007.
[Bar84]
Henk P. Barendregt. The Lambda Calculus: Its Syntax and Semantics. Studies
in Logic 103, second, revised edition, North-Holland, Amsterdam, 1984.
[Bar90]
[BB87]
[BHH+ 06] Bernhard Beckert, Tony Hoare, Reiner Hhnle, Douglas R. Smith, Cordell Green,
Silvio Ranise, Cesare Tinelli, Thomas Ball, and Sriram K. Rajamani. Intelligent
systems and formal methods in software engineering. IEEE Intelligent Systems,
21(6):7181, 2006.
[BHR84]
[BK84a]
Jan A. Bergstra and Jan Willem Klop. The algebra of recursively defined processes
and the algebra of regular processes. In Jan Paredaens, editor, ICALP, volume
172 of Lecture Notes in Computer Science, pages 8294. Springer, 1984.
[BK84b]
Jan A. Bergstra and Jan Willem Klop. Process algebra for synchronous
communication. Information and Control, 60(1-3):109137, 1984.
[CE81]
Edmund M. Clarke and E. Allen Emerson. Design and synthesis of synchronization skeletons using branching-time temporal logic. In Dexter Kozen, editor,
Logic of Programs, volume 131 of Lecture Notes in Computer Science, pages 5271.
Springer, 1981.
[CGP99]
326
Bibliografia
[Chu41]
[DV90]
Rocco De Nicola and Frits Vaandrager. Action versus state based logics for transition systems. In Irene Guessarian, editor, Semantics of Systems of Concurrent
Processes, volume 469 of Lecture Notes in Computer Science, pages 407419.
Springer Berlin Heidelberg, 1990.
[Fok00]
[Gor79]
[Hen88]
[HM85]
Matthew Hennessy and Robin Milner. Algebraic laws for nondeterminism and
concurrency. J. ACM, 32(1):137161, January 1985.
[Hoa78]
[Hoa85]
[HP85]
[Koz83]
[Mil80]
[Mil89]
[Pnu77]
Amir Pnueli. The temporal logic of programs. In FOCS, pages 4657. IEEE
Computer Society, 1977.
[Pri57]
Arthur Norman Prior. The Logic of Time and Modality. Oxford University Press,
1957.
[Sch86]
[Sch99]
Steve Schneider. Concurrent and Real Time Systems: the CSP approach. John
Wiley & Sons, Ltd., 1999. Available at http://www.computing.surrey.ac.uk/
personal/st/S.Schneider/books/CRTS.pdf.
Prentice-Hall, 1985.
327
[Sco76]
[SM92]
Davide Sangiorgi and Robin Milner. The Problem of Weak Bisimulation up to.
In Rance Cleaveland, editor, CONCUR, volume 630 of Lecture Notes in Computer
Science, pages 3246. Springer, 1992.
[SW74]
Christopher Strachey and Christopher W. Wadsworth. Continuations: A Mathematical Semantics for Handling Full Jumps. Technical report, Tech.Monoghraph,
PRG-11, Oxford University, 1974.
[Win99]
[Win09]
Appendice A
Tabelle
A.1
Op
Significato
Regole
exit
exit
terminazione
Di base
(sinonimo: skip)
processo azione
chaos
chaos
chaos
exit ! stop
oppure
exit !
p
a
chaos ! stop
chaos ! chaos
Di sequenzializzazione
.
.E
azione prefissa
.E ! E
E; F
E ! E0
comp. sequenziale
o enabling
E; F ! E 0 ; F
( 6=
E ! E0
E; F ! F
[>
E [> F
disabling
E ! E0
E [> F ! E 0 [> F
( 6=
330
Appendice A Tabelle
F ! F0
E ! E0
E [> F ! F 0
E [> F ! E 0
Di scelta
+
E+F
scelta mista
o somma
scelta interna
E F
scelta esterna
E ! E0
F ! F0
E + F ! F0
E + F ! E0
F !E
F !F
E ! E0
E F ! E0
( 6= )
F ! F0
E F ! F0
( 6= )
E ! E0
F ! F0
E F ! E0 F
E F ! E F0
Di composizione parallela
E |F
comp. parallela
E ! E0
F ! F0
E | F ! E0 | F
E ! E0
E |F ! E |F0
F ! F0
E | F ! E0 | F 0
( 6= )
EkF
merge
E ! E0
E k F ! E0 k F
E ! E0
F ! F0
E k F ! E k F0
F ! F0
(, )
! E0 k F 0
EkF
ETF
|c
E |c F
|||
E ||| F
left merge
communication
merge
E ! E0
ETF ! E 0 k F
E ! E0 F ! F 0
E |c F
(, )
! E0 k F 0
interleaving
E ! E0
E ||| F ! E 0 ||| F
F ! F0
E ||| F ! E ||| F 0
331
|[L]|
E |[L]| F
comp. parallela
con interfaccia
E ! E0
E |[L]| F ! E 0 |[L]| F
( 2
/ L)
F ! F0
E |[L]| F ! E |[L]| F 0
E ! E0
( 2
/ L)
F ! F0
E |[L]| F ! E 0 |[L]| F 0
( 2 L)
EF
prodotto
E ! E0 F ! F 0
! E0 F 0
EF
Di astrazione
E\L
restrizione
abilitazione
E ! E0
(,
2
/ L)
E\L ! E 0 \L
E ! E0
E
L ! E0
( 2 L _
2 L _ = )
H (E)
encapsulation
E ! E0
H (E)
H (E
( 62 H)
E/L
hiding
E ! E0
E/L ! E 0 /L
( 62 L)
E ! E0
E/L ! E 0 /L
[f ]
E[f ]
Rietichettatura
o relabelling
( 2 L)
E ! E0
E[f ]
f ()
! E 0 [f ]
A,P
costanti
di processo
E ! E0
A ! E0
(A , E)
rec x
rec x.E
ricorsione
E{rec x.E/x} ! E 0
rec x.E ! E 0
332
Appendice A Tabelle
replicazione
!E
E ! E0
E| ! E ! E 0
oppure
!E ! E 0 | !E
! E ! E0
input
e.E
output
! E{v/x}
comunicazione
di valori
!E
(v)
! E0
(e espressione)
val(e)
e.E
E |F
! F0
E | F ! E0 | F 0
E ! E0
if e then E else F
(v valore)
(v)
(x).E
(v valore)
val(e) = true
if e then E else F ! E 0
F ! F0
val(e) = f alse
if e then E else F ! F 0
A.2
(e espressione)
(e espressione)
.E
E\L
E[f ]
E1 + E2
E1 |E2
recX.E
:E
E1 + E2
E1 E2
recX.E
skip
E1 E2
a!E
E1 k E2
E\L
E[f ]
E1 ||| E2
E1 ; E2
E1 |[L]| E2
E1 u E2
333
E1 TE2
E1 | c E2
exit
E1 + E2
; E
E1 k E2
E/L
E[f ]
E1 ||| E2
E1
E2
E1 |[L]| E2
E1 [> E2
A
denota