Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Informatica teorica
Seconda edizione
CilWStudi
EDIZIONI
Indice
485 Bibliografia
497 Indice analitico
Capitolo 1
GLOSSARIO MATEMATICO
Una relazione n-aria, o di arità n, R sugli insiemi _¥b ..., Xn è un sotto insieme di
Xi X ... XX„. La notazione 7?(xb ...,x„) è usata talvolta al posto della
(xb ...,Xi) e R. In questo caso si dice che R vale per la w-upla (xb ...,xf. Una
relazione 1-aria è detta anche proprietà. Sia P una proprietà definita su un dato
insieme X: la notazione {x | P(x)} indica l’insieme formato da tutti gli elementi
x e X tali che la proprietà P valga per x.
Una relazione 2-aria è detta anche relazione binaria. Se R è una relazione
binaria, la notazione infissa xRy può essere usata al posto della notazione prefìssa
R(x,y).
Data una relazione binaria R sugli insiemi X e Y, X è chiamato dominio di R e
Y è chiamato codominio di R. La relazione inversa R~' di R è l’insieme di tutte le
coppie ordinate (y, z) tali che (z, y) e R. Si consideri una relazione R £ X X X, per
la quale, cioè, X costituisca sia il dominio che il codominio; in questo caso si dice
che R è una relazione su X. R si dice riflessiva se xRx. R si dice simmetrica se xRy
implica yRx, mentre si dice transitiva se xRy e yRz implicano xRz. R si dice
irriflessiva se xRx non è mai valida, qualunque sia x, mentre si dice antisimmetrica
se xRy implica la negazione di yRx.
La chiusura transitiva e riflessiva R* di R, relazione binaria su X, è definita da
xR*y se e solo se esistono x0, xb ..., x„, con n > 0, tali che x0 = x, x„ =y e, per ogni
i, i = \,...,n, risulti X; flx.. Quindi, per ogni R vale la xR*x qualunque sia x. La
chiusura transitiva R+ e la A-esima potenza Rk di R vengono definite in modo
analogo a R*, con l’unica differenza che valgono rispettivamente le condizioni
n > 1 e n = k.
Una relazione binaria che sia riflessiva, simmetrica e transitiva è detta
relazione di equivalenza. Data una relazione di equivalenza R su un insieme X, e
preso un qualunque y, con v e L si definisce come l’insieme di tutte le z in X
tali che valga yRz. è detta classe di R-equivalenza di y. È facile verificare che
= lzfl se e s°l° se la relazione yRz è vera, e che, se [y]À [y]R, allora
[v]à n tzìx = 0, cioè che differenti classi di ^-equivalenza non hanno elementi in
comune. Quindi X è completamente suddiviso nelle sue classi di .^-equivalenza.
L’indice di R, indicato come indice(R), è il numero delle sue classi di equivalenza,
siano esse finite o infinite. Il simbolo R verrà omesso dalla notazione [x]ft quando il
contesto lo consentirà.
Gli ordinamenti riflessivi parziali su un insieme X sono relazioni riflessive,
antisimmetriche e transitive su X, mentre gli ordinamenti irriflessivi parziali sono
relazioni irriflessive, antisimmetriche e transitive sul. L’espressione “ordinamento
parziale” è usata sia per gli ordinamenti parziali riflessivi che per quelli irriflessivi.
Per ogni ordinamento parziale R, due elementi x, y e X, tali da non soddisfare le
relazioni xRy e yRx, vengono detti non comparabili o non confrontabili. Un
ordinamento (riflessivo) totale è un ordinamento (riflessivo) parziale che soddisfa,
per ogni x e y, o la relazione x = y, oppure una delle due relazioni: xRy, yRx.
Glossario matematico 5
Per ogni insieme X, la sua funzione identità Idx è definita come Idfx) = x per ogni
x g X. ,
Si considerino due funzioni: f.X^rY e g:L^Z. La loro composizione
g°fiX Z è definita dall’uguaglianza g °fix) = g(flx))1. Per ogni coppia di
funzioni/ g, l’espressione f = g indica che f e g sono identiche (ossia che sono la
medesima funzione), ossia che Df= Dg e fix) = g(x) per ogni x g Df. Si noti che
fix) = ± implica che g(x) = ± e viceversa. Se f è una biiezione tra X e Y, allora
jT1 o f= idx ef ° = Idy. Se/è una biiezione frale K egè unabiiezione tra Ye
Z, allora g° fè una biiezione fra X e Z.
Si definisce operazione «-aria (o operazione con n argomenti) su un insieme X
una funzione con dominio X1 e codominio X. Per convenzione, un’operazione
0-aria è un elemento fissato (o costante) di X.
Due insiemi X e Y si dicono equinumerosi (e si scrive X ~ Y), o aventi la
stessa cardinalità, se e solo se esiste una biiezione fra.Ye Y. Ovviamente si ha che
X™ X; X ™ Yimplica che Y » X, mentre f e f ~ Z implicano che X » Z. Se
X è equinumeroso ad un sottoinsieme di Y, ma Y non è equinumeroso ad alcun
sottoinsieme di X, si dice che la cardinalità di X è più piccola della cardinalità di Y.
Si dice che un insieme X è finito se e solo se è vuoto, o esiste un intero positivo
n tale che Xè equinumeroso all’insieme dei numeri positivi minori o uguali ad n. In
tal caso si dice che U ha cardinalità n. Un insieme che non sia finito è detto infinito.
Un insieme X è detto numerabile se e solo se è equinumeroso all’insieme M
dei numeri naturali, ossia all’insieme degli interi non negativi. Si dice che un
insieme numerabile ha cardinalità Ko- Ogni insieme equinumeroso all’insieme di
tutti i sottoinsiemi di un insieme numerabile, ha cardinalità 2*“ (detta anche
cardinalità del continuo). L’insieme potenza p(M) dell’insieme dei numeri naturali
N, e l’insieme di tutte le funzioni che vanno da N a se stesso, hanno cardinalità
2N° . Un insieme è detto contabile, o al più numerabile, se e solo se è finito o
numerabile. Ovviamente, ogni sottoinsieme di un insieme numerabile è contabile.
La scrittura indica la cardinalità dell’insieme X. Siano A e B due insiemi finiti;
la cardinalità dell’insieme di tutte le funzioni totali aventi come dominio A e come
codominio B è |5||X|.
Una sequenza numerabile è una funzione totale j avente per dominio l’insieme
dei numeri interi positivi (o non negativi); solitamente si scrive sn al posto di sin) e
l’argomento n viene chiamato indice di sn. Una sequenza finita è una funzione il cui
dominio è {1, 2, ...,n}, dove n è un intero positivo. Le sequenze finite e infinite
vengono indicate rispettivamente con {.s'i, s2, ■■■, sn} e {ó-i, .ss, Una
sottosequenza ss di una sequenza numerabile .$• = {.s'i, s2, ...} è una sequenza
{.y.s'i, ss2, ...} tale per cui, per ogni j, con j > 1, si verifichi che ss, = s, per qualche
z > 1, e, inoltre, le due relazioni ssj = sh ss,, = sf, con j > j , implichino che z > ì'.
Una sottosequenza di s = {sb sz, ...} è solitamente indicata con {s. , , ...}.
È importante notare che 2*“ è una cardinalità maggiore della No. Infatti 2N“ è
chiaramente non minore di Xo (esiste un’ovvia biiezione fra i numeri naturali e un
sottoinsieme di p(N)). Si supponga ora per assurdo che essi abbiano la stessa
cardinalità. Ciò implicherebbe l’esistenza di una biiezione
s: N-> p(N) = {s0, sb ...}. Si consideri adesso l’insieme DEH, costituito
esattamente da quei numeri n che non appartengono all’insieme sn 6 p(IN).
Formalmente ciò si esprime con la scrittura D = {n | n £ s„}. Servendosi della
Figura 1.1, si cerca ora di definire D; infatti si osserva che 0 g D se e solo se
0 & s0, mentre 1 e D se e solo se 1 ob ... D è un sottoinsieme di N, quindi
D g p(N). Deve dunque esistere un indice z per cui D = Sj (la successione s
enumera tutti i sottoinsiemi di N). Si considerino ora i due casi, distinti dalla
validità o meno della relazione z g st. Nel caso affermativo, poiché D = s{, i non
deve appartenere a in base alla definizione di D, il che è un assurdo.
Analogamente, nel caso negativo, z £ s, implica per definizione che z sia in D, cioè
in s,: di nuovo un assurdo. Quindi N e p(N) non sono equinumerosi.
Il ragionamento sopra esposto è detto diagonalizzazione (vedi Figura 1.1) ed è
dovuto a Cantor. Come si avrà modo di verificare in seguito, questa è una delle
tecniche fondamentali di dimostrazione impiegate nella teoria della computazione.
detto esplicitamente il contrario. In ogni lato orientato (v;, v7), v, viene chiamato
sorgente del lato, mentre v7 viene chiamato pozzo. Un grafo S-etichettato, sia
orientato che non orientato, è un grafo i cui lati vengono associati ad etichette
appartenenti ad un dato insieme S; quindi un lato è una coppia ((v,-, v7), /) quando
(v;, v7) è una coppia di vertici e l e S.
I grafi devono il loro nome alla rappresentazione grafica normalmente usata
per raffigurarli. In base ad essa, il grafo G = ({A, B, C, D, E}, {(A,B),
(B, A),(A, C), (C, E), (E, D), (D, A), (D, B)}) viene indicato come risulta in Figura
1.2. Se G fosse stato un grafo non orientato, avrebbe avuto, invece, la
rappresentazione di Figura 1.3, in cui, come si può notare, le frecce della Figura 1.2
sono state sostituite da lati non orientati e i due lati (A, B/ e (B, A) sono stati fusi in
un unico lato. Talvolta due nodi possono risultare connessi da più archi, nel qual
caso si parla di multigrafì. I multigrafi possono essere definiti formalmente per
mezzo di multiinsiemi dell’insieme degli archi.
Un cammino di lunghezza n, in un grafo, è una sequenza di lati del tipo
{(v0, uX (vi, vf, ..., v„)}. Due vertici v e v' si dicono connessi, o, in modo
equivalente, si dice che v' è raggiungibile da v, se e solo se esiste un cammino tale
che v = vq, v„ = v'. Per convenzione, un vertice v è sempre connesso a se stesso da
un cammino di lunghezza 0. Un ciclo (o cammino ciclico) è un cammino nel quale
v„ = v0- Due nodi di un grafo vengono detti adiacenti se e solo se risultano connessi
da un cammino di lunghezza 1, ossia se costituiscono la sorgente e il pozzo di un
medesimo lato. Un grafo orientato aciclico (DAG) viene definito come un grafo
orientato che non contiene cicli.
ESERCIZI
1.1 Si enumerino le prime dieci stringhe xb...,Xi0 di L7 in ordine crescente di
lunghezza, cioè in modo tale che 1 < i <j < 10 implichi |x;| < |x,|.
1.2 È vera l’uguaglianza L6* = V*?
1.3 Per ogni linguaggio L, è vero che (L*)* = L*?
1.4 Si dimostri che L7 = L9+ • L10 • Lio+, dove L9 = {ab}+, Lw = {c}. In forma
breve, per evitare parentesi inutili, L7 = (abf • c ■ c+.
1.5 Si dimostri che, per ogni alfabeto V, l’insieme dei linguaggi su V, ossia ।
p(F*), è un algebra Booleana se si pone < = £, u = u, n = n, —। = .
1.6 Si dimostri che la concatenazione è distributiva rispetto all’unione e
all’intersezione, ossia che, per ogni Lb L2,L3,(Li u L2)
• L3 — Li • L3 vj L2 • L3 e (Li o L2) * L3 — Li * L3 o L2 * L3.
Note bibliografiche
I concetti matematici richiamati in questo capitolo, con la eventuale eccezione della
sezione 1.5, sono trattati approfonditamente in ogni testo introduttivo sull’algebra.
Si menziona, fra tutti, il classico macLane Birkhoff (1970). La terminologia di base
della teoria dei linguaggi può essere reperita in ogni testo sui linguaggi formali,
come Hopcroft e Ullman (1969, 1979), Hopcroft, Motwani e Ullman (2006) e
Harrison (1978).
Capitolo 2
ELEMENTI ESSENZIALI DI LOGICA MATEMATICA
matematica, ma solo dare una visione introduttiva che fornisca al lettore quella
minima conoscenza di base indispensabile per comprendere il resto del libro.
Definizione 2.1
Una teoria formale ,‘JT è una quadrupla (.Sf TTTfsf \ dove
0 V u +
se...allora
se e solo se
Esempio 2. 1
Si consideri la proposizione composta “Lucia ha i capelli lunghi e Linda ha gli
occhi azzurri”. Se si indica con la lettera proposizionale A la proposizione “Lucia
ha i capelli lunghi” e con la lettera proposizionale B la proposizione “Linda ha gli
occhi azzurri”, l’intera proposizione può essere scritta in come A a B.
■
Formalmente, l’alfabeto del composto da:
- Lettere proposizionali, usualmente indicate da lettere latine maiuscole: A,
B,...;
- Connettivi: a, v, =>, <=>;
- Simboli ausiliari: ‘(’,
- Lettere proposizionali costanti: vero (T, o anche V o 1) e falso (±, o anche F o
0).
Definizione 2.2
- Ogni lettera proposizionale è una fbf;
- Se 24 e B sono fbf, (->24), (24 a B), (24 v B), (24 => B), (24 <=> B) sono fbf;
- Nient’altro è una fbf.
Elementi essenziali di logica matematica 21
Esempio 2.2
((-i (A a B)) o ( A^> (B v C))) è una fbf. Infatti:
- A, B e C sono lettere proposizionali, quindi sono fbf;
- Poiché A e B sono fbf, (A a B) è una fbf;
- Poiché B e C sono fbf, (B v C) è una fbf;
- Poiché (A a B) è una fbf, (—>(A a B)) è una fbf;
- Poiché A e (B v C) sono fbf, (A a> (B v C)) èuna fbf;
- Poiché (-.(A a B)) e (A =^> (B v C)) sono fbf, l’intera formula di partenza è
una fbf.
Esempio 2.3
Nella formula A =^> B =^> C, il primo =^> è applicato tra A e (B =^> C), quindi la
formula è un’abbreviazione per (A => (B =^> C)); diversamente, nella formula
A a B a C, il secondo a viene applicato fra (A a B) e C, cioè la formula è
equivalente a (A a B) a C e a ((A a B) a C ).
Esempio 2.4
Si consideri la formula ((—.(A a B)) « (A (Bv C))), presentata nell'Esempio
2.2. Non tutte le parentesi presenti in essa sono necessarie e la formula può essere
riscritta nella forma -.(A a B) o A => B v C. Infatti, v viene applicato prima di
=>, =^> viene applicato prima di <=^> e —. prima di Invece, le parentesi che
racchiudono A a B sono necessarie, poiché, senza esse, il connettivo —, sarebbe
applicato solo a A e non ad A a B.
22 Informatica teorica
Definizione 2.3
Una sottoformula è una parte di una fbf che è a sua volta una fbf.
Esempio 2.5
Si consideri nuovamente la formula. ->(A a B) <=> A => B, che verrà richiamata
come fi.
- -.(A a B) è una sottoformula di fi, poiché è contenuta in fi ed è una fbf;
- A v C non è una sottoformula di fi, perchè, anche se è una fbf, non è
contenuta in fi;
- o A =>Bv C non è una sottoformula di fi, infatti, anche se è contenuta in fi,
non è una fbf.
■
Data ima fbf, l’insieme di tutte le sue sottoformule può essere calcolato
ricorsivamente come segue.
Definizione 2.4
Data una formula J4, l’insieme delle sottoformule di J4, Stfin(JzL), è definito come
segue:
- Se J4 è ima lettera proposizionale A, Stfin(JzL)={ A} ;
- Se J4 è della forma —iS, Stfm(J4)={ J4}uStfin(2?);
- Se J4 è della forma 2? a C, B v C, B => C, B <=> C, Stfm(JzL) = {34} u
Stfin(S) o Stfin(Q.
Esempio 2.6
Considerando nuovamente la fbf fi e applicando la Definizione 2.4, si ottiene
Stfm(—i(A a B) o A => B v C) =
={->(A A B)« A=> B v C; u Stmf(->(A a B)) o Stmf(A x>BvC) = {-.(A a B)
« A => B v C, 4A a B), A a>B v C] u Stmf(A a B) u Stmf(A) u Stfin(B v C)
= {-.(A a B) <=> A=> B v C, ->(A a B), A => B v C, A a B, A, B v C} u Stmf(A)
o Stmf(B) o Stfm(C) =
={->(A a B) o A => B v C. -,(A a B), A => B v C, A a B, A, B v C, B, C }
Elementi essenziali di logica matematica 23
Si noti che ogni nodo può essere visto come la radice di un sottoalbero massimale
che rappresenta l’albero sintattico di una sottoformula.
Esempio 2.7
Definizione 2.5
L’interpretazione delle formule proposizionali è una funzione v>: {fbf.} {0,1}
che soddisfa le seguenti proprietà:
- o(l) = 0;
- o(T)=l;
- uGH) = l-u(JT);
- u(A?a 2B) = min(u(^f), o(.2));
- u(A?v 22} = max(u(l?), u(^);
- ^) = max(l-u(U?),u(^));
- u(A?aa 22} = min(max(l - u(^), u(^), max(u(_^), 1— o(_2))).
■
Informalmente, l’interpretazione assegna un valore di verità, vero (1) o falso (0), a
ogni lettera proposizionale, il valore vero (1) e falso (0) rispettivamente alle lettere
proposizionali costanti Tele valuta il valore di verità di ->J4, H a B, H v B,
H => B, H o B, sulla base dei valori di verità di H e B.
Esempio 2.8
Si consideri nuovamente la formula ^introdotta nella Sezione 2.2.1. Se A e C
sono entrambe vere (u(A) = u(C) = 1) e B è falso (u(B) = 0), il suo valore di verità
può essere calcolto utilizzando la Definizione 2.5 come segue:
u(-i(A aB)« A =>Bv C) = min(max(l - u(-,(A a B)), u(A =>B v C)),
max(u(-,(A a B)), 1 - u(A => B v C))).
Poiché,
u(-i(A a B)) = 1 - u(A a B) = 1 - min(u(A), u(B)) = 1 - min(l, 0) = 1 - 0
=1
u(A => B v C) = max(l - u(A), u(B v C)) = max(l - 1, max(u(B), u(C)))
= max(0, max(0,l)) = max(0, 1) = 1
diventa
v>(—i(A a B) o A => Bv C) = min(max(l - 1, 1), max(l,l - 1)) = min(l, 1)
=1
■
Un modo equivalente per calcolare il valore di verità di una fbf è quello di
utilizzare le tavole di verità, che mostrano come propagare il valore di verità delle
sottoformule attraverso i connettivi. La tavola di verità per il connettivo —। è
mostrata nella Tabella 2.2, mentre quelle dei connettivi binari sono rappresentate
nella Tabella 2.3.
Elementi essenziali di logica matematica 25
J4
0 1
1 0
J4 B B 24 v B .A > B 24 o B
0 0 0 0 1 1
0 1 0 1 1 0
1 0 0 1 0 0
1 1 1 1 1 1
Esempio 2.9
Il valore di verità della formula J- è dato dalla Tabella 2.4, in cui ogni riga
rappresenta una combinazione dei valori di verità delle lettere proposizionali A, B
e C e l’ultima colonna, riporata in grassetto, rappresenta il valore di verità
dell’intera formula.
■
In generale, l’interpretazione di una formula può essere vera o falsa a seconda dei
valori che vengono assegnati alle lettere proposizionali che la compongono.
Tuttavia, alcune formule possono essere valutate indipendentemente dal valore di
Definizione 2.6
Una fbf 34 è. soddisfacibile se esiste un’interpretazione u tale che u(34) = 1; in tal
caso u è chiamato modello di 34
■
Si noti che una formula è soddisfacibile se e solo se la sua tavola di verità contiene
almeno un 1. Il valore delle lettere proposizionali corrispondenti alla riga che
contiene un 1 rappresentano un modello della formula.
Definizione 2.7
Una fbf 34 è insoddisfacibile se nessuna interpretazione u è un modello di 34.
■
Una formula insoddisfacibile è spesso chiamata contraddizione e la sua tavola di
verità contiene solo 0.
Definizione 2.8
Una formula 34 è una tautologia se ogni interpretazione è un modello di 34 e si
indica con |= 34.
■
Una formula 34 è una tautologia se e solo se —.34 è insoddisfacibile. Infatti, quando
una formula è una tautologia, la sua tavola di verità contiene solo 1.
Le definizioni appena introdotte possono essere estese a insiemi di formule
come segue.
Definizione 2.9
Sia T un insieme di fbf
- Un modello di F è un’interpretazione che è un modello per tutte le formule in
F;
- Tè soddisfacibile se ha un modello;
- Tè insoddisfacibile se nessuna interpretazione è un modello per T.
Elementi essenziali di logica matematica 27
Esempio 2.10
Si consideri l’insieme di formule T={A, A=>B, B vC};F è soddisfacibile in
quanto ha almeno un modello: u(A) = u(B) = u(C) = 1.
■
Partendo dalla Definizione 2.8, si può introdurre il concetto di conseguenza
semantica e il teorema di deduzione semantica.
Definizione 2.10
Una fbf 24 è conseguenza semantica di f (o è implicata da E o è soddisfatta da T)
se ogni modello di T è un modello di 24; in tal caso si indica con r |= 24.
Esempio 2.11
Esempio 2.12
- Ipotesi: T |= B =f> A
Tesi: Tu {B} |=A
Sia u un modello di T u {B}, allora è un modello di T e u(B) = 1. Per ipotesi
u(B =f> A) = 1 e, poiché u(B) = 1, allora u(A) = 1.
■
JT e B si dicono logicamente equivalenti se J41= B e B |= JA Si scrive che
J4 = B per indicare che due formule sono logicamente equivalenti. Informalmente,
due formule sono logicamente equivalenti se hanno la stessa tavola di verità
Si noti che J4 = B se e solo se |= J4<=> B. Infatti, l’equivalenza logica è
l’interpretazione del connettivo se e solo se.
Sia J4 una fbf e sia B una sottoformula di JA Se B viene sostituita con una
formula B', tale che B = B', si ottiene una formula JA' tale che JA=JA Questo
significa che se si sostituisce una sottoformula di una formula data con una formula
equivalente (alla sottoformula sostituita), si ottiene una formula equivalente alla
formula originale.
Esempio 2.13
Se si sostituisce A B in C a ( A B) con —A v B, si ottiene
C a (—.A v B) s C a (A =f> B), poiché ~A v B = A =f> B.
■
Inoltre, se, in una tautologia JA si sostituiscono tutte le occorrenza di una lettera
predicativa A con una fbf B, si ottiene una nuova formula Jl’ che è ancora una
tautologia.
Di seguito viene riportata una lista di alcune equivalenze di base. Il lettore è
invitato a riflettere sul loro significato intuitivo.
- ^JA>JA
- JAaJA^JA;
Elementi essenziali di logica matematica 29
- 34 v 34 =34;
- 34. a B = B a 34. (Commutatività);
- 34. v B= 2? v 34. (Commutatività);
- (34.a S) a J4 a (2 a C) (Associatività);
- (34.v B) v C = 34. v (2? v C) (Associatività);
- 34. a (34. v B) = 34. (Assorbimento);
- 34. v (34. a B) = 34. (Assorbimento);
- 34a(Sv Q = (34a S) v(34a Q;
- 34v(Sa Q = (34v S) a(34v Q;
- —1(34. a B) = —134. v —12? (Legge di De Morgan);
- —1(34. v B) = ~34. a —<B (Legge di De Morgan);
- 34. => 2? =-.34, v 2?;
- 34. => S = ^(34.a-hS);
- 34<x> B = (34.=> B) a (S^34);
- 2vl = S;
- S = TaS.
Utilizzando le equivalenze, è possibile mostrare che ogni fbf può essere riscritta
usando solamente un insieme minimale di connettivi, che sono:
Definizione 2.11
Una fbf è in forma normale congiuntiva (FNC) quando è la congiunzione di una ò
più fbf, ciascuna delle quali è una disgiunzione di una o più lettere proposizionali o
della loro negazione.
■
Ad esempio, -A a (A v B v C) e (C v -A) a (B v C) a (A v -,B) sono in FNC.
Definizione 2.12
Una fbf è in forma normale disgiuntiva (FND) quando è la disgiunzione di una o
più fbf, ciascuna delle quale è una congiunzione di una o più lettere proposizionali
o della loro negazione.
■
Le fbf A v (B a C) v (-A a B a -.C) e (A a -nC) v (B a C) sono in FND.
Si noti che sia la forma normale congiuntiva sia la forma normale disgiuntiva
di una formula data non sono uniche, ma possono essere costruite in modo diverso.
Le forme normali possono essere costruite automaticamente attraverso
un’adeguata analisi delle tavole di verità. Precisamente, è possibile guardare agli 1
nella colonna che rappresenta il valore di verità della formula come alla
combinazione di valori delle lettere proposizionali (i valori che hanno nella riga)
che rendono la formula vera. Quindi, tutti gli 1 in una tabella di verità
corrispondono alle sole combinazioni di valori di verità delle lettere proposizionali
che rendono la formula vera. Sfruttando questa osservazione, è possibile partire
dalla tavola di verità di una fbf e costruire la formula equivalente in FND attraverso
la seguente procedura:
1. Per ogni 1 nella colonna della formula si costruisce una congiunzione che
contiene tutte le lettere proposizionali nella tabella
- in forma positiva, se, nella riga considerata, la colonna della lettera
contiene un 1 ;
- in forma negata, se, nella riga considerata, la colonna della lettera
contiene uno 0;
2. Si crea una formula in FND come disgiunzione delle formule costruite al
punto precedente.
Quando una formula contiene molti uno, è possible ragionare nel seguente modo:
uno 0 nella colonna della formula nella sua tavola di verità corrisponde a una
combinazione di valori delle lettere proposizionali (i valori cha assumono nella riga
corrispondente) che rende la formula falsa e, di conseguenza, tutti gli 0 in una
tabella di verità corrispondono alle sole combinazioni di valori di verità delle
lettere proposizionali che rendono la formula falsa, cioè le combinazioni non
desiderabili. Analogamente al caso della FND, questa osservazione può essere
Elementi essenziali di logica matematica 31
utilizzata per costruire una procedura, simmetrica al caso precedente, che permette
di costruire una formula in FNC a partire dalla sua tavola di verità:
1. Per ogni 0 nella colonna della formula si costruisce una disgiunzione che
contiene tutte le lettere proposizionali nella tabella
- in forma positiva, se, nella riga considerata, la colonna della lettera
contiene uno 0;
- in forma negata, se, nella riga considerata, la colonna della lettera
contiene uno 1 ;
2. Si crea una formula in FNC come congiunzione delle formule costruite al
punto precedente.
Esempio 2.14
ABC jzi
0 0 0 1
0 0 1 0
0 1 0 1
0 1 1 1
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 1
32 Informatica teorica
ESERCIZI
2.1 Si trasformino le seguenti fbf in FNC e in FND:
1. Ao(Bv(A^C)J
2. (B => A) a (->B (C v A))
2.2 Si sviluppino degli algoritmi per trasformare una qualunque fbf in FNC e
FND.
1. Assiomi
Se "K VK e TZ sono tre fbf del Ey; allora i seguenti sono assiomi del 2EU2
Al. V7 (W =>
A2. => uyy,
A3, => ((-,ìr
2. Regola di inferenza
La sola regola di inferenza del 'BA'A’e il Modus Ponens (MP): VF è una diretta
conseguenza di Ve V=> VP.
Esempio 2.15
Viene derivata ora la deduzione A B, B C <- A C, che afferma la
transitività dell’implicazione logica.
1 Si tenga presente che quella proposta in questo capitolo non è l’unica assiomatizzazione
(ossia l’unico insieme di assiomi) possibile per il AAEssa privilegia la minimalità del
numero di assiomi; altre assiomatizzazioni privilegiano ad esempio l’intuività degli assiomi
come “basi naturali” del ragionamento basato sulle proposizioni.
Elementi essenziali di logica matematica 33
Si noti che la deduzione precedente resta valida anche se si sostituisce alle lettere
A, B, C ima qualunque formula ben formata. Si è ottenuto così uno schema di
deduzione "V W, Tl >- Il per ogni bf "V, W, U.
ESERCIZIO
2.3 Si dimostrino i seguenti schemi di teorema per ogni fbf Ve
1. v
2.
3. (V=>W)=>(Ov
2 Per una spiegazione del termine “prim’ordine” si vedano i riferimenti bibliografici alla
fine di questo capitolo.
36 Informatica teorica
Esempio 2.16
“essere bello” è una relazione di arità 1 su un insieme P di persone. Se P = {Maria,
Lisa, Tommaso, Michele} and Essere_bello = {Lisa, Tommaso}, “Maria è bella” è
falso.
Si consideri ora la frase “Il padre di una persona x è bello”. Si è già osservato che x
è una variabile, mentre il padre di x è una persona la cui identità dipende dall’x
considerato. Più precisamente, “il padre di” è una funzione che data una persona
restituisce suo padre.
Le relazioni posso essere espressi attraverso nomi di relazione o predicati,
denotati da simboli del tipo A", dove i e n sono interi positivi e rappresentano
Tidentificativo del nome di relazione e Parità della relazione, rispettivamente.
Analogamente, le funzioni possono essere espresse attraverso nomi di funzioni f",
in cui, di nuovo, i e n sono interi positivi e rappresentano T identificativo del nome
di funzione e Parità della funzione, rispettivamente.
Attraverso i concetti di oggetti variabili o costanti e delle loro proprietà
(formalizzate attraverso relazioni matematiche), si possono costruire frasi come
quelle degli esempi visti precedentemente, che sono “sempre vere o sempre false”
Elementi essenziali di logica matematica 37
3 II vincolo che i quantificatori si possano applicare solo a variabili genera il nome “logica
del prim’ordine”: le variabili sono “oggetti del prim’ordine” e i quantificatori possono
essere applicati solo ad essi. Esistono logiche di ordine superiore che permettono di
quantificare nomi di funzioni e di relazione. Come precedentemente anticipato, per ulteriori
dettagli si faccia riferimento alle note bibliografiche.
Elementi essenziali di logica matematica 39
Definizione 2.13
i termini sono definiti induttivamente come segue:
- i simboli di variabile e di costante sono termini;
- se f"1 è un simbolo di funzione e t\, t2, ..., tn sono n, termini, allora
f”‘ (r,..., t ) e un termine4*
.
Esempio 2.17
Definizione 2.14
Si definiscono le formule atomiche di 222 come le espressioni del tipo
A(Zj,...,tn ), dove Aè un simbolo di predicato e t^... ,tn sono i termini.
■
Esempio 2.18
4 D’ora in poi, nelle definizioni induttive del tipo qui esposto, non si ripeterà più
esplicitamente che solo gli oggetti costruiti in tale modo soddisfano la definizione.
40 Informatica teorica
Definizione 2.15
Una fbf è definita induttivamente come segue:.
1. Ogni formula atomica è una fbf5.
2. Se V e 3V sono fbf e x è un simbolo di variabile, allora (—> V), (V => "W) e
(VxV) sono fbf.
Esempio 2.19
Definizione 2.16
Una sottoformula di ima fbf è una parte della fbf che è a sua volta una fbf.
5 Analogamente a quanto fatto nel caso di 22, le fbf verranno indicate con lettere corsive
maiuscole.
Elementi essenziali di logica matematica 41
Esempio 2.20
Data la formula
Definizione 2.17
Data una formula 24, l’insieme delle sottoformule di 24, Stfm(24), è definito come
segue:
- Se 24 è una formula atomica A, Stfm(24) = {A};
- Se 24 ha la forma -fB, VxS (3xB), Stfm(24) = {24} u Stfm(S);
-Se 24 ha la forma B => C (B /\ C, Bv C, Bo C),
Stfm(24) = {24} u Stfm(S) u Stfm(C).
■
Esempio 2.21
3xA2 (x,a ) => Vx(^A2 (f2 (xf 2 (a,x )) ) a A2 (x,x )),3xA2 (x,a ),
Vx^A2 (f2 (xf2 (a,x )) ,b ) a A2 (x,x ))
3xA 2 (x,a ),\/x(—iA2 (fi2 (x,f2 (a,x )),/>) a A2 (x,x )),Z(2 (x.a ),
-4 (fi2 (xf2 (a,x )),b)^ A2 (x,x ),—iA2 (// (x/22 (a.x )fib\
A2 (x.x )
<; Vx(—,/l2 (fi2 (x,f2 (a,x )) ,b ) a A2 (x,x )) A 2 (x,a ),-.A2 (f2 (x,f 2 {a,x )) ,b ), (.
i(f2(x,f2(a,x)),b)
p/l|2(/12(x/22(«,x)),/>) A A2(x,x),A2(x,x),A2 j
■
Per concludere questa introduzione alla sintassi di si devono analizzare i
quantificatori. Un quantificatore agisce su una variabile. Se si scrive Vx (o Ex), il
quantificatore si riferisce ad x. I quantificatori hanno una visibilità limitata, in
modo analogo alle variabili nei linguaggi di programmazione. Ad esempio, nella
formula Vx J4 => 'B, V si riferisce alle occorrenze di x in J4, ma non a quelle di x
in B.
Definizione 2.18
Sia J4 una fbf e sia Vx B (Ex B) un elemento di Stfìn(J4), allora B è chiamato
campo d’azione del quantificatore Vx (Ex)
Esempio 2.22
Si consideri nuovamente la formula J4. dell’Esempio 2.20:
3xA2 (x,a) => Vx(^X12(/12(x,/’22(a,x))J6) a A2(x,x))
- Il campo d’azione di Ex è la sottoformula zt2 (x,a ) ;
- Il campo d’azione di Vx è la sottoformula -.z^2(fi2(xfi2(a,x)),b) a A2(x,x).
Elementi essenziali di logica matematica 43
Una variabile può apparire più volte in una fbf e ogni occorrenza può essere libera
o vincolata. Formalmente, un’occorrenza di una variabile x si dice libera quando
non è nel campo d’azione di un quantificatore Vx o 3x, altrimenti, si dice vincolata.
L’occorrenza di una variabile che appare nel quantificatore è vincolata per
definizione.
Definizione 2.19
Un termine t in una formula 34 è libero per una variabile x in 34 se non ci sono
occorrenze libere di x in A nel campo d’azione di un quantificatore che quantifica
una variabile che appare in t.
■
Come vedremo nella Sezione 2.3.4, la Definizione 2.19 ha un ruolo importante
nella definizione delle regole che permettono di manipolare formule di3^32
Esempio 2.23
Si consideri la formula fi
A2 (a,b)v 3yA2(f2 (x,y),f2 (a.xj) => Ax(^.A2 (fi2 (xf2 (a,x )),b ) a A2 (x.x ))
1. (x,-.V xX/yA2(x, y) )
2. (fi2(x,y) , xVyA2(x,y) => VxAÌ(x))
3- {fi{x,y}, x(A2 (x,y) VxAÌ(y)) )
4. (f2(z,y), —iV xV_vVz(^422 (x,_v) => YxA2(z,y)))
Definizione 2.20
Una fbf è detta chiusa se non contiene variabili libere.
Quando una fonnula non è chiusa, può essere resa chiusa premettendo all’intera
formula o il quantificatore universale o il quantificatore esistenziale delle variabili
che nella fbf abbiano occorrenze libere.
Definizione 2.21
Si consideri la fbf J4, denotata con J4(xb x2,... , x„), che contiene come uniche
variabili libere xb x2,... , xm. Vxi Vx2... Vx„J4(xb x2,... , x„) è chiamata chiusura
universale di AL
Definizione 2.22
Si consideri la fbf J4, denotata con J4(xb x2,... , x„), che contiene come uniche
variabili libere xb x2,... , xm. 3xi 3x2... 3x„J4(xb x2>... , x„) è chiamata chiusura
esistenziale di AL
Esempio 2.24
Si consideri nuovamente la fbf fidell’Esempio 2.23
Z (a,b ) v JyA 2(f2 (x,y )f2 (a,x )) => V x(-,A2 (f2 (x,f 2 (a,x )),&) a A2
2 (x,x ))
Tale formula non è chiusa poiché le occorrenze di x in A2 (Zi2 (*,y (a,x )) sono
libere. La sua chiusura universale e la sua chiusura esistenziale sono
rispettivamente:
Vx(^2 (a,b ) v JyA 2 (f2 (x,y )f2 (a,x )) => Vx(-,^2 (// (x/22 (a,x )),b)A. A2 (x,x )))
Bx(A2 (a,b) v 3yA2 (f2 (x,y )f2 (a,x)) => Vx(-,A2 (// (xf2 (a,x )) ,b ) a A2(x,x)))
■
Ottenute le formule e la loro struttura, bisogna ora interpretarle, ossia assegnare
loro un significato. Si ricordi che, nel interpretare una fbf significa assegnare
ad essa un valore di verità. Analogamente, in ZAgf l’interpretazione di una fbf
comporterà l’assegnazione di valori (o insiemi di valori) ai simboli di costante e di
variabile, di funzioni “vere” ai simboli di funzione, e di relazioni ai simboli di
predicato, in modo tale da poter stabilire, alla fine, se una formula è vera o falsa.
Per giungere a questo risultato occorrono però più definizioni e spiegazioni di
quanto fosse necessario per il
Elementi essenziali di logica matematica 45
Definizione 2.23
Dato un linguaggio del primo ordine, cioè un insieme di fbf definite su un insieme
fissato di variabili, costanti, simboli di funzione e di relazione, una struttura
interpretativa è una coppia M = (D, 7), in cui
- D è un insieme non vuoto, chiamato dominio-,
- I è una tripla di funzioni6 che assegnano rispettivamente a ciascun simbolo di
costante c un elemento di D, a ciascun simbolo di funzione f”’ una funzione
di arità n.f: D"’ —>D e a ogni simbolo di relazione A"' una relazione di arità
ni A c D .
■
Si noti che le funzioni I possono assegnare lo stesso valore a costanti diverse;
inoltre, possono esserci strutture interpretative diverse per lo stesso linguaggio del
prim’ordine.
Esempio 2.25
Si consideri un linguaggio del prim’ordine che ha a, b, c come simboli di costante,
x e sy come variabili,7 Jf,l 17, Jf?
[
,
7 J 2.
come nomi di funzione e A?,
1’2
A:} come simboli
di relazione. Una possibile struttura interpretativa è = (Db f), in cui D, è
l’insieme dei numeri naturali e f è definita come segue:
- Zì(«) = 1,Z1(Ò) = 2, Z!(c) = 3;
- 7i assegna a f' l’operatore unario che restituisce per ogni numero il suo
successore, a il prodotto e a /22 la somma;
- 7i assegna a A: la relazione di uguaglianza e a /l2 la disuguaglianza “minore
di”.
In questa struttura la formula J7
6 Si osservi che in realtà sarebbe sufficiente vedere 7 come una coppia di funzioni in quanto
le costanti sono un caso particolare di simboli di funzione con arità 1.
46 Informatica teorica
(a,b ) v 3yA' (J? (x,y (a,x )) => Vx^A? (fi2 (xf2 (a,x )),/>) a A2 (x,x ))
>
introdotta nell’Esempio 2.23, viene interpretata come “Se 1 < 2 o esiste un numero
naturale y tale che x * y = 1 + x, allora per ogni numero naturale x, x * (1 + x) ^2
e x < x”.
■
Si noti che nella formula dell’Esempio 2.25 appaiono sia occorrenze libere sia
occorrenze vincolate della variabile x: intuitivamente, si può dedurre che, anche se
viene utilizzato lo stesso simbolo, il significato che il simbolo x assume nella
formula cambia con le diverse occorrenze, a seconda che esse siano libere o
vincolate. A breve questa differenza verrà analizzata più in profondità.
In una struttura le costanti sono interpretate come elementi del dominio D, i
termini sono composizioni di funzioni e le formule atomiche sono relazioni fra i
termini. Data una struttura, il valore di verità delle fbf dipende dal valore assegnato
alle variabili in quella formula.
Definizione 2.24
Un assegnamento o in una struttura interpretativa di un linguaggio L di JEf è
una funzione (parziale) dall’insieme di variabili di L a D.
■
Esempio 2.26
Si consideri nuovamente la formula jF usata negli Esempi 2.22-2.24 e
l’assegnamento c> tale che o(x) = 5 e c>(y) = 2. La formula sarà interpretata come
“Se 1 < 2 o esiste un numero naturale y tale che 5 * y = 6, allora per ogni numero
naturale x, x * (1 + x) 2 e x < x”.
■
Si noti che nell’Esempio 2.26 non è stato assegnato alcun valore alle occorrenze
vincolate delle variabili. Infatti, esse non fanno riferimento a uno specifico
assegnamento, come verrà mostrato nella Definizione 2.27.
Un valutazione di un termine f"' (xp... ,x n ) dipende dall’assegnamento o e da
I. Essa viene fatta considerando l’interpretazione f"' della funzione f e applicando
c> alle variabili. Formalmente, è definita induttivamente come segue.
Elementi essenziali di logica matematica 47
Definizione 2.25
Una valutazione di un termine t = f"'^,...,^) rispetto all’assegnamento cr è
definita come = I(f”' a n o) , dove I(f"‘ ) è l’operazione di arità m, su
D associata da lai simbolo funzionale f"‘ .
■
Esempio 2.27
Si consideri la struttura interpretativa M2 = (Z)2,Ej, in cui D2 è l’insieme dei numeri
naturali e I2 è definita come segue:
- h(a) = 2,
- I2 assegna a f' l’operazione di arità 1 che restituisce per ciascun numero il
suo successore, a il prodotto e a /22 la somma,
Definizione 2.26
[In una struttura M = (Z>,7)] un assegnamento c soddisfa la formula atomica
A"' (tv... ,t n ) se e solo se ,... ,t „d) e 7(J” ),dove I(A"') è la relazione di
aritàn, che interpreta A"' .
■
Esempio 2.28
Si consideri come dominio D l’insieme dei numeri naturali e si interpreti a come 2,
// interpretata come l’operazione di arità 1 che assegna a ciascun numero il suo
successore, /22 come l’operatore di somma e A: come la disuguaglianza “minore
di” e l’assegnamento c tale che <j(x) = 5, <s(y) = 2. la formula atomica
A^ (ffaìfi (x,y )) diventa 2 + 1 < 5 * 2. Questo significa che l’assegnamento c
soddisfa la formula nella struttura data.
48 Informatica teorica
11 concetto di soddisfacibilità si estende dalle formule atomiche alle fbf nel modo
seguente.
Definizione 2.27
Data una struttura M = (D, I), si dice che un assegnamento a soddisfa la fbf 34 se e
solo se:
- Se 34 è della forma —>2?, allora o non soddisfa B;
- Se34 è della forma B => C, allora o non soddisfa B o soddisfa C;
- Se34 è della forma Vx®, allora tutti gli assegnamenti r che differiscono da <y
al più per il valore della variabile x soddisfano 2>;
- Se 34 è della forma B a C, allora o soddisfa sia B sia C7;
- Se 34 è della forma B v C, allora o soddisfa (almeno uno fra) B o C;
- Se 34 è della forma B C, allora a soddisfa sia B sia C o o non soddisfa ne’
Sne’ C;
- Se 34 è della forma 2xB, allora esiste un assegnamento r che differisce da o
per al più il valore della variabile x e soddisfa B.
■
Si noti che, come anticipato nell’Esempio 2.26, l’assegnamento di una variabile x
non è significativo per le occorrenze vincolate di x; infatti, il valore di verità di
formule chiuse non dipende dal particolare assegnamento.
Esempio 2.29
Data la struttura = (Db li), in cui Di è l’insieme dei numeri naturali, Ifa) = 1,
Ifb) = 2, Zi(c) = 3 e E interpreta come l’operazione unaria che assegna a
ciascun numero il suo successore, // come il prodotto, /22 come la somma, A2
come l’uguaglianza e A2 come la disuguaglianza “minore di”, presentata
nell’Esempio 2.25. Si consideri nuovamente l’assegnamento o definito come
o(x) = 5 e o(y) = 2. Tale assegnamento non soddisfa la formula fi (Esempi 2.18
2.21)
A2(a,b)v 3yA2(fi2(x,y)f2(a,x)) V x(^A2 (fi2 (xfi 2 (a.xf ,/>) a A2(x,x))
in Mb infatti la formula è interpretata come “Se 1 < 2 o esiste un numero naturaley
tale che 5 * y = 6, allora per ogni numero naturale x, x * (1 + x) 2 e x < x”. Poiché
“1 < 2” è vera l’antecedente è vero, ma il conseguente è falso.
Esempio 2.30
Si consideri la struttura M2 = (D2, I2), che differisce da Af solo perchè I2 assegna a
Al la disuguaglianza “maggiore di” al posto della disuguaglianza “minore di”; in
questo caso, lo stesso assegnamento ct(x) = 5 e ct(v) = 2 soddisfa la formula J7
dell’Esempio 2.29. Infatti, la formula è interpretata come“Se 1 > 2 o esiste un
numero naturale y tale che 5 *y = 6, allora per ogni numero naturale x,
x*(l+x)*2ex> x”. Poiché 1 non è ovviamente maggiore di 2 e non esiste un
numero naturale che moltiplicato per 5 dia 6, entrambi gli elementi della
disgiunzione nell’antecedente sono falsi, quindi l’antecedente è falso e la formula
J7 è valutata come vera a prescindere dal valore del conseguente.
Quindi, la formula J7 è soddisfacibile in M2 e quindi è soddifacibile in
generale. La stessa formula, perciò, può essere soddisfacibile in una o più strutture,
ma non soddisfacibile in altre.
■
Definizione 2.28
Una formula 34 è vera in una struttura M = (D, I) se tutti i possibili assegnamenti
su D soddisfano JU
■
Si osservi che la soddisfacibilità delle formule chiuse, non dipende
dall’assegnamento scelto; esse non possono essere soddisfacibili ma non vere in
una data struttura M. Inoltre, la chiusura universale di una formula 34 è vera in M
se e solo se 34 è vera in M e la chiusura esistenziale di una formula 34 è vera in M
se e solo se 34 è soddisfacibile in M (ovviamente ogni formula vera è anche
soddisfacibile).
Analogamente, si può definire la falsità di una formula in una data struttura
come segue.
50 Informatica teorica
Definizione 2.29
Una formula 34 è falsa in una struttura M = (D, I) se nessun assegnamento in M
soddisfa 34.
■
Quindi, una formula 34 è falsa in una struttura M se e solo se è insoddisfacibile in
M. La chiusura universale di una formula 34 è falsa in M se e solo se esiste almeno
un assegnamento che non soddisfa 34 e la chiusura esistenziale di una formula 34 e
falsa in M se e solo se 34 è insoddisfacibile in M.
Esempio 2.31
Si consideri la struttura M3 = (Z)3, Z3) del tutto uguale alla struttura definita
nell’Esempio 2.29, con la sola differenza che, mentre Z2 assegna a X2 la
disuguaglianza “minore di”, I3 assegna a A 2 la disuguaglianza “minore di o uguale
a”. Si definisca poi l’assegnamento a, tale che a(x) = 1 e o(y) = 2. La formula Q:
^22(a,Z>)v 3yA2 (J2 (x,y)f2 (a,x)) => Bx(A2 (J2 (xf2 (a,x )),b ) a A2(x,x))
viene quindi interpretata come 1 < 2 v By(y = 2) => 3x(x * (1 + x) = 2 a x < x).
Quindi, (f è soddisfatta da a in M3 e, poiché esiste una assegnamento che
soddisfa Q, la formula è soddisfacibile in M3 ed è soddifacibile in generale. Inoltre,
nella struttura M3 esiste un assegnamento r che soddisfa il conseguente, quindi il
conseguente è vero in M3 e, di conseguenza, lo è anche la formula (f Se si
considera, invece di M3, la struttura MdeH’Esempio 2.29, (g viene interpretata
come 1 < 2 v Ey(y = 2) => 3x(x * (1 + x) = 2 a x < x) e l’assegnamento o non
soddisfa la formula in Mh Inoltre, poiché x < x è falso per ogni x e l’antecedente è
sempre vero, non esiste alcun assegnamento che soddisfa la formula in M3, e quindi
la formula è falsa in M3.
Ci sono poi casi in cui è possibile assegnare il valore di verità a formule della
indipendentemente dalla struttura scelta.
Definizione 2.30
Una formula 34 è (logicamente') valida se e solo se è vera in tutte le strutture;
questa proprietà è indicata con la notazione |= 34.
Elementi essenziali di logica matematica 51
Esempio 2.32
Definizione 2.31
Una formula JL è detta esempio di tautologia se è possible ottenerla da una
tautologia B (in sostituendo le lettere proposizionali in B con fbf di ,
Ovviamente lettere uguali in B sono sostituite da fbf uguali.
■
Gli esempi di tautologia sono sempre formule logicamente valide, mentre le
formule logicamente valide non sono necessariamente esempi di tautologia. Ad
esempio, 3xV;M12(x,iy) => VylxA* (x,y) è logicamente valida, ma non è un
esempio di tautologia.
Dopo avere definito la semantica della AA2ES2 si possono analizzare le
equivalenze e le implicazioni fra formule.
Definizione 2.32
Una fbf. JL è semanticamente equivalente a una fbf B se per ogni struttura
M = (D, I) e per ogni assegnamento <7, <7 soddisfa JL se e solo se <7 soddisfa B. In
tal caso si scrive JL = B.
Definizione 2.33
Una fbf B è conseguenza semantica di una fbf 34 se, per ogni struttura M = (Z), 7) e
per ogni assegnamento c>, che soddisfa 34, c> soddisfa B. Questa proprietà è
indicata dalla notazione 34 |= B.
■
Si noti che 34 |= B se e solo se |=34 => B, infatti |= 34 => B significa che la
formula 34 => B è valida.
Esempio 2.33
La formula (A 2 (x,x ) \/xA2 (x,xj) => (~iA2 (x,x ) v VxA2 (x,x )) è logicamente
valida, poiché -<A2 (x,x) v VxA2 (x,x) è conseguenza semantica di
A2(x,x) <=> VxA2(x,x) . Infatti, se A2 (x,x ) VxA2 (x,x ) è soddisfatta da un
assegnamento in una struttura, allora anche -.^f2 (x,x ) v PxA2 (x,x ) è soddisfatta.
■
Analogamente a quanto fatto con si possono introdurre forme speciali in
e in particolare, verrà introdotta la forma normale prenessa (FNP). Infatti, a volte,
forme particolari per le fbf sono necessarie, sia allo scopo di comprendere meglio
la formula sia a scopi algoritmici. Una fbf in J^2?può essere manipolata in modo
da ottenere la forma desiderata, comunque semanticamente equivalente alla
formula originale.
La FNP di una fbf 34 è una fbf B, semanticamente equivalente ad 34, che ha
tutti i quantificatori all’inizio della formula. In B, la parte iniziale, composta da
tutti e soli i quantificatori viene chiamata prefisso e la stringa senza quantificatori
matrice.
Per trasformare una fbf 34 in FNP, bisogna applicare le seguenti
trasformazioni ricorsivamente:
- —iVx34 è sostituito con la formula equivalente Ex—,34;
- —13x34 è sostituito con la formula equivalente Vx—,34;
- Vx34(x) a B è sostituito con la formula equivalente \/y(2A.[y/x] a B);
- Ex34(x) a B è sostituito con la formula equivalente 3y(34([j/x] a B);
- Vx34(x) v B è sostituito con la formula equivalente Vy(34([j/x] v B);
- Ex34(x) v B è sostituito con la formula equivalente 3y(34([j/x] v B);
- Vx34(x) => B è sostituito con la formula equivalente 3y(34[j/x] => B);
- Ex34(x) => B è sostituito con la formula equivalente \/y(2A.[y/x] v B);
- B Vx34(x) è sostituito con la formula equivalente VjfS => 34[y/x]);
- S => 3x34(x) ) è sostituito con la formula equivalente EvfS => 34[y/x]);
Elementi essenziali di logica matematica 53
Esempio 2.34
Si consideri la formula 3xA2(x,a ) => —>V xA2 (f2 (xf2 (a,x )),y) a 3yA2 (x,y )) .
Tale formula può essere trasformata in FNP, applicando i seguenti passi:
Vz(A2 (z,a)=> —.V xA 2 (f2 (xf 2 (a,x )) ,y ) a 3yA 2 (x,y )) =
Vz(A2 (z,a ) => 3 x->A2 (f2 (xf 2 (a,x )) ,y ) a 3yA 2 (x,y )) =
Wz(A2(z,a) => 3w(^A2(f2(wf2(a,w)),y)/\3yA2(x,y))) =
V z(A2 (z,a) => 3w3v(^A2(f2 (wf 2 (a.w^y) a A2(x,vf) =
Wz3w(A2 (z,a) => 3v(^A12(f12(wf2(a,w)')y)AA2(x,v))) =
Vz3w3v(A2 (z,a ) => (^A2 (f2 (wf2 (a,w)),y) a A2 (x,v))) =
■
ESERCIZIO
2.5 Si dimostri che ogni esempio di tautologia è logicamente valido.
Al.
A2. ( 7/)) => (( T7^ X) => ( T7^ 7/))
A3. (-^ 7^ T) => ((-^ 7^ T7) => 7T)
ESERCIZI
1. Nessun uomo ha tre gambe. Bobby ha tre gambe. Quindi Bobby non è
un uomo.
2. Nessun uomo può essere felice e affamato. Giovanni è un uomo ed è
affamato. Quindi Giovanni non è felice.
Definizione 2.34
Una teoria formale del prim’ordine dotata unicamente degli schemi d’assioma Al,
..., A5 e delle regole di inferenza II, 12 è chiamata calcolo dei predicati del primo
ordine (
■
Intuitivamente, un è una teoria priva di verità dipendenti da qualche
particolare interpretazione. Non è quindi sorprendente che le seguenti affermazioni
fondamentali valgano per ogni
Enunciato 2.5
Ogni ^3^ è
- fondato (corretto), ossia ogni teorema è una fbf logicamente valida;
- coerente, ossia per nessuna fbf V valgono sia >- V che > V;
- completo, ossia ogni fbf logicamente valida è un teorema.
■
Senza entrare nella dimostrazione tecnica dell’enunciato, si invita il lettore a
verificare, su base intuitiva, la validità logica degli schemi d’assioma Al, ..., A5
(si ricordi l’Esercizio 2.5). Chiaramente, le regole II e 12 mantengono la loro
validità logica, ossia se T •- Ve ogni fbf di T è logicamente valida, altrettanto è V.
La coerenza è un ovvio corollario della fondatezza, poiché, per assurdo, •-'V e
>- -i V implicherebbero che sia V che —fV siano logicamente valide, ossia vere
sotto ogni interpretazione. La completezza è invece molto più difficile da
dimostrare, anche su base intuitiva, quindi ci limitiamo ad asserirla.
ESERCIZIO
2.8* Si formalizzi il seguente ragionamento in un “Un barbiere di una città
taglia la barba esattamente a quegli uomini che non se la tagliano da soli.
Quindi non ci sono barbieri nella città”. Si stabilisca se il fatto che non ci
siano barbieri nella città sia o meno una conseguenza logica della prima
frase.
Elementi essenziali di logica matematica 57
Abbiamo visto che, nel il Teorema della Deduzione Sintattica (Enunciato 2.2)
permette di ottenere F >- V=> "VP, da una deduzione T, V >- Tale enunciato è
stato utile nel rendere più semplici le deduzioni, è quindi naturale chiedersi se sia
altrettanto valido per le Si verifica a questo proposito che il Teorema della
Deduzione Sintattica, come formulato dall’Enunciato 2.2, non vale per Si
supponga infatti che V sia A^(x), dove A.‘ sia interpretata come la relazione
unaria “è pari” sui numeri naturali. Da una parte è dunque possibile costruire la
deduzione zf‘(x) |-Vxz(11(x) attraverso la regola 12 (Gerì), ma dall’altra è chiaro
che A'(x) 'VxA'(x) non risulta vera. Infatti ogni sequenza di numeri pari
soddisfa zf’(x), ma nessuna sequenza di numeri soddisfa VxA'(x). Quindi
A*(x) VxA^(x) non può essere logicamente valida e, quindi, per l’Enunciato
2.5 non può essere un teorema di alcun rìy-rì.
Queste osservazioni chiariscono meglio la regola 12. Precisamente, essa è di
aiuto nella deduzione di formule vere da formule vére, ma non ha il significato di
implicazione logica.
In ogni caso il Teorema della Deduzione Sintattica può essere adeguatamente
riformulato all’interno della struttura della Qui sotto (Enunciato 2.6) ne
vengono date, senza dimostrazione, due versioni semplificate, ma ugualmente utili.
Enunciato 2.6
1. Se una deduzione T, V |-Ì¥ non implica alcuna applicazione della regola di
inferenza logica 12 (Gerì), in cui la variabile quantificata sia libera in V, allora
i - v... >
2. Se T, V '-ÌV e Vè chiusa, allora P- V
■
Vengono ora fomiti assiomi propri per alcune semplici teorie formali del
prim’ordine. Per comodità si suppone che tali teorie non abbiano regole di
inferenza proprie. Ogni volta che la verità di ÌV debba essere dedotta dalla verità
dell’insieme {Vi, ..., V„}, si può affermare l’assioma Va...aV„ =>
consentendo la deduzione {V, ..., V„} •- ÌVmediante il MP.
Esempio 2.35
Presentiamo una formalizzazione degli ordinamenti parziali come una teoria
formale del prim’ordine. È sufficiente introdurre, a tale scopo, un solo predicato
A^, con arità due, mentre non è necessaria alcuna funzione. Allo scopo di rendere
la notazione più vicina al suo significato consueto, si scrive x < y al posto di
Af (x, y) e x > y al posto di -^Af (x, y). Si richiama comunque l’attenzione del
58 Informatica teorica
8 Si noti che POI e P02 non sono schemi d’assioma ma veri assiomi.
Elementi essenziali di logica matematica 59
ESERCIZIO
2.9 Si dimostri che, nella teoria dell’ordinamento parziale
VxVy(x < y =^> —i(y < x))
Suggerimento', si usi la tautologia V=^> (3Va —= —iV.
Definizione 2.35
Un modello di una teoria formale del prim’ordine è un’interpretazione della teoria
stessa in cui tutti i suoi assiomi sono veri.
■
Vengono ora elencate alcune semplici ma importanti conseguenze della
Definizione 2.35.
Enunciato 2.7
1. In un modello di una teoria formale del prim’ordine tutti i teoremi della teoria
sono veri. Ciò discende dal fatto che le regole di inferenza MP e Gen
conservano la verità delle formule in ogni interpretazione.
2. Se una teoria ha un modello, allora è coerente. Infatti, poiché i teoremi della
teoria sono veri in una interpretazione, quella costituita dal modello, non può
esistere alcuna fbf V per la quale '-"Ve'- —TV, poiché in tale modello "V
risulterebbe contemporaneamente vera e falsa.
■
Ogni insieme parzialmente ordinato è un modello della teoria avente per assiomi
propri POI e P02. I numeri naturali, ad esempio, corredati dalla relazione
“strettamente minore di” sono un modello di tale teoria. Ciò non vale però se la
relazione è “minore o uguale a”. Un altro modello di questa teoria è dato
dall’insieme degli esseri umani, con la relazione “essere antenato di”, una volta che
si sia convenuto che nessun uomo è antenato di se stesso.
60 Informatica teorica
Esempio 2.36
Diamo ora un’assiomatizzazione dei monoidi. A tale scopo sono necessari: una
funzione con arità 2, un simbolo di costante e un predicato con arità 2. Come
effettuato in precedenza, questi sono indicati rispettivamente dai simboli “w”,
“=”, usando la notazione infissa, allo scopo di rendere le formule immediatamente
comprensibili. Gli assiomi propri per i monoidi sono i seguenti:
MI. Vx(x = x) Riflessività
M2. Vx Vy(x = y => y = x) Simmetria dell’uguaglianza
M3. VxVyVz(x = _yA_y = z=>x = z) Transitività dell’uguaglianza
M4. VxVyVz(x o (y o z)) = ((x o y) ° z) Associatività della concatenazione
M5. Vx(m °x = xax°m = x) Identità
M6. VxVyVz((y = z) => Sostitutibilità dell’uguaglianza
(x°y = x°zAy°x = z°x)
Ovviamente ogni monoide è un modello della teoria precedente.
ESERCIZI
2.10 Si dimostri che l’identità è unica aH’intemo della teoria dei monoidi, ossia
che Vy(Vx(x ° y = x a y ° x = x) => y = u).
2.11 Si fornisca una «teoria formale del prim’ordine per gli ordinamenti totali
riflessivi.
2.12 Si fornisca una teoria formale del prim’ordine per i gruppi. Si noti che gli
assiomi per i gruppi devono includere gli assiomi per i monoidi. Se lo si
desidera, M5 può essere sostituito dal più “debole” M5: Vx(m°x = x). Perché?
2.4 Studio di un caso: una teoria formale per l’aritmetica e le sue funzioni
In questo paragrafo si accenna brevemente ad un’importante applicazione delle
teorie formali, e precisamente aH’assiomatizzazione dell’aritmetica, una teoria
fondamentale per quasi tutti i procedimenti matematici.
Questa sezione è a sua volta divisa in altre tre sottosezioni. Nella Sezione 2.4.1
viene descritto e commentato brevemente il classico sistema assiomatico di Peano
per l’aritmetica: una teoria formale del prim’ordine chiamata (Peano
Arithmetic). La Sezione 2.4.2 presenta invece una classe fondamentale di funzioni
definite sui numeri naturali: le funzioni ricorsive. La Sezione 2.4.3, infine, contiene
una panoramica sui risultati fondamentali dell’assiomatizzazione dell’aritmetica,
senza tuttavia dilungarsi in dimostrazioni formali.
Elementi essenziali di logica matematica 61
2.4.1 Gli assiomi di Peano
Peano fu. il primo matematico che suggerì di definire un insieme di “verità
elementari”, riguardanti i numeri naturali e le loro applicazioni, da cui si potesse
dedurre la maggior parte delle altre verità. Una descrizione informale di tali verità
elementari è la seguente.
PEI. Esiste un numero naturale indicato da 0.
PE2. Se x è un numero naturale, esiste allora un altro numero naturale, indicato
con x", chiamato successore di x.
PE3. Dato un numero naturale x, il suo successore x' è diverso da 0.
PE4. Se i successori di due numeri x e y sono uguali, allora x e y sono uguali.
PE5. (Principio di Induzione matematica). Sia Q una proprietà dei numeri
naturali. Se la proprietà Q vale per 0 (base dell’induzione) e la validità della
proprietà Q per un qualsiasi numero x implica la validità della stessa
proprietà per x' (passo dell’induzione), allora Q vale per tutti i numeri
naturali.
Si noti che, informalmente, da PEI, ..., PE4 si può dedurre l’esistenza di infiniti
numeri naturali. Da PEI e PE2 si ottengono infatti i numeri 0, 0', (0')', ... . Per
comodità si usi la notazione 0x e (F al posto della ((0')'...)', dove x e y
corrispondono al numero di apici. Se x è diverso da y, allora anche (fi deve risultare
diverso da (F, ossia deve indicare un numero diverso. Si supponga, per assurdo, che
0x = (F e, ad esempio, x > y. Da PE4 segue allora che 0*’1 = CF"1, ..., 0^ = (F^, ossia
il simbolo 0 con esattamente 0 apici e quindi il simbolo 0 stesso, risulta uguale a 0
con x-y apici, ossia (0*9'4)'. Questa conclusione è però in contraddizione con PE3,
quindi si è giunti ad un assurdo, come volevasi dimostrare.
Il principio dell’induzione matematica è uno strumento molto potente per
dimostrare le proprietà dei numeri naturali. Si consideri ad esempio la nota
n
l’ipotesi induttiva, che la prima parte del secondo termine vale n(n + l)/2 e quindi
che
n+1
y i =n(n + 1) / 2 + (n + 1) = (n(n + 1) + 2(n + 1)) / 2 =
i =0
= ((n +1) • (n + 2)) / 2 = (n +1) • ((n +1) +1) / 2, dimostrando in questo modo il passo
induttivo. Si può dunque concludere che P è valida per ogni n.
L’induzione matematica verrà usata nel corso di questo testo come principale
strumento di dimostrazione. Essa sarà applicata non solo all’insieme dei numeri
62 Informatica teorica
Gli assiomi PAI, ..., PA9 consentono di dedurre la maggior parte delle note
proprietà dell’aritmetica in un modo molto semplice, sebbene talvolta noioso.
Eccone alcuni esempi:
Esempio 2.37
Le seguenti fbf TH1 e TH2 sono teoremi di ///
TH1 : x = x, come dimostra la seguente deduzione.
1.1 x + 0 =x (per PA5).
1.2 (x + 0 = x) a (x + 0 = x) (x = x), come si ricava da PAI sostituendo x, y,
z rispettivamente con x + 0, x, x. In particolare, si supponga che V sia
PAI. Si deduce dunque VxVyVzV, applicando ripetutamente la Gen. Si
definisca poi Vi come VyVzV e si consideri l’istanza di A4,
VxVl => V7("J. Si ponga V2 pari a VzX ° e si consideri l’istanza di
A4 Vy V2 V2 x. Infine, si definisca V3 come (X e consideri
l’assioma VzV? V3*. Applicando ripetutamente il MP, si ottiene,
Elementi essenziali di logica matematica 63
TH2: x=y =>y = x, come si dimostra sulla base delle seguenti deduzioni.
2.1 ((x = y) a (x = x)) =5- y = x (da PAI, sostituendo z con x).
2.2 (x = x) => ((x =7) => (y = x)), dalla 2.1, applicando la tautologia ((A a B)
=> C) = B => (A => C).
2.3 x = x(daTHl).
2.4 x =y =>y = x (dalle 2.2 a 2.3, per il MP).
ESERCIZIO
2.13 Si dimostrino i seguenti teoremi.
1. x=yA_y = z=>x = z;
2. x=yAz = _y=>x=z.
Esempio 2.38
0 + x = x è un teorema, che può essere dedotto nel modo seguente servendosi
dell’induzione matematica.
Base dell 'induzione
0 + 0 = 0 è ottenuto da PA5 sostituendo x con 0.
Passo dell 'induzione
La seguente deduzione deriva la tesi 0 + x = x partendo dall’ipotesi induttiva
0 + x = x.
1. 0 +x=x (da PA6 sostituendo x con 0 e y
2. 0 + x = (0 + x)' conx)
3. 0 + x = x => (0 + x)' = x (da PA29)
4. (0 + x)' = x (da 1, 3 e dal MP)
5. (0 + x = (0 + x)') a ((0 + x)' = x')
=> 0 + x' =x' (dal punto 1 dell’esercizio 2.13)
6. 0 +x =x (dalle 5, 2, 4 tramite
l’applicazione di un’ovvia
tautologia)
ESERCIZIO
2.14 Si dimostrino i seguenti teoremi.
1. x =y x + z =y + z
2. x+y=y + x
3. x-y=y-x
ESERCIZI
2.15 Si determino le fbf aventi per interpretazione, nell’aritmetica consueta, le
seguenti relazioni.
1. x <y
2. x>y
3- -(x<p)
2.16 Si dimostrino i seguenti teoremi.
1- ~<x<y)
2. 0<x'
3. x <y = x'< y
Elementi essenziali di logica matematica 65
2.17 Si determini un sistema di assiomi per l’algebra dei numeri interi relativi con
le consuete operazioni di addizione, moltiplicazione e divisione intera.
2.18 Si dimostri che per ogni fbf V il seguente Principio di Induzione Completa è
un teorema di .^^(basato su PA9): (Vx(Vy(y < x) => V’' ) => V* ) =>
Vx'V' , dove y e x sono liberi per z in V.
Definizione 2.36
Le seguenti funzioni vengono chiamate funzioni di base o iniziali.
1. La funzione zero, Z: N —> N definita come Z(x) = 0 per ogni x.
2. La funzione successore'. N —> N definita come '(x) = x + 1 per ogni x. Per
coerenza con la Sezione 2.4.1 si adopera la notazione postfissa x' al posto
della prefissa'(x)-
3. Le funzioni di proiezione: U. : N* —> N dove 1 < i < k, definite come
u) (Xj,..., xk ) = x,, per ogni &-upla (xb ..., xfi.
Definizione 2.37
Le seguenti operazioni consentono di definire nuove funzioni a partire da altre
funzioni.
1. Sostituzione (o composizione)
Siano date le funzioni g: N* —> N, hi. N” —> N, con 1 < i < k. Allora la
funzione fi N” —> N, definita come/(xi, ..., x„) = gfhfxi, ..., x„), ..., hfxi, ...,
x„)), si dice ottenuta per sostituzione (o composizione) dalle g, hi, ..., hk.
66 Informatica teorica
2. Ricorsione primitiva
Siano date due funzioni g: N" N, /?: N"+2 N qualsiasi, con n > 0. Allora
la funzione fi N"+7 N, definita dalle due equazioni
/(%!,... ,X„,0) = g(xp... ,xfi .
/(Xi,... ,xn,y') = h(xi,...,xn,y,f(xl,...,xn,y))
si dice ottenuta per ricorsione primitiva da g e h (se n = 0 allora g è una
costante in M).
3. Minimizzazione (attraverso Eoperatore-fi)
Sia data una funzione g: N'!l/ N, qualsiasi, con n>0. Si indichi con
//yCgCxi, ..., x„,y) = 0) il minimo numeroy, se esiste, tale che g(xb ..., xmy) = 0
In generale, per ogni relazione (n + l)-aria R, si indica come py(R(xi, ..., x„,y)), il
minimo y, se esiste, tale per cui R risulti valida per (xb ..., x„,y). La funzione fi
N” —> N, definita come/(xi, ..., x„) = pfijfixi, ..., x„,y) = 0), si dice ottenuta da g
per minimizzazione o tramite l’operatore-p.
■
Si noti che se/(xi, ..., x„) = py(g(x\, xmy) = 0), allora f(xx, xn) è indefinita,
ossia, fifii, ..x„) = ±, ogni volta che non esiste uny tale che g(xb ..., x„,y) = 0.
Definizione 2.38
La classe delle funzioni ricorsive primitive viene definita nel seguente modo.
1. Tutte le funzioni di base sono ricorsive primitive.
2. Tutte le funzioni ottenute per composizione o per ricorsione primitiva da
funzioni ricorsive primitive sono funzioni ricorsive primitive.
La classe delle funzioni ricorsive parziali è definita in modo analogo, consentendo
però l’uso dell’operazione di minimizzazione.
■
Si userà il termine generico funzione ricorsiva quando non verrà richiesta ima netta
distinzione fra funzioni ricorsive primitive e funzioni ricorsive parziali.
Gli esempi seguenti mostrano la potenza delle operazioni precedenti nel
definire nuove funzioni.
Esempio 2.39
Vengono ora presentati alcuni esempi di funzioni ricorsive primitive.
1. fi(x, y) = x + y è definibile per mezzo della ricorsione primitiva nel modo
seguente.
/i(x, 0) = x
ffit, y} =fi(x,yY
Elementi essenziali di logica matematica 67
Nella definizione precedente /i(x, 0), ossia, x + 0, è definita per mezzo della
ricorsione primitiva usante Lf come funzione g; f(x, y') è definita usando
come funzione h la composizione C/22 = (y, f(x, y)').
2. f2(x, y) = x-y è definibile per mezzo della ricorsione primitiva nel modo
seguente.
x • 0 = 0 (g è la funzione zero)
x-y’ = x-y + x (h è la funzione h(x, y,z) = x + z)
3. y(x) = if x > 0 then x - 1 else 0 è definibile nel modo seguente.
/3(0) = 0
y3(x')=x
4. /i(x, y) = if x>y then x -y else 0 è definibile nel modo seguente.
/4(x, 0) = x
f&, y) =f3(ffx,y)')
n
/5(0) = 0
/5(x') = x’ +f5(x)
Le seguenti funzioni sono ricorsive parziali.
6. /6(x) = if x = 0 then 0 else ± è definibile per mezzo della minimizzazione nel
modo seguente.
/6(x) = pfy + x = 0)
7. /7(x) = if x > 0 then x - 1 else ± è definita da.
/7(o)=/6(oy
=X
Si noti che f7, diversamente day, è una funzione parziale sul dominio N
poiché non risulta definita per x = 0.
8- fifx,y) = ifx > y thenx-y else ± è definita da.
/8(x,0) = x
/8(x,j/) =fi(f(x,y))
9. y(x) = radice quadrata esatta di x, ossia il valore y, se esiste, tale per cui x = y2,
è definibile nel modo seguente.
/7(x) = ^(x-y2 = 0)
(Ovviamente la funzione “quadrato” è ricorsiva primitiva).
■
E immediato riconoscere che tutte le funzioni ricorsive primitive sono totali,
mentre alcune funzioni ricorsive parziali non lo sono.
ESERCIZI
2.19 Si mostri che le seguenti funzioni sono ricorsive primitive.
68 Informatica teorica
Si è visto come l’induzione sia uno strumento molto potente per dimostrare le
proprietà dei numeri naturali. Analogamente, la ricorsione primitiva è uno
strumento potente per costruire funzioni sull’insieme dei numeri naturali. Questi
due strumenti concettuali sono fortemente correlati l’un l’altro, come mostrato dal
seguente esempio.
Esempio 2.40
Dimostriamo per induzione la proprietà associativa dell’addizione, ossia il fatto
che, per ogni x, y, x, (x + y) + z = x + (y + z). Non si entrerà in tutti i noiosi dettagli
della deduzione formale poiché il lettore dovrebbe ormai essere in grado di
svilupparli da solo, se necessario. L’induzione è basata sulla variabile z.
Base dell’induzione
Dobbiamo dimostrare che (x + y) + 0 = x + (y + 0).
Ciò, a sua volta, può essere dimostrato per induzione su y nel modo seguente.
- (x + 0) + 0 = x + (0 + 0) poiché x + 0 = xe0 + 0 = 0.
- Sia (x+y) + 0 =x + (y + 0). Allora (x+yr) + 0 = ((x +yf + 0) = (0 + (x
+ L)') = (0 + (A +.Q)' = ((x + y) + 0)' = (x + (y + 0))' = (x + (y + 0)') =
(x + (0 +y)') = (x + (0 + a')) = x + (y' + 0).
Passo dell 'induzione
Si supponga, come ipotesi induttiva, che (x + y) + z = x + (y + z). Allora (x + y)
+ z = ((x + y) + z)' = (x + (y + z))' = (x + (y + z)') = x + (y + z'). La
dimostrazione è quindi completa.
■
ESERCIZIO
2.21 Si dimostri che, per ogni x, y e z, x^z = x’' • x2.
Enunciato 2.8
L /ha un modello, quindi coerente.
■
Si fa notare, comunque, che l’Enunciato 2.8 non può essere dimostrato come un
teorema della stessa teoria, ossia non esiste alcuna fbf che stabilisca la coerenza di
e che sia deducibile dai suoi assiomi. Per questo motivo, l’enunciato 2.8 non è
in contraddizione con il seguente enunciato fondamentale.
naturali per mezzo di fbf di /'. / D’altro canto, i numeri naturali vengono poi
associati alle fbf, ai teoremi ed alle dimostrazioni di cosicché è possibile
parlare del “numero di una fbf’, del “numero di una dimostrazione” ecc. Tali
numeri possono essere calcolati come valori di funzioni che, a loro volta, vengono
rappresentate per mezzo di qualche fbf. Tratteggiamo alcuni punti fondamentali
della precedente esposizione.
Definizione 2.39
xv otte
r-“A'—~<
Definizione 2.40
Una funzione fi N"~>N si dice rappresentabile in .A'/se e solo se esiste una fbf V
con variabili libere Xj, ...,x„ tale che, per ogni numero naturale kx, ..., kn+1.
1. Se/Uj, U) = U+), allora
2. i-VxVX^ 1"
X1 >•• • >xn + I
A XI ’••• ’xn + l
=>x=y)
■
Si noti che se fi è totale e rappresentabile, allora per ogni k\, ..., kn •-
Bxn+yV*'” . Infatti, per ogni kx, ...,kn esiste una k^ tale che i-V*1’””*”1. Si può
quindi dedurre Bx^iV*1’' ’*”+‘ (in generale, per ogni fbf Ve termine t, libero per x
ESERCIZIO
2.22 Si dimostri che tutte le funzioni base sono rappresentabili in
Enunciato 2.10
Tutte le funzioni ricorsive parziali sono rappresentabili in
Elementi essenziali di logica matematica 71
Si è così riusciti a rappresentare ogni funzione ricorsiva parziale per mezzo di una
fbf di AFsXL’opposto dell’enunciato 2,10 si ottiene associando biiettivamente i
numeri naturali agli elementi di e di ogni teoria del prim’ordine nel modo
seguente.
Definizione 2.41
Si consideri una qualunque teoria formale del prim’ordine, dove X = {xj indichi
l’insieme delle sue variabili, A = {a,} l’insieme delle sue costanti, F = {f"‘}
l’insieme delle funzioni, la cui arità è diversa da 0, PL = {A"' } l’insieme dei
predicati ed <5 l’insieme dei simboli, ossia XuAuFuPLu {(,)/,’, V, =^>};
siano poi E l’insieme delle espressioni ed SE l’insieme di tutte le sequenze di
espressioni.
1. Si definisce, nel modo seguente, una funzione biiettiva g: S u E u SE -> N.
1.1 g(‘C) = 3, g(‘)’) = 5, g(‘,’) = 7, g(V) = 9, g(^) = 11, g(^) = 13.
1.2 Per ognix; in X, g(x() = 5 + 8 • i.
1.3 Per ogni in A, g(a.) = 7 + 8 • i.
1.4 Per ogni f"‘ in F, g( /,"' ) = 9 + 8 • i.
1.5 Per ogni A"‘ in PL, g( A"' ) = 11 + 8 • i.
2. Sia e = 5152 • • • 5„ una qualunque espressione appartenente ad E. Risulta allora
g(e)=2g(’1’ -3g(j2)... psn(Sn), dove p, indica l’z-esimo numero primo,
supponendo che pi = 2.
3. Sia se = {eb e2, ..., en} una qualunque sequenza di espressioni in SE. Si
ottiene allorag(se)= 2g(e') •3g(<'2) ••• .
che la relazione y = 23 -3*1 ••• p5t ha come funzione caratteristica una funzione
ricorsiva primitiva di x, y, z.
ESERCIZIO
2.23 Si dimostri che le relazioni, che esprimono il fatto che x è il numero di Godei
di un termine di e di una formula atomica di sono ricorsive
primitive.
Ulteriori analisi, che si sviluppano a partire dai concetti ora esposti, portano alla
dimostrazione del seguente enunciato, che è la controparte dell’enunciato 2.10.
Enunciato 2.11
Una funzione f sui numeri naturali, che sia rappresentabile in A, è ricorsiva
parziale.
■
Un ovvio corollario degli Enunciati 2.10 e 2.11 afferma che una funzione risulta
ricorsiva parziale e totale se e solo se esiste una fbf V, con variabili libere xb ...,
x„+b nella quale, per ogni numero k}, kn+i, valgano le seguenti condizioni:
1. Se/(£i, • ••, kn) = kn+1, allora >- 'V^1’ ’^"+1
Mediante gli Enunciati 2.10 e 2.11 si può ora costruire, seguendo il procedimento
accennato qui di seguito, una fbf di ^<3/ che stabilisca la sua indimostrabilità. Si
Note bibliografiche
La logica matematica è un campo importante della matematica che ha le sue radici
negli antichi scritti di Platone, Aristotele, Descartes, ecc. La maggiore spinta in
avanti verso l’attuale formulazione matematica è stata data tuttavia alla fine del
1800 e nella prima metà del 1900. Peano (1891) ha dato contributi fondamentali
soprattutto nella trattazione assiomatica dell’aritmetica. Godei (1930, 1931, 1934)
ha fornito importanti contributi sui sistemi completi e incompleti ed ha dimostrato
l’incompletezza dell’aritmetica. Church (1936) e Rosser (1936) hanno esteso
considerevolmente i risultati di Godei.
Alcuni testi classici che vengono suggeriti per una trattazione approfondita di
questa materia sono: Kleene (1952, 1967), Church (1956) e Mendelson (1964).
Alcuni capitoli sulla logica matematica sono spesso inseriti all’interno di testi
di informatica teorica. Si vedano ad esempio: Manna (1974), Lewis e
Papadimitriou (1981) e Manna e Waldinger (1985).
Si ricorda che, recentemente, alcuni argomenti di logica matematica più
complessi di quelli introdotti qui, hanno trovato rilevanti applicazioni
nell’informatica (Pnueli, 1979). Un esempio importante è dato dalle teorie di
ordine superiore. In contrasto con le teorie del prim’ordine, che, prendono il nome
dal vincolo che i quantificatori si possano applicare solo a varibili, ossia “oggetti
del prim’ordine”, le teorie di ordine superiore permettono di quantificare nomi di
funzioni e di relazione; inoltre, tali teorie consentono ai predicati di avere altri
predicati o simboli di funzione come argomenti. Hasenjager e Scholz (1961)
fornisce alcune nozioni fondamentali su questo argomento. Si noti che, sotto
un’opportuna semantica, è stato dimostrato che qualsiasi logica di ordine superiore
può essere “tradotta” in perdendo brevità e naturalezza (Montagne, 1965).
Infine, si sottolinea che recentemente sono stati sviluppati strumenti a supporto
delle prove formali in logica del prim’ordine. La maggior parte di tali strumenti,
quali Spass (Weidenbach et al., 2009) e Prover9 (McCune, 2005), utilizzano come
tecnica di dimostrazione la risoluzione (Gallier, 1986).
Capitolo 3
Nella maggior parte dei campi dell’ingegneria, la fase di progetto si fonda sull’uso
di modelli, in quanto risulta spesso impossibile, o poco pratico, verificare se la
soluzione di un problema sia adeguata o meno, applicandola direttamente al mondo
reale. Ad esempio, nella maggior parte dei casi pratici, sarebbe assurdo costruire un
ponte senza prima effettuare determinate scelte di progetto fondate su un opportuno
modello del problema.
In alcuni casi l’ingegnere può usare modelli fisici', le osservazioni e le misure
su un ponte reale, anche se di dimensioni notevolmente ridotte, possono aiutare a
prevedere il comportamento del ponte che deve essere effettivamente costruito. I
modelli fisici non possono tuttavia risolvere tutti i problemi ingegneristici per una
serie di motivi:
a. Può risultare difficile, o molto costoso, costruire un modello fisico del
fenomeno che si sta studiando.
b. Un modello fisico può rivelarsi utile, dopo che tutte le principali decisioni di
progetto siano state prese, come strumento sperimentale per il controllo di
qualità. La costruzione di molti modelli fisici diversi, per esaminare
approfonditamente progetti differenti, risulterebbe inaccettabilmente costosa
nella maggior parte dei casi pratici. Di conseguenza, i modelli fìsici sono più
utili per la valutazione del progetto piuttosto che per la sua sintesi.
c. Può risultare difficile tradurre i risultati di esperimenti effettuati sul modello in
risultati validi per il caso reale.
d. Può risultare difficile ottenere un controllo accettabile sulla accuratezza delle
misurazioni effettuate sul modello fisico.
Il progetto può anche essere coadiuvato dall’uso di modelli formali. Un modello
formale opera su oggetti matematici che rappresentano le astrazioni delle entità
reali che devono essere modellate. I modelli formali consentono all’utente di
applicare il rigore del ragionamento matematico per dedurre le proprietà delle
entità modellate. Ad esempio, la struttura di un ponte e le forze ad esso applicate
possono essere descritte da un sistema di equazioni matematiche, la cui risoluzione
consente al progettista di conoscere in anticipo le intensità e le direzioni degli
sforzi interni.
I modelli formali richiedono fondamentalmente:
1. La formalizzazione del problema, ossia la traduzione del problema reale in
una notazione propria di qualche formalismo matematico.
78
Informatica teorica
Esempio 3.1
Si consideri il problema seguente. In un’aia vi è un certo numero di polli ed un
certo numero di conigli. La loro somma è 20. Inoltre il numero totale delle zampe è
60. Quanti polli e quanti conigli vi sono nell’aia?
Uno studente che conosca l’uso delle equazioni probabilmente ragionerebbe
nel seguente modo: “Siano x e y, rispettivamente, il numero dei polli e dei conigli.
Le conoscenze relative agli animali nell’aia possono essere rappresentate dalle
seguenti equazioni
x + y = 20
2x + 4y = 60
79
L’uso dei modelli in campo scientifico e ingegneristico
Esempio 3.2
Si supponga che una mela matura cada dalla cima di un melo alto h metri. Si
chiede di calcolare il tempo t richiesto dalla mela per raggiungere il suolo.
La fisica elementare suggerisce una semplice astrazione del fenomeno che si
sta studiando. La mela può essere rappresentata da un punto materiale; la sola forza
applicata al punto è il suo peso. Secondo la legge della gravità di Newton, la mela
ha un’accelerazione g = 9.81 m/sec2. Poiché la velocità di partenza della mela è
nulla, la relazione fra h e t è rappresentata dalla seguente equazione.
À=--g-r2 (El)
2
L’equazione (El) mostra che t dipende solo da h. Da osservazioni pratiche,
tuttavia, è noto che ciò non vale, in generale, per ogni oggetto. Ad esempio, il
tempo ta richiesto da una mela è diverso dal tempo ts richiesto da un foglio di carta
per raggiungere il suolo dalla medesima quota h.
Per comprendere meglio le ragioni per cui si è giunti a questa apparente
contraddizione, bisogna analizzare attentamente il modello formale che è stato
impiegato e le astrazioni che esso comporta. In questo caso, infatti, si è
rappresentato l’oggetto che stava cadendo come un punto materiale soggetto solo
alla forza di gravità: nel modello formale, quindi, l’attrito dell’aria è stato
completamente ignorato. Le osservazioni pratiche mostrano che questa è un’ipotesi
ragionevole nel caso della caduta di una mela, ma produce risultati inaccettabili nel
caso di un foglio di carta.
■
Come si è avuto modo di osservare nell’introduzione di questo capitolo, i modelli
formali forniscono una visione astratta e semplificata della realtà; i risultati che si
ottengono ragionando sui modelli sono quindi a loro volta un’approssimazione dei
risultati osservabili nella realtà. Se la discordanza fra essi è troppo ampia, il
modello deve essere ripetutamente raffinato, fino a raggiungere
un’approssimazione soddisfacente (ossia un astrazione opportuna).
80
Informatica teorica
Esempio 3.3
Si supponga di voler progettare un paracadute. Sia hm la minima altezza per aprire
il paracadute e sia h la quota dell’aeroplano da cui il paracadutista si lancia. Si
desidera conoscere il massimo ritardo di sicurezza tm dopo il quale il paracadute
deve essere necessariamente essere aperto per garantire una discesa sicura.
L’equazione (El) può essere nuovamente usata come modello del fenomeno
fisico sotto esame nella fase iniziale del moto, ossia prima dell’apertura del
paracadute. Quindi tm deve soddisfare l’equazione:
h-hm=^-g-tm2 (E2)
essi devono essere formali, ossia devono conformarsi alla sintassi e alla semantica
del linguaggio di programmazione scelto.
L’evoluzione dell’ingegneria informatica e dell’ingegneria del software in
particolare, invece, si dirige sempre più verso l’impiego di linguaggi e modelli
formali in tutte le fasi della progettazione. La formalità è richiesta per migliorare
non solo l’affidabilità e la facilità di manutenzione dei programmi, ma anche per
consentire l’impiego di strumenti automatici di supporto alla progettazione. Molti
esempi di tali linguaggi formali sono già apparsi in letteratura, ma il loro impiego
sistematico nelle applicazioni pratiche richiede ancora molta ricerca e
sperimentazione per adeguarli ad esigenze in continua e spesso disordinata
evoluzione. È importante notare che i fondamenti di questi numerosi formalismi
sono radicati nei concetti teorici che verranno analizzati in questo testo. I concetti
che verranno studiati qui forniranno, perciò, soprattutto la base su cui si può
fondare la definizione e l’analisi di rigorosi linguaggi formali impiegabili nella
definizione di modelli per le varie attività dell’ingegneria informatica.
L’astrazione e la costruzione di modelli svolgono dunque un ruolo essenziale
anche nella comprensione e nel progetto dei sistemi informatici, in maniera molto
simile a quanto si è visto per altri campi della scienza e deH’ingegneria. Ad
esempio, allo scopo di comprendere il funzionamento, o anche di progettare, una
nuova automobile, è perfettamente inutile modellarla come un insieme di molecole.
L’utente dell’automobile potrebbe modellarla come insieme di blocchi costruttivi
di alto livello (astrazioni), quali i freni, il volante, il pedale della frizione ecc. il cui
interesse risederebbe principlamente nelle prestazionii funzionali (spazio di frenata,
raggio di curvatura ecc.). Il progettista invece dovrebbe servirsi di un modello più
dettagliato, che evidenzi, ad esempio, i meccanismi che collegano il volante con le
ruote; quest’ultimo modello sarà a sua volta definito in termini di un altro insieme
di astrazioni, in modo da poter garantire le prestazioni funzionali richieste
dall’utente.
Analogamente, per poter usare un programma di elaborazione testi su di un
personal computer, l’utente può considerare il calcolatore come una macchina per
scrivere sofisticata, dotata di una tastiera, di uno schermo video e di una stampante,
in grado di fornire un insieme specifico di comandi per impaginare e manipolare
testi. Il progettista del programma di elaborazione testi, da parte sua, richiede
invece una visione del sistema molto più dettagliata, anche se non ha ancora la
necessità di rappresentarlo a livello di circuiti hardware. Questo argomento verrà
ora sviluppato in maggior dettaglio.
Si consideri la CPU (ossia l’unità di controllo) di un moderno calcolatore.
Essa è un insieme di un enorme numero di dispositivi a semiconduttore: alcuni di
essi sono del tipo mostrato in Figura 3.1. Il circuito di Figura 3.1 è un modello
formale di un dispositivo reale: è formato da diodi, transistori e resistor! ideali.
Questi componenti ideali possono essere rappresentati da opportune equazioni che
legano le tensioni e le correnti ai loro terminali. A seconda del tipo di analisi che il
progettista desidera svolgere sul modello, queste equazioni possono esibire diversi
82
Informatica teorica
n 1
se---- •—
V
I (a/
W
AUTOMI
Lunedi, Martedì,
lavoro Giorno lavoro
in ufficio successivo in ufficio
Giorno
successivo
Giovedì,
lavoro
in ufficio
venerdì,
Giorno
lavoro
successivo
in ufficio
Divertimento Giorno
con oh amici
successivo
Sabato,
Giorno pulizia della
successivo casa e del
giardino
Definizione 4.1
Un automa a stati finiti è una tripla (Q, I, 8\ dove
1. Q è un insieme finito di stati.
2. Z è un insieme finito di simboli d’ingresso.
3. 5 è la funzione di transizione, che può anche essere una funzione parziale:
8: gX I^Q
■
È immediato stabilire una corrispondenza con la precedente rappresentazione
grafica: i nodi rappresentano gli stati, cioè nel grafo ci sarà un nodo per ogni
elemento di Q, mentre un arco etichettato con z e diretto da q a q', con q, q'e Q
indica che 8 definita su q e i come 8(z/, z) = q’. Nel seguito, il termine AF verrà
usato indifferentemente per indicare la definizione matematica e la sua
rappresentazione grafica.
Estendiamo ora la funzione 8, che rappresenta la transizione da uno stato ad un
altro, in modo da rappresentare una sequenza di transizioni', in altre parole, se 8
indica, a partire da uno stato, quale sarà lo stato in cui si troverà l’automa in
conseguenza della ricezione di un simbolo in ingresso, introdurremo il simbolo 8 *
per definire lo stato in cui si troverà l’automa, partendo da un dato stato, dopo aver
ricevuto zero o più simboli in ingresso in sequenza. Quindi 8* definisce
l’evoluzione dell’automa, partendo dallo stato q, come conseguenza di una
sequenza qualunque di valori di ingresso x e Z*. Formalmente, 8*: Q X Z*—> Q è
tale che
4.1 II commutatore che seleziona il canale di un televisore (di vecchio tipo) può
essere ruotato sia in senso orario che in senso antiorario per scegliere fra tre
possibili canali. Nel primo caso i canali A, B e C vengono scelti in
quest’ordine. Si costruisca un modello di questo dispositivo usando un AF.
Si arricchisca poi la soluzione proposta al fine di descrivere gli odierni
telecomandi dei televisori, senza necessariamente entrare nei dettagli, ma
confrontando tale modello con l’AF precedentemente.
4.2 Si descriva il seguente gioco per mezzo di un AF. Due giocatori, detti A e B,
tirano a turno un dado. Ogni volta gioca per primo il vincitore del lancio
precedente, ad esempio A-, successivamente gioca B. Siano x e y, con
l< x, y < 6 i punteggi, rispettivamente, di A e di B. A vince se x > y,
altrimenti vince B. Si trascuri l’inizio e la fine del gioco.
4.3 * Si descriva un registro a scorrimento ad otto bit per mezzo di un AF. (Nota-.
l’esercizio richiede conoscenze elementari di hardware).
indicato da una sequenza di lettere e cifre. Il primo carattere deve essere una
lettera”. Un semplice modello può essere costruito mediante un AF in cui ciascun
carattere della sequenza di ingresso produca una transizione dell’AF e una
sequenza di ingresso corretta provochi l’evoluzione dell’AF da uno stato iniziale ad
un determinato stato finale. Tutto ciò è descritto, intuitivamente, dal grafo di Figura
4.4, in cui q0 è lo stato iniziale e qF è lo stato finale. Allo scopo di rendere
chiaramente visibili gli stati iniziale e finale nella rappresentazione grafica, lo stato
iniziale q0 viene indicato da una freccia entrante nel nodo corrispondente e che non
proviene da alcun altro nodo, mentre gli stati finali vengono indicati da un doppio
cerchio.
La rappresentazione grafica della Figura 4.4 modella la struttura degli
identificatori Pascal ammissibili, servendosi di un ipotetico processo di
riconoscimento. L’automa raggiunge il suo stato finale qF, partendo dal suo stato
iniziale qo, se e solo se la sequenza in ingresso è un identificatore Pascal corretto,
fri tal caso, si dice che TAF riconosce, o accetta, la sequenza di ingresso. La
sequenza di ingresso non è riconosciuta, ossia è rifiutata, se l’automa non
raggiunge il suo stato finale partendo dal suo stato iniziale. La tabella seguente
mostra alcuni esempi di sequenze accettate e rifiutate dall’AF mostrato in Figura
4.4.
Accettato_____ Rifiutato______
ALPHA 512
ALPHA29 9AB3C
AB3C 17
92
Informatica teorica
Si noti che l’automa di Figura 4.4 rifiuta (ossia non accetta) stringhe che iniziano
con una cifra, poiché nessun arco etichettato da una cifra esce dallo stato iniziale,
ossia la funzione 8 non è definita in q0 per un ingresso i e {0, 1, 2, ...9}; in altri
casi la funzione 8* potrebbe invece essere definita in corrispondenza di una stringa
in ingresso, ma non “portare” l’automa in uno stato finale.
Formalizziamo ora il concetto di riconoscimento di stringhe mediante AF,
introdotto intuitivamente attraverso l’esempio degli identificatori in Pascal, fri
generale, le stringhe accettate da un AF sono tutte e sole le stringhe che, se lette a
partire dallo stato iniziale, portano con una sequenza di transizioni a uno stato
finale.
Definizione 4.2
Un accettare (riconoscitore) a stati finiti è una quintupla (Q, I, 8, qn, F), dove Q, I
e 8 sono definite come nella Definizione 4.1, q0 e Q è detto stato iniziale qF cz Q è
detto insieme degli statifinali (o stati di accettazione).
■
Si noti che, mentre intuitivamente si era parlato di uno stato iniziale e uno stato
finale, la Definizione 4.2 introduce un insieme di stati finali. Si tornerà su questo a
breve, dopo aver definito che cosa si intende per stringa accettata (o riconosciuta)
da un AF.
Definizione 4.3
Una stringa x e /* è accettata (o riconosciuta) da un accettare a stati finiti se e
solo se 8*(^o, x) e F. Il linguaggio accettato (o riconosciuto) da un accettare a stati
finiti è l’insieme delle stringhe accettate dall’automa. Se A è un riconoscitore a stati
finiti, L(A) indica il linguaggio accettato da A.
■
Nelle pagine seguenti, il termine automa a stati finiti e la sigla AF verranno usati
anche nel caso di accettori a stati finiti, ogni volta che l’esistenza degli stati iniziale
e finali risulterà evidente dal contesto. Vengono ora presentati altri esempi di
accettori a stati finiti.
Esempio 4.1
Una sequenza di bit rappresenta un numero dispari se la cifra meno significativa è
un 1. Ciò può essere modellato mediante l’AF mostrato in Figura 4.5, supponendo
che l’automa legga le cifre di ingresso dalla più alla meno significativa.
93
Automi
L’AF si trova inizialmente nello stato q<h dove rimane finché continua a leggere
dall’ingresso la cifra 0. Appena legge un 1 una transizione fa passare l’automa allo
stato finale qx, poiché 1’1 letto potrebbe essere l’ultima cifra della stringa in
ingresso e, quindi, la sequenza rappresenterebbe un numero dispari, cioè una
sequenza che deve essere accettata dall’automa. Se dopo 1’1 vengono lette altre
cifre, con la cifra 1 l’AF resta in q-,, seguendo lo stesso ragionamento fatto per il
primo 1 letto, mentre se legge uno 0 una transizione riporta l’AF in q(i', infatti, se
l’ultima cifra letta è uno 0, l’automa non si deve trovare in uno stato finale.
Esempio 4.2
L’AF di Figura 4.6 accetta sequenze di 0 e 1 che cominciano con almeno due 0 e
terminano con almeno due 1. Formalmente, l’automa accetta il seguente
linguaggio:
L = {0”xlm| n > 2, m > 2, x e {0, 1}*}
0 1
Figura 4.6 Un accettare a stati finiti che riconosce stringhe che iniziano con
almeno due 0 e terminano con almeno due 1.
94
Informatica teorica
L’AF dallo stato iniziale ha definito solo una transizione verso qx quando legge 0 e,
analogamente da qi, ha la sola transizione etichettata con 0 verso g2. Questo
cammino da q0 a q~, è l’unico definito e serve per verificare che i primi due simboli
della stringa letta siano due 0.
In q-2., se in ingresso c’è uno 0, l’AF resta in g2, mentre, con un 1, si muove in
q3, poiché quell’1 potrebbe essere il primo dei due 1 necessari per terminare una
sequenza accettata. Da q3, se in ingresso c’è uno 0, l’automa toma in g2, poiché la
sequenza di 1 è stata interrotta, mentre, con un 1, si muove verso lo stato finale g4.
L’AF in q3 toma in g2 con uno 0, poiché la sequenza di almeno due 1 finali è stata
interrotta, mentre rimane in #4 con un 1; infatti il linguaggio da riconoscere deve
terminare con almeno due 1 e non con esattamente due 1.
■
ESERCIZI
Inoltre non più di due occorrenze consecutive di $ possono apparire nel testo
in ingresso, esclusa la sequenza di tre $ che indica la fine dell’ingresso. Il
carattere $ non viene riportato sul testo in uscita; la sua presenza nel testo in
ingresso ha esclusivamente la funzione di carattere di controllo per le
conversioni.
Definizione 4.4
Un trasduttore a stati finiti (TF), ossia un automa a stati finiti con stati iniziale e
finale e dotato di uscita, è una 7-upla (Q, I, ò, qlt, F, O, p), dove Q, I, 5, qo, F sono
definiti come nella Definizione 4.2. O è un insieme finito di simboli di uscita e p è
la funzione di uscita (eventualmente parziale).
Definizione 4.5
Sia dato un trasduttore a stati finiti T. La traduzione if. O* associata a T è così
definita:
Esempio 4.3
Si supponga di voler costruire il modello di un robot dotato di due “mani”. Il robot
riceve da un nastro trasportatore in ingresso una sequenza di piatti e tazze, e opera
nel modo seguente all’atto del ricevimento di un oggetto.
97
Automi
Esempio 4.4
Una rappresentazione interna binaria comunemente usata per codificare i numeri
interi è la cosiddetta rappresentazione “in complemento a due”. Con questa tecnica
gli interi positivi vengono rappresentati dal loro consueto valore binario preceduto
dal bit di segno posto a 0, mentre la negazione di un numero positivo è ottenuta
complementando ciascun bit e sommando 1 al numero così ottenuto.
Vi è un altro modo equivalente di effettuare la negazione di un numero m: si
scandisce la rappresentazione binaria dalla cifra meno significativa a quella più
significativa. Le cifre vengono copiate identicamente in uscita fino al primo 1
(compreso) che si incontra. Da questo punto in poi, ogni cifra viene copiata
complementata.
La Figura 4.10 illustra un TF che modella la negazione di un numero
rappresentato in complemento a due, utilizzando la tecnica appena spiegata.
99
Automi
ESERCIZI
4.8 Si progetti un TF che:
a. Riconosca il linguaggio L = Aab)nccc(ba)in | n > 1, m > 0}
b. Traduca ogni stringa del linguaggio nella stringa dove n e m
sono gli stessi numeri di cui al punto a e, come al solito, [m/2\ indica il
troncamento intero di m/2.
4.9 Si progetti un TF che scriva un $ ogni volta che riconosce, all’interno del
testo in ingresso x e {a, b,0, 1} *, tre b consecutive con almeno uno 0 nei
precedenti cinque caratteri. Ad esempio, abbabbb(ìa\bbb produrrebbe $,
a()bbbb\cM\ab\abbb(Abbb produrrebbe $$$, etc...
4.10 Si costruisca un programma che simuli il comportamento di ogni automa a
stati finiti A usato come riconoscitore di linguaggi. Il programma deve
ricevere in ingresso una descrizione dell’automa da simulare e la stringa x da
riconoscere e deve produrre in uscita un messaggio che afferma se x e L(A).
Suggerimento: A può essere descritto da ima struttura dati costituita da:
a. Una lista degli stati di A, il cui primo elemento è lo stato iniziale.
b. Una lista di stati finali.
c. Una lista di simboli di ingresso.
d. Una matrice rettangolare di dimensioni |(?| X \I\ rappresentante la
funzione 5.
e. La simulazione del comportamento di A consiste nella lettura, carattere
per carattere, della stringa in ingresso x e nella determinazione, ad ogni
passo, del nuovo valore dello stato corrente di A, che è inizializzato a q0.
100
Informatica teorica
Teorema 4.1
Sia dato un automa a stati finiti A = {Q, I, ò, q0, F), dove Q ha cardinalità n. Il
linguaggio riconosciuto da A è non vuoto se e solo se A accetta una stringa x con
|x| < n.
" i
Dimostrazione
La parte relativa al “se” è banale, infatti se A accetta una stringa x con |x| <n, x
appartiene al linguaggio riconosciuto da A, che quindi è non vuoto. Per quanto
concerne invece la parte relativa al “solo se”, sia x e L(A) una stringa tale che
|x| < [y|, per ogni y e L(A), ossia x sia dia lunghezza minima tra le stringhe
riconosiute da A. Se |x| < n, allora il risultato è dimostrato. Si supponga dunque per
assurdo che |x| > n. Poiché A effettua una mossa ad ogni lettura di un simbolo di
ingresso, A deve passare attraverso lo stesso stato più di una volta durante il
riconoscimento di x. Si può dunque trovare uno stato q in Q e scrivere x come
X|X2x3, x2 f s, in modo tale che:
- 8*(^0, xi) = q-,
- 8*(q, X2) = q;
- &*(q, x3) e F.
101
Automi
Ciò implica che 8*(^0, Xix3) e F e quindi X]X3 g L(A). Viene perciò contraddetta la
supposizione che |x| < |y|, per ogniy e L(A). Infatti, poiché x2 * e, |xix3| < |x|.
Teorema 4.2
Sia dato un automa a stati finiti A = {Q, I, S, qo, F), dove Q ha cardinalità n. Il
linguaggio riconosciuto da A è infinito se e solo se A accetta una stringa x con
n < |x| < 2n.
Dimostrazione
Parte relativa al “se”.
La dimostrazione del Teorema 4.1 indica che per x e L(A), |x| > n implica
l’esistenza di uno stato q e delle stringhe xlrx2rx3 con x2 # s tali che x = x^2x3 e
S*(/7o, Xi) = q, ò*(q, x2) = q, ò*(q, x3) e F. Quindi 8*(^0, x;x™ x3) e F per ogni
m > 0 e infinite stringhe del tipo Xj x'" x3 appartengono a L(A).
Parte relativa al “solo se”.
Se L(A) è infinito, esiste una stringa x e L(A) tale che |x| > n. Si decomponga x
come xix2x3, in modo analogo a quello visto nella precedente parte relativa al “se”.
Se si ottiene che |xix3| < n e che |x2| < «, allora |xi x2x3| < 2n e la tesi è dimostrata.
Altrimenti, si supponga dapprima che |X]X3| > n. Se |xix3| < 2n la tesi è dimostrata
poiché X]X3gL(A). Nell’altro caso la medesima decomposizione viene applicata a
xjx3 e così via, fino a che si trova una stringa y tale che y = TiTùT con 8*(^o, Li) =
qh 8*(^i, y2) = qi, &*(qi, x3) g F e |yiT3| < n- Se [y2| <«, la tesi è dimostrata.
Altrimenti y2 può ancora essere decomposto come ziz2z3, in modo tale che z2 s e
che 8*(^i^iz3)=^i. Questo procedimento continua fino a che non si ottiene un y2
tale che 8*^!, y2') = q\Q \y2\ < n.
I teoremi precedenti sono basati sul fatto che un AF può presentare cicli nella sua
rappresentazione grafica. Se ciò non avviene, il linguaggio accettato è finito, in
quanto, poiché con una stringa in ingresso può far passare l’automa una sola volta
in ciascuno dei suoi stati, tutte le stringhe che appartengono al linguaggio
riconosciuto dall’automa sono lunghe al più come il numero di stati meno 1 (e
l’insieme delle stringhe di lunghezza limitata su un insieme finito è finito).
L’eventuale presenza di cicli giustifica anche il seguente teorema, che descrive
un’importante proprietà generale dei linguaggi riconosciuti dagli AF e che è alla
radice dei Teoremi 4.1 e 4.2.
102
Informatica teorica
Lettera cifra
Lettera
Teorema 4.4
Sia ^l’insieme dei riconoscitori a stati finiti che riconoscono un dato linguaggio
L <z /*. Sia A = (q ,1,5 ,q0,F^~un automa a stati minimi di -s/, ossia tale che
\Q | < |2| per ogni A = (Q, I, 5, q0, F). Aliorari è unico a meno di un
isomorfismo, ossia di un riassegnamento dei nomi agli stati.
■
Dimostrazione
Per dimostrare questo teorema bisogna analizzare alcune interessanti proprietà
algebriche dei linguaggi e degli AF. Si osservi innanzitutto che è possibile
associare una relazione naturale di equivalenza EL ad ogni linguaggio Z.c /*. xEyy
vale per ogni x e y e I* se e solo se x e y appartengono o non appartengono
entrambe a L. E immediato verificare che EL è effettivamente una relazione di
equivalenza su /*. Si modifichi ora EL in una nuova relazione RL, definita in modo
tale che xR^y se e solo se, per ogni z in /*, xz e yz appartengono, o non
appartengono, entrambe a L. E altrettanto immediato comprendere come anche RL
sia una relazione di equivalenza e che RL <z EL, ossia RL implichi EL. Inoltre, RL è
una congruenza destra rispetto alla concatenazione, ossia xRy implica xzRiyz per
ogni z e I*.
Si consideri ora un automa a stati finiti A e si definisca la relazione RA su /*, in
modo tale che xRyy se e solo se 5*(^0, x) = 5*(^o, y), ossia se x e y conducono al
medesimo stato partendo da q0. Si intuisce facilmente che RA è una relazione di
equivalenza ed è anche una congruenza destra, così come si era visto per RL. Inoltre
xRyy implica evidentemente xRL^Ay, poiché A raggiunge, per x e per y, il medesimo
stato, appartenente o meno a F. Si ottiene dunque il seguente enunciato.
Enunciato 4.5
Per ogni automa a stati finiti A, la relazione RA è un raffinamento della relazione
Rl(a), ossia Ra cz Rjyi). Inoltre, poiché Vindice di RA, ossia il suo numero di classi
di equivalenza, è pari a \Q\, per ogni linguaggio L accettato da qualche AF, segue
che Rl è di indice finito. In generale, indice^Ruff) < indiceiRff
■
Si verifica anche la validità dell’enunciato inverso.
Enunciato 4.6
Si consideri un qualunque linguaggio L, tale che RL sia di indice finito. E allora
possibile costruire un AF AR = (Qr, I, 8r, q0R, FR} tale che L = L(AR) e
I2à| = indice(RL).
104
Informatica teorica
La coppia di Enunciati 4.5 e 4.6 è nota anche con il nome di teorema di Myhill-
Nerode.
A questo punto è possibile completare la dimostrazione del Teorema 4.4,
osservando che AR è l’automa a stati minimi A , a meno di un eventuale
riassegnamento dei nomi agli stati. Infatti, sia q uno stato di A . Deve allora
esistere un x tale che 5* (qQ ,x) = q, poiché altrimenti q potrebbe essere rimosso
da Q senza alterare L(a ), contraddicendo così la minimalità di A . In
corrispondenza di tale x, si indichi q con il simbolo [x] e si verifichi la coerenza
della definizione attraverso il fatto che se 8*(qQ,x) = 8* (q(i,y) allora xR~y e
quindi xRyy, a causa dell’Enunciato 4.5. Si ha quindi [x] = [y].
La minimalità di A = AR si deduce allora dal fatto che
|2r| = indice(Ri) < indice(RA) = |0| per ogni automa a stati finiti A che riconosce
L.
■
L’automa a stati finiti AR è chiamato riconoscitore (accettare) canonico di L poiché
è unico, a meno di una ridefinizione del nome degli stati. La dimostrazione del
Teorema 4.4, tuttavia, afferma 1’esistenza di un automa minimo senza fornire
un’esplicita procedura per costruirlo. Allo scopo di ottenere una dimostrazione
costruttiva del Teorema 4.4, si può procedere nel modo seguente. Si consideri un
qualunque automa a stati finiti A.
1. Si eliminino dapprima tutti gli stati inutili da Q. Uno stato q si dice inutile se
non esiste un x per cui 8*(g0, x) = q oppure se non esiste un y per cui
8*(g, y) e F. È facile costruire un algoritmo che effettui tale eliminazione.
Tale costruzione viene lasciata per esercizio al lettore.
2. Si definisca poi una relazione di equivalenza D su Q in modo tale che qDq se
e solo se, per ogni x, entrambi o nessuno dei due stati 8*(q, x), 8*(q',x)
appartengono a F. D può essere facilmente verificata per mezzo di un
algoritmo, poiché, come al solito, se per qualche q e qualche q' esiste un x per
105
Automi
Esempio 4.5
Si consideri l’AF di Figura 4.11. È immediato comprendere che q\Dq2 poiché
8*(<7i,x) e F, così come 8*(<72, x) per ogni x e {A, ..., Z, 0, 1, ..., 9}*. Tuttavia
q^Dqx non vale poiché 8 *(<70, s) £ F, mentre 8*(<7b e) e F. Quindi, applicando la
costruzione precedente, si ottiene l’AF di Figura 4.12, che coincide con l’AF di
Figura 4.4 a meno di un cambiamento di nomi per gli stati.
ESERCIZI
4.11 Si minimizzi l’AF soggiacente al TF di Figura 4.7.
4.12 Si minimizzi l’AF di Figura 4.13.
4.13 Si suggerisca una procedura per minimizzare i TF e si costruisca un
programma che la implementi
4.14 Si minimizzi il TF di Figura 4.7.
107
Automi
Corollario 4.7
Dati due AF Ai e A2, risulta L(AA = L(A2) se e solo se gli automi minimi associati
e A2 sono identici, a meno di una ridefinizione dei nomi degli stati.
■
11 Teorema 4.4 e il Corollario 4.7 sono esempi che mostrano come l’applicazione
delle proprietà matematiche di un modello possa fornire risultati di interesse
pratico. Minimizzare il numero di stati di un automa, infatti, corrisponde spesso a
minimizzare le risorse necessarie alla realizzazione del sistema da esso modellato.
Analizziamo ora le proprietà di chiusura dei linguaggi riconosciuti dagli AF
rispetto alle comuni operazioni insiemistiche, la concatenazione e l’operazione
Il concetto di chiusura rispetto a un’operazione OP si estende in modo naturale dal
comune concetto di chiusura matematica, che definisce un insieme X chiuso
rispetto a un’operazione OP, se, presi due qualsiasi elementi xi e x2 di X, Xi OP x2 è
ancora un elemento di X. Ad esempio, è noto che i numeri naturali sono chiusi
rispetto alla somma e alla moltiplicazione, ma non rispetto alla sottrazione e alla
divisione, mentre i numeri interi sono chiusi rispetto alla somma, alla sottrazione e
alla moltiplicazione, ma non rispetto alla divisione. Per una famiglia di linguaggi L,
tale nozione si estende in modo banale. Diremo, cioè, che la classe L è chiusa
rispetto a un’operazione OP se e solo se per ogni coppia di linguaggi Li e L2 in L,
Li OP L2 è ancora in L.
Analogamente al problema della minimizzazione degli AF, lo studio delle
operazioni applicate a linguaggi non ha un puro interesse matematico, ma è di
notevole utilità nella pratica. Si consideri ad esempio il seguente problema. Sia Li il
linguaggio dei documenti Word Mac-compatibili e L2 il linguaggio dei documenti
Word Windows-compatibili. Quali sono i documenti Word non compatibili con
Windows? E l’insieme dei documenti compatibili con entrambi i sistemi operativi?
Per rispondere a queste domande basta calcolare il complemento di L2 nel primo
caso e l’intersezione tra Li e L2 nel secondo.
Esistono molti altri esempi in cui le operazioni sui linguaggi si dimostrano
utili per risolvere problemi pratici. Questa considerazione rende molto interessante
studiare le proprietà di chiusura della famiglia di linguaggi riconosciuti da una
classe di automi rispetto a tali operazioni. I seguenti teoremi analizzeranno quindi
tale problema per gli AF.
In particolare i Teoremi 4.8, 4.9 e 4.10 mostrano che la classe di linguaggi
accettati dagli AF è chiusa rispetto all’intersezione, al complemento e all’unione.
Altre proprietà di chiusura verranno dimostrate successivamente.
Teorema 4.8
La classe dei linguaggi accettata dagli automi a stati finiti è chiusa rispetto
all’intersezione.
108
Informatica teorica
Traccia di dimostrazione
Siano dati due generici AF Ar = (Qi, E, 6b <701, Fi) e A2 = (Q2,12, 82, q02, F2). Si
supponga che I\= I2 = T, si noti che tale ipotesi non comporta nessuna perdita di
generalità, infatti qualora gli alfabeti su cui sono definiti Ai e A2 fossero diversi,
poiché la funzione di transizione non deve essere necessariamente totale, si
possono considerare i due automi come definiti su I\ u I2. Siano poi Q\, Q2
disgiunti; anche questa ipotesi non lede la generalità della dimostrazione, poiché
può essere banalmente garantita cambiando il nome agli stati di imo dei due. Si
consideri quindi l’AF A = (Q, I, 8, q0, F) costruito nel modo seguente.
- Q = Qi * Qi,
- qo = (qoi, qoì);
~ F= {(q',q")\q' e Fh q" e F2};
- q2), a) = )qi, q2) se e solo se 81(^1, a) = qi , ò2(q2, a) = q2 .
Per dimostrare che A riconosce effettivamente il linguaggio L(A|) n L(A2) è
sufficiente applicare un naturale ragionamento per induzione alla funzione 6*.
■
Intuitivamente, l’AF che riconosce il linguaggio L(At) n L(A2) è ottenuto
simulando il funzionamento parallelo di Ai e A2, accoppiando i due automi
attraverso il prodotto cartesiano tra gli stati e definendo la funzione di transizione
di A solo dove è definita sia in Ai sia in A2. Il seguente esempio illustra la
costruzione del Teorema 4.8.
Esempio 4.6
Consideriamo l’automa Ai = (0b/b 61,901,-Ai), con Qi = {s0, 5J, I\ = {a,b,c},
qoi = So, F\ = {s$} e 81 definita nel seguente modo bi(s0,a') = s0, 8i(50, Z>) = 5b
61(50,c)=Si, 61(51,a) = Sd, 51(s1,b)=sI, 61(5/,e) = sh rappresentato graficamente in
Figura 4.14(a), e l’automa A2 = )Q2,12, 82, 902, F^, con Q2 = {t0, fj, I2 = {a, b, c},
q02 = io, F2 = {f0} e 82 definita nel seguente modo 62(f0, c) = f0, 62(f0, b) =
62(fb c) = fb 62(/|, a) = f0, rappresentato graficamente in Figura 4.14(b).
I due automi rispettano le ipotesi enunciate nella traccia della dimostrazione
del Teorema 4.8: A = I2 e Q\ e Q2 sono disgiunti. Analizzando gli automi, possiamo
dedurre che Ai riconosce il linguaggio L| = {x e {a, b, c}* | x = ya con
y e {a, b, c} *} e A2 riconosce il linguaggio L2 = {x e {a, b, c} * | x = x1x2...xn con
x; = c * oppure x,- = bc *a}.
Intuitivamente, appartengono all’intersezione quelle stringhe su {a, b, c} che
rispettano i vincoli imposti sull’ordine dei letterali da L2 e che finiscono con ‘a’
come imposto da Lx. Possiamo quindi costruire l’intersezione in modo preciso
secondo lo schema proposto precedentemente, ottenendo l’automa rappresentato in
Figura 4.15.
109
Automi
Teorema 4.9
La classe dei linguaggi accettata dagli automi a stati finiti è chiusa rispetto al
complemento.
HO
Informatica teorica
Traccia di dimostrazione
Si consideri l’AF A=(Q,I,8,q^F). Si costruisca dapprima un AF A', aggiungendo
un nuovo stato q ad A in modo tale che la funzione di transizione di A ' conduca a
q ogni volta che è indefinita in A. Inoltre, si imponga che l’automa rimanga in q
per ogni simbolo di ingresso. Con questa operazione si rende totale la funzione di
transizione di A e la corrispondente 8*. Si completa la dimostrazione mostrando
che l’AF che accetta L(A) = I* -L(A) si ottiene da ri', semplicemente scambiando
fra loro stati finali e stati non finali.
■
Si noti che l’operazione che rende totale la funzione di transizione di un automa
prima di complementarlo, aggiungendo lo stato q, chiamato stato pozzo, è
necessaria. Infatti, l’idea sfruttata dall’operazione di complemento è quella di
invertire gli stati finali con quelli non finali, invertendo cioè l’accettazione con il
rifiuto quando viene letta una stringa. Tale filosofia funziona se la stringa in
ingresso viene letta completamente dall’automa di partenza A. Infatti, in tal caso, se
la lettura termina in uno stato finale di A, terminerebbe in uno stato non finale di A'
e viceversa. Se però durante la lettura della stringa in ingresso A si blocca in
qualche stato, perché la funzione di transizione non è definita per il valore in
ingresso che si sta considerando, sia A sia A ' non riconoscono la stringa. Rendere
totale la funzione di transizione permette quindi di superare questo problema,
poiché in un automa completo qualsiasi stringa in ingresso viene letta fino alla fine.
Illustriamo anche questa costruzione attraverso un esempio.
Esempio 4.7
Si consideri l’automa A = (Q, I, 8, q<j, F), rappresentato graficamente in Figura
4.16. Tale automa riconosce il linguaggio L composto dalle stringhe sull’alfabeto
{0, 1} che contengono esattamente un ‘1’. Qualora ci limitassimo a invertire gli
stati finali e non finali, senza analizzare la totalità della funzione di transizione,
otterremmo un automa identico ad A, con l’unica differenza che risulterebbe
F’= {q0}. L’automa così ottenuto riconosce solamente la stringa vuota e le stringhe
composte da soli ‘0’, cioè solo parzialmente il linguaggio complemento di L. In
particolare tutte le stringhe che portano A a bloccarsi nello stato q\, cioè quelle
composte da più di un ‘1’, non verrebbero riconosciute. Questo è dovuto al fatto
che A non è completo, infatti 8(#b 1) non è definita. Per ottenere una funzione di
transizione totale è sufficiente aggiungere a Q uno stato pozzo q2, in cui si rimane
per qualunque simbolo dell’alfabeto, e definire la transizione da q\ a q2 con H’ in
ingresso, ottenendo l’automa in Figura 4.17. Se si invertono poi gli stati finali e
non in tale automa, si ottiene l’automa che riconosce il complemento di L.
111
Automi
Teorema 4.10
La classe dei linguaggi accettata dagli automi a stati finiti è chiusa rispetto
all’unione.
■
Dimostrazione
Si considerino due AF ztj e zt2. Allora L = L(Aj) u L(A2) = L(A1) n L(A2). Quindi,
secondo quanto affermato dai Teoremi 4.8 e 4.9, L è accettato da un AF.
■
ESERCIZI
4.15 Si completi la dimostrazione del Teorema 4.8 mostrando che gli AF definiti
nelle rispettive costruzioni accettano effettivamente L(AA n L(A2) e L(A),
rispettivamente.
4.16 Si fornisca un procedimento per costruire un AF in grado di riconoscere
l’unione di due linguaggi riconosciuti da due AF. Si svolga l’esercizio nei
due seguenti modi:
112
Informatica teorica
Gli automi a stati finiti sono anche chiusi rispetto alla concatenazione e
all’operazione Intuitivamente, per costruire l’automa che riconosce la
concatenazione dei linguaggi Li e L2, riconosciuti rispettivamente dagli automi Ai e
A2, basta costruire un automa A in cui Ax e A2 sono “in cascata”. Per quanto
riguarda la “stella” di Kleene, invece, è sufficiente creare un ciclo sui cammini
dell’AF che portano all’accettazione. Si daranno maggiori dettagli di questa
costruzione nella Sezione 4.4.
Torniamo ora ad analizzare il Pumping Lemma, che aiuta a capire i limiti
espressivi dei linguaggi riconosciuti da AF. Esso, infatti, dà una condizione
necessaria sulla struttura dei linguaggi che possono essere riconosciuti da AF.
Questo suggerisce che esistano molti linguaggi, che, non possedendo quella
struttura, hanno bisogno di un modello diverso che li descriva. Si consideri ad
esempio il linguaggio L = {d'b'"\ n > 0}. Se L fosse riconosciuto da un AFA
dovrebbe rispettare la condizione enunciata dal Pumping Lemma, cioè dovrebbe
esistere una costante k per la quale, se x e L e |x| > k, x può essere scritta come
ywz, dove 1 < |w| < k eyw'z & L, per ogni i > 0.
Cerchiamo quindi di scomporre una generica stringa di L come appena descritto.
Esistono tre possibili scomposizioni
- x = ywz con w = a e r > 0: se così fosse anche a + krbn dovrebbe appartenere a
L Vk>0;
- x = ywz con w = br e r > 0: se così fosse anche anbs + dovrebbe appartenere a
L Vk>0;
- x = ywz con w = abs e r, s > 0: se così fosse anche d'~\dbs)kbn~s dovrebbe
appartenere a L 'dk > 0.
In tutti i casi si ottiene una contraddizione e dunque L non è un linguaggio
riconoscibile da AF. Si noti che questo modo di utilizzare il Pumping Lemma è
molto comune; tuttavia serve solo a dimostrare che un linguaggio non è
riconoscibile da un AF, poiché esistono linguaggi che soddisfano il Pumping
Lemma senza essere riconoscibili con AF.
Si osservi anche che la struttura del linguaggio L considerato precedentemente
suggerisce già intuitivamente che esso non sia riconoscibile da un AF. Infatti L =
{anbn\ n > 0} ha una struttura che richiede di contare e ricordare il numero di a lette
prima di leggere una b. Questo tipo di conteggio richiede una memoria illimitata e
non può quindi essere effettuato con un AF, poiché essi contano usando gli stati
che sono per definizione finiti. Nella sezione successiva introdurremo un nuovo
modello in grado di superare questa limitazione.
113
Automi
Figura 4.18 Un robot che unisce tazze e piatti usando una pila.
Definizione 4.6
Un automa a pila è una 6-upla IQ, I, T, 8, q0, Zo) dove
1. Q è un insieme finito di stati.
2. Z è un insieme finito di simboli di ingresso.
3. T è un insieme finito di simboli, tale che T n I = 0, detti simboli ausiliari (o
simboli della pila).
4. 8 è la funzione di transizione (eventualmente parziale):
8: Q X (I u {s}) X T Q X r*
tale che se per qualche q ed A ò(q, s, A) è definita, allora ò(q, i, A) è indefinita
per ogni i.
5. q0 e 2 è lo stato iniziale.
6. Zo e T è il simbolo iniziale della pila, ossia l’unico simbolo che appare
inizialmente nella pila.
■
Prima di definire formalmente il comportamento di un AP, cerchiamo di spiegarlo
in modo intuitivo. Si ritorni dapprima al comportamento dell’AF. La lettura della
stringa di ingresso effettuata dall’AF può essere realizzata da un dispositivo ideale
dotato di una testina di lettura. Inizialmente, la testina di lettura è posizionata
all’inizio della stringa di ingresso, che si suppone scritta su di un nastro-, q0 è lo
stato iniziale del dispositivo. Ad ogni passo la testina legge un nuovo carattere e il
dispositivo passa allo stato ò(q, i), dove q è lo stato precedente ed i è il simbolo
letto, cioè passa allo stato definito dalla funzione di transizione a partire dallo stato
115
Automi
x e r
Dispositivo di controllo
ESERCIZIO
Nastro di Ingresso
Pila
Definizione 4.7
La configurazione di un AP è una tripla c = {q, x, fi), dove q e Q, x e /*, y e T. q è
lo stato corrente, x è la porzione non ancora letta della stringa di ingresso, e y è il
contenuto della pila.
■
Ogni volta che viene eseguita una transizione, l’automa che si trova in una certa
configurazione passa in un’altra configurazione, correlata alla precedente dalla
transizione appena eseguita.
Definizione 4.8
Per un dato AP A, la relazione binaria di transizione '"a nello spazio di tutte le
possibili configurazioni di A è definita da c = {q, x, fi)*~Ac'={q', x , y') se e solo se
vale una delle due condizioni:
1. x = ay, x = y, y = A[Ì, fi = aP e ò(q, a, A) = {q , a)
2. x = x , y = AP, y' = ap e ò(q, s, A) = {q', a)
■
Si noti che il simbolo A in •"a indica l’automa e non va confuso con un simbolo
della pila. Esso verrà omesso quando il contesto non consentirà equivoci. Si noti
inoltre che la condizione 1. descrive il passaggio da una configurazione all’altra
quando viene letto un simbolo in ingresso, mentre la condizione 2. prende in
considerazione il caso di s-mosse, cioè il caso in cui la testina in ingresso rimane
ferma.
Come si è osservato in precedenza, il punto 4 della Definizione 4.6 garantisce
che l’AP non si trovi in situazioni in cui può evolvere, a parità di condizioni, in
modi diversi, e di conseguenza assicura che, per ogni c, esiste al più una c tale che
c >- c . Si noti inoltre che nessuna mossa è possibile se la pila è vuota.
Analogamente a quanto fatto per la funzione di transizione degli AF, possiamo
introdurre la chiusura transitiva e riflessiva •- di •- ad indicare una sequenza di
transizioni fra configurazioni in corrispondenza a una sequenza di mosse dell’AP.
insieme di stati finali, come è stato fatto per gli automi a stati finiti. Intuitivamente,
un AP riconosce una parola quando esiste un “cammino” o sequenza di transizioni
dell’automa che, partendo dallo stato iniziale, legge tutta la parola in ingresso
giungendo in uno stato finale.
Definizione 4.9
Un accettore (o riconoscitore) a pila è una 7-upla A = ‘Q, I, T, 8, q0, Zo, F), dove
Q, 1, T, 8, q(t e Zo sono definiti come nella Definizione 4.6, e F <z Q è l’insieme di
stati di accettazione. La stringa x e I* è accettata dall’automa se e solo se
(q0, x, Zo) •- (q, 8, y) per qualche q e F, y e T*.
Il linguaggio accettato (riconosciuto) da un AP è l’insieme delle stringhe accettate
dall’AP. Se A è un AP, L(A) indica il linguaggio accettato da A.
■
Intuitivamente, una stringa x è riconosciuta da un accettore a pila se esiste un
cammino coerente con x nell’automa che porta dallo stato iniziale a uno stato finale
leggendo tutta la stringa in ingresso.
Per semplicità, il termine “automa a pila” e il suo acronimo AP verranno usati
anche per riferirsi ad un accettore a pila, ogni volta che il contesto non farà nascere
equivoci.
Analogamente a quanto visto per gli AF, un automa a pila può essere descritto
da un grafo i cui nodi rappresentano gli stati dell’automa, mentre gli archi
rappresentano le transizioni. Se 8C<y0, i, A) = (q', a), allora esiste un lato orientato
che collega q a q' e che è caratterizzato dall’etichetta a, A/a.
Esempio 4.8
Un linguaggio di programmazione di tipo classico, come il Pascal, il C, Java, ...
conferisce ai programmi una struttura ad annidamento. Tale struttura viene
realizzata mediante le seguenti parole chiavi ed i seguenti simboli:
if..fi (per le istruzioni condizionali);
do...od (per i cicli);
begin...end (per racchiudere sequenze di istruzioni);
(...) (per racchiudere espressioni e sottoespressioni).
Il simbolo speciale $ indica la fine del programma.
Desideriamo ora specificare formalmente l’idea intuitiva di corretto
annidamento e bilanciamento delle parole chiave e dei simboli. Per questo scopo
utilizziamo un AP. Quando l’automa incontra, sul nastro di ingresso, un if, do,
begin, o ‘(’> mette sulla pila rispettivamente i caratteri I, D, B o P. Quando invece
esso incontra un fi, od, end oppure ‘)’, allora, per ottenere una corrispondenza
corretta, sulla cima della pila dovranno essere presenti, rispettivamente, i caratteri
119
Automi
i
A if fi do od Begin end ( ) $
I q0JI qo.£ q^Di q»Bi q0PI
D qo,ID qQ,DD q^ qn.BD qo,PD
B qo,IB qa,DB qo,BB q^ qo,PB
P qo,IP qo,DP qo,BP qo,PP
z0 qo,IZo q^DZo qt>,BZ<} q:i:PZ0 qo,E
Esempio 4.9
Consideriamo il linguaggio L = {anbn\ n > 1}, ossia l’insieme delle stringhe
formate da un qualunque numero intero positivo di a seguito da un ugual numero di
b. Tale linguaggio può essere riconosciuto da un AP, che verifica che nella stringa
letta le a precedano le b e che per ogni a letta sul nastro di ingresso salva il simbolo
Z sulla pila, verificando poi che il numero di b letto sia pari al numero di Z salvato
sulla pila. Formalmente,
A = {{q0, qx, q2}, {a, b}, {Z, Zo}, 8, q0, Zo, {q2})
dove 8 è descritta dal grafo di Figura 4.23.
■
Per convincersi che un automa riconosce un dato linguaggio si possono effettuare
alcune prove e osservare la sequenza di mosse dell’automa. Se consideriamo
l’automa A dell’Esempio 4.9, possiamo convincerci che riconosce L, considerando
l’elaborazione relativa alla stringa di ingresso aaabbb e alla stringa aaabb, che
dovrebbero essere rispettivamente accettata e rifiutata da A. L’elaborazione relativa
a aaabbb sarà:
aaabbb, Zò) •- aabbb, ZZÒ) l“ abbb, ZZZÒ) •“
(tfo, bbb, ZZZZÒ) >- bb, ZZZÒ) >- (tfi, b, ZZÒ) ■" (tfi, e, Zò) •- (tf0, U ò)
e quindi conferma che la stringa viene accettata dell’automa. La stringa aaabb
viene invece rifiutata, in quanto A si blocca nella configurazione (cp, 8, ZZÒ), che
ESERCIZI
4.18 Con riferimento all’AP di Figura 4.23, si dimostrino le affermazioni seguenti
da 1. a 5.:
1. \/n, (q0, a„, Zo) -* (q0, e, Z”Z0)
2. (q0,b,Z,Z0)^(q1,S,Z’-1Z0)
3. (qh b\ ZZ0) -* (qu e, Zo) e (qu bl, ZZ0) (qìf £, Zo) se i +j
4. lqqx, £, Zo) -* (#2, £, £>
5. La congiunzione di 1., 2., 3. e 4. chiaramente implica che
x, Zq) (q2, £, s) se e solo se x = anbn, n > 1
Suggerimento', si usi l’induzione.
4.19 Si definisca un AP che riconosca L = {anb2n\ n > 0}.
4.20 Si descriva un AP che riconosca il seguente linguaggio parentetico L, di
alfabeto Z:
/={(,), [,],<> )>•}
Le parentesi devono risultare opportunamente annidate, e l’annidamento può
avvenire a qualunque profondità. Il simbolo ‘.‘Rappresenta la fine della
stringa.
b, Zq| BZo
b,A\BA
b,B\BB
\
Figura 4.24 Un AP che accetta {wcwA}.
122
Informatica teorica
Definizione 4.10
Un trasduttore a pila (TP) è una 9-upla T= (Q, I, T, 8, q0, Zo, F, O, T|), dove Q, I, T,
8, z/0, Zo e F sono definiti come nella Definizione 4.9, O è un insieme finito di
simboli di uscita, q è la funzione di uscita r|: Q X (F-u {e}) X F O* definita ogni
volta che è definita 8. L’automa a pila A, ottenuto da un trasduttore a pila T
eliminando O ed q, è detto automa sottostante o soggiacente a T.
■
Una descrizione grafica di un TP si può facilmente ottenere come estensione della
notazione usata per gli AP. Nel caso dei TP, gli archi vengono etichettati mediante
una 4-upla {a, A, a, z) (scritta a, A/a, z), dove a, A, e a sono definite come nel caso
degli AP, mentre z è la stringa di uscita.
Definizione 4.11
Una configurazione di un TP T è una quadrupla c = {q, x, y, z), dove q e Q, x e /*,
ye l’, z e O*. La relazione di transizione c^c, con c = {q, x, y,z),
Automi 123
c = (q, x, y', z'\ viene definita analogamente a quanto visto per la >-A nella
Definizione 4.8, con le seguenti aggiunte:
z -zz ;
z = q(y, a, A) nel caso (a);
z = r|(<y, e, A) nel caso (b).
Definizione 4.12
Una traduzione r: /* —> O* è associata a Tnel seguente modo:
= z se e solo se {q0, x, Zo, e) >-T* {q, e, y, z), q e F, e,
t(x)
per nessun q', y', z', (q, e, y, z) >- (qr, e, y', z')1
■
Si osservi che, dato un TP T e una stringa x, la traduzione di x è definita solo se x
viene accettata dall’AP sottostante a T.
Esempio 4.10
Si ritorni al robot di Figura 4.18 che assembla piatti e tazze. La pila illimitata, che
non si poteva modellare mediante la memoria finita di un AF, si può invece
modellare efficacemente mediante la memoria a pila di un AP. Il TP che modella il
robot si può descrivere nel modo seguente.
1. Q = {qG, qi, q2}, dove gli stati hanno il seguente significato intuitivo:
q0: entrambe le mani libere;
qit nella mano sinistra c’è una tazza, la destra è libera;
q2: nella mano sinistra c’è un piatto, la destra è libera.
2. I = {p, t}, dove p sta per piatto e t per tazza.
3. T = {Zo, P, T}. La pila modella la pila del robot. Zo è il simbolo iniziale della
pila. P (rispettivamente, T) rappresenta il piatto (la tazza) quando viene
deposto sulla pila per un successivo assemblaggio.
4. O = {a} dove a indica un oggetto assemblato.
5, 6 ò e q sono definite dalla Figura 4.25.
1 Si assume questa restrizione per rendere univoca la definizione di t. Si osservi però che
essa potrebbe avere anche la conseguenza di non definire la traduzione di una stringa x pur
accettata dall’automa sottostante nel caso il trasduttore possa eseguire una sequenza infinita
di mosse del tipo (q, s, y, z) •- (q', s, y', z'). Approfondiremo questa osservazione nella
Sezione 4.4.3 (Definizione 4.14. e Teorma 4.13).
124
Informatica teorica
t, T\ TT, £ t, PI e, a p, P | PP, s
Esempio 4.11
Si supponga di voler tradurre una stringa x del tipo wd, w^{a, b}*, in >/, ossia
nella stringa riflessa. Così, ad esempio, x = aabbabad verrebbe tradotta in
ababbaa. Il seguente TP T è in grado di svolgere questo compito:
T= ({q0, qi, q2}, {a, b, d}, {A, B, Zo}, 5, q0, {q2}, {a, b}, T|)
dove 8 e q sono descritti in Figura 4.26.
T legge la stringa di ingresso nello stato q0 e memorizza A (B) nella pila se
riceve una a (b). Leggendo d, T commuta allo stato q2, dove viene prodotta l’uscita
senza ulteriore lettura. Se una A (B) è sulla cima della pila, una a (è) è presente in
uscita. Quando appare Zo sulla cima della pila, T entra nel suo stato finale q2.
125
Automi
d, Zo| Z0; £
b, Zo| BZf} e
b, A | BA £
h RI RR p
Si osservi che, mentre nell’Esempio 4.10 la pila viene usata per riconoscere il
linguaggio da tradurre, nell’Esempio 4.11 la pila non è necessaria per riconoscere il
linguaggio delle stringhe del tipo wd, w <= {a, b}*, ma serve invece per poter
generare la traduzione.
ESERCIZI
4.24 Si dimostri formalmente che il TP dell’Esempio 4.11 compie effettivamente
la traduzione richiesta.
Suggerimento', si usi l’induzione per dimostrare che:
1. {q0, w, Zo, e) >-T* (q0, £, Zo, dove W indica il risultato della
sostituzione delle lettere minuscole in w con le corrispondenti lettere
maiuscole, e indica il riflesso di W.
2. (qa, d, XZ0, e) ^T^qi, £, XZo, s) per ogni X& {A,B}*.
3. (</b £, XZ0, e) |-r* {qi, e, Zo, x), dove x indica il risultato della
sostituzione delle lettere maiuscole in X con le corrispondenti
minuscole.
4. (<ji, £, Zo, x) e, x) per ognix e {a, b}*.
4.25 Si costruisca un TP che realizza la traduzione
x(a”bmcm) = cb'”e\ per m,n > 1
(Non importa quale sia l’uscita se la stringa di ingresso non è del tipo
precedente).
126
Informatica teorica
Teorema 4.11
Ogni linguaggio accettato da un AF è accettato anche da un AP. Quindi gli AP
sono almeno potenti quanto gli AF.
■
Dimostrazione
Per un dato AF A = {Q, I, 5, q0, F) è immediato costruire un AP
A = {q ,I,T,8 ,q0,Z0,F^ tale che L(A) = L(A). Si definisca semplicemente
Teorema 4.12
Il linguaggio L = {anbn | n > 1} può essere accettato da un AP ma non può essere
accettato da un AF. Quindi gli AP sono strettamente più potenti degli AF.
Dimostrazione
È noto dall’Esempio 4.9 che L può essere accettato da un AP, inoltre alla fine della
Sezione 4.1.3 abbiamo mostrato attraverso il Pumping Lemma che L non è
riconoscibile da alcun AF.
127
Automi
ESERCIZIO
4.26 Si dimostri che i TP sono trasduttori di linguaggi più potenti dei TF.
Analizziamo ora un’altra differenza fra gli AF e gli AP. Ad ogni mossa, gli AF
sono obbligati a leggere un simbolo. Ciò significa che un AF A con in ingresso una
stringa x composta da n simboli fa al più n mosse. Infatti A deve continuare a
leggere tutta la stringa, finché o la stringa è stata completamente letta o entra in uno
stato per cui la funzione di transizione non è definita per il corrispondente simbolo
di ingresso. Si noti che, come osservato in precedenza (nella Sezione 4.1), preso un
qualsiasi AF è sempre possibile trasformare la sua funzione di transizione in modo
da renderla totale. Si può dunque supporre che un AF legga sempre tutta la stringa
in ingresso fino all’ultimo carattere.
Lo stesso risultato non vale, in generale, per gli AP, anche se si aggiunge un
opportuno stato di errore, come avveniva per gli AF. Infatti, poiché gli AP non
devono necessariamente leggere un simbolo ad ogni mossa, può accadere che un
AP, in qualche configurazione, entri in una sequenza infinita di E-mosse (ossia
mosse che non fanno avanzare la testina sul nastro di ingresso). Ad esempio, se
l’AP fosse nella configurazione c = {q, x, AZ(j/ e <ì(q, e, A) = {q, AA\ esso
entrerebbe nella sequenza infinita di configurazioni {q, x, AZò) (q, x, AAZg) •-
(q, x, AAAZ0) Fortunatamente, questo comportamento spiacevole per gli AP
può essere eliminato, se necessario, mediante la seguente operazione.
Definizione 4.13
Si consideri un AP A.
{q, x, a) (q',y, fi) indica che
(q, x, a) l~*A {q',y, P) e, per p = ZP', 8(g', e, Z) è indefinito.
■
Intuitivamente, ,-*d è una sequenza di mosse che porta a una configurazione da cui
non è possibile procedere con un E-mossa, cioè per potere “evolvere” dalla
configurazione raggiunta, è necessario leggere un simbolo di ingresso.
Definizione 4.14
Un AP A è aciclico se e solo se per ogni xe/*, (g0, x, Zo) »-*d (q, e, y) per qualche
?ey.
■
Quindi un AP aciclico legge sempre tutta la stringa di ingresso (senza
necessariamente riconoscerla), qualunque sia, per poi fermarsi dopo un numero
finito di mosse.
128
Informatica teorica
Teorema 4.13
Per ogni AP A esiste un AP aciclico AL ad esso equivalente.
qualche a,/3 e r’ (ossia A entra in un ciclo). In tal caso, A può essere modificato
in un equivalente AL imponendo
8(q ,s,z ) = {qE,z
se durante (q, e,z) (p, a, pay^ non si entra mai in uno stato finale; altrimenti
si impone
dove qF è un nuovo stato finale. In entrambi i casi qE è uno stato di errore adatto a
consumare tutta la stringa di ingresso restante. I dettagli della costruzione sono
lasciati al lettore per esercizio.
■
L’importanza del Teorema 4.13 appare evidente quando si analizza la chiusura dei
linguaggi riconosciuti da AP rispetto al complemento. Infatti, la costruzione
proposta per gli AF, consistente semplicemente nello scambio tra stati finali e stati
non finali, non può essere estesa ad AP non aciclici. Infatti, una parola che
determina una sequenza infinita di s-mosse non sarà riconosciuta né dall’automa
originale né dall’automa “a stati invertiti”. Potendo invece trasformare l’automa in
modo da evitare cicli, rimane possibile utilizzare una costruzione simile a quella
proposta per gli AF, mostrando così che i linguaggi riconosciuti da AP sono chiusi
rispetto al complemento. I dettagli di tale dimostrazione sono lasciati al lettore nel
seguente Esercizio 4.27.
129
Automi
ESERCIZIO
Per analizzare la chiusura dei linguaggi riconosciuti dagli AP rispetto alle altre
usuali operazioni insiemistiche, consideriamo il seguente teorema, che mostra una
limitazione importante del potere riconoscitivo degli AP dovuto ai limiti (la
strategia LIFO) relativi alla gestione della memoria a pila.Vedremo poi come
questo risultato influenza la chiusura dei linguaggi riconosciuti dagli AP rispetto
all’unione (e di conseguenza, rispetto all’intersezione e alla differenza).
Teorema 4.14
Nessun AP è in grado di riconoscere il linguaggio L = {anb™\ m = 2n oppure m = n,
n > 1}.
■
Il teorema è dimostrato in termini intuitivi, poiché la dimostrazione formale
richiede molti meccanismi tecnici che sono propri di uno stadio più avanzato della
teoria dei linguaggi formali.
L’Esempio 4.9 e gli Esercizi 4.19 e 4.21 hanno mostrato che un AP può
“contare” un numero illimitato di a solo per mezzo della sua pila, e può
“confrontare” il valore conteggiato con un altro intero solo disimpilando gli
elementi dalla pila, il che implica la distruzione dell’informazione immagazzinata
nella pila relativa al valore di n. Quindi, nel caso dell’Esempio 4.9, dopo aver letto
a”bn, un AP perderà l’informazione su n. Ciò non implica necessariamente che la
pila debba essere svuotata, ma piuttosto che il suo contenuto non può più avere
alcuna relazione con l’intero n.
D’altra parte, per ogni AP, se
{qa, anbn, Zo/ •-* (q, s, y) allora (q0, anbn+k, Zo} •-* {q, bk, y)
ESERCIZIO
4.28 Si mostri che nessun AP può riconoscere il linguaggio L = {cfbnan\ n>l},
usando un ragionamento informale simile a quello impiegato per giustificare
il Teorema 4.14.
Il risultato del Teorema 4.14 è legato al problema della chiusura dei linguaggi
riconosciuti dagli AP rispetto all’unione. Infatti il linguaggio L = {abm\ m = 2n
oppure m = n, n > 1} può essere visto come l’unione dei linguaggi {a"b"l n > 1} e
{anb2n\ n > 1} entrambi riconoscibili da AP. Questo significa quindi che gli AP non
sono chiusi rispetto all’unione, in quanto un linguaggio ottenuto per unione di due
linguaggi riconoscibili da AP non è riconoscibile da AP.
Come conseguenza del risultato appena ottenuto, possiamo affermare che i
linguaggi riconoscibili da AP non sono neanche chiusi rispetto all’intersezione e
alla differenza. Infatti, se fossero chiusi rispetto all’intersezione, visto che sono
chiusi rispetto al complemento e che l’unione di due insiemi A e B si può esprimere
come (A n B), dovrebbero essere chiusi anche rispetto all’unione. Con un
ragionamento analogo si può mostrare che i linguaggi riconoscibili da AP non sono
chiusi neanche rispetto alla differenza.
leggere un simbolo che si trova in mezzo alla pila, tale politica di accesso obbliga a
eliminare tutti i simboli impilati sopra ad esso.
Come ulteriore esempio, si consideri il robot che impila piattini e tazze,
menzionato precedentemente., La politica LIFO della pila forza il robot ad
accoppiare ima nuova tazza con il piatto più recentemente ricevuto, che si trova
sulla cima della pila. Si supponga ora che il robot debba assemblare insiemi
costituiti da un piatto grande, un piattino ed una tazza, in cui la tazza deve essere
posta sopra un piattino che, a sua volta, deve essere posto su di un piatto grande. È
facile comprendere che una memoria a pila basata su politica LIFO è inutile in
questo caso. Si indichino i piatti grandi, i piattini e le tazze con i simboli g, p e t,
rispettivamente. Se il robot immagazzina tutti gli oggetti in arrivo in una memoria
sequenziale e se segue una politica LIFO, esso non sarà mai in grado di maneggiare
sequenze di oggetti del tipo gggpppttt. Non è infatti disponibile alcun insieme
completo fino a che non vengono ricevute le tazze. Quindi tutti gli oggetti ricevuti
prima delle tazze devono essere messi da parte. Si noti che alcuni di essi
potrebbero essere tenuti nelle mani del robot, solo in numero finito, però; quindi
per sequenze del tipo gnpnf con n sufficientemente grande, gli oggetti dovrebbero
alla fine essere accantonati in una memoria secondaria. Se poi la memoria
secondaria è una memoria a pila, dopo aver ricevuto la prima tazza il robot può
prendere il piattino, ma non il piatto grande, a meno che non elimini tutti gli altri
piattini ricevuti, perdendo però la possibilità di recuperarli.
Questo esempio conferma in modo intuitivo i limiti della memoria gestita a
pila e fornisce una motivazione per cercare dispositivi ancor più generali e potenti.
Introduciamo quindi un altro modello classico dell’informatica e,
precisamente, le macchine di Turing (MT), che prendono il nome da Alan Turing,
un pioniere della teoria della computazione che per primo propose e studiò questo
modello. Seguendo lo stile consueto, viene dapprima presentato in modo informale
il modello, poi vengono fomite le definizioni formali ed esempi chiarificatori ed
infine si studiano le sue proprietà principali.
Informalmente, una macchina di Turing (MT) consiste di:
- Un nastro di ingresso T/.
- Un nastro di uscita To.
- k nastri di memoria Tb ..., T^.
Ciascun nastro è una sequenza di celle ed è infinito a destra. Ciascuna cella
contiene un unico simbolo scelto all’interno di un insieme finito di simboli del
nastro, contenente fra gli altri anche il cosiddetto spazio vuoto (blank),
indicato da b. Ciascun nastro viene letto da una testina che può leggere,
scrivere, muoversi a destra o a sinistra di una posizione, o rimanere ferma. La
testina di T/non può scrivere. La testina di To non può né leggere né muoversi
verso sinistra.
- Un dispositivo di controllo dotato di un numero finito di stati.
132
Informatica teorica
La Figura 4.27 fornisce una descrizione schematica di una MT. Tale macchina è
solitamente chiamata MT multinastro o a k-nastri.
Una configurazione di una MT a k nastri, cioè una fotografia della macchina dopo
un passo di computazione, è composta dallo stato dell’unità di controllo, dal
contenuto dei k + 2 nastri e dalla posizione delle k + 2 testine. La configurazione
iniziale corrisponde allo stato della macchina prima di iniziare la computazione ed
è composta dallo stato iniziale dell’unità di controllo, dal nastro di ingresso
contenente un numero finito di simboli non vuoti, dai nastri di memoria che
contengono solamente un simbolo speciale non vuoto Zo nella loro prima cella e
nessun altro simbolo non vuoto e dal nastro di uscita vuoto. Tutte le testine sono
posizionate sulla prima cella dei rispettivi nastri. Ad ogni passo, quindi, poiché una
transizione può scrivere solo un simbolo per nastro, solo un numero finito di
simboli non vuoti si troverà su uno qualunque dei nastri.
Esempio 4.12 •
Un robot che metta insieme una sequenza di piatti grandi (g), piattini (p) e tazze (?)
può funzionare nel modo seguente:
- Riceve tutti gli oggetti da un nastro in movimento e pone ciascun oggetto in
cima a tre pile diverse, una per le g, una per le p ed una per le i;
- Dopo aver ricevuto tutti gli oggetti, estrae una g, una p, ed una t, da ciascuna
pila e produce un insieme assemblato (a) (si veda la Figura 4.29);
- Alla fine delle sue operazioni verifica che tutte le pile siano vuote. Ciò
garantisce che sia stato ricevuto un ugual numero di oggetti dei tre tipi.
La descrizione di ima MT M che modella il precedente robot è riportata qui di
seguito. Questa macchina ha cinque stati, q0, qR, qw, qA, qE e tre nastri di memora
Ti, T2 e T3.
- Inizialmente M è in qn. Essa passa allo stato qR (uno stato di lettura), lascia
inalterati i simboli speciali Zo sui nastri Tb T2, T3 e muove le corrispondenti
testine a destra, non curandosi di quale simbolo venga letto da T/ (cioè esegue
la mossa a prescindere dal simbolo in ingresso). Entrambe le testine T/ e To
non vengono mosse (si veda la Figura 4.30a).
134
Informatica teorica
- Quando M è in qR e legge g,p oppure t dal nastro Tj, essa rimane in qR e scrive
i simboli di ingresso in I), dove j = 1 se i = g, j = 2 se i = p ej = 3 se i = t. Le
testine di Tz e di T, vengono mosse verso destra, mentre le altre testine restano
ferme (si veda la Figura 4.30b). Il nastro Ti memorizza quindi il numero di
piatti grandi, il nastro T2 il numero di piattini e il nastro T3 il numero di tazze.
- Quando M è nello stato qR e legge un simbolo vuoto da T/, ciò significa che
tutti gli oggetti sono stati letti. D’ora in poi, la testina di Tz non si muoverà
più. M commuta a <7;y(uno stato di scrittura), sposta a sinistra le testine di Tb
t2,t3e non scrive nulla su To (si veda la Figura 4.30c).
- Quando M è in qw e legge i simboli g, p e t da Tb T2, T3 rimane in qw, scrive
un simbolo vuoto al posto del simbolo letto e sposta le testine a sinistra.
Inoltre scrive una a su To e muove la corrispondente testina verso destra (si
veda la Figura 4.30d). In questo modo per ogni tripla di oggetti viene scritta
una a sul nastro in uscita.
- Quando M è in qw e legge Zo da tutti i nastri Tb T2, T3 significa che è stato
ricevuto un ugual numero di g, p e t e che tutti sono stati assemblati. La
macchina allora passa nello stato qA, uno stato di accettazione, scrive uno
spazio vuoto al posto di Zo, scrive il carattere Y (per indicare il successo) su To
e si ferma (si veda la Figura 4.30e).
- In tutti gli altri casi, cioè se in almeno uno dei tre nastri di memoria non si è
giunti a Zo, M entra nello stato di errore qE, e quindi scrive il carattere N (per
indicare il fallimento) su To e si ferma (si veda la Figura 4.301).
135
Automi
ì<Zo,2q,Zq>/«. <Zb.Zo,Zo>, <s,JtR,R.S>
^,<Zo,s,c>iN,<^,g,e >,<s,s,s,s,s>
^,<S,S,»>/K<e,g,e><sfs,s,s,s>
(d) (H
Figura 4.30 Una MT che modella un robot, i indica un qualsiasi carattere tra g,
p ot. (a) Inizializzazione. (b) Lettura, (c) Commutazione verso imo
stato di scrittura, (d) Scrittura, (e) Accettazione, (f) Rifiuto.
ESERCIZI
4.29 Ispirandosi all’Esempio 4.12, si costruisca una MT che modelli un robot che
compone insiemi formati da un piatto, una tazza, due forchette, due coltelli e
un cucchiaio.
4.30 Si costruisca una MT in grado di rappresentare un robot che mette insieme
piatti grandi, piattini e tazze, come nell’Esempio 4.12, con la differenza che
un oggetto assemblato deve essere emesso non appena ciascuna delle tre pile
contiene almeno un elemento.
4.31 Si costruisca una MT che risolva il problema dell’Esempio 4.12 usando un
solo nastro di memoria.
Definizione 4.15
Una MT a k nastri è una 9-upla M = {Q, I, T, 0,5, r|, qo, Zo, F) dove
- Q è un insieme finito di stati-,
- Z è un alfabeto di ingresso finito;
- T è un alfabeto di memoria finito;
- O è un alfabeto di uscita finito;
- F c Q è l’insieme degli statifinali-,
- qoe. g è lo stato iniziale',
- Zq g T è il simbolo iniziale dell’alfabeto di memoria;
- I, T e O contengono un simbolo speciale, detto simbolo vuoto, indicato con H> ; '
- S è la funzione, eventualmente parziale, di transizione-,
Ò:(Q-F)X IX r* -> Qx r*X {Rfi,S}k+1;
- p è la funzione, eventualmente parziale, di uscita
ipCg-Z^X Ix T4 —> Ox {R, 5'}, definita là dove è definita 5.
Definizione 4.16
Una configurazione c di una MT a k nastri Mè una (k + 3)-pla
c = {q, xliy, cxUAPa, ulo)
dove q e Q, x e y e I*, i e I ar e /f e T*, AreT, per 1 <r<k, u e O*, o g O,
T é/uTuO.
■
q indica lo stato corrente di M, xiy, arAfir, uo, indicano rispettivamente il contenuto
del nastro di ingresso, dei nastri di memoria e del nastro di uscita, in modo tale che
le restanti porzioni siano tutte vuote. Le testine di ciascun nastro sono posizionate
sulla cella che memorizza il primo simbolo della stringa che segue il simbolo T.
Definizione 4.17
Una configurazione iniziale Cq di M è del tipo
Cq = 1(1q, 7iy, 7Z0, ...,TZo,T«)
Definizione 4.18
La relazione di transizione *-M (detta anche mossa o passo computazionale) fra due
configurazioni c e c di M è definita nel modo seguente.
Siac = (p, xTiy, afMiPi, ..., aklAkfik, u\o) con
x= xi ,y = jy , ar= ar Ar ,flr = Brf3r ;
Sia c = Ip , xAi'y, a/TA/p/, ..., a/TA/P/, zz'To').
Sia ò(p, z, Ai, .Ak) = (p,Ci, Ck, N, Nj, ..., Nk) con
p e Q,Ne {R,L,S}, Cr e T,Nr e {/?,£,£} per
1 < r < k',
Sia r|(#, i, Ai, ...,Ak) = (y, M) con v e O, Me {R, S}. Allora c>-Mc’ se e solo se
vale innanzitutto la:
1. p = q.
Deve poi valere una delle seguenti condizioni mutuamente esclusive, numerate 2.1,
2.2 e 2.3:
2.1 x = x, i = i, y = y' e N= S;
2.2 x' =xi,i' = j ,y’ = y eN= R
(se y = e, allora i" = V> e y’ = s);
2.3 x = x , z" = z, y’ = iy e N=L.
Inoltre, per 1 < r < k, deve valere anche uno dei seguenti casi mutuamente
esclusivi, numerati 3.1, 3.2 e 3.3:
Infine deve verificarsi anche una delle seguenti condizioni, mutuamente esclusive,
numerate 4.1 e 4.2:
4.1 u = u e o' = v, M = S;
4.2 u = uv e o' = b , M = R.
Se, nei casi 2.3 e 3.3 x = s oppure ex = s (ossia se la testina di lettura è posizionata
sulla cella più a sinistra del nastro) non esiste un c tale che c '-Mc e M si ferma.
141
Automi
La stessa cosa avviene seSet] non sono definite in (q, i,A\, ...,At). In tali casi c
viene chiamata configurazione di arresto.
. ■
Esaminiamo il significato delle diverse condizioni alla luce del comportamento del
modello informalmente definito in precedenza. Se ò(q, i,A^, =
(p, Q, Ck,N,Ni, ...,Nk), la condizione 1. vincola lo stato di c a essere quello
di arrivo della transizione.
Le condizioni di tipo 2. definiscono l’evoluzione del nastro di ingresso nel
passaggio da c a c \ se la testina rimane ferma (2.1), le tre parti in cui la testina
divide il nastro (parte sinistra, simbolo corrente e parte destra) saranno identiche in
c e c . Se la testina si muove a destra (2.2), la parte a sinistra della testina in c
conterrà anche il simbolo corrente di c, il simbolo corrente di c sarà il primo
simbolo della parte destra in c e la rimanente parte destra di c sarà la parte destra di
c . Infine, se la testina si muove a sinistra (2.3), la parte a sinistra della testina in c
conterrà tutti i simboli della parte sinistra in c, tranne l’ultimo che diverrà il
simbolo corrente di c e la parte destra di c sarà composta dal simbolo corrente in
c seguito dalla sua parte destra.
Analogamente le condizioni di tipo 3. specificano l’evoluzione dei nastri di
memoria e le condizioni 4. quella del nastro di uscita. Si noti che nel caso delle
condizioni 3. e 4. bisogna anche considerare il simbolo che viene scritto nella
posizione corrente da 8, e che nella condizione 4. ci sono solo due possibili mosse.
Si osservi ché, come al solito, per ogni configurazione c, la relazione di
transizione vale al più per un c . Inoltre, se lo stato q di una configurazione c
appartiene a F, allora c è ima configurazione di arresto, ossia M si ferma sempre
quando raggiunge uno stato finale, anche se non è vero necessariamente l’opposto.
Come di consueto, il simbolo M verrà eliminato da *~M quando non vi saranno
rischi di ambiguità.
Definizione 4.19
Sia Muna MT multinastro. Una stringa xe/* è accettata da M se e solo se
Co = (?o, Tx, TZ0, TZ0) '~*M{q,xVy, ■■■, afL4ApA)conq e F.
Il linguaggio accettato da M è definito come L(M) = {x\x e I* e x è accettato da
M}.
■
Intuitivamente quindi, il linguaggio riconosciuto da una MT M è composto da tutte
e sole le stringhe che, coerentemente alla funzione di transizione, permettono di
andare dallo stato iniziale a uno stato finale. Si noti che per le MT, poiché nel
nastro in ingresso è possibile muoversi in entrambe le direzioni, non è richiesto che
al termine della computazione la testina si trovi al termine della stringa di ingresso;
in alcuni casi particolari la stringa potrebbe anche essere accettate pur senza essere
stata letta completamente. Si osservi, inoltre, che una volta che M ragiunge uno
stato finale, per come è definita la funzione di transizione, non lo può più lasciare e
termina la sua computazione.
Esempio 4.13
Si consideri il linguaggio L = {a>1bncn\ n> 1}. E’ facile comprendere che la MT M
ad un solo nastro schematizzata qui sotto è in grado di riconoscerlo.
Intuitivamente, M, che inizialmente si trova nello stato q0, opera nel modo
seguente.
Passo 1: Leggendo a, M passa allo stato q\ e muove la testina del suo nastro di
memoria verso destra, stando ferma in ingresso, allo scopo di spostarsi
nella prima cella libera sul nastro di memoria, senza però dimenticarsi di
contare la a sul nastro in ingresso.
Passo 2\ M legge tutte le a fino a che non viene raggiunga la prima b (se esiste).
Nel fare ciò, M scrive tanti * alla destra di Zo nel suo nastro di memoria
quante sono le a del nastro di ingresso.
Passo 3: Alla prima b, Mpassa allo stato q2, tenendo ferma la testina nel nastro in
ingresso e muovendosi a sinistra nel nastro di memoria.
Passo 4\ M legge tutte le b. Nel fare ciò, muove verso sinistra la testina del nastro
di memoria di tante posizioni quante sono le b del nastro di ingresso. Nel
suo passaggio la testina lascia inalterati i simboli * contenuti nelle cella,
ossia li riscrive identici. In questo modo, dopo aver letto tutte le b, la
testina è posizionata su Zo se e solo se il numero di b eguaglia il numero
delle a. Inoltre il numero di a (e di b) letti è rimasto memorizzato nel
nastro di memoria grazie alla lettura non distruttiva che ne è stata fatta.
Passo 5: Alla prima c, Mpassa allo stato g3, tenendo ferma la testina nel nastro in
ingresso e muovendosi a destra nel nastro di memoria, usando lo stesso
accorgimento del Passo 1.
143
Automi
Passo 6: M legge tutte le c (se ve ne sono). Nel fare ciò, muove la testina del suo
nastro di memoria verso destra di tante posizioni quante sono le c lette in
ingresso. In questo modo, quando si raggiunge il primo b a destra della c
posta più a sinistra, la testina del nastro di memoria raggiunge il primo b
alla destra dei * se e solo se il numero delle c uguaglia il numero delle b.
In tale caso M entra in uno stato finale e si ferma.
In tutti gli altri casi M si ferma in imo stato non finale.
Il diagramma della Figura 4.32 fornisce una descrizione più dettagliata di M.
Come al solito, gli stati finali sono indicati con un doppio cerchio e la mancanza di
un arco uscente significa che 8 non è definita per quei valori.
Si fornisce qui sotto la sequenza di computazione completa di M in
corrispondenza della stringa di ingresso aabbcc. Il lettore è invitato a simulare il
comportamento di M sia con altre stringhe del tipo anbncn che con stringhe non
appartenenti aL, verificando se Meffettivamente accetta/,.
(q0, ^aabbcc, TZ0) •- (qJr ^aabbcc, Zg\ b( (q}, a^abbcc, Z0*l b) •-
(q}, aa\bbcc, Z0**L b}1- (fa, aa\bbcc, Zo*1* b)1- (q2, aabTbcc, Zgt** b) .
(q2, aabblcc, 7Z0** b)1- (q3, aabb\cc, ZoV** b) >- (fa, aabbc\c, Zo*^* b) >~
(q3, aabbcc\ b , ZgV** b)1- (q4, aabbcc\ b , Z0**T b )
a,»h,<R,R>
Esempio 4.14
Si consideri il linguaggio L = {ab"\ n > 1} u {a"Z>2"| n > 1}. La MT a 2 nastri M
schematizzata qui sotto è in grado di accettare L.
Dopo un banale passo di inizializzazione, equivalente al Passo 1 dell’Esempio
4.13,
Passo P. M legge tutte le a e scrive tanti * a destra di Zo su Ti quante sono le a
presenti sul nastro di ingresso. Contemporaneamente, in modo analogo,
scrive coppie di * su T2.
Passo 2: Mentre sta leggendo le b, muove di un passo a sinistra sia le testine di Ti
che di T2.
Passo 3: Se sono state lette tutte le b e se la testina di Ti è posizionata su Zo, M
entra in uno stato finale e si ferma.
Passo 4\ Altrimenti, M legge tutte le restanti b e nel fare ciò continua a muovere la
testina di T2 di un passo a sinistra per ogni b letta.
Passo 5: Se tutte le b sono state lette e la testina di T2 è posizionata su Zo, M entra
in uno stato finale e si ferma.
In tutti gli altri casi, la stringa di ingresso viene rifiutata.
Come esercizio, il lettore è invitato a fornire una descrizione dettagliata di M,
mediante un diagramma di stato, e a verificare che M effettivamente accetti L.
■
ESERCIZI
4.32 Si costruiscano MT multinastro che accettino i seguenti linguaggi
Li = {wcw| w e {a, b}+}
L2 = {wcwA| w g {a, b}+}2
L3= {anbnl |m> 1}
L4 = {x g {a, b, c}* tale che il numero di occorrenze di a in x sia uguale al
numero di occorrenze di b o al numero delle c}.
4.33 Si costruisca una MT a 1 nastro che accetti L ={anbn} u {anb2n}.
ctVM.<S,R>
Definizione 4.20
Sia M una MT multinastro. M definisce una traduzione rM: I* O* secondo la
regola seguente:
TmCQ =y se e s°l° se Tx, TZ0, TZ0, T# )
(q, xAiy, afiAfii, con q e F.
■
Come al solito, M verrà omesso in >-M e quando non vi sarà rischio di
ambiguità.
Intuitivamente, una stringa x viene tradotta in una stringa y da una MT M, se
esiste un cammino che parte da una configurazione iniziale con x sul nastro di
ingresso e termina in una configurazione finale con y sul nastro di uscita.
Si noti che, in generale, una MT M definisce una traduzione parziale, ossia
una funzione parziale zM'-1*^0*. Infatti è indefinita sia se M raggiunge una
configurazione di arresto il cui stato non appartiene a F sia se M non si ferma mai
quando opera su x. Ciò è illustrato dai seguenti esempi.
Esempio 4.15
La MT ad un nastro schematizzata qui sotto duplica ogni stringa di ingresso di
alfabeto {a, b}+. Precisamente, = xx per ogni xe {a, b}+.
Passo 1: M legge x da sinistra a destra, copiandola, carattere per carattere, sia in
TycheinTo. -
Passo 2\ Quando si raggiunge la fine di x in Tj, M smette di scrivere e muove
all'indietro la testina di T; fino a che non viene raggiunto Zo. In questa
fase la testina di To rimane ferma e non scrive nulla.
Passo 3: A questo punto, M ripercorre T/ copiandone il contenuto carattere per
carattere su To. In questo modo una nuova copia di x viene concatenata a
To.
Passo 4\ Quando si raggiunge il primo spazio vuoto in Tj, M entra in uno stato
finale e si ferma.
Il diagramma di Figura 4.34 fornisce una descrizione dettagliata di M. Il lettore è
invitato a simulare manualmente il comportamento di M in corrispondenza della
stringa di ingresso abb.
147
Automi
Figura 4.34 Una MT che duplica le stringhe di ingresso. Una doppia etichetta
per un singolo lato è un’abbreviazione per indicare due lati
paralleli etichettati rispettivamente con le due etichette.
Esempio 4.16
La MT a 2 nastri M schematizzata qui sotto effettua la seguente traduzione:
T^anbn-) = *” ^anb2n-) = *2n n> 1
r.v(x) è indefinita se xg {anbn\ n > 1} u {anb2n\ n > 1}
Esempio 4.17
Il nastro di ingresso T, di una MT M contiene una sequenza di parole inglesi w0,
wi, ..., wm organizzate nel modo seguente.
Wo$Wib w2b ...wn*
I simboli $, b e * fungono da delimitatori e non possono apparire aH’intemo delle
parole. M cancella dalla sequenza w0$uq lb w2 b ... w„* tutte le occorrenze di stringhe
uguali a u’o e stampa la sequenza risultante sul nastro di uscita To.
Mè una MT a 2 nastri ed opera nel modo seguente.
Passo 1 : u’o viene copiata su Tp
Passo 2\ Mlegge il testo, parola per parola (la fine della lista è marcata con *). Per
ciascuna parola w, si effettuano le seguenti operazioni:
2.1 Wt è dapprima copiata su T2. Nel fare ciò, M confronta u’, con w0
carattere per carattere. La fine della parola è indicata da b o da *.
2.2 M cambia stato se e w0 risultano diverse, continuando a copiare
wt su T2.
2.3 II contenuto di T2 viene copiato su To se /Wha cambiato stato in 2.2.
2.4 Lo stato viene azzerato se c’è già stato un cambiamento di stato in
2.2 e le testine di Tj e di T2 vengono posizionate sulla prima cella
del nastro.
■
ESERCIZI
4.34 Si dia una descrizione formale dettagliata della MT deH’Esempio 4.16.
4.35 Si costruisca una MT ad 1 nastro che effettui la medesima traduzione della
MT dell’Esempio 4.16.
4.36 Si costruiscano le MT multinastro che effettuano le seguenti traduzioni:
- T/(x) = XX/<
- t2(x) = xx se il primo e l’ultimo carattere di x a, xxR altrimenti
- Tj(x)= x1*1
2 3
- T4(an)= b" se nè pari, bn se nè dispari.
4.37 Si dia una descrizione dettagliata della MT schematizzata nell’Esempio 4.17.
4.38 Si costruisca ima MT che sostituisce ogni occorrenza di ima parola data in un
testo inglese con un’altra parola data.
Suggerimento: si tragga ispirazione dall’Esempio 4.17.
149
Automi
Esempio 4.18
La MT a 2 nastri schematizzata qui sotto riceve in ingresso un numero naturale n
codificato con la notazione decimale e produce il suo successore n + 1.
Passo 1: M copia tutte le cifre di n su Tb alla destra di Zo. Nel fare ciò, muove la
testina di T2 dello stesso numero di posizioni, senza però scrivere nulla.
Si noti che l’ingresso contiene il numero n dalla cifra più significativa a
quella meno significativa, per cui la cifra più vicina a Zo sarà quella più
significativa.
Passo 2\ M legge le cifre immagazzinate in Ti da destra a sinistra, cioè dalla meno
significativa alla più significativa.
Per ciascuna cifra d
2.1 Finché d è 9, Mscrive 0 nella corrispondente cella di T2.
2.2 Alla prima cifra d diversa da 9, M scrive la cifra rappresentante
d+ 1 nella corrispondente cella di T2. Se il simbolo letto non è una
cifra (ossia è Zo), allora M scrive 1 nella prima cella del nastro To.
150
Informatica teorica
ESERCIZIO
4.42 Si simuli il comportamento della MT dell’Esempio 4.18 con gli ingressi 99,
12899 e 312.
Esempio 4.19
Costruiamo una MT M in grado di sommare due numeri naturali codificati in
binario. I due numeri n e m sono scritti sul nastro di ingresso, dalla cifra più
significativa a quella meno significativa, separati dal simbolo $. M ha tre nastri di
memoria Tb T2 e T3, e funziona nel modo seguente.
Passo 1: Copia n su T] alla destra di Zo. Nel fare ciò, le testine di T2 e di T3 non
vengono spostate.
Passo 2\ Dopo aver letto il simbolo $ che separa n e m, M copia m su T2
mantenendo ferme le testine di Tj e di T3.
Passo 3: Dopo aver letto m, le testine di T; e diT2 vengono posizionate sui
caratteri più a destra di n e di m, cioè i meno significativi. Così, M
comincia a sommare n e m, cifra per cifra, secondo le regole descritte
dalla Tabella 4.2, in cui e a, indicano rispettivamente la cifra
z-esima di n, m ed a = n + m. rt rappresenta il riporto zesimo; inizialmente
(ossia per i = 1) r, = 0.
Le cifre di a vengono scritte su T3 da sinistra a destra (ossia a-, è
memorizzato nella cella alla destra di Zo), quindi dalla cifra meno
significativa a quella più significativa. In ciascun passo, dati i valori di n,,
Legenda
152
Informatica teorica
<13
fa/
(0 = 0)
8 <0,0,« > /» < 0,0.1 > <8,1,, L.R. S >
e,<Zo,l,O>,<S,S,L,R,S> K,<l,Zo.O>,<S.4S.B,S>
b,<O,Zo,b>l
»,<Zo,O,l>,<S,S,L,R,S> b,<Ò,Zo,l> ,<S,L,S,R,S>
98
e,<Zo,i,ii >i
b,<Zo,l,0>,<S.S,L,R,S>
b,<O,Zo,b>l
«,<Zo,O,l> ,<S,S,L,R,S> »,<O,Zo,l>,<S,L,S,R,S>
(d)
154
Informatica teorica
fe)
Figura 4.36 Una MT che effettua l’addizione binaria, (a) Fase di lettura,
corrispondente ai passi 1,2. (b) Passo 3. (c) Passo 4, quando r, = 0.
(d) Passi 4 e 5, con rt■ = 1. (e) Passo 6. □ indica 0 o 1. Diverse
occorrenze di □ nell’etichetta del medesimo arco indicano la
stessa cifra. Le etichette multiple su di un singolo arco sono
un’abbreviazione per indicare diversi archi etichettati dalle
rispettive etichette. Quando necessario, i nodi racchiudono un
breve commento sul significato dello stato.
ESERCIZIO
4.43 Si simuli a mano il comportamento della M dell’Esempio 4.19 su qualche
esempio.
4.44 Si mostri che q5, q7, q$ e q9 nell’Esempio 4.19 potrebbero essere eliminati
nella costruzione di M, ossia che si può costruire una MT equivalente senza
questi stati.
4.45 Si costruisca (o perlomeno si schematizzi) una MT che effettua la somma di
due numeri decimali.
4.46 Si schematizzi una MT che esegue la moltiplicazione di due numeri
codificati in una base qualunque.
4.47 Si schematizzi una MT che stabilisce se un numero dato è primo o meno. La
macchina si deve fermare per ogni ingresso con una risposta affermativa o
negativa.
Teorema 4.15
La classe dei linguaggi riconosciuti dalle MT include strettamente la classe dei
linguaggi riconosciuti dagli AP.
Dimostrazione
Per dimostrare l’inclusione debole basta mostrare che, per ogni AP A, si può
sempre costruire una MT ad 1 nastro M che agisca esattamente come A, usando il
nastro di memoria esattamente come la memoria a pila di A. Si lascia al lettore
l’esercizio di mostrarlo formalmente.
Per provare l’inclusione in senso stretto, si osservi che una MT può
riconoscere il linguaggio {anbn} o {anb2n}, come mostrato nell’Esempio 4.14,
mentre un AP non può fare altrettanto, come dimostra il Teorema 4.14.
■
Lo stesso risultato vale per le MT usate come traduttori di linguaggio rispetto ai
TP, come enunciato dal seguente teorema, la cui dimostrazione viene lasciata al
lettore per esercizio.
Teorema 4.16
Le MT sono traduttori più potenti dei TP, ossia tutte le traduzioni effettuate da un
TP possono essere effettuate anche da una MT, ma non viceversa.
■
ESERCIZIO
La Definizione 4.15 presenta solo una delle molte versioni, leggermente differenti
fra loro, del modello di macchina che ha preso il nome da Alan Turing. In seguito
viene ora mostrato un campione di tale varietà. Si anticipa fin d’ora che tutte le
versioni presentate hanno la medesima potenza di calcolo del modello precedente.
Consideriamo, dapprima, il modello di Turing originale; esso è leggermente
diverso da quello esaminato in precedenza. Informalmente, la differenza consiste
nell’avere, al posto di nastri distinti usati rispettivamente come ingresso, memoria e
uscita, un solo nastro, che viene usato contemporaneamente come dispositivo di
ingresso, uscita e memoria (si veda la Figura 4.37).
156
Informatica teorica
Dispositivo
di controllo
Un’altra differenza rispetto alla Definizione 4.15 è che l’unico nastro del modello
originale è infinito in entrambe le direzioni. Come al solito, l’unità di controllo può
effettuare diverse mosse in dipendenza dal simbolo sotto la testina e dallo stato
interno. Una mossa consiste in:
- Cambiamento dello stato interno;
- Riscrittura del simbolo sotto la testina;
- Spostamento della testina a sinistra (L) o a destra (R) o in nessuna direzione
(5).
Convenzionalmente, l’ingresso della macchina è il contenuto del nastro all’inizio
della computazione. La testina è inizialmente posizionata sul simbolo non vuoto
più a sinistra e lo stato dell’unità di controllo viene posto pari a q0. Quando la
macchina si ferma, qualora ciò avvenga, un’opportuna convenzione definisce quale
porzione del nastro vada considerata come uscita della macchina. Formalmente,
una macchina di Turing a nastro singolo può essere definita nel modo seguente.
Definizione 4.21
Una MT a nastro singolo è una 5-upla {Q, A, 8, q$, F) in cui
- Q è un insieme finito di stati;
- A è un alfabeto finito caratteristico del nastro, comprendente un simbolo
speciale vuoto b ;
- q0 e Q è lo stato iniziale;
- F è l’insieme degli stati finali;
- 8 è la funzione, eventualmente parziale, di transizione
bfiQ-F) X A^Q 'X AX {R,L,S}.
157
Automi
ESERCIZIO
4.49 Si formalizzino le nozioni di configurazione, configurazione iniziale,
transizione, riconoscimento di un linguaggio e traduzione di un linguaggio
per le MT a nastro singolo.
Teorema 4.17
Le MT multinastro e le MT a nastro singolo sono formalismi equivalenti, ossia
accettano la stessa classe di linguaggi e realizzano la stessa classe di traduzioni.
■
Schema della dimostrazione
Ovviamente, la simulazione di una MT a nastro singolo mediante una MT
multinastro non è un problema. È sufficiente infatti aggiungere in modo molto
semplice alcuni passi, per copiare il contenuto dell’ingresso su di un nastro di
memoria all’inizio della computazione e dal nastro di memoria al nastro di uscita
alla fine della computazione.
Si consideri brevemente, invece, il caso opposto. Si supponga che una generica
configurazione di una MT a k nastri Msia del tipo di quella di Figura 4.38. Si può
rappresentare tale configurazione mediante una configurazione di una MT a nastro
singolo M' nel modo indicato dalla Figura 4.39. Il contenuto dei diversi nastri di M
può essere rappresentato in M’ sull’unico nastro, mettendo prima il nastro di
ingresso, poi i nastri di memoria e infine il nastro in uscita. Il contenuto dei diversi
nastri è memorizzato, segnando con il simbolo speciale * il punto in cui si trova la
testina in M. In M', poi, il contenuto dei diversi nastri è separato dal simbolo
speciale $, che segna anche l’inizio della stringa sul nastro di ingresso. La fine
della sequenza è invece indicata con il simbolo speciale q .
158
Informatica teorica
Dispositivo
di controllo
Dispositivo
di controllo
che marca la fine di c(Tx). Ad esempio, si supponga che c(Tx)" contenga un solo
carattere e che la testina debba muoversi a destra. M' dapprima fa scorrere di una
posizione tutti i caratteri a destra di c(Tx)”, compreso $, poi scambia c(Tx)" con *
e scrive un b nel “buco” restante.
I dettagli della costruzione sono lasciati al lettore per esercizio.
■
Sia le MT multinastro che quelle a nastro singolo si possono dotare di nastri
multidimensionali: il modello risultante è la MT con nastro multidimensionale. Un
nastro ^-dimensionale è realizzato in modo tale che ciascuna cella sia
univocamente determinata da una £-upla di interi positivi, analogamente a quanto
avviene per le matrici nella programmazione. La Figura 4.40 illustra il caso di un
nastro bidimensionale (un nastro planare). Una MT con nastro bidimensionale può
muovere le sue testine (o la sua testina) in quattro direzioni: sopra, sotto, sinistra,
destra o rimanere ferma.
Anche questo modello è equivalente agli altri e l’equivalenza con il modello
originale può essere facilmente dimostrata una volta che si stabilisca una
conveniente corrispondenza biiettiva fra N - {0} e (N - {0})\ che indicano
rispettivamente l’insieme delle posizioni della testina per i nastri lineari e l’insieme
delle posizioni della testina per i nastri multidimensionali. Ad esempio, è possibile
enumerare le celle di un nastro bidimensionale seguendo un metodo diagonale,
come mostrato in Figura 4.41, dove, per ciascuna coppia {x,y),
Informatica teorica
Una volta che si è stabilita una corrispondenza fra le posizioni del nastro, è facile
stabilire una corrispondenza fra le configurazioni delle macchine e le relative
sequenze di mosse.
ESERCIZI
Esistono altre varietà di MT, ma non è negli obiettivi di questo testo riportarli in
modo esaustivo.
Analizziamo ora il problema dell’esistenza di forme minime per le MT. Infatti,
quando si ha a che fare con modelli formali, si affronta spesso il problema della
trasformazione di un modello formale in un'altra forma equivalente più concisa, o
anche “minima”. Ciò avviene anche con i programmi per calcolatori, che si
possono trasformare in versioni equivalenti che riducono la quantità di memoria
161
Automi
Teorema 4.18
Ogni MT è equivalente ad un’opportuna MT dotata solo di due stati non finali e di
uno stato finale (ed eventualmente di un numero accresciuto di simboli).
■
La dimostrazione del Teorema 4.18 è altamente tecnica e può essere saltata dalla
maggior parte dei lettori. Il lettore interessato può cercare di ottenerla come
esercizio un po’ pesante nei dettagli tecnici da prendere in considerazione, ma
concettualmente non insormontabile, almeno facendo ricorso al “piccolo aiuto”
fornito. Una soluzione schematizzata è anche proposta alla fine del capitolo.
ESERCIZIO
4.51* Si dimostri il Teorema 4.18.
Suggerimento', senza alcuna perdita di generalità, si può considerare una MT
a nastro singolo M ed una singola mossa di M, consistente ad esempio nella
transizione:
(#7, ...<75T<73Ui3...) '“A/ (#3, .. .<75<78T<713...)
Sì costruisca una MT M a nastro singolo con due soli stati non finali, qa,
che simuli la mossa di Mattraverso la seguente sequenza di mosse.
XX, ...a5T(<77, a3,-,*)a13 ...)3 >- (q$, ...a5(q3, a*, +, 7?)Ta13 ...)>-
...T5T(g3, a8, +, R}{q0, a^, -,R)...)-
(<7p, ...as(q2, as, +, 7?XXo, «b,
«8, +, 7?Xtfl, «13, -, L')---')'-
{q?, ...a5{qx, a^, +, 7?XXi, «13, -, L')...')-
<?«,••• «5 X^l, «8, +, X%2, «13, -, L')...')
Xp, •••«5X0, «8, +, ^X<#3, «13, ”, L')---') *-
•••«s'KtfO, «8, +, ^X?3, «13, ”, ?,)•••) -
Teorema 4.19
Ogni MT è equivalente ad un’opportuna MT avente un alfabeto con due soli
simboli (eventualmente dotata di un numero maggiore di stati).
■
Il Teorema 4.19 afferma quindi che la codifica di un problema non influenza la
capacità di una MT di risolverlo. Si noti però che i Teoremi 4.18 e 4.19 impongono
una scelta: possiamo ridurre gli stati “agendo” sull’alfabeto o viceversa, ma
difficilmente, in generale, non possiamo ottenere entrambi gli scopi
contemporaneamente: una tipica situazione in cui si viene a trovare quasi ogni
ingegnere nelle sue scelte di progetto. Nel corso di questo testo troveremo diversi
altri esempi di questo genere.
Anche la dimostrazione del Teorema 4.19 è lasciata come esercizio per il lettore,
dopo aver notato che due simboli sono sufficienti per codificare qualunque alfabeto
finito. Ad esempio, siano dati i due alfabeti A = {$ , ai, ..., am}, A = {b,a}. Si può
allora rappresentare la stringa ... b b a3b ... come
... bbaabaaaaababbaaabb ...
Il simbolo a, viene cioè codificato da i occorrenze di a , mentre b viene usato
come separatore fra la codifica di ciascuna a, ed un doppio b codifica il simbolo b
originale.
Diversamente dalle MT, gli AF possono essere sensibili alla scelta della
codifica. Ad esempio, un TF può facilmente calcolare la funzione successore di un
numero naturale, se codificata in base unaria (in cui cioè n è rappresentato dalla
sequenza di n simboli identici, ad esempio a ). Il TF semplicemente copia il suo
ingresso sul nastro di uscita aggiungendovi preliminarmente un ulteriore a . La
stessa computazione non può essere effettuata da un TF se n è scritto in qualunque
altra base, come afferma il seguente teorema.
Teorema 4.20
Nessun TF è in grado di calcolare il successore di un numero naturale codificato in
una qualunque base k > 1.
Dimostrazione
La dimostrazione è data per k = 10, ma chiaramente vale allettante per ogni k > 1.
163
Automi
ESERCIZI
4.52 Si dimostri la seguente versione, più forte, del Teorema 4.20. Nessun TF può
calcolare la traduzione t: Z*$ —> (9*$ tale che t(x$) = y$, dove y è la
codifica del successore di un dato numero naturale codificato da x.
4.53 Si mostri che esiste un TP che calcola la stringa riflessa di una codifica
decimale del successore di un dato numero naturale codificato in base
decimale.
4.54 Si definiscano formalmente le seguenti variazioni delle MT e si dimostri la
loro equivalenza con il modello multinastro:
1. MT non stazionaria', ad ogni passo le testine dei nastri devono
necessariamente muoversi a destra o a sinistra e non possono restare
ferme.
2. La macchina può effettuare una delle seguenti azioni:
a. Riscrivere, senza muovere la testina.
b. Muovere la testina senza scrivere alcun simbolo.
3. MT con nastro singolo semi-infinito: il nastro della macchina è
infinito solo a destra.
164
Informatica teorica
4.55 Si dimostri che l’insieme dei linguaggi accettati dalle MT è chiuso rispetto
all’unione e all’intersezione.
4 Si ricorda che p(0 rappresenta l’insieme delle parti di Q, i cui elementi sono quindi
insiemi di stati.
166
Informatica teorica
S S
(b)
Figura 4.43 Un AFN (a) e l’albero delle scelte (b) realizzate durante il
riconoscimento. S indica accettazione. □ indica uno stato da cui la
computazione non può procedere. L’albero rappresenta tutti i
cammini attraversati durante il riconoscimento di abaaa.
167
Automi
ESERCIZIO
4.56 Si scriva un programma per calcolatore che simuli un AFN. Il programma
riceve in ingresso una descrizione deH’accettore ed una stringa da analizzare
e fornisce in uscita un messaggio di accettazione o di rifiuto della stringa.
Suggerimento', si può costruire una struttura ad albero per rappresentare tutti
i possibili cammini attraversati dall’accettore durante il riconoscimento
(Figura 4.43). Quando un cammino non può essere percorso ulteriormente, il
programma deve ritornare indietro e tentare un nuovo cammino,
scegliendolo fra quelli uscenti dallo stato più recentemente incontrato ed
ancora in grado di offrire transizioni di uscita inesplorate.
Gli automi non deterministici a stati finiti non sono più potenti dei loro
corrispondenti deterministici finché si rimane nel campo del riconoscimento di
linguaggi. Questa proprietà viene dimostrata dal seguènte teorema.
Teorema 4.21
Per ogni AFN A, può essere costruito un AF AD che accetti il medesimo linguaggio.
■
Dimostrazione
Sia A = (g, I, 8, q0, F), 5: QXl
Si definisca AD come (QD, I, òD, q0D, Fa') con
- 2n = P(e);
- &o(qD, i) = q D= U S (q, i) ;
Allo scopo di dimostrare che L(Ad) =L(A), bisogna mostrare che 8//(g0/j, x) g Fd
se e solo se 8*(g0, x) n F 0. Questa è una conseguenza immediata del fatto che
8d*(<?od, x) = 8*(g0, x) per ogni x.
Quest’ultima affermazione a sua volta può essere dimostrata per mezzo di una
semplice induzione. Infatti,
Esempio 4.20
L’AFN di Figura 4.44 riconosce alcune unità lessicali di un linguaggio di
programmazione molto semplificato: numeri, identificatori, operatori aritmetici e
commenti. Le unità lessicali vengono separate da uno o più lb. I commenti
cominciano con /* e terminano con */. L’accettore di Figura 4.44 è non
deterministico. Ad esempio, dopo aver letto una / nello stato qt), l’accettore può
entrare sia in q3 che in q4. Analogamente, dopo aver letto una * nello stato q3, può
entrare in q(> oppure rimanere in q5.
169
Automi
ESERCIZI
Definizione 4.23
Un trasduttore non deterministico a stati finiti (TFN) è definito come nella
Definizione 4.4, con l’unica differenza che le funzioni 5 e r| costituiscono una
coppia
(5, n): Q X I fpfiQ x O*)
dove pXG X O*) denota l’insieme dei sottoinsiemi finiti di Q X O*. 5 e rj sono
la proiezione di (5, r|) su Q e su O* rispettivamente:
8(g, z) = fi' | fi’, -w) e (5, T|)(g, z) per qualche w e O*}
r\fi,i)={w | fi', -w) e (5, rp(<T z) per qualche q e Q}
fi, T])*: Q X /* -> X (?*) è definito come al solito induttivamente da
fi, fi)* fi, e) = fi, e)
(5, T])*(<7, xz) = {fi’,fi) | 3q",u,v tale chey = uv e
fi",ù) e fi,fi)* fi, x) e fi',v) e <S,T]>(X', z)}
ESERCIZIO
4.60 Si scriva un programma che simuli un TFN. Si noti che, per calcolare r(x), la
simulazione richiede la costruzione di tutte le possibili sequenze di mosse
che conducono agli stati finali.
Definizione 4.24
Un accettare a pila non deterministico (APN) è una 7-upla {Q, I, T, 8, q0, Zo, F)
in cui tutti i simboli hanno il medesimo significato dèlia Definizione 4.8, escluso 8,
che è definito nel modo seguente:
8: Q x (/ u {e}) x r —> x T*)
(dove X T*) indica i sottoinsiemi finiti di Q X T*). La relazione su
Q X I* X T* è definita da {q, x, y) (q', x , y') se e solo se
1. x = ay, x =y, y = A(Ì, y' = a0, (q ,a) e 8(q, a, A)
oppure
2. x = x', y = A(Ì, y' = a0, tq',a) e ò(q, e, A)
x e I* è accettato dall’automa se e solo se
{q0, x, Zo) {q, e, y), q e F, y e T*
■
Si noti che gli automi a pila sono modelli intrinsecamente non deterministici:
infatti, nella Definizione 4.8 si era dovuto aggiungere il vincolo che, se per
determinate condizioni è definita una e-mossa, allora non è definita nessuna altra
transizione con quelle condizioni. Questo vincolo viene ora rimosso.
Il non determinismo non aumenta la potenza di calcolo degli automi a stati
finiti quando vengono usati come riconoscitori di linguaggi. Lo stesso risultato non
vale nel caso degli automi a pila, come formalizzato nel seguente teorema.
Teorema 4.22
Il linguaggio L = {anbn\ n > 1} u {anb2n\ n > 1} è accettato da un APN ma non
da un AP deterministico.
Dimostrazione
La seconda parte del teorema coincide con il Teorema 4.14. Bisogna dunque solo
determinare un APN A in grado di accettare L. Tale automa è illustrato nella Figura
4.45. L’APN in figura salva sulla pila due A per ogni a in ingresso, poi, in modo
non deterministico, si sposta in qi o in q2, dove verifica rispettivamente se il
numero di b coincide con il numero di a o è il doppio del numero di a. Se almeno
una possibile computazione porta in uno stato di accettazione leggendo tutta la
stringa in ingresso, questa fa parte del linguaggio.
172
Informatica teorica
Figura 4.45 Un APN che accetta L = {anbn\ n > 1} u {anb2n\ n > 1}.
ESERCIZIO
4.61 Si progetti un APN che riconosce il linguaggio
L= w e {a, b}*}
Poiché gli APN sono più potenti degli AP, la classe di linguaggi riconosciuti dai
primi è più ampia di quella riconosciuta dai secondi e di conseguenza non è detto
che valgano le stesse proprietà di chiusura. Analizziamo brevemente cosa cambia.
Avevamo visto che i linguaggi riconoscibili da AP sono chiusi rispetto al
complemento, ma non rispetto all’unione e all’intersezione. Nel caso degli APN le
proprietà di chiusura cambiano. Infatti, gli APN sono chiusi rispetto all’unione.
Intuitivamente, presa una qualsiasi coppia di linguaggi riconoscibili da APN, è
sempre possibile costruire un APN che riconosce l’unione, aggiungendo uno stato
iniziale che viene collegato tramite due e-mosse agli stati iniziali degli automi di
partenza, ottenendo così l’APN che riconosce l’unione.
Gli APN rimangono invece non chiusi rispetto all’intersezione, infatti il non
determinismo non permette di superare alcuni limiti della memoria a pila, che
rimane una memoria distruttiva. In particolare gli APN non possono riconoscere il
linguaggio {anbncn\ n > 1} che può essere ottenuto come intersezione di due
linguaggi riconoscibili da APN ({a*è"c"| n > l}e{a*bncn\n > 1}).
Infine, essendo chiusi rispetto all’unione, ma non rispetto all’intersezione, non
possono essere chiusi rispetto al complemento (ricordiamo infatti che l’intersezione
di due insiemi può essere riscritta in funzione di unione e complemento).
Passiamo ora a considerare l’effetto del non deterinismo sulle macchine di
Turing.
173
Automi
Definizione 4.25
Le macchine di Turing non deterministiche (MTN) vengono definite come le loro
corrispondenti deterministiche, con la solita differenza che, per una MT
multinastro, le funzioni di transizione e di uscita sono date da:
<5,r|):(e-F) X / X FÀ A p(0 X T* X {R,L,S}k+ì X {R,S})
ESERCIZIO
4.62 Si formalizzi il comportamento delle MTN quando vengono impiegate in
qualità di accettori di linguaggi, trasduttori di linguaggi e valutatori di
funzioni. Come nel caso degli altri automi, una MTN accetta una stringa se
esiste almeno una sequenza di mosse che conduce ad uno stato finale. La
MTN definisce quindi una funzione a più valori che associa la stringa di
ingresso all’insieme di tutti i possibili valori di uscita ottenuti mediante una
sequenza consentita di mosse.
Analogamente a quanto avvenuto per gli AFN rispetto agli AF, il non
determinismo non aggiunge potenza alle MT, come formalizzato dal seguente
teorema.
Teorema 4.23
Le macchine di Turing non deterministiche non sono più potenti delle macchine di
Turing deterministiche, se usate in qualità di riconoscitori di linguaggi.
Dimostrazione informale
Per dimostrare che le MTN non sono più potenti delle MT è necessario mostrare
che, data una qualsiasi MTN M, è sempre possibile costruire una MT M’ che
riconosce lo stesso linguaggio di M. Supponiamo, senza nessuna perdita di
generalità, che Msia una MTN a nastro singolo.
174
Informatica teorica
Definizione 4.26
Una rete di Petri (RP) è una 4-upla (P, T, IF, OF) in cui
- P = {pi, .. ,,pn} è un insieme finito di posti',
- T= {h, ..., tm} è un insieme finito di transizioni',
- IF: PxT —> N èiafunzione di transizione - ingresso;
— OF: TXP —> N è la funzione di transizione - uscita.
178 Informatica teorica
Come abbiamo precedentemente visto attraverso l’esempio, una rete di Petri si può
descrivere graficamente per mezzo di un grafo bipartito (più propriamente un
multigrafo) con due insiemi di nodi: uno rappresentato in modo convenzionale da
cerchi e l’altro attraverso delle barre, cioè il primo è associato a P e l’altro,
disgiunto dal precedente (P n T = 0), è associato a T. Rispetto alla precedente
introduzione informale, la funzione IF(p,t) definisce, per ogni coppia (posto,
transizione) (p, t), il numero di archi che vanno dal posto p alla transizione t. Se
IF(p,t) è diverso da zero, allora p è un posto in ingresso (o in entrata) per t.
Simmetricamente, per ogni coppia (transizione, posto) (t, p\ OF(t,p) definisce il
numero di archi che vanno dalla transizione t al posto p. Se OF(pJ) è diverso da
zero, allora p è un posto in uscita per t.
Esempio 4.21
Consideriamo la rete di Petri (P, T, IF, OF) in cui
- P={P1,...,P5};
- t= {c,
- IF è definita dalla Tabella 4.3;
- OF è definita dalla Tabella 4.4.
179
Automi
\ p
T \ Pi P2 P3 P4 PS
h 1 0 2 0 0
h 110 0 0
t} 0 0 0 1 0
t4 0 0 0 0 0
Ì5 0 0 0 0 1
T
P Ti t2 Ts L h
Pi 0 0 0 1 0
p2 0 0 2 0 0
p3 0 0 0 0 1
P4 0 2 0 0 0
P5 1 0 0 0 0
Definizione 4.27
Definizione 4.28
Data una marcatura M di una rete di Petri, si dice che una transizione t g Tè
abilitata da M se e solo se, per ogni posto p, M(p) > IF(p, t).
Definizione 4.29
La relazione di transizione •- è definita sullo spazio delle possibili marcature, ossia
suH’insieme di funzioni {M\ M: P—> }: M <- M', se e solo se esiste una t
abilitata da Me, per ognip, M'(p) = M(p) - IF(p, t) + OF(t, p).
■
La relazione di transizione >- definisce quindi l’evoluzione della rete mettendo in
relazione due marcature, solo quando da una si può passare all’altra a causa dello
scatto di una transizione abilitata. Qualora si voglia rendere esplicito che il
passaggio da una marcatura ad un’altra avviene attraverso lo scatto della
transizione t, si utilizza il simbolo •—t.
Analogamente a quanto fatto con la funzione di transizione degli automi visti fino
ad ora, possiamo definire la chiusura riflessiva e transitiva, >-*, della relazione di
tranzione. M •-* M' mette in relazione due marcature se esiste una sequenza di
scatti che porta da Afa M'.
Esempio 4.22
La marcatura M mostrata in Figura 4.49a abilita due transizioni, e f2, che possono
quindi entrambe scattare. Dalla marcatura M la rete di Petri può raggiungere quindi
sia la marcatura M\, mostrata in Figura 4.49b (nel caso in cui scattasse q), che la
M2, mostrata in Figura 4.49c (nel caso in cui scattasse t2)- M2 non è in relazione con
nessun’altra marcatura, non avendo alcuna transizione abilitata, mentre M2, a sua
volta, può produrre M2, dove Mfzò ) = Àf3(p3) = Àf3(p5) = 1, Àf3(p2) = 0, Àf3(p6) = 2,
Automi 181
Figura 4.49 Una rete di Petri (a) e le sue possibili evoluzioni (b e c).
182
Informatica teorica
Esempio 4.23
Si consideri il problema di valutare una espressione aritmetica, ad esempio (a +
ò)*(c + d). Tale problema può essere rappresentato in modo intuitivo attraverso le
RP: i posti indicano gli operandi (e quindi anche i risultati parziali ottenuti nel
calcolo dell’espressione), le transizioni indicano gli operatori, mentre la presenza di
un token in un posto indica la disponibilità del valore dell’operando
corrispondente.
La Figura 4.50 riporta la RP che rappresenta l’espressione (a + b) * (c + d).
Qualora i valori di a, b, c e d fossero disponibili, ci sarebbe un token nei quattro
posti corrispondenti e entrambe le transizioni indicate con il simbolo + sarebbero
abilitate e quindi possono scattare in qualunque ordine. La transizione marcata con
*, invece, risulta abilitata solo dopo lo scatto delle due transizioni etichettate con +,
cioè quando i risultati parziali ((a + è) e (c + d)) sono pronti.
Come si può notare dall’esempio appena considerato, le RP esprimono bene
l'ordine parziale delle operazioni e sottolineano come alcune sottoespressioni di
una espressione data possano essere parallelizzate.
ESERCIZI
4.64 Per la RP di Figura 4.48 si trovino tutte le marcature M raggiungibili dalle
marcature iniziali Mo sotto elencate, ossia tutte le Mtali che Mo >-* M.
1. Àf0(P4) = 1, M0(pi) = 0 per i * 4.
2. Mo(pì) = 1, = 0 per z #5.
3. À/o(p5) = 2, Mfe) = 1, = 0 per z #2,5.
4.65 Analogamente a quanto fatto nell’Esempio 4.23 si descriva una RP per
ciascuna delle seguenti espressioni:
1. ((a + * (c + </)) + (e -f *g))
2. (a + b * (c + d)) + a
3. a-(b + c* (b + (d-c* b)))
Le reti di Petri sono dunque un modello evolutivo non deterministico, poiché può
accadere che da ima marcatura M, dove più di una transizione è abilitata, la rete
evolva in modi diversi a seconda della transizione che scatta, cioè, M '-f M' e
Può inoltre succedere che M |-;1 Mi '-a A6 e M M2 |-,i M3, nel qual caso ri e
t2 si dicono concorrenti, per M, poiché entrambe possono verificarsi, partendo da
M, in qualunque ordine ottenendo la stessa marcatura, cioè l’ordine in cui scattano
non influenza la marcatura che viene raggiunta. Se consideriamo nuovamente
l’esempio in Figura 4.47 possiamo osservare che ri e t2 sono concorrenti; infatti,.se
in una marcatura in cui sono entrambe abilitate, una delle due scatta, l’altra rimane
abilitata.
Quando, invece, a partire da una configurazione M in cui ci sono due
transizioni abilitate, lo scatto di una porta in una marcatura dove l’altra transizione
non è abilitata, tali transizioni si dicono in conflitto, in quanto la scelta di ima di
loro impedirebbe all’altra di sparare. Le transizioni t3 e t4 della rete di Petri in
Figura 4.47 sono in conflitto.
Esistono diverse caratteristiche che una rete di Petri può avere rispetto a una
data marcatura M; tra queste risulta particolarmente interessante il numero
massimo di token che si possono generare a partire da M.
Definizione 4.30
Una rete di Petri si dice k-limitata rispetto alla marcatura M se e solo se, per ogni
marcatura M'tale che M >-* M' si ha che il numero di token nei posti della rete è al
massimo k, cioè Vp e P, M'(p) < k.
Una rete di Petri è limitata se esiste un k tale che la rete è ^-limitata.
184
Informatica teorica
Definizione 4.31
Un accettare a rete di Petri (ARP) è una 6-upla (fi, T, IF, OF, S, L, Mo, F) dove P,
T, IF, OF sono definite come nella Definizione 4.26, Mo è la marcatura iniziale, F
è un insieme finito di marcature finali, S è l’alfabeto di ingresso e L: f-> Su {s}
è una funzione che etichetta ogni transizione della rete con un simbolo dell’alfabeto
di ingresso oppure con a, nel caso di etichetta vuota.
■
Un ARP, quindi, non è altro che un rete di Petri per cui viene definita una
marcatura di partenza e un insieme di marcature finali e in cui le transizioni
possono essere etichettate con simboli dell’alfabeto di ingresso.
Definizione 4.32
Una sequenza di sparo (o sequenza di scatto) t, per un dato ARP R, è un elemento
di T*-t =ti1 ti2 ■■■t. e la stringa s, definita come
b zi
s =
l2 L(t.)L(t.
ìn )---L(t. ), è
accettata da R se e solo se esistono n - 1 marcature Mi, ..., M„.\ di R tali che:
Ma'-, Mt*- M2...Mn.!'~t‘ M„ conMn F
‘ '1 * '2 ‘ hi
■
Intuitivamente, il linguaggio riconosciuto da un APR è formato dalle stringhe che
si possono ottenere da tutte le sequenze di sparo che dalla marcatura iniziale
portano in una marcatura finale. Formalmente, dato un ARP R, il linguaggio
riconosciuto da7? è definito come L(R) = {s| s e X* ed5 è accettato da/?}.
Esempio 4.24
Si consideri la rete di Petri di Figura 4.51 e si assuma come Mo la marcatura in
figura. L’insieme delle marcature finali F è composto dalla sola marcatura MF, tale
che MfiPl) = MfiPfi = 0 e MF(P2) = 1. Alcuni esempi di sequenze di sparo che
portano dalla marcatura iniziale alla marcatura finale sono t2, tq2h, tddzhh,
tdd\ht-ìhh, ..., a cui corrispondono le stringhe c, acb, aacbb, aaacbbb, ....
La marcatura iniziale abilita sia fi che t2, ma, mentre lo scatto di fi, oltre a
aggiungere un token nel posto P2, riporta il token consumato nel posto Pi, lo scatto
185
Automi
Cerchiamo ora di capire in che relazione si trovano gli ARP con gli altri modelli
visti fino ad ora. Essi sono strettamente più potenti degli automi a stati finiti. Infatti
un AF A non può riconoscere il linguaggio L = {ancbn | n > 0}, che è invece, come
visto nell’Esempio 4.24, riconoscibile con un ARP, mentre può essere banalmente
trasformato in una rete di Petri R equivalente nel seguente modo:
- per ogni stato q, di A viene definito un posto Pi in R;
- se 8(</„ 5) = qj, si definisce una transizione 4, con L(tk) = s con il solo P, in
ingresso e il solo Pj in uscita;
- la marcatura iniziale è definita mettendo un token nel posto Pq,
- l’insieme delle marcature finali è composta da tutte le marcature che hanno un
unico token in un costo PF corrispondente a imo stato finale di A.
Qualora si considerassero però ARP limitati, essendo finito e fissato a priori il
numero massimo di token per ciascun posto, gli ARP perderebbero la capacità di
“contare” un numero non noto di simboli, come è necessario ad esempio per L =
{ancbn | n > 0}, e avrebbero la stessa potenza espressiva degli AF.
Confrontiamo ora la capacità di riconoscimento di linguaggi degli ARP con
quella degli APN.
Esempio 4.25
Si consideri il linguaggio L = {d'bncn | n > 0}, che come già visto in precedenza
non può essere riconosciuto da un APN. Tale linguaggio può essere invece
riconosciuto da un ARP, ad esempio quello riportato in Figura 4.53, con la
marcatura iniziale riportata in figura e F = {MF} tale che M^Pp) = 1 e MAPj = 0,
Vi <5.
187
Automi
ESERCIZIO
4.68 Si mostri che i linguaggi riconoscibili con ARP sono chiusi rispetto all’
unione. Si suggerisce di procedere in modo analogo a quanto fatto nella
dimostrazione del Teorema 4.10
Definizione 4.33
Una rete di Petri con archi inibitori è una 5-upla (P, T, IF, OF, 1) in cui
- P, T, IF e OF hanno lo stesso significato della Definizione 4.25;
- I: P X T è la relazione di inibizione.
L’introduzione degli archi inibitori nelle reti di Petti aumenta il potere espressivo
del formalismo originale, rendendo le reti di Petti equivalenti alle macchine di
Turing. Anche in questo caso ci limitiamo ad illustrare l’affermazione attraverso un
esempio, rimandando alla letteratura specializzata per una dimostrazione rigorosa
dell’asserto.
ESERCIZIO
Esempio 4.26
Si consideri il linguaggio L = | w e {a, b}*} che, come visto
precedentemente in modo intuitivo, non può essere riconosciuto da un ARP. Esso
però può essere riconosciuto con l’aggiunta di archi inibitori. Il problema della
“mancanza di identità” dei token può essere infatti parzialmente superato
sfruttando la seguente idea.
Ciascun elemento dell’alfabeto viene codificato con una cifra, nel nostro caso
ogni ‘a’ viene codificato con un 1 e ogni b con uno 0, a partire dalla stringa vuota
che viene rappresentata con 1. .Ogni stringa viene poi interpretata come fosse un
numero rappresentato in binario; una stringa w corrispondeperciò in modo univoco
a un numero naturale. Ad esempio la stringa vuota viene codificata con 1 e
corrisponde quindi al numero 1, la stringa aab viene codificata con 1110 e
corrisponde quindi al numero 14. L’idea è quindi di rappresentare la stringa w con
il numero di token corrispondente alla sua codifica, per cui l’aggiunta di una ‘6’
corrisponde a raddoppiare la codifica della stringa precedentemente ottenuta,
mentre l’aggiunta di una ‘a’ corrisponde a raddoppiare tale codifica e a sommarvi
1. Con l’aiuto degli archi inibitori si colleziona quindi il numero “giusto” di token
per codificare la stringa w e, simmetricamente, sottraendo e dividendo la codifica
ottenuta, sempre con l’aiuto degli archi inibitori, si verifica che w sia seguito da
L’ARP completo è riportato in Figura 4.55, come composizione della parte (a)
e (b), che corrispondono rispettivamente alla parte che tiene traccia di w e alla parte
che riconosce Si noti che nomi uguali nelle due parti corrispondono allo stesso
posto. Il posto Pe nella Figura 4.55(q) mantiene il numero di token corrispondente a
w. Ad ogni scatto della transizione viene consumato un token di Pc e vengono
generati due token in Ptemp- Quando tutti i token in Pc sono stati consumati può
scattare t4, che è abilitata solo da una a in ingresso. Alla fine Ptemp conterrà il
numero di token che corrisponde alla stringa letta fino a quel momento. Con lo
scatto di t6 questi token verranno spostati in Pc e lo scatto di t1 riporterà il token in
Po per leggere un nuovo carattere. Un token in Po abilita anche la transizione /8 che
porta un token in Pb La parte (b) della Figura 4.55 è preposta al controllo di wR,
cioè verifica che la nuova stringa corrisponda al riflesso della stringa letta in
190
Informatica teorica
(a)
191
Automi
192
Informatica teorica
Figura 4.56 Confronto del potere espressivo degli ARP, ARP con archi
inibitori, AF, AP, APN e MT.
Esempio 4.27
Si supponga che un calcolatore sia composto da una CPU e da due video-terminali
(FTi e VTi). Ciascun terminale invia al sistema un task alla volta. La CPU può
eseguire un solo task alla volta, indipendentemente dal terminale che lo ha inviato.
Se non sono noti i criteri in base ai quali il sistema operativo assegna la CPU
ai vari task, il comportamento esterno del sistema può essere descritto dalla RP di
Figura 4.57. Chiaramente, una RP siffatta consente al sistema di scegliere sempre
ti, lasciando così VT~, nella situazione di blocco individuale. Ciò potrebbe
verificarsi, ad esempio, se il sistema operativo assegnasse una priorità più alta ai
task generati da VT\.
193
Automi
Viene elaborato
il task
proveniente
da VT
Si supponga invece di sapere che il sistema operativo serve in modo alternato i due
terminali FTi e VT2. Per semplificare la discussione, si supponga anche che vi sia
sempre qualche utente seduto al terminale, pronto a generare nuovi task non
appena possibile. In questo caso il sistema può essere modellato dalla rete di Figura
4.58, che impone a t\ e t2 di alternarsi. Si noti inoltre che, in questo caso, il
comportamento del sistema è deterministico.
■
ESERCIZI
CPU
1. La CPU è disponibile.
2. È disponibile un banco di memoria (Si supponga Bi sia usato
esclusivamente da T\ e B2 da T2).
Dopo l’esecuzione, i task richiedono la stampante per stampare i risultati.
4.71 Si rappresenti una variazione multiprocessore dell’Esercizio 4.70 in cui sono
presenti due diverse CPU che possono essere utilizzate sia da task generati
da Ti sia da task generati da T2 e in cui la memoria è ancora divisa in due
banchi, ciascuno però utilizzabile indistintamente da tutti i task.
Esempio 4.28
Un esempio ben noto in letteratura per mostrare le caratteristiche e le
problematiche tipiche dei processi concorrenti è il problema dei filosofi a cena
(meglio noto con il nome inglese dining philosophers). Il problema è stato
originariamente introdotto da E. W. Dijkstra nel 1965 come problema di
sincronizzazione ed è stato poi rivisitato da Tony Hoare.
Immaginiamo di avere cinque filosofi seduti intorno a un tavolo rotondo, come
rappresentato in Figura 4.59. Ciascun filosofo può svolgere una delle due seguenti
attività: pensare o mangiare (o meglio, provare a mangiare). Per mangiare un
filosofo ha bisogno di due forchette e al tavolo ci sono solo cinque forchette,
ciascuna posizionata tra due filosofi adiacenti. Quando un filosofo vuole mangiare,
deve prendere prima le due forchette che ha di lato, una a destra e l’altra a sinistra,
e questo è ovviamente possibile solo se le forchette non sono già in mano ai suoi
vicini.
Fi
Figura 4.60 RP che rappresenta il problema dei filosofi a cena per cinque
filosofi.
Torniamo ora ad analizzare le reti di Petri arricchite con gli archi inibitori. Come
anticipato nella Sezione 4.5.1, tale estensione delle RP è particolarmente utile
quando si voglia entrare in maggiori dettagli sulle politiche di gestione di risorse
condivise in sistemi concorrenti, ad esempio mediante l’uso di priorità.
Supponiamo infatti di rappresentare una richiesta da parte di un processo i come un
token nel posto Ph la presenza della risorsa richiesta come un token nel posto Pr e
l’accoglimento di tale richiesta come una transizione ti>r, che ha in entrata Pt e Pre
quando scatta consuma i token in P, e Pr. Intuitivamente, se diversi processi hanno
diverse priorità, ad esempio il processo j ha priorità più alta del processo i rispetto
alla risorsa r, sarà sufficiente aggiungere un arco inibitore da Pj a tir, ad indicare
che se il processo j ha fatto una richiesta per la risorsa r, il processo i non può avere
tale risorsa. Una rappresentazione grafica di tale schema è rappresentato in Figura
4.61.
197
Automi
Introduciamo ora un altro tipo di estensione delle reti di Petri con lo scopo di
modellare esplicitamente gli aspetti temporali dell’evoluzione dei sistemi
concorrenti; questa estensione del modello risulta perciò particolarmente indicata
per le applicazioni “in tempo reale”. Anche aH’intemo di questa categoria di reti di
Petri esistono diversi possibili formalismi. In seguito ci riferiremo all’estensione
proposta da Merlin e Farber, che è probabilmente la più intuitiva e meglio
conosciuta estensione di RP in tale direzione.
Intuitivamente ima rete di Petri temporizzata (RPT) è una rete di Petri in cui a
ciascuna transizione viene assegnata una coppia di valori non negativi, che
rappresentano rispettivamente il minimo e il massimo tempo di scatto della
transizione dal momento in cui essa è abilitata. Una transizione abilitata dalla
presenza dei token nei suoi posti in ingresso scatterà quindi all’interno
dell’intervallo relativo indicato. Se uno dei posti in ingresso viene svuotato prima
che la transizione scatti, essa viene disabilitata e al momento in cui ritornerà
abilitata, si considererà come se non fosse stata mai stata abilitata precedentemente,
cioè si riconsidererà da 0 il tempo di attesa per il suo scatto rispetto all’intervallo
ad essa associato. Formalizziamo ora tali idee intuitive attraverso la seguente
definizione.
Definizione 4.34
Una rete di Petri temporizzata (RPT) è una 6-upla (P, T JF ,OF, eft, Ift) in cui
- P, T, IF, OF hanno lo stesso significato introdotto nella Definizione 4.26;
- eff. T . F+ è una funzione che assegna ad ogni transizione un valore che
rappresenta il minimo tempo di scatto da quando viene abilitata;
Informatica teorica
Esempio 4.29
Riprendiamo ora il problema dei filosofi a cena, introdotto nella sezione precedente
e risolto nell’Esempio 4.28. Si assuma che la sessione di “pensare” per ciascun
filosofo duri almeno dp e al più Dp unità di tempo, dopo le quali il filosofo è
affamato e cerca di prendere le forchette, in qualsiasi ordine, e di mangiare. Come
visto precedentemente una sessione di “mangiare” inizia quando il filosofo ha
entrambe le forchette, ma ora dura almeno dm e al più Dm unità di tempo.
La versione temporizzata dei filosofi a cena è formalizzata in Figura 4.62,
dove per semplicità si è rappresentato un solo filosofo, in quanto gli altri risultano
tutti identici a quello mostrato.
La scelta dei tempi da assegnare a ciascuna attività dei filosofi può essere fatta
in modo da costruire un sistema che non vada mai in deadlock. Ad esempio, se dp =
Dp = 4 dm = 4-Dm e la rete viene modificata in modo che i filosofi inizino a
mangiare la prima volta in modo sequenziale, ogni sessione successiva di
“mangiare” avverrà esattamente dopo dm unità di tempo. Questa scelta rende il
sistema completamente deterministico.
■
ESERCIZIO
4.72 Considerando l’Esempio 4.29, si suggerisca un insieme di vincoli per gli
intervalli di scatto, in modo da permettere un po’ di parallelismo, ma
evitando possibilità di deadlock e starvation.
Figura 4.62 Parte di RPT che gestisce un filosofo nella formalizzazione del
problema dei filosofi a cena.
Esempio 4.30
Tra le varie versioni del problema del passaggio a livello presenti in letteratura,
consideriamo una versione molto semplificata in cui il sistema consiste di un solo
binario unidirezionale e di un solo treno. Uno schizzo dell’attraversamento è
rappresentato nella Figura 4.63.
4.6 Alcune annotazioni sul confronto fra modelli non deterministici e quelli
stocastici
I modelli non deterministici non vanno confusi con i modelli probabilistici o
stocastici. Usando un’espressione poco rigorosa, si può affermare che, nell’ambito
dei formalismi evolutivi, i sistemi stocastici sono caratterizzati dal fatto che le
transizioni da uno stato ad un altro avvengano con una probabilità prefissata.
Esistono in letteratura molti modelli stocastici che vengono applicati sia all’interno
che all’esterno del campo dell’informatica. Alcuni di essi sono derivati dai
formalismi deterministici in modo molto simile a quelli non deterministici.
Un tipico esempio è fornito dalle catene di Markov, che sono automi a stati finiti in
cui, a ciascuna transizione, è associata una data distribuzione di probabilità.
zuz
Informatica teorica
In tale contesto, il semplice automa di Figura 4.65 stabilisce che il sistema, qualora
raggiunga lo stato e riceva in ingresso una a, effettuerà una transizione verso qk o
q, con probabilità, rispettivamente, del 60% e del 40%; se invece l’ingresso è b,
certamente raggiungerà qt.
In un certo senso, i modelli non deterministici descrivono un grado maggiore
di “incertezza” rispetto ai modelli probabilistici. Infatti la disponibilità di una
distribuzione probabilistica sulle transizioni corrisponde ad una maggiore
conoscenza del comportamento del sistema.
I modelli stocastici si prestano bene a rispondere a domande del tipo “Qual è
lo stato più probabile in cui si verrà a trovare il sistema se si fornisce una data
sequenza di ingresso?” oppure “Qual è il tempo medio di servizio di un sistema che
riceve clienti con una data distribuzione probabilistica?”.
Sebbene i modelli stocastici siano usati estensivamente in alcune aree
dell’informatica, come la valutazione delle prestazioni, si è deciso di non dedicarvi
ulteriore attenzione, in quanto il loro impiego è più specialistico rispetto a quello
degli altri modelli presentati in questo testo.
ALTRI ESERCIZI
4.73 Si costruisca un AF che modelli l’algebra degli interi modulo k, dotato delle
operazioni Succ: [N]ì->[N]ì definita da Succ([n]k) = [(« + 1)]*, Preck
[N]£—>[N],t definita da Predi [n]k) = [(« - I)]*.
4.74 Qual è il linguaggio accettato dall’AF mostrato in Figura 4.66? Si trasformi
l’automa in un equivalente AF deterministico.
4.75 Si dimostri che l’insieme dei linguaggi riconoscibili da APN è chiuso
rispetto all’unione, alla concatenazione e alla stella di Kleene.
4.76 * Si dimostri che l’intersezione di un linguaggio riconoscibile da APN con un
linguaggio riconoscibile da AF è un linguaggio riconoscibile da APN.
4.77 Si formalizzino gli automi a pila doppia. Essi sono come i consueti AP,
tuttavia sono dotati di due pile invece che di ima. Una singola mossa dipende
dal valore contenuto sulla cima delle due pile, oltre che dallo stato corrente e
dal simbolo di ingresso. L’automa opera inoltre su entrambe le pile nello
stesso tempo. Si dia una versione deterministica e non deterministica di tale
automa.
4.78 Si dimostri che gli automi a pila doppia, sia deterministici che non
deterministici, sono equivalenti alle MT.
APPENDICE 4.A
— ni =m
- n = n.
(per ogni a, m, n e per ogni t > 0. cpq si può facilmente dimostrare che è
primitiva ricorsiva, purché Zq, Za, Zm e Zn siano anch’esse ricorsive
primitive). Si noti, tuttavia, che <pq non è definita dall’applicazione
immediata della ricorsione primitiva.
Analogamente, si possono definire le funzioni <pa, 4ym, <t>n e si può dimostrare
che sono ricorsive primitive.
4. Definizione delle funzioni MT-computabili come funzioni ricorsive parziali.
Sia fM la funzione sui numeri naturali calcolata da M secondo le precedenti
convenzioni. M si ferma all’istante tf (se ciò avviene) tale che
Q f , ossia,
Teorema 4.24
Ogni funzione MT-computabile è una funzione ricorsiva parziale.
Corollario 4.25
Ogni funzione ricorsiva parziale si può definire mediante una sola applicazione
dell’operatore di minimalizzazione.
■
Note bibliografiche
Tutti i modelli presentati in questo capitolo vengono estensivamente impiegati in
campo informatico. Gli automi a stati finiti, gli automi a pila e le macchine di
Turing sono descritti praticamente in ogni libro sulla teoria della computazione.
Alcuni testi classici che coprono questi argomenti sono Ginsburg (1966), Hopcroft
e Ullman (1969), Hopcroft e Ullman (1979), Hopcroft, Motwani e Ullman (2006),
Harrison (1978), Lewis e Papadimitriou (1981), Sipser (1997). Questi testi sono
stati la fonte principale del materiale qui presentato. Essi sono anche suggeriti per
un’ulteriore lettura nel campo degli automi, dei linguaggi e della teoria della
computazione.
I lavori originali più importanti che hanno originato i risultati qui presentati
sono dovuti a Bar - Hillel, Perles e Shamir (1961), (Pumping Lemma), Myhill
(1957), Nerode (1958), (teorema di Myhill - Nerode) e Turing (1936) (macchine di
Turing).
La dimostrazione del Teorema 4.13 è dovuta a Ginsburg e Greibach ed è
riportata in Harrison (1978). La dimostrazione di Ginsburg e Greibach è stata
riveduta e corretta da Citrini, Crespi-Reghizzi e Mandrioli (1986). Il Teorema 4.18
è dovuto a Shannon (1956). Lo schema di dimostrazione dato qui è adattato da
Brady (1977).
Le reti di Petri non sono ancora un modello “classico” dell’informatica, ma
sono state analizzate profondamente nelle loro proprietà matematiche e sono state
anche ampiamente applicate a problemi pratici. Il lettore interessato può trovare
una descrizione ampia e di facile lettura di questo modello in Peterson (1977,
1981).
Z1U
Informatica teorica
Inoltre, esse hanno ispirato molti modelli utilizzati anche in ambito industriale.
Alcuni esempi sono gli activity diagram di UML e BPMN (Business Process
Modeling Notation), di cui si può trovare una descrizione nel libro di Allweyer
(2009).
Sempre in Peterson (1981) è possile trovare un’ampia descrizione dell’uso
delle reti di Petri come accettori di linguaggi, compresa la dimostrazione di
chiusura dei linguaggi riconosciuti da tali modelli rispetto all’intersezione. Altre
pubblicazioni importanti ed originali sulle reti di Petri e relative applicazioni sono
Petri (1962) e Holt e Commoner (1970).
Una visione generale sull’uso dei modelli stocastici e delle loro applicazioni
all’informatica si può ottenere da Kleinrock (1976).
Capitolo 5
GRAMMATICHE
Come abbiamo visto nel Capitolo 4, molto spesso gli automi vengono usati come
modelli astratti nei problemi di riconoscimento dei linguaggi. Un riconoscitore è,
quindi, uno strumento formale per la definizione di un particolare linguaggio,
quello costituito daH’insieme di tutte le stringhe accettate dal riconoscitore. Se A è
un riconoscitore ed I è il suo alfabeto di ingresso, si usa la notazione
L(A) = {x| x e /*, x è accettata da A}
per indicare il linguaggio definito da A. Questo tipo di formalismo è uno strumento
operativo che definisce un linguaggio, fornendo una procedura meccanica per
stabilire l’appartenenza o meno di una stringa al linguaggio definito.
Esistono però altri tipi di formalismi per descrivere linguaggi. In questo
capitolo viene presentato un altro dispositivo formale utilizzabile per questo scopo:
le grammatiche formali. Una grammatica formale definisce un linguaggio fornendo
il procedimento, mediante il quale si può derivare ogni stringa appartenente al
linguaggio; si tratta quindi di un meccanismo di tipo generativo.
Secondo la normale accezione del termine, una grammatica è un insieme di
regole per costruire le frasi di un particolare linguaggio, di qualsiasi tipo esso sia.
Una grammatica formale genera le stringhe di un linguaggio attraverso un
meccanismo di riscrittura (più spesso chiamato con il termine inglese rewriting')
definito matematicamente. Esso consiste in un ampio insieme di tecniche che
determinano come sostituire parti, o meglio sottotermini, di una “formula” con altri
termini. Tali tecniche si applicano in svariati campi, quali la matematica,
l’informatica e la logica, oltre, naturalmente, la linguistica. A seconda del contesto
dove ci si trova, la “formula” diventa quindi una frase di un linguaggio naturale,
un’equazione, un frammento di programma, uno spartito musicale ecc.
Constateremo inoltre che il processo di sostituzione di un sottotermine è
potenzialmente non deterministico, cioè un sottotermine può essere sostituito da
diversi termini la cui scelta non è determinata da nessun evento o storia precedente.
Esempi di riscrittura sono le regole che permettono di riscrivere una formula di
logica proposizionale con una formula semanticamente equivalente ad essa oppure
la costruzione di esempi di tautologie.
Anche la tecnica con cui si costruiscono le frasi in linguaggio naturale è
generalmente una tecnica di riscrittura. Ad esempio, è possibile costruire le frasi di
un linguaggio applicando le seguenti regole:
- Una frase è composta da un soggetto seguito da un predicato;
- Il soggetto può essere un nome oppure un pronome;
- Un predicato può essere un verbo seguito da un complemento;
212 Informatica teorica
Definizione 5.1
Una grammatica non ristretta (o, brevemente, una grammatica) G è una quadrupla
G={VT, Vn,P,S)Aovz
- VT è un insieme finito di simboli terminali, detto alfabeto terminale',
- VN è un insieme finito di simboli non terminali, tali che VT n Fv = 0, detto
alfabeto non terminale. V indica VT u Fv5
- P è un sottoinsieme finito di , detto insieme delle produzioni di G. Un
elemento p = (a,p) di P verrà indicato con a —> p. La stringa « è la parte
sinistra di /?; la stringa p ne è invece la parte destra',
- S è un elemento particolare di VN, detto assioma, o simbolo iniziale.
■
Mettiamo esplicitamente in relazione gli elementi introdotti informalmente
precedentemente con gli elementi della Definizione 5.1: un elemento che deve
essere dettagliato o raffinato è un simbolo non terminale; un elemento di base è un
simbolo terminale. Le componenti di un oggetto possono essere sia simboli
terminali sia simboli non terminali, infatti la parte destra delle produzioni
appartiene a V*. Una produzione corrisponde a una regola di raffinamento: infatti,
sostituisce un non terminale o una sequenza di non terminali con una sequenza
generica di simboli, come illustrerà in maniera più precisa le Definizione 5.2.
Grammatiche 213
Esempio 5.1
Consideriamo la grammatica G = (VT, Vn, P, S), dove VN = {S, A, B, C, D} è
l’alfabeto non terminale, VT = {a, b, c} è l’alfabeto terminale e S è il simbolo
iniziale. Si noti che, anche se abbiamo usato il simbolo S anche nella Definizione
5.1, non è obbligatorio usare proprio questo simbolo come simbolo iniziale, ma è
sempre necessario specificare quale tra i simboli non terminali è quello iniziale.
Infine le produzioni sono:
P= { S^ AB,
BA -> cCD,
CBS ab,
A e}
■
Formalizziamo ora il concetto di generazione di linguaggio. Come anticipato
informalmente, ciò avviene attraverso la nozione di derivazione, che spiega come
passare da una stringa ad un’altra applicando le produzioni.
Definizione 5.2
Data una grammatica G, si definisce su F* la relazione binaria di derivazione
immediata, indicata dalla notazione => :a => p, sussiste se e solo se a = a/ycG,
G
Esempio 5.2
Consideriamo la grammatica G introdotta nell’Esempio 5.1. Si verifica facilmente
che aaBAS => aacCDS, sostituendo BA con cCD, come indicato nella seconda
G
Definizione 5.3
Data una grammatica G, il linguaggio L(G) generato daG è definito come
L(G) = {x| S=^*g x, x e VT*}.
■
Il linguaggio generato da una grammatica è quindi costituito da tutte e sole le
stringhe di soli simboli terminali, che possono essere derivate a partire dal simbolo
iniziale S, applicando un qualsiasi numero di sostituzioni.
Esempio 5.3
Si consideri la seguente grammatica
<?! = ({(), 1}, {5},Pb5)
dove
Pi= {S->05,5-> 15,S-> 1}.
Alcuni esempi di possibili derivazioni di Gj sono:
1
5^05^01
11
5=> 0S=> 005=> 001
5=> 0S=> 015=> Oli
105 => 101
5=> 15=> 115 => 111
È immediato generalizzare questi esempi ed osservare che:
Z(Gi)= {0,1}*-1
ossia che il linguaggio generato da risulta costituito dall’insieme delle sequenze
di bit che rappresentano un numero intero dispari. Infatti, si può notare che la
grammatica ha tre possibili produzioni, due delle quali sostituiscono il simbolo non
terminale S con una stringa composta da un terminale e dal non terminale S e una
che sostituisce S con il terminale 1. Per arrivare a una stringa di soli terminali è
quindi necessario sostituire il non terminale S con 1, che essendo il simbolo più a
destra della stringa generata, la rende la rappresentazione in binario di un numero
dispari.
£(Gi) coincide quindi con il linguaggio riconosciuto dall’automa discusso
nell’Esempio 4.1.
Esempio 5.4
Si consideri la seguente grammatica.
215
Grammatiche
G2 = ({a,b}, {S},P2,S)
dove
P2 = {SaSb, Sab}.
Alcuni esempi di possibili derivazioni di G2 sono:
S^> ab
S => aSb => aabb
S => aSb => aaSbb => aaabbb
Ogni stringa che appartiene a L(G2) può essere derivata mediante un’opportuna
sequenza di applicazioni della prima produzione (che genera amSbm, m > 0), seguita
dall’applicazione della seconda produzione (che genera amabbm, > 0). In questo
modo:
£(G2)= {anbn\n> 1}
Si osservi che anche il linguaggio generato da G2 coincide con quello riconosciuto
da un automa esaminato precedentemente, precisamente l’automa a pila di Figura
4.23.
■
Esempio 5.5
Si consideri ora la seguente grammatica.
U3 = {{a, b, c}, {S, A, B, C, D},P3, S)
dove
P3 = }S—>aACD, A^aAC, A^>s, B-Db , CDBDc , CB BC ,
D^&}.
Alcuni esempi di derivazioni di G3 sono
S => aACD => aCD => aBDc => abDc => abc
S => aACD => aaACCD => aaCCD => aaCBDc => aaNCDc => aabCDc =>
aabBDcc => aabbDcc => aabbcc
ossia si cancellasse D, non sarebbe poi più possibile derivare alcunché dai soli C
rimasti). Poiché poi CB può essere sostituita con BC, l’applicazione di questa
ultima coppia di sostituzioni, ripetuta n volte, porta a a 'BnDcn. Infine il non
terminale D può essere sostituito con s e ogni non terminale B con il terminale b,
ottenendo anbncn.
■
I precedenti esempi dovrebbero aver chiarito perché le grammatiche costituiscono
un formalismo generativo per la definizione dei linguaggi. Le grammatiche
descrivono la generazione di tutte le stringhe appartenenti ad un linguaggio
mediante ima successione di passi di derivazione che partono da un assioma.
Ciascun passo della derivazione impiega una produzione a -> p come regola di
riscrittura, in grado cioè di specificare in che modo effettuare la sostituzione di una
sottostringa a con un’altra sottostringa p aH’intemo di una stringa data.
Il prossimo esempio serve ad illustrare una delle principali applicazioni di
questo formalismo in campo informatico, ossia la definizione dei linguaggi di
programmazione.
Esempio 5.6
Si consideri la seguente grammatica
G = ({if, do, begin, fi, od, end, $}, {S, A}, P, S)
dove
P = {5 -> begin A end, A if A fi, A do A od, A $}.
Alcuni esempi di derivazioni di G sono
S > begin A end > begin $ end
S => begin A end => begin if A fi end => begin if $ fi end
S => begin A end => begin do A od end => begin do $ od end
S => begin A end => begin do A od end => begin do if A fi od end
=> begin do if $ fi od end
oppure
o Un’istruzione condizionale (denotata ad esempio dal nuovo simbolo non
terminale C);
oppure
o Un’istruzione ciclica (denotata ad esempio dal nuovo simbolo non
terminale L -dal termine inglese loop-)
oppure
o Un’istruzione di assegnamento (denotata ad esempio dal simbolo non
terminale A);
Un’istruzione condizionale a sua volta può essere riscritta secondo la
produzione C if (E) then I else I fi, dove E è un nuovo simbolo non
terminale che verrà riscritto in modo da definire una generica espressione;
ESERCIZI
5.1 Si scriva una grammatica che genera il linguaggio L = {anbm [n>m>
5.2 Si scriva una grammatica che genera il linguaggio L = {a1 b” ab" | n pari e
^1}
Definizione 5.4
Sia G = {VT, VN, P, S) una grammatica non ristretta. Se, per ogni produzione
a —> [3 contenuta in P, si verifica |a| = 1 (ossia a g Pn), allora G viene chiamata
grammatica non contestuale (NC) o di tipo 2. Un linguaggio L è non contestuale se
e solo se è generabile da una grammatica non contestuale.
■
Le grammatiche definite negli Esempi 5.3, 5.4 e 5.6 hanno tutte la forma richiesta
dalla Definizione 5.4 e sono quindi grammatiche non contestuali.
Definizione 5.5
Sia G = {VT, VN, P, S) una grammatica non ristretta. Si supponga che, per ogni
produzione a —> P in P
- |a| = 1 (ossia a g Vn);
- P sia nella forma aB o nella forma a, con B g VN,a& VT, oppure sia e.
Si dice allora che G è una grammatica regolare (R) o di tipo 3. Un linguaggio L è
regolare se e solo se è generabile da una grammatica regolare.
■
In alcuni casi la letteratura fornisce una definizione leggermente più restrittiva di
grammatica regolare: solo l’assioma S può avere e come parte destra; in tal caso
però S non può apparire nella parte sinistra di alcuna produzione. Secondo questa
definizione le grammatiche regolari dunque, a parte l’eccezione suddetta,
contengono solo produzioni del tipo A p, dove A è un simbolo non terminale e P
è una stringa composta da un simbolo terminale o da un simbolo terminale, seguito
da un simbolo non terminale (A —> aB). Secondo altre definizioni, ancora, le
produzioni ammissibili per le grammatiche regolari ammettono parti destre
costituite da un simbolo terminale o da un simbolo non terminale, seguito da un
NC. Come esempio, il lettore è invitato a verificare che la struttura lessicale degli
identificatori del Pascal (o del C o di lava, Ada ecc.) (si veda anche la Figura 4.4) è
descrivibile mediante una R-grammatica. Analogamente, l’annidamento sintattico
delle strutture degli stessi linguaggi (si veda l’Esempio 5.6) può essere descritto da
una grammatica NC.
ESERCIZI
5.3 Si scriva una R-grammatica che generi il linguaggio riconosciuto dall’AF di
Figura 4.4.
5.4 Si scriva una grammatica NC che generi il linguaggio L = {wcwÀ |
w e {a, b}*}, descritto nell’Esercizio 4.21.
5.5 Si scriva una grammatica NC che generi il linguaggio
L = {anbmambn\n,rn> 1}
5.6 Si analizzi la soluzione ottenuta nell’Esercizio 5.1 e si dica se è a potenza
minima, ossia non esiste ima grammatica ad essa equivalente appartenente
ad una classe di minor potenza generativa. In caso contrario si fornisca una
soluzione a potenza minima. In caso di difficoltà si suggerisce di tornare su
questo esercizio dopo la lettura della sezione seguente.
5.7 Si scrivano le grammatiche che generano i seguenti linguaggi.
{anbn2 \n> 1}
L2 = L^
Teorema 5.1
Dato un AF A, è possibile costruire una R-grammatica G ad esso equivalente, ossia
in grado di generare lo stesso linguaggio riconosciuto da A, e viceversa.
221
Grammatiche
Traccia di dimostrazione
Cominciamo con il dimostrare che dato un AF A è sempre possibile costruire una
R-grammatica G che genera il linguaggio riconosciuto da A. Sia A = (Q, I, ò, q(l, F).
Si definisca G = (I, Q, P, q0), dove gli elementi di P hanno la seguente forma.
- 5 —> Z>C se e solo se C e ò(5, b);
- B £ se B e F.
È facile constatare (la dimostrazione può essere formalizzata mediante una
semplice induzione) che L(A) = L(G); si supponga infatti che x e L(G). Esiste
allora un’opportuna derivazione tale che
Esempio 5.7
Si consideri il linguaggio L = {0"xl'"| n > 2, m > 2, x e {0, 1}*}, cioè il linguaggio
delle sequenze di 0 e 1 che cominciano con almeno due 0 e terminano con almeno
due 1, per cui si è costruito un AF nell’Esempio 4.2. L’AF A che riconosce tale
linguaggio viene riportato per convenienza in Figura 5.2.
La grammatica che genera tale linguaggio può essere costruita utilizzando la
costruzione proposta nella prima parte della dimostrazione del Teorema 5.1. Quindi
G= Vn, P; S), dove
- VTè l’alfabeto di ingresso di A, cioè {0, 1};
- VN è composto dagli stati di A, cioè{q0, qu q2, q3, qPp,
- P è definito come segue:
o qn Oqi
o qx 0q2
o q2 0q2 | 1#3
o q3 0q2 | 1^4
o q40q2 |1^4 |s
Si noti che l’insieme delle produzioni di G contiene tante produzioni quante
sono le transizioni in A, oltre alla produzione e, dovuta al fatto che è
uno stato finale in A;
- S è lo stato iniziale di A, cioè q0.
0 1
Figura 5.2 AF che riconosce stringhe che iniziano con almeno due 0 e
terminano con almeno due 1.
223
Grammatiche
0, 1
Esempio 5.8
Si consideri la G-grammatica Gz dell’Esempio 5.3, definita come
Gj = ({0,1}, {S},Pi,S)
dove
A= {S-> OS, S-> 1S,S^> 1}.
Essa genera il linguaggio delle stringhe su {0, 1} che terminano con 1. Utilizzando
la costruzione proposta nella seconda parte del Teorema 5.1, è possibile costruire
un AFN Ai, che riconosce lo stesso linguaggio. In particolare Ai ha due stati, S e
qF, cioè Q = {S, qF}, l’alfabeto dei simboli terminali di Gb {0, 1} come alfabeto di
ingresso, S come stato iniziale, qF come stato finale e 8 definita nel seguente modo:
- S g 8(S, 0), S g 8(S, 1), per via delle produzioni S —> OS, S —> 1S;
- qF g 8(S, 7) per via della produzione S —> 1.
L’automa^; è rappresentato in Figura 5.3.
■
ESERCIZI
5.8 I Teoremi 4.8, 4.9 e 4.10 hanno dimostrato che la classe dei linguaggi
riconoscibili da AF è chiusa rispetto all’unione, all’intersezione e al
complemento. Si dimostrino i medesimi risultati per le R-grammatiche in
maniera diretta, ossia senza passare attraverso gli automi equivalenti.
5.9 Si costruisca la R-grammatica che genera lo stesso linguaggio dell’AF
dell’Esempio 4.19.
Teorema 5.2
Dato un APN A, è possibile trovare una grammatica NC G ad esso equivalente,
ossia in grado di generare lo stesso linguaggio riconosciuto da A, e viceversa.
224 Informatica teorica
Traccia di dimostrazione
Vediamo prima come dimostrare che, dato un automa A, è possibile trovare una
grammatica NC G tale che L(A) = L(G). La dimostrazione è composta da due parti.
Bisogna infatti prima mostrare la costruzione di G a partire da A e poi
l’equivalenza tra L(Z) e L(G).
Sia A = {Q, I, T, 8, q0, ZQ, F), allora è possibile costruire una grammatica
G = (VT, VN, P, S) che generi lo stesso linguaggio riconosciuto da A. Per rendere più
semplice la costruzione di G, è conveniente preliminarmente trasformare A in un
APN A ’ equivalente ad A, che riconosce cioè lo stesso linguaggio di A, ma che
svuota la pila prima di entrare nello stato finale. In primo luogo, se così già non
fosse, il simbolo iniziale di pila Zo è utilizzato esclusivamente come marca per
indicare il fondo della pila, ossia sempre e soltanto all’inizio della pila; è un facile
esercizio operare ima tale trasformazione, se necessaria; su una tale base A ’ è così
definito: A ’ = (Q u {qs, qF}, I, T, 8 q0, Zo, {qF}), dove 8 ’ aggiunge a 8 le seguenti
transizioni:
1. Vq eF, \/A eT-{Z0},<qs,£> e 8(q,e,A);
2. Vq g F, <qF, e> € ò(q, e, Zo);
3. VA g r - {Zo}, 8fe, s, A) = {<q$, e >};
4. 8(qs, e, Zo) = {<qF, £>}.
Intuitivamente le transizioni di tipo 1. portano con un £-mossa A ’ da ogni stato
finale di A allo stato di supporto qs per qualsiasi simbolo di pila tranne Zq. Nello
stato qs, con qualsiasi simbolo sulla pila tranne Zo, A ' rimane in qs, svuotando la
pila (transizioni di tipo 3.). Le transizioni di tipo 2. e 4. portano invece A’ nello
stato finale qF e svuotano completamente la pila quando è stata ridotta a contenere
solo Zo.
La non difficile dimostrazione che L(A ’) = L(A) viene lasciata per esercizio al
lettore, osservando però che la costruzione suggerita potrebbe trasformare un
automa A originariamente deterministico in un A ’ nondeterministico.
Notiamo che l’automa A ’ ha per costruzione un unico stato finale qF. Questa
premessa, insieme alla condizione di aver svuotato la pila prima di accettare una
parola, semplifica notevolmente la costruzione della grammatica NC equivalente
G. Partendo da A ’ possiamo quindi costruire la grammatica G nel seguente modo:
- vT=i-
- Lv= {[qMq']: V q, q' e Q e V M e T}; '
- L’insieme delle produzioni P contiene i seguenti elementi:
o [qMq'} —> a, ^<q', £ > g Ò(q, a, M)~ dove a può anche essere e;
o [qMq„ +1] -> a[q ’Niq2} [q\N2qr} ...[qn.2Nn. iq„. J [q„. iN„q„]
per ogni possibile scelta di qr, q2, ...,q„ <= Q,\f <q y> g Ò(q, a, M),
con y = V N2...Nn. i N„, dove a può anche essere e;
- [qoZfflp} è l’assioma della grammatica.
Intuitivamente, tale grammatica è costruita in modo da simulare il comportamento
dell’APN A. L’assioma ([qoZoqF}') “simula” le sequenze di mosse che portano dalla
configurazione iniziale (<q<j, x, Zo>), allo stato finale (qF). Le produzioni di
225
Grammatiche
secondo tipo simulano transizioni tra due generici stati q e q’, che scrivono una
stringa non vuota sulla pila, generando il non terminale che porta da q a q’ e
considerando tutte le altre possibili sequenze di generazione (che rappresentano i
possibili cammini su A ’ con la nuova condizione della pila); le produzioni del
primo tipo, invece, eliminano un simbolo non terminale sostituendolo con un
simbolo terminalem quando la corrispondente transizione nell’automa A ’ fa una
transizione che non prevede la scrittura sulla pila, quindi elimina semplicemente il
simbolo letto. Vedremo nell’Esempio 5.9 un’applicazione di questa costruzione.
Per concludere la prima metà della dimostrazione è necessario ora mostrare
che L(A 9 = L(G). Questa dimostrazione può essere fatta per induzione, la cui parte
*
essenziale consiste nel fare vedere che V q, W, q' [qWq'l => w se e solo se A
trovandosi in una configurazione in cui lo stato è q e il simbolo in cima alla pila W.
scandendo w, si porta nello stato q' e toglie W dalla pila (senza toccarne la parte
sottostante durante la scansione di w). Un’ulteriore generalizzazione permette poi
di stabilire che
*
[glPi?'] w/se e solo se (q, w, W) >-* (q', e, f.
Il completamento della dimostrazione è lasciato al lettore come esercizio (non
banale).
Passiamo ora alla seconda parte della dimostrazione: data una grammatica G è
sempre possibile costruire un APN A che riconosca lo stesso linguaggio generato
da G. Per questa parte di dimostrazione è conveniente introdurre una particolare
forma normale per le grammatiche NC, detta forma normale di Greibach (FNG).
Una grammatica NC è in FNG se tutte le sue produzioni sono del tipo A —> a[5 con
A e Jfr, a e VT e 0 g Fy*, cioè le produzioni hanno come parte sinistra un simbolo
terminale seguito da una stringa, eventualmente vuota, di non terminali. E possibile
dimostrare che ogni grammatica NC può essere trasformata in FNG (a meno della
generazione della stringa nulla che verrà considerata a parte). Il lettore interessato
può trovare dettagli su questa trasformazione nelle note bibliografiche.
Sia quindi G in FNG e quindi tale che £ <£. L(G). In questo caso l’APN
equivalente A è composto da tre soli stati e i simboli non terminali della
grammatica possono essere usati come simboli di pila. Costruiamo quindi A =
{Q, I, T, 8, q0, Zo, F) nel seguente modo:
- Q= {qo, q,qp};
- i= Vf,
- r= Fy c Zo;
- F={qp}-,
- 8 è definita come:
o 8(<?0> e, Zq) = {<q, SZq >} ;
o Per ogni produzione A —> ay con y e VN*> <q, y> 6 ò(q, a, A);
o 5(q, e, Zo) = {<qF, Zq>} .
226 Informatica teorica
Si noti che la prima transizione (ò(r/0, e, Zo) = {<?, SZ0>}) ha l’unico scopo di
aggiungere l’assioma S sulla pila, per poi simulare in q l’applicazione delle diverse
produzioni di G.
Se rimuoviamo il vincolo s g L(G), basta aggiungere una nuova transizione
<qF, s>g 8(^0, £, ^ó) (8(^0, s, Zo) = {<q, SZ0>, <qF, s>}) per considerare la
stringa vuota. Un esempio di tale costruzione è riportato nell’Esempio 5.10.
Per completare la dimostrazione è necessario ora dimostrare che L(G) = L(A).
Analogamente al caso opposto, tale dimostrazione viene fatta per induzione ed è
lasciata al lettore come esercizio.
■
Il Teorema 5.2 dimostra l’equivalenza tra il potere di riconoscimento degli APN
(più potenti di quelli deterministici) e il potere di generazione delle grammatiche
NC, cioè afferma che la classe dei linguaggi riconosciuti dagli APN è la stessa di
quella generata dalle grammatiche NC, cioè la classe dei linguaggi non contestuali.
Vediamo ora due esempi di trasformazione: da grammatica NC ad APN e
viceversa.
Esempio 5.9
Consideriamo il linguaggio L = {anbn\ »>!}, analizzato nell’Esempio 4.8, di cui
riportiamo l’automa riconoscitore in Figura 5.4 per convenienza.
La costruzione della grammatica G che riconosce L può essere fatta a partire
da A seguendo la costruzione proposta nella prima parte della dimostrazione del
Teorema 5.2. Notiamo che, in questo esempio, A si muove nello stato finale
u,ZqIZZq
a.ZIZZ b,Zk
quando sulla pila contiene il solo simbolo Zo, cancellandolo. Quindi A è già nella
forma richiesta dalla trasformazione proposta. In particolare, G sarà così definita:
- L’insieme dei simboli terminali Vt corrisponde all’alfabeto di ingresso di A,
cioè {a, b};
- L’insieme dei simboli non terminali è formato dai termini costruiti
combinando in tutti i modi possibili coppie di stati e simboli dell’alfabeto
della pila: {[^0Z0^0], [qoZqd, [qoZoqi], [qoZqi], [qoZoq2], [qoZq2], [qiZoqo],
[qiZq0], [qiZoqi], [q^j, [qjZ0q2], [qiZq2], [q2Z0q0], [q2Zq0], [tfzZotfi], feZ^i],
\q2Zgq2}, \q2Zq2\] . Tra questi [^0Z0^2] è l’assioma;
- Le produzioni in P sono costruite a partire dalla relazione di transizione di A
nel seguente modo:
o [^oZ?i] —> b poiché <q2, 8> e 8(7/0, b, Z)
o [^iZ^i] —> b poiché <qi,é> e 8(#i, b, Z)
o [^iZ0^2] s poiché <q2, 8> e S(gb 8, Zo)
o [^oZo^o] a[qQZqo\[qoZoqo] | alq^Zq^q^Z^qg] | a[q0Zq2][q2Z0q0]
[qoZoqi] alqoZqoJlqoZoqi] | g[^0Z7i][^iZ0^i] | a[qGZq2][q2Z^{\
[qgZgq2] alqoZqQWq^q^ | a\_qoZq\\[q\Z()q2\ | a^Zq^q^q^
poiché <qn, ZZg> e S( qQ, a, Zo)
o [<?0Zg0] a[tfoZtfo][tfoZtfo] | a^gZq^q^Zqg] | a[q0Zq2\[q2Zq0]
[qGZq{\ alqoZqollqoZq^ | alqoZq^lq^Zq^ | a^oZ^lfeZ^]
[q0Zq2] a[qoZqo][qoZq2] | alqgZq^qiZq^ | a[q0Zq2\[q2Zq2]
poiché <q0, ZZ> e 5(7/0, a, Z).
Possiamo semplificare la grammatica così ottenuta rinominando i simboli \_qiZoqj}
con Zjj, i simboli [qiZqj\ con Ay e il simbolo [qgZgq^ con S, ottenendo il seguente
insieme di produzioni
Zoo —> aAooZoo | gZqiZio | aAg2Z2g .
Zoi —> aZooZoi | aZoiZn | aAo2Z2i
S —> aAooS | aZoiZ|2 | oAq2Z22
Aqo —> ciAooAqo | aAgiAio | aAQ2A2o
Aqi —> aAooAoi | azloi^ii I oAq2A2\
Zq2—> gZooZo2 | <Zz4oiZ12 I <^402^22
Aqi —> b
Zìi —> b
Z12 —> e
Eliminando i non terminali che non possono essere sostituiti e le relative
produzioni e le produzioni non feconde si ottiene:
S —> a Z01Z12
Agi —> a AqiAh
Agi —> b
An^b
Z12 —> 8
228 Informatica teorica
Figura 5.5 APN che riconosce il linguaggio delle stringhe ben parentetizzate.
Esempio 5.8
Consideriamo ora la grammatica G = ({(,)}, {5, C}, {8 (C | (CS | (SC, C )},
8), che genera il linguaggio delle stringhe ben parentetizzate. Costruiamo ora l’AP
A che riconosce lo stesso linguaggio generato da G, sfruttando la procedura
proposta nella seconda parte della dimostrazione del Teorema 5.2. Osserviamo che
G è già in FNG e quindi possiamo direttamente costruire l’automa A senza ulteriori
passaggi. A contiene tre stati {q0, q, qF}, dove q0 è lo stato iniziale e qF lo stato
finale. L’alfabeto di ingresso di A corrisponde a VT, cioè {(, )} e l’alfabeto della
pila corrisponde al simbolo iniziale Zo unito all’insieme dei simboli non terminali
VF, cioè T = {Zo, S, C}. La funzione di transizione 8 è definita nel seguente modo:
- 8(^0, S, Zo) = <q, szo>;
- <q, C> e ò(q, (, 8) poiché S —> (C;
- <q, CS> e <5(q, (, S) poiché S —> (CS;
- <q, SC> e 8(q, (, S) poiché S (SC;
- <q, s> e ò(q, ), Q poiché C —> );
- 5(q, s, Zo) = <qF, Zo>.
La rappresentazione grafica dell’automa è riportata in Figura 5.5.
Si noti che l’AP ottenuto è non deterministico. Il linguaggio delle stringhe ben
parentetizzate non richiede il non determinismo per essere riconosciuto, ma, visto
che l’insieme dei linguaggi NC corrisponde a quello riconosciuto da APN, e
contiene quindi quello dei linguaggi riconosciuti da AP, la procedura proposta
come dimostrazione del Teorema 5.2 costruisce in generale un APN.
■
ESERCIZI
5.10 Si costruisca una grammatica NC che genera il linguaggio L = {wwÀ|
w e {a, b}*} (Si veda l’Esercizio 4.62).
5.11 Si costruisca un automa a pila equivalente alla grammatica seguente:
Grammatiche 229
S —> aAB
A —> aAA | bAB | c
B^> bBB \ aBA | c
Se l’automa così costruito non è deterministico, si analizzi se è possibile
costruirne uno equivalente deterministico.
Analogamente a quanto visto per la classe dei linguaggi regolari, cioè quelli
riconoscibili da AF, è possibile dare delle condizioni necessarie sulla struttura dei
linguaggi appartenenti a tale classe, attraverso una versione del Pumping Lemma
per i linguaggi NC.
Esempio 5.11
Consideriamo il linguaggio L = | n>0}, che, come abbiamo visto
intuitivamente nelle Sezioni 4.2 e 4.4 non è riconoscibile da AP e da APN e non è,
quindi, un linguaggio NC. Dimostriamolo ora rigorosamente attraverso l’uso del
Pumping Lemma, cioè verifichiamo che esso non ha la regolarità richiesta ai
linguaggi NC.
Mostriamo quindi che per qualsiasi valore di p esiste una stringa x, con |x| > n,
che non è decomponibile in uvwzy, con le cinque stringhe aventi le proprietà
richieste dal lemma.
Supponiamo per assurdo che sia x = anbncn = uvwzy, secondo le specifiche del
lemma. Allora abbiamo due casi possibili: o almeno una tra v e z contiene almeno
due simboli diversi (ad esempio z potrebbe contenere una sottostringa del tipo bkch)
o sono composte entrambe da un unico simbolo. Nel primo caso, se consideriamo
la stringa uv2w^y, che, se la scomposizione di x fosse corretta, dovrebbe
appartenere a L, notiamo che essa contiene simboli mescolati (ad esempio, b seguiti
da c e poi ancora da 6) e quindi non può appartenere a L. Nel secondo caso, cioè se
v e z contengono un solo simbolo, uv2wx2y non può avere un ugual numero di a, di
b e di c e quindi non può appartenere a L.
ESERCIZI
5.12 Si dimostri, facendo uso del Pumping Lemma, che il linguaggio L = {ww |
w e {a, b}*} non èNC.
5.13 (Eliminazione delle E-produzioni in una grammatica NC). Sia G una
grammatica NC. Si dimostri che è possibile costruire una grammatica NC G'
equivalente a G tale che
- Se a £ L(G) allora G' non ha produzioni del tipo A e.
- Se e e L(G) allora S —> e è la sola produzione di G che genera la
stringa vuota ed S non compare nella parte destra di alcuna produzione.
Suggerimenti:
- Si trovi una procedura che stabilisca, per ogni non terminale A di G, se
A => E.
G
*
- Si osservi che se A => e e .8 —> (X]Aa2, con aia2 e, è una
G
contigua alla stringa in ingresso può essere letta o scritta dalla testina. Per
approfondimenti su tali automi e la loro relazione con le grammatiche di tipo 1 si
rimanda il lettore ai cenni bibliografici.
Analizziamo ora invece la relazione delle grammatiche non ristrette, o di tipo
0, con le MT.
Teorema 5.4
Le grammatiche non ristrette sono equivalenti a MT usate come accettori di
linguaggi; ossia, per ogni grammatica G non ristretta, esiste una MT M che accetta
lo stesso linguaggio generato da G, e viceversa.
In questo modo vi è in G una derivazione che porta dalla stringa a alla stringa |3 se
e solo se esiste in M una sequenza di mosse che porta dalla configurazione c =
<q, alla configurazione c ' = <q, Zop>.
Se e quando sul nastro si trova una stringa y e VT*, cioè una stringa composta
da soli simboli terminali, la si confronta con la stringa x in ingresso. Se x e y
coincidono, x viene accettata, altrimenti questa particolare sequenza di mosse non
porta a una configurazione di accettazione.
Si noti che nel caso in cui x £ L(G), M potrebbe tentare infinite sostituzioni,
alcune delle quali anche non terminanti, senza poter giustamente concludere che
x e L(G), ma neanche il contrario. Infatti, la definizione di accettazione richiede
che M giunga in una configurazione di accettazione se e solo se x e L, ma non
richiede che M termini la computazione se x £ L.
■
ESERCIZI
ALTRI ESERCIZI
5.17 Si considerino Li = {a"è2,”| n, m> 1}, L2 = {a"è3"| n > 0}. Si costruisca una
grammatica G che generi il linguaggio L = Li n L2. È preferibile una
grammatica a potenza minima.
5.18 E noto che le due seguenti definizioni di grammatica regolare sono
equivalenti, ossia generano la stessa classe di linguaggi:
- Va —> P g P, |a| = 1 e P g VNVT u Pfu {e}
- Va —> P g L, |a| = 1 e P g VTVN 'jVTlu {e}
Si dica, giustificando la risposta, se la seguente ulteriore modifica della
definizione è anch’essa equivalente alle precedenti:
Va -> p g P, |a| = 1 e p € VNVTv Pru VTVNu {s}
5.19 Si scriva una grammatica che generi il linguaggio L = {x g {a, b, c} * |
#(o, x) = 2n, #(b, x) = 4, #(c, x) = n, n > 0}, dove la funzione # è definita
come nell’Esercizio 5.15. Si dica, giustificando la risposta, se la grammatica
scritta è a potenza minima tra quelle che riconoscono L.
5.20 Si scrivano un automa e una grammatica che, rispettivamente, riconosca e
generi il linguaggio L ={anamamam \n, m>l, n pari, m dispari}.
5.21 Si consideri il linguaggio L = {wcJP | w, W g {a, b} *; Wè una stringa che
differisce dalla stringa riflessa, vZ, di w, per al più 3 caratteri} Si scrivano
una grammatica e un automa, preferibilmente a potenza minima che generi e
riconosca L, rispettivamente.
5.22 Sia dato il linguaggio L sull'alfabeto {a, b, c} contenente tutte e sole le
stringhe che hanno le seguenti caratteristiche:
- la stringa inizia e termina con esattamente lo stesso numero di a;
- la stringa contiene almeno un carattere diverso da a.
Ad esempio, aabcaa, aca, aacabbabaa e aaaacaaaa appartengono a L,
mentre aaabaa, aaaa e aaacaccaaaaaa non appartengono a L. Si scriva una
grammatica che generi il linguaggio L.
5.23 Siano Ax e A2 due alfabeti e h una finizione da.<41 ad A2. h è estesa ad un
omomorfismo da ri]* adA2* come segue:
- ù(e) = e;
- Vx, y g Ai *, h(xy) = h(x)h(y).
Siano Li e L2 due linguaggi non contestuali.
Dire se le seguenti affermazioni sono vere o false, giustificando brevemente
la risposta:
1. Li o L2 è sicuramente non contestuale;
2. Li n L2 è sicuramente non contestuale;
3. h(Li) è sicuramente non contestuale;
4. Li o L2 è sicuramente regolare;
5. Li n L2 è sicuramente regolare;
6. ù(Li) è sicuramente regolare;
7. Se Li e L2 non sono regolari, Li o L2 è sicuramente non regolare;
8. Se Li e L2 non sono regolari, Li n L2 è sicuramente non regolare;
235
Grammatiche
- S è il simbolo iniziale.
5.15 Una grammatica che risolve l’esercizio proposto è così composta
et, Zo\AZo
a, X|jU
a, BfAB
b, Zo\BZq
b, A\BA
b, B\BB
Note bibliografiche
Le grammatiche hanno ampio uso in informatica, soprattutto nel campo dei
linguaggi di programmazione e relativi compilatori. Il lavoro di Noam Chomsky è
stato fondamentale per lo sviluppo delle grammatiche (Chomsky 1956, Chomsky
1957, Chomsky 1965).
Le grammatiche sono inoltre descritte, come molti dei modelli presentati nel
Capitolo 4, in quasi ogni libro sulla teoria della computazione. Alcuni testi classici
che coprono questi argomenti sono Hopcroft e Ullman (1969), Hopcroft e Ullman
(1979), Kozen(1997) Hopcroft, Motwani e Ullman (2006), Harrison (1978), Lewis
e Papadimitriou (1981), Sipser (1997). Essi sono stati la fonte principale del
materiale qui presentato e sono anche suggeriti per un’ulteriore lettura in questo
campo.
Tutte le dimostrazioni presentate nel capitolo solo informalmente e la
trasformazione delle grammatiche NC in FNG sono presentate nei testi sopra citati.
In Blum e Kloch (1999), si trova invece una procedura non classica per la
trasformazione in FNG.
Esistono diversi tipi di forme normali per le grammatiche NC, non presentate
in questo testo e la cui descrizione si può trovare nei testi sopra citati. Tra esse
ricordiamo la BNF (Backus-Naur forni), un metalinguaggio usato per descrivere
grammatiche NC (Backus 1959). Essa è stata ampiamente applicata in campo
238 Informatica teorica
In questa parte del testo abbiamo dedicato molta attenzione ad automi (Capitolo 4)
e grammatiche (Capitolo 5), visti (ma non solo) come formalismi in grado di
definire linguaggi. In questo capitolo analizzeremo altri due formalismi in grado di
definire linguaggi, ma con caratteristiche completamente diverse dai precedenti: le
espressioni regolari e le equazioni negli spazi dei linguaggi. Tra i possibili
formalismi presenti in letteratura, abbiamo scelto di trattare questi argomenti per la
loro eleganza matematica e perché offrono la possibilità di affrontare e
comprendere un diverso stile di costruzione dei modelli formali: lo stile
denotazionale. Tale stile presenta notevoli differenze rispetto allo stile
operazionale, analizzato in precedenza con automi e grammatiche, ed è quindi
interessante sottolinearne le differenze.
Nel resto del capitolo, presenteremo prima singolarmente i due nuovi modelli
e, successivamente, li confronteremo, dal punto di vista stilistico, con i modelli già
noti.
Definizione 6.1
Dato un alfabeto di simboli terminali, che per analogia con la notazione usata per le
grammatiche nel Capitolo 5 chiameremo VT, mediante le seguenti regole si
definiscono, su di esso, le espressioni regolari e i corrispondenti linguaggi
denotati.
1. 0 è un’espressione regolare che denota il linguaggio vuoto.
2. Va e VT, a è un’espressione regolare. Il linguaggio denotato da a è costituito
dall’unica stringa a.
3. Se 7?। e 7?2 sono espressioni regolari, anche (7?, u 7?2), spesso indicata come (7?,
+ 7?2), è un’espressione regolare. Il linguaggio denotato da (7?, u7?2) è l’unione
dei linguaggi denotati da 7?j e da 7?2.
4. Se Rx e 7?2 sono espressioni regolari, anche (7?, • 7?2), spesso indicata come
(7?i7?2) è un’espressione regolare. Il linguaggio denotato da (R\ • 7?2) è la
concatenazione dei linguaggi denotati da R\ e da R2.
240 Informatica teorica
Esempio 6.1
Sia VT = {a, b}. Allora R = (a u b)* è un’espressione regolare. Infatti in base alla
regola 2. della Definizione 6.1, a e b sono ER. Poiché a e b sono ER, per la regola
3. anche (a u b) è una ER. Infine, quindi poiché (a u b) è una ER, in base alla
regola 5., R è una ER.
Il linguaggio L denotato da R è
L = {e, a, b, aa, ab, ba, bb, ...} = V *
■
Si noti che, in modo analogo a quanto avviene per le operazioni aritmetiche e le
operazioni insiemistiche, gli operatori u, • e *, definiti per le ER, hanno un
implicito ordine di applicazione, se non indicato diversamente dall’uso delle
parentesi. In particolare, * ha precedenza rispetto a •, che ha precedenza rispetto a
u. Quindi, in tutti i casi in cui l’applicazione desiderata degli operatori segue
l’ordine di precedenza, le parentesi possono essere omesse.
Esempio 6.2
Sia VT = {0, 1}. Allora R = ((0 • (0 u 1)*) u ((0 u 1)* • 0)) è un’espressione
regolare sull’alfabeto E, anche indicata come ((0 (0 + 1)*) + ((0 + 1)* 0)).
Osserviamo che alcune parentesi in questo caso sono ridondanti e R può essere
scritta come 0 • (0u 1)* u(0u 1)* • 0, o alternativamente come 0 (0 + 1)* + (0 +
1)* 0.
Il linguaggio denotato da R è composto dalle stringhe su {0, 1} che iniziano
con 0 (come descritto dall’espressione 0 (0 + 1)*) o finiscono con 0 (come
descritto dall’espressione (0 o 1)* • 0).
Definizioni denotazionali dei linguaggi 241
ESERCIZI
6.1 Qual è il linguaggio definito dalle seguenti ER su a e bl
Ri: (a* u è*)*
Z2: a* ■ b
R3: ((a u è)* u (a • b)*) • b • a*
6.2 Si definiscano due ER che denotano, rispettivamente, Zi = {a”ù| n > 0} e
Z2 = {x| x contiene almeno due a consecutive}.
Teorema 6.1
La classe dei linguaggi denotati dalle espressioni regolari coincide con la classe dei
linguaggi regolari.
■
La dimostrazione del Teorema 6.1 è lasciata al lettore per esercizio.
Si suggerisce di dimostrare prima che ogni linguaggio denotato da una ER è
regolare, osservando che:
- Il linguaggio vuoto e tutti gli elementi di Vt sono linguaggi regolari.
242 Informatica teorica
Esempio 6.3
Si consideri l’automa A rappresentato in Figura 6.1. Cerchiamo di dedurre a partire
da esso l’ER che denota il linguaggio riconosciuto da A.
Procediamo identificando “sottoparti” del linguaggio. Poiché tutte le parole
accettate da A, sono quelle per cui esiste un cammino dallo stato iniziale allo stato
finale, iniziamo ad analizzare le sottostringhe che “portano” da q0 a q0. In
particolare, poiché q0 ammette una transizione che porta in q0 etichettata con b, la
stringa che permette di percorrere zero o più volte quel cammino sarà denotata da
b*.
Se consideriamo ora tutti i cammini che portano da q0 a q^, otteniamo
b*a(bb*a)*, dove b* descrive la transizione da g0 a q$ etichettata con b, a denota la
transizione da qo&qi e bb*a un generico cammino da q} a qL che passa per q0. Tale
cammino può essere percorso zero o più volte. Si osservi che, anche se non
propriamente parte degli operatori usati per definire ER, spesso si usa
l’abbreviazione a+ al posto di aa*, ad indicare che il simbolo a viene ripetuto una o
più volte. L’espressione b*a(bb*a)* è quindi equivalente a b*a(b+a)*.
Consideriamo ora tutti i cammini che portano da q0 a q2, cioè i cammini percorsi
dalle stringhe riconosciute da A. Le stringhe che permettono di percorrere questo
cammino sono denotatate dall’ER b*a(b+a)*a(a* + (b(b+a)*a)*)*, dove b*a(b+a)*
descrive le stringhe che portano da q0 a qi, a descrive la transizione tra q> e q2 e
(a* + (ò(ò+a)*a)*)* rappresenta i possibili cammini da q2 a q2. In particolare a*
descrive un autoanello su q2 e (b(b+a)*d)* un ciclo che passa per q< ed
eventualmente ((Z>+a)*) per q$.
■
Questo procedimento si può generalizzare ottenendo un algoritmo che permette di
costruire un’espressione regolare a partire da un automa a stati finiti e viceversa. In
questo testo non approfondiremo oltre le ER, formalismo peraltro semplice e
intuitivo, grazie all’equivalenza con automi a stati finiti e grammatiche regolari. Il
lettore interessato ad approfondire l’argomento può fare riferimento ai tradizionali
libri sulla teoria della computazione, già citati nelle note bibliografiche dei Capitoli
4 e 5.
fi(X, ...,Xm) = 0
dove sono funzioni fi: ftfVffij = 1, ..., m sono variabili
definite su p(Fr*).
Una soluzione del sistema di equazioni è una nz-upla di linguaggi che,
sostituiti alle variabili, soddisfano tutte le equazioni.
Nel seguito si concentrerà l’attenzione su equazioni scritte nella forma X =
F(X), in cui X= (Ai, ..., Xm) è un vettore di variabili, F = fi, è un vettore di
funzioni e ciascuna fi è ottenuta come composizione di unioni “u” e di
concatenazioni “ • ”. Poiché “ • ” è distributiva rispetto a “u” (si veda l’Esercizio
1.6), ogni fi può essere espressa, in una forma normale, come l’unione della
concatenazione di variabili (e costanti).
244 Informatica teorica
Esempio 6.4
Si consideri il seguente sistema costituito da una sola equazione nella variabile-
linguaggio A:
X = A-X-B'jA-B
dove A = {a} qB = {b}, per cui l’equazione diventa A= {a} -X- {b} u {a} ■ {b}.
Il linguaggio L = {<Fb”\ n > 1} è un punto fisso per la precedente equazione, poiché
{a}L • {b} = {anbn\ n > 2} e {a}-L • {b} u {a} ■ {b} = {anbn | n > 2} u {a} • {b} =
{anbn\ n> 1} = L.
■
Si osservi che, in generale, un sistema di equazioni nella forma A = F(A) non ha un
unico punto fisso. Questa caratteristica viene illustrata nel seguente esempio.
Esempio 6.5
Si consideri la seguente equazione in una sola variabile-linguaggio A:
A=A-AuA
dove A = {aa}.
Questa equazione ha infiniti punti fissi del tipo
Lk = Fu Llk per ogni k>Q con
L0={a2n\n>Q},Lìk={a2n+k\n>()}.
Un dubbio che sorge quasi spontaneamente, dopo aver osservato che per
un’equazione vettoriale X = F(X) possono esistere più punti fissi, eventualmente
anche infiniti, è se esista sempre un punto fisso, e, tra tanti, un minimo punto fisso.
Per minimo punto fìsso si intende una w-upla di linguaggi L tale che L = F(L) e, per
ogni L', tale che L' = F(L'\ L czL'. Ovviamente un minimo punto fisso, se esiste,
deve essere unico. Infatti, se L\ e L2 fossero due minimi punti fissi, per definizione
dovrebbero valere entrambe le relazioni L\ cz L2 e L2 £ L\. Quindi necessariamente
deve risultare LY=L2.
Per equazioni vettoriali del tipo considerato in questa sezione, cioè equazioni
X=F(X), dove F è una funzione vettoriale i cui elementi sono unioni di
concatenazioni di variabili-linguaggio e di costanti-linguaggio, esiste sempre un
minimo punto fisso L, dato dalla seguente formula:
L= Jf'(0)
J=1
cioè, L = 0 u F(0) u F(F(0))....’
Le equazioni del tipo precedente possono quindi essere usate per indicare il
loro unico minimo punto fìsso. Poiché esiste una corrispondenza uno-ad-uno fra
questa classe speciale di equazioni negli spazi dei linguaggi ed i loro minimi punti
fissi, si dice che le equazioni denotano un linguaggio: il loro minimo punto fisso.
Consideriamo ora le grammatiche non contestuali, introdotte nella Sezione
5.1, e osserviamo che l’insieme di produzioni di una grammatica NC G = (VT, VN,
P, S) si può scrivere come:
1 II lettore non digiuno di matematica del continuo avrà sicuramente riconosciuto l’analogia
con il classico teorema di punto fisso dell’analisi matematica, dove i domini delle variabili
sono i più tradizionali numeri reali o complessi (o altri ancora, più sofisticati, sempre dotati
della caratteristica di continuità). Infatti non solo la forma dell’equazione (x = ffxj) è
identica, ma anche il modo con cui se ne dimostra l’esistenza della soluzione, o punto fisso,
e la si costruisce è lo stesso: nel continuo il punto fisso (unico in un opportuno sottoinsieme
dello spazio e sotto opportune condizioni per la trasformazione f) è il limite di una
successione {x„}, dove xn+I =f(x„) (con xn scelto arbitrariamente in un certo sottoinsieme).
246 Informatica teorica
Xn | • • I ® fl/in
è una abbreviazione di
dove, se
allora
“■ti ..............
Teorema 6.2
Sia G = (VT, Vn, P, S) una grammatica non contestuale in cui VN = {Xi, Xn} e sia
S = Xh Sia X = F(X) il sistema di equazioni associato a G. Allora la n-upla di
*
linguaggi L = (Lr, L„), con L, = {x, e VT* \ X (=> xj, i = 1, ..., n, è il minimo
G
Traccia di dimostrazione
Come osservato in precedenza, l’equazione vettoriale X = F(X) ammette minimo
punto fisso. Sia dunque X tale minimo punto fìsso. Si intuisce immediatamente
247
Definizioni denotazionali dei linguaggi
che x non è altro che l’intersezione di tutti i punti fissi dell’equazione X= F(X).
x è quindi dato da:
x = r>x \ x = F(X) .
La dimostrazione di questa affermazione è lasciata al lettore per esercizio.
Sia Xf la componente z-esima del vettore x . Si è già potuto notare, in
CO
precedenza, che X = [J FJ (0). Viene ora dimostrato che, per tutti gli interi k e z,
7=1
k
con k > 1, 1 < z < n, X,■ = S => x se e solo se x appartiene alla componente z-esima
G
k *
di I I FJ (0). Ciò consente di concludere che, per ogni x e Fp*, X, => x, se e solo
G
7=1
£+1 k
Inoltre, Yr => zr, per ogni hr<k, per ogni r, con 1 < r < m e XgZiXj... zinxm = x.
k
k i+l
Quindi x appartiene alla componente z-esima di F(|J F3 (0)) c F3 (0). In
7=1 7=1
modo analogo si può dimostrare l’enunciato opposto, ossia che, se x appartiene alla
, h
Esempio 5.4
Si consideri la grammatica
G = ({a, b}, {.S}, {.S -> aSb, S ab}, S):G si trasforma nella seguente equazione
S = {a}-S- {b}u {ab}.
Come è noto, L = {anbn\ n > 1} è il linguaggio generato da G ed è anche un punto
fisso per l’equazione corrispondente. In base al teorema precedente, L è il minimo
punto fisso.
00
L si può anche ottenere come F3 (0)={ab} u {aabb} u .... Si verifica
7=1
immediatamente in questo esempio che il processo di costruzione di L come
00
F3 (0) produce stringhe le cui derivazioni grammaticali hanno lunghezza
7=1
crescente. Questa è una proprietà generale della costruzione.
■
ESERCIZIO
6.4 Si calcolino i minimi punti fissi delle seguenti equazioni e si verifichi che
coincidono con i linguaggi generati dalle grammatiche corrispondenti. Si
controlli anche se, per le medesime equazioni, esiste qualche punto fisso non
minimo e lo si confronti con il punto fisso minimo.
St:X=aX
S2'. X ~ aX VJ a
jX = aY
S3 :
[Y = bX ub
S4:X=Xua
Definizioni denotazionali dei linguaggi 249
S5:X=X2Uaub
U = auXY
S6: J
y = 6u xy
2 Si avverte il lettore che il termine “stato” viene qui impiegato informalmente con un
significato più generale di quello che caratterizza lo stato dell’unità di controllo di un
automa. Un simile uso informale e colloquiale del termine “stato” è molto comune, anche
se, in termini formali, il concetto intuitivo di stato viene effettivamente formalizzato dalla
nozione di configurazione.
3
250 Informatica teorica
essere viste sia come un insieme di equazioni che come un modo per computare la
soluzione di un insieme di equazioni: L = F(0) o F(F(0)) u .... Quindi, è
possibile affermare che le grammatiche costituiscono una sorta di ponte ideale fra i
modelli puramente denotazionali e quelli puramente evolutivi. In ogni caso è bene
ricordare, come già preavvisato nel Capitolo 3, che questa classificazione dei
modelli ha un “sapore” prettamente stilistico ed è legata più all’intuizione che a
una definizione matematicamente precisa; non a caso i diversi teoremi di
equivalenza dimostrati in questi capitoli permettono di passare agevolmente da uno
“stile di definizione” all’altro.
Nel Capitolo 7 vedremo un’ulteriore importante classe di modelli descrittivi: la
logica matematica, introdotta nel Capitolo 2 verrà applicata alla definizione di
sistemi informatici (e non solo) di vario tipo.
ALTRI ESERCIZI
6.5 Si scrivano le ER che denotano i seguenti linguaggi:
- L = {x e {a, b}* | ogni a è seguito da almeno tre b}\
- L2 = {x e {a, b}* | ogni a è seguito da esattamente tre b}; ,
- L3= {x e {a, b}* | x inizia con almeno due a};
- L4= {x e {a, è}* | x contiene un numero pari di a e di b};
- £5 = {x e {a, è}* | il numero di a è divisibile per 5}.
6.6 Si costruisca l’espressione regolare che denota il linguaggio accettato
dall’AFN in Figura 4.43(a).
6.7 Si costruisca l’espressione regolare che denota il linguaggio accettato
dall’AFN in Figura 4.44.
6.8 Si costruisca l’automa a stati finiti che riconosce il linguaggio denotato dalla
seguente ER
a* + (a b*}*.
Cosa cambia se b * viene sostituito con b+r!
6.9 Si descriva l’equazione che denota li linguaggio L = | w G {a, b}*}.
Cosa cambia se w e {a, b}+r?
6.10 Data la grammatica NC G = ({a, b}, {S, X, Y},P, S), dove P è formata dalle
seguenti produzioni:
251
Definizioni denotazionali dei linguaggi
Note bibliografiche
Le espressioni regolari sono state studiate da McNaughton e Yamada (1960). Per il
lettore interessato ad approfondire l’argomento, vale la pena menzionare le
applicazioni dei modelli denotazionali, basati sulle equazioni su algebre
eterogenee, alla descrizione, implementazione e verifica di correttezza dei tipi di
dati astratti (ADI (1975) e Guttag (1977)).
Le equazioni negli spazi di linguaggi sono forse meno ampiamente usate e il
loro studio è in genere di interesse più specifico. Esse sono state trattate, ad
esempio, in Gross e Lentin (1967) e approfondite in Gatto e Mandrioli (1974).
Questo formalismo è stato presentato qui solo come semplice ed elegante esempio
introduttivo di un modello denotazionale. Vale anche la pena di segnalare che un
approccio denotazionale basato su equazioni e relativo punto fisso è stato utilizzato
in informatica anche per definire la semantica dei linguaggi, oltre che la loro
sintassi, come abbiamo fatto in questo capitolo. Il lettore interessato può fare
riferimento al Capitolo 4 del “fratello maggiore” di questo testo (Ghezzi e
Mandrioli, 1989) per un’introduzione abbastanza accurata alla semantica
denotazionale dei linguaggi (di programmazione) e alla relativa bibliografia per
eventuali approfondimenti.
Capitolo 7
Esempio 7.1
Il linguaggio L formato dall’insieme di tutte le stringhe sull’alfabeto {a, b} che
iniziano con a, cioè, L = {x e {a, b}*\ x = a.y ey e {a, b}*}, può essere espresso
nella sintassi della mediante la fbf:
x e L <=> 3y(x = a.y ay e {a, b}*).
L’Esempio 7.1 evidenzia già alcune domande che nascono quando si vuole
ricorrere alla logica per definire linguaggi: che cosa si deve formalizzare? Con
quali elementi della EErEEEl Come si possono comporre le diverse parti della
definizione? Che cosa si può assumere come elemento primitivo?
Consideriamo nuovamente il linguaggio (a"b" | n > 1}, più “vincolato”
rispetto al linguaggio dell’Esempio 7.1. La notazione precedente può essere vista
come un’abbreviazione della formula x g L <=> 3n(n > 1 a x = an.bn). Una prima
osservazione è che si usano simboli noti quali g, >, a , = come predicati; inoltre si
usa anche il tradizionale simbolo di esponente (potenza di) come simbolo di
funzione. Come già accennato, in qualche modo si devia dalle rigide regole
sintattiche di ATTESE in favore della leggibilità: e.g. il simbolo di predicato ‘g’ è
usato al posto di un “anonimo” , questo suggerisce la sua interpretazione
naturale; inoltre si passa da una forma puramente prefissa a una infissa; si agisce in
modo simile per altri simboli di funzioni note e simboli di predicati. In letteratura, è
comune riferirsi a notazioni di formalismi modificati e/o arricchiti senza
cambiamenti nella semantica, con l’obiettivo di renderli più facilmente intuibili,
con l’espressione “zucchero sintattico”.
Si noti che non tutte le notazioni funzionali e relazionali possono essere viste
ed interpretate come elementi di base: in realtà, dovrebbero essere necessari solo
poche operazioni di base e i simboli a loro correlati, mentre tutti i rimanenti
dovrebbero essere definiti come derivati.
Nel primo esempio si è visto che la concatenazione e la potenza sono funzioni.
Ma cosa vuol dire x che appare nel secondo esempio? Si tratta di una funzione
256 Informatica teorica
derivata che può essere definita in modo ricorsivo sulla base della concatenazione,
come segue:
Vw((w = 0 => xn = s) a (n > 0 => xn = x"'7.x)).
Perciò essa non può essere considerata una primitiva.
In generale, tutti i predicati e le funzioni non elementari necessitano di essere
definiti mediante formule adatte; per semplicità, considereremo invece come
elementari, oltre la concatenazione di stringhe, i seguenti elementi, presi “in
prestito” dalla tradizionale teoria degli insiemi e daH’aritmetica:
- L’uguaglianza, indicata con il simbolo di predicato ‘=’;
- L’ordinamento (stretto, debole, parziale o totale), generalmente indicato con i
simboli ‘<’, ‘>’, ‘<’, ‘>’;
- L ’ appartenenza a un insieme : ‘ g ’ ;
- Le operazioni aritmetiche di base ‘+, -, *, /’.
Esempio 7.2
Si consideri il linguaggio L, composto dalle stringhe in {a, b, c}*, in cui tutte le a
(se ce ne sono) precedono tutte le b (se ce ne sono) e queste a loro volta precedono
tutte le c (se ce ne sono), in altri termini L = a*Z>*c*. Tra i tanti modi possibili di
definire formalmente L, consideriamo il seguente: si possono definire due
linguaggi ausiliari più semplici Li = «*A* e L2 = A*c* e affermare che una stringa
appartiene a L se:
- èinLbo
- è in L2, o
- può essere decomposta nel carattere a seguito da un suffisso y che appartiene a
sua volta a L, 0
- può essere decomposta in un prefisso y che appartiene a L seguito da una c.
Questa definizione può essere formalizzata nel modo seguente:
x e L <=>(x g Li) v (x g L2) v
3y{(x = a.y aj g L)) v (x =y.c aj g L)).
Rimangono quindi semplicemente da definire Li e L2; poiché hanno la medesima
struttura, focalizziamoci solo su Lb Li è il linguaggio delle stringhe in {a, b}* con
tutte le a che precedono le b. Più precisamente, una stringa è in Li se è la stringa
vuota oppure si può decomporre nel carattere a seguito da un suffisso y che
appartiene esso stesso a Lb o in un prefisso y (appartenente esso stesso a Li)
seguito da una b. Questo può essere espresso mediante la formula
xgLi<5>x = sv 3y(* = a.y a y g Li) v 3j/(x =y. b a y g Li).
257
La logica matematica in informatica
Esempio 7.3
Sia L {x g {a, b}*\ il numero di a sia uguale al numero di b}. Per definire questo
linguaggio in si può introdurre la funzione di arità 2 #(a, x), che conta il
numero di apparizioni del simbolo a nella stringa x. Questa funzione può essere
formalmente definita dalla formula
(x = e => #(a, x) = 0) a
VX(X = a-y => x)= y)+1 ) a
(x = b.y => #(a, x) = #(a, y)).
Si noti che questa definizione dipende dall’alfabeto su cui x è definita.
Sulla base della funzione #, il linguaggio L può essere definito mediante la
seguente fbf in
x g L <=> x g {a,b}* a #(óz, x) = #(b, x).
■
ESERCIZI
7.1 Dare due differenti formule in T^LES7 per definire il linguaggio L = {anbn |
n > 0}.
Suggerimento', una formula può sfruttare la ricorsione, formalizzando che in
un “caso normale” una stringa di L consiste nella coppia di caratteri a e b che
include un altra stringa di L\ un’altra formula potrebbe esprimere la stringa
di L come sequenza di a seguita da una sequenza di b, tale che il numero di
occorenze di a si uguale al numero di b.
258 Informatica teorica
{Precondizione: Pre}
Programma o frammento di programma : P
{Postcondizione: Post}
Figura 7.1 Specifica delle proprietà di un programma mediante pre e
postcondizioni.
259
La logica matematica in informatica
Esempio 7.4
Sia P un programma implementato per svolgere la ricerca di un elemento x in un
array ordinato A di n elementi. La precondizione, ovvero l’ipotesi sotto cui
l’algoritmo proposto deve funzionare correttamente, è, ovviamente, che l’array sia
ordinato. La postcondizione stabilisce che la variabile logica trovato sia vera se e
solo se esiste nell’array l’elemento x cercato dall’algoritmo.
Si noti che definire le precondizioni e le postcondizioni non implica alcuna
assunzione su come il programma sia implementato. Per esempio, anche se è
richiesto che l’array A sia ordinato, questo non obbliga il programmatore a
implementare un algoritmo binario di ricerca.
Formalmente la precondizione può essere espressa in J’KS’come segue:
{Vz(l <i<n^A[i]<A[i + 1])}
Ovvero, ciascun elemento dell’array è minore o uguale di quello che lo segue (è
implicito che n denoti la cardinalità dell’array).
Analogamente si definisce la postcondizione:
{trovato <=> 3z (1 <i<n a A[i] = x}
Ovvero la variabile logica trovato è vera se e solo se esiste un indice valido
dell’array corrispondente all’elemento cercato.
La struttura completa è quindi:
{Vz(l < z < n A[i] < A[i + 1])}
P
{trovato <=> Ez (1 < z < n a A[z] = x}
Si noti che gli elementi di un array sono indicati secondo la normale notazione
usata in programmazione, che enfatizza che gli array sono casi speciali di
funzione2.
2 Questa naturale assunzione potrebbe creare difficoltà nei casi in cui sia necessario
quantificare gli array visti come variabili di programma: le teorie del prim’ordine infatti
non permettono di applicare quantificatori ai simboli di funzione. In questi casi si può fare
riferimento a teorie di ordine superiore che sciolgono questi vincoli, oppure applicare
qualche “trucchetto” alle formule del prim’ordine. Tali casi non rientrano però negli scopi
di questo testo.
260 Informatica teorica
Esempio 7.5
Sia ORD un programma per ordinare un array A di n elementi che non contenga
apparizioni ripetute del medesimo elemento. La precondizione è che l’array non
contenga ripetizioni, in quanto l’algoritmo deve lavorare sotto questa ipotesi. La
postcondizione, invece, stabilisce che l’array ottenuto sia ordinato, cioè, se un
elemento x precede un elemento y nell’array A, allora x è minore di y.
Formalmente, la specifica generale può essere rappresentata come segue:
{-i(3z'3j (1 < z < n a 1 <j < n a i a A[i] = ^4[/]))} ,
ORD
{Vz (1 <i<n^A[i] <34[z + 1]}
Questa fbf è una formalizzazione corretta della specifica espressa precedentemente
in linguaggio naturale. Una specifica però, indipendentemente dal linguaggio con
cui viene espressa, potrebbe non essere adeguata, ossia non riflettere in maniera
completa o esatta ciò che realmente si desidera ottenere dal programma. In questo
caso, ad esempio, abbiamo omesso di esplicitare un requisito essenziale di ogni
algoritmo di ordinamento, che molti darebbero per scontato, ma la cui mancanza
renderebbe accettabili (formalmente “corretti”) programmi che non eseguono un
vero ordinamento di un array.
Si considerino per esempio i seguenti valori dell’array A:
- A prima dell’esecuzione di ORD è [7 6 2 4 22],
- A dopo l’esecuzione ORD è [2 6 22].
In questo caso A rispetta sia la precondizione sia la postcondizione, ma il valore di
A dopo l’esecuzione non è quello atteso: mancano infatti alcuni elementi di A dopo
l’esecuzione di ORD.
Si noti che anche [3 5 10 11 29] rispetta la postcondizione, anche se nessun
elemento di tale array era in A prima dell’esecuzione di ORD: non è infatti
esplicitato che il programma preservi gli elementi di A, ma solamente che A sia un
array ordinato. La postcondizione deve, quindi, stabilire che tutti e soli gli elementi
che erano nell’array prima dell’esecuzione siano contenuti nell’array ottenuto da
ORD. Si deve perciò stabilire una relazione tra il valore di una variabile prima
dell’esecuzione del programma (o frammento di programma) e il valore della
stessa variabile dopo l’esecuzione. A questo scopo conviene introdurre una
variabile ausiliaria che non è parte del programma, ma ha l’unico scopo di definire
il valore di una variabile a un dato punto del programma. In questo caso un “array
di supporto” B è utilizzato per denotare i valori degli elementi di A prima
3 Si noti che il simbolo di ordinamento “minore o uguale” può essere sostituito dal simbolo
“strettamente minore” in quanto l’array A per ipotesi non contiene ripetizioni. Utilizziamo
questa formulazione apparentemente più debole - che comunque non influisce sui risultati
prodotti dal programma - per supportare future osservazioni.
i
La logica matematica in informatica
4 La formula stabilisce che tutti gli elementi dell’array ordinato siano presenti anche
nell’array da ordinare.
5 La formula stabilisce che tutti gli elementi nell’array da ordinare siano presenti anche
nell’array ordinato.
262 Informatica teorica
ESERCIZI
7.4 Si modifichi la specifica originale per l’algoritmo di ordinamento, in modo
che il risultato desiderato mantenga il numero di occorrenze di tutti gli
elementi di un array inalterato. ’
7.5 Specificare precondizione e postcondizione per una funzione che, dati due
numeri naturali, x e y, restituisce la migliore approssimazione intera per
difetto di logxy.
7.6 Specificare precondizione e postcondizione per un programma che, dati due
numeri interi positivi, x e y, pone la variabile z a 1, se x e y sono primi tra
loro, a 0, altrimenti.
7.7 Si specifichi mediante opportune precondizioni e postcondizioni il seguente
requisito di un frammento di programma FP:
- Sia dato un array A contenente n < interi positivi;
- Gli n interi sono memorizzati nelle prime posizioni di A a partire da
^4[0]. Dopo di essi vi è il valore 0, usato come terminatore;
- FP deve produrre un array B (anche esso terminato da uno 0) che sia il
risultato dell’ordinamento in ordine crescente di A e dell’eliminazione
di eventuali ripetizioni;
- FP usa A come variabile “read-only”.
La logica matematica in informatica 203
Esempio 7.6
Si consideri un semplicissimo sistema di illuminazione che consiste in una lampada
controllata mediante un interruttore; il suo comportamento è dettato dalla seguente
regola: “Se l’interruttore è premuto, la luce si accende entro A unità di tempo”. Per
descrivere questa specifica, si usano due predicati:
- P_B(t)-. l’interruttore viene premuto al tempo t;
- L_On(t)-. la luce viene accesa al tempo t.
La variabile t indica un istante di tempo; il dominio su cui la formula è definita è
un insieme numerico in cui ciascun elemento rappresenta un istante di tempo. Una
formula di 333.che rappresenta il requisito richiesto è la seguente:
6 Crediamo fortemente che la maggior parte delle attività umane potrebbe beneficiare
dell’esposizione alla logica matematica, specialmente le attività di alto livello intellettuale
come organizzazione della società, politica, affari legali ecc.
264 Informatica teorica
L On
L_Off
P_B(t) t+K
Con l’aiuto della Figura 7.2 si può produrre una nuova formula in che
formalizza meglio il comportamento atteso della lampada. Per prima cosa si
aggiunge il predicato L_Off(t), con l’ovvio significato di rendere la specifica più
leggibile, anche se è solo il “complemento” di LjDn(t)\ Come conseguenza, si
deve anche esplicitare la complementarietà tra i due predicati mediante la formula
L_0n(t): \/t(L_On(f) <4> —,
La formula seguente, che sostituisce la precedente dell’Esempio 7.6, dovrebbe
esprimere meglio il comportamento esemplificato nella Figura 7.2:
Vt(P_B(f) => $/t\(t < t\ < t + K L_On(tx)) /\Wt2(t +K<t2=> P_Offit2)))).
La nuova formula fornisce certamente un’idea migliore del comportamento della
lampada, ma non è ancora sufficientemente precisa. Rispetto alla formula
precedente essa specifica la durata per cui la luce rimane accesa e definisce
chiaramente che dopo questo tempo la lampada si spegne automaticamente; manca
però di chiarezza in alcuni punti, ad esempio, non definisce se la luce possa
accendersi in assenza di azioni sull’interruttore.
La specifica sopra presentata implica che la lampada si accenda(o sia accesa)
quando l’interruttore è premuto; da quel momento la lampada rimane accesa per K
unità di tempo e poi rimane spenta per sempre. Ancor più gravemente, essa
comporta una contraddizione nel caso in cui, dopo aver premuto Finterruttore ad
un tempo t, lo si prema nuovamente ad un tempo t’, con t’ > t. In questo caso infatti
la formula implica che, per ogni istante nell’intervallo [f ... t’ + K\, la luce sia
accesa, ma, poiché t’ + K è > t + K, essa deve essere anche spenta; questa
contraddizione è data dalla mutua esclusione tra L_On e L Off. Si noti, infatti, che
in accordo alla semantica della una struttura interpretativa in cui la relazione
associata con il predicato P_B valga in più di un istante di tempo t comporta che la
formula non venga soddisfatta.
Questo è un esempio di un errore che si verifica abbastanza frequentemente
quando si generalizza il comportamento di un sistema partendo da pochi
“esperimenti”: in questo caso la Figura 7.2 fornisce una buona “schermata” di un
singolo possibile comportamento, il più semplice corrispondente a una sola azione
suH’interruttore, ma, basando la formalizzazione sull’osservazione di quel solo
caso, si ottiene una specifica abbastanza superficiale. Una volta realizzato questo
nuovo errore, si può porre rimedio con un’altra formula:
Vt(P_B(t) a LOfflf) => V6((t < h < t + K => L On(tx)) a + X))) a
\/t^t2(L_Off{tx) A < t < t2 => -n P_B(t)) => L_Offlt2)).
7 Si noti che questa affermazione non è necessariamente vera: ci sono casi in cui una
lampada può impiegare un po’ di tempo per passare da accesa a spenta e in questo tempo
non può essere considerata né accesa né spenta.
266 Informatica teorica
ESERCIZI
7.8 Si modifichi la precedente specifica in ..33S" in modo che, se l’interruttore
viene azionato mentre la lampada è già accesa, essa rimanga accesa per
ulteriori K unità di tempo.
7.9 Si formalizzino mediante formule in 3~(33\e, seguenti affermazioni:
1. L’insieme dei numeri naturali primi è illimitato.
2. Esistono macchine di Turing in grado di stabilire se un generico numero
è primo o no.
8 Si noti che in casi complessi potrebbero esserci differenze importanti tra quello che
l'utilizzatore desidera o crede di desiderare e quello che è veramente necessario per il buon
funzionamento del sistema. Questo argomento va, però, oltre lo scopo introduttivo di
questo testo.
La logica matematica in informatica 267
EventoPB a
ESERCIZI
7.12 Nell’esempio sopra riportato si interpreta la mutua esclusione tra i due stati
L_On e LjOff assumendo che in qualunque momento la lampada sia
necessariamente in uno dei due stati. Ci sono casi in cui quando la
transizione tra i due stati non può essere trascurata, esiste un intervallo di
tempo non nullo in cui la lampada non è né accesa né spenta. Si adatti la
specifica precedente a questi casi. Si noti che tale compito può essere
eseguito in due modi differenti:
1. Si introducono nuovi stati per esprimere che il sistema passa da uno
stato stabile a un altro.
2. Il dominio stato si mantiene inalterato, ma il requisito di mutua
esclusione deve essere modificato e le transizioni tra stati non possono
essere modellate mediante notazioni Fino ad ora e Da_ora_in_avanti
relative allo stesso istante.
7.13 Si formalizzi in il comportamento di una cabina telefonica, tale per
cui quando una persona arriva e trova la cabina occupata non può entrare;
quando invece la cabina è libera, allora la persona entra ed esce entro un
tempo K.
7.14 Si formalizzino le seguenti regole per l’apertura di una cassaforte:
1. esistono 2 chiavi diverse in possesso di 2 impiegati diversi;
270 Informatica teorica
- Se il treno sta viaggiando alla velocità Fmax, il tempo per attraversare le sezioni
R,IeI + R sarà il minimo :
d d+h
R in in )A(5Imb
Vmax Vmax
Analizziamo ora il comportamento del treno:
- Se il treno entra nella regione R, esce da R ed entra in I dopo almeno 8Rniin
istanti di tempo e al più òRmax; formalmente
< t, < t+ 5Sirax )) ;
- Se il treno esce dalla regione R, per entrare nella regione I, significa che era
entrato in R almeno 8Rniin istanti di tempo prima e al più òRmax istanti di tempo
prima, e uscirà da I almeno 8Tmin istanti prima e al più S^x istanti prima:
at.UrOjA (7-s^ <t, <t-zRvia ))) A
ar/^COA (r + staùl <r( ))) ;
- Se il treno esce dalla regione I significa che era entrato in R almeno 8min istanti
di tempo prima e al più 8max istanti di tempo prima:
< t, < t- 6nm ))) ;
- Il treno è nella sezione critica al tempo t se vi è entrato prima di t e da quel
momento non è ancora uscito:
Vr(Zw(O« ^(JEn^)^ <t2 <t)))) •
E abbastanza intuitivo che In è uno stato del sistema, mentre Ar, En ed Ex sono
eventi. Perciò si può fare riferimento alle proprietà generali introdotte nella Sezione
7.3.1. Inoltre, dato che si assume di considerare l’arrivo di un solo treno, si può
272 Informatica teorica
specificare che questi eventi occorrono solo una volta nell’intero dominio di
tempo:
^(O^V^^tv^Q^.^))))
con E che definisce un qualunque evento tra Ar, En, Ex.
Si deve ora descrivere il comportamento della sbarra. Prima di tutto, come ulteriore
e “drastica” semplificazione, si assuma che il tempo per l’apertura e per la chiusura
della sbarra sia trascurabile. Gli stati della sbarra vengono quindi formalizzati dalla
coppia di predicati Down e Up. Ovviamente essi sono in mutua esclusione e
complementari, cioè:
— \/t(Down (/) —.Up (/)) .
9 Lo stesso tipo di osservazione potrebbe essere sollevata anche nel caso di proprietà di
programmi: una volta che le precondizioni e le postcondizioni sono state definite ed è stato
costruito un programma allo scopo di garantire le postcondizioni sotto le ipotesi delle
precondizioni , è possibile affrontare il problema di verificare se il programma progettato
rispetta gli obiettivi prefissati.
275
La logica matematica in informatica
ALTRI ESERCIZI
7.16 L’assunzione che il tempo impiegato dalla sbarra per passare dallo stato di
“aperto” a quello di “chiuso” sia trascurabile è, come precedentemente
osservato, una semplificazione drastica che rende il modello lontano dalla
realtà. Infatti, il treno potrebbe percorre un considerevole tratto di strada
mentre la sbarra cambia la sua posizione.
Si modifichi la specifica appena introdotta, assumendo che la sbarra si alzi e
si abbassi in y unità di tempo. Che relazione deve legare y e le altre costanti
di tempo per garantire la sicurezza? Quando deve essere dato il comando di
chiudere o aprire la sbarra dal controllore al sottosistema? Qual è l’ultimo
istante di tempo utile per dare tale commando in modo da evitare di tenere la
sbarra inutilmente chiusa e garantire comunque la sicurezza?
7.17 Dopo aver introdotto la generalizzazione proposta nell’Esercizio 7.16, si
generalizzi ulteriormente il problema considerando la possibilità di avere più
treni che viaggiano nella stessa direzione sul binario. Si può e si dovrebbe
assumere che la distanza (sia di spazio sia di tempo) tra due treni consecutivi
sia sufficiente per garantire la sicurezza, cioè che, dopo che la sbarra ha
iniziato ad aprirsi, essa deve essere completamente aperta prima di essere
chiusa nuovamente, garantendo però la completa chiusura prima dell’arrivo
del prossimo treno.
276 Informatica teorica
10 Si noti che, per rendere le formule più comprensibili, ci siamo concessi qualche “libertà”
rispetto alle strette regole della sintassi della FFFF'-. se gli array sono rappresentati come
funzioni, applicare una funzione a un simbolo di funzione dovrebbe essere vietato.
Possiamo però interpretare la scritturalungh(z) = n come una notazione abbreviata per
lungh_z(n), dove lungh_z è un predicato vero quando la lunghezza di z è n. Similmente z <
lungh(A) va letto come 3zn (lungh_A{m) /\i< m), e così via.
La logica matematica in informatica
!Fino_ad_ora/Inserimento Codice!/) /\
Fino_ad_ora_CifraInserita/, k)
a 0 k < 5 a PremiCifra/))
=> Da_ora_in_avantiJlnserimentoCodice/) a
Da_ora_in_avanti_CifraInserita/, £+1)) a
{Fino_ad_ora_InserimentoCodice(t, 5) a PremiEnter/)
=} Da_ora_in_avanti_~InserimentoCodice!t) a
Da_ora_in_avanti_Verifìca/)) a
!Fino_ad_ora_InserimentoCodice/, 5) a PremiCifra/ - 5) a
(Vt7 !ft - 5 < ti < f) => (—PremiEnter(t) a —PremiCifraity)))
=> Da_ora_in_avanti_—InserimentoCodice(t) a
Da_ora_in_avanti_ Verifica!/)) ;
Regola (f):
Fino_ad_ora_InserimentoCodice/) /\
Fino_ad_ora_CifraInserita!t, k)/\0^k<5/\
kftì !t~5 <t]<t=> —PremiEnter(t) a —PremiCifra(t))
=> Da_ora_in_avanti_—InserimentoCodice(t) a
Da_ora_in_avanti_Idle!t) a Cartarestituita/).
278 Informatica teorica
APPENDICE 7.A
esempio I Ora. Si supponga ora che P sia corretto rispetto a questo requisito, mentre
P’ garantisca solo un limite di approssimazione di 10.00In. Chiaramente,
considereremo ancora P’ più affidabile di P, anche se, rigorosamente, P’ non è
corretto, mentre P lo è.
Questo esempio mostra che la correttezza di un programma e la capacità di
reagire a situazioni anormale o inaspettate sono tipiche proprietà che rientrano
nella nozione di affidabilità. Non intendiamo qui approfondire ulteriormente il
concetto di affidabilità, poiché risulta caratterizzato da molti aspetti informali
propri del campo dell’ingegneria del software. Si osservi che, almeno in linea di
principio, è possibile cercare di tradurre ogni proprietà che influisce
sull’affidabilità di un sistema in un’opportuna specifica formale, formalmente
dimostrabile. Il vero problema con cui ci scontriamo è però la difficoltà di
esprimere formalmente tutte le possibili proprietà del software.
Il resto di questa appendice introduce prima alcuni semplici elementi per
l’analisi formale di programmi e poi mostra in modo più formale rispetto al caso di
studio in Sezione 7.3.3 come si possano verificare proprietà per un sistema
specificato in logica.
Assioma di assegnamento
Per ogni fbf Post, per ogni termine t e variabile x derivabili dai non terminali
(Expr) e (SimpleVar) della grammatica di SMALG, la fbf
Af. {Post '} x = t {Post } è un assioma.
■
Post x è equivalente alla notazione Post\t/x}, utilizzata nella Sezione 2.3.1 ad
indicare l’espressione ottenuta da Post sostituendo tutte le occorrenze libere di x
con il termine t. In questo contesto l’applicazione della regola A\ per derivare
Post x da Post viene chiamata sostituzione all’indietro. Infatti, informalmente,
l’assioma di assegnamento esprime il fatto che un predicato Post è valido dopo un
assegnamento se e solo se, prima della sua esecuzione, vale il predicato ottenuto
sostituendo tutte le occorrenze della variabile a sinistra del simbolo ‘=’ (x) con il
termine (t) a destra del simbolo. Un banale esempio di questo fatto è la proprietà
{3 > 0} x = 3 {x>0}.
Le regole di inferenza sono definite mediante la classica notazione di Hoare
In :---------------------
f
che significa “l’enunciato f è diretta conseguenza degli enunciati /b f2, ...,/, in
virtù della regola In”.
A voler essere rigorsi, bisogna osservare che ogni teoria del prim’ordine non
dovrebbe possedere nessuna regola di inferenza oltre a MP e Gen. Si può tuttavia
considerare In come una riformulazione dell’assioma /j a /2 a ... a /„ => f ,
che ci consente di derivare f da f\,f2, -..,fn mediante MP. Chiameremo quindi In
regola di inferenza, per coerenza con la letteratura e con il suo significato intuitivo.
283
La logica matematica in informatica
0, 1, ..., 9,!,>,<,
(Digit)—> 0| 1 | 2 | ... | 9
(Letter) -^a|b|...|z|A|B|...|Z
if ((Cond)) {(StatList)}
Regola di composizione
Per ogni frammento di programma Si, S2 e S = Si, S2 e per ogni formula R,Q,T
rD . {R}SfQ},{R}S2{T}
{R}S{T}
■
Intuitivamente, la regola di composizione significa che, se una precondizione R
garantisce la validità della postcondizione Q dopo l’esecuzione di Si e la Q,
considerata come precondizione, garantisce la validità della postcondizione T dopo
l’esecuzione di S2, allora la validità di R garantisce la validità di T dopo che sono
stati eseguiti in sequenza Si e S2.
Ad esempio, se Si è x = f (x) e S2 è x = f2 (x), l’applicazione di Ai
consente di ottenere, per ogni R
{R^x)}x = /2(x){7?}
e
{^(/‘W)}x = /1(x){^(l)}
Successivamente, applicando IRi, otteniamo
{RxhWx))}x = fl(x);x = f2(x){R}
che, intuitivamente, significa che il frammento precedente consiste nella
composizione delle due funzioni/; e f.
La prossima regola non è strettamente legata alla semantica del linguaggio,
anche se si rivela spesso utile per facilitare le dimostrazioni.
Regola di conseguenza
Per ogni frammento di programma S e per ogni formula Ri, R, Q, Qi
R^ R,{R}S{Q},Q^ Q,
1K ~ ---------------------------------------
{RiWQ,}
■
Ad esempio, quindi
x>3aj>>4=> x + y > 7,{x + y > 7}x = x + y{x >7}, x > 7 => x > 5
Regola if-then-else
Per ogni frammento di programma Si e S2, per ogni condizione c derivabile da
(Cond)e per ogni formula R e Q
{R/\c}Sx{Q},{R f\^c}S2{Q}
lìx. :-------------------------------------------
{À}if(c)S1else S2{Q}
La logica matematica in informatica
Regola while
Per ogni frammento di programma 5, per ogni condizione c e per ogni formula I
■ {^ac}5{7}
Zzi .
{7} while (c)S{7a—.e}
■
Si noti che nella regola while si richiede che l’asserzione 7, se risulta vera prima
dell’ingresso nel ciclo, continui a essere vera anche dopo l’esecuzione del suo
corpo. Infatti, se vale c, viene eseguito il corpo del ciclo e {7 a c}S{I} implica la
286 Informatica teorica
Esempio 7.A.1
Si consideri il seguente programma P, scritto in SMALG, senza considerare le
istruzioni di input e output:
{
x = 1;
j = i;
while(y >= j){
j = j + i;
x = x * z;
}
}
Il programma calcola l’espressione zy, dove si suppone che i valori di z e y siano
già presenti in memoria. Un’asserzione ovvia che rappresenta la correttezza di P è:
PA: {y > 0} P {x = zy}
Per dimostrare la correttezza di P rispetto a PA dobbiamo quindi dimostrare PA,
considerandola come un teorema all’interno della teoria formale descritta
precedentemente. PA può essere dedotta dimostrando i seguenti lemmi
{y > 0} x = 1 ; j = 1 ; {1}
{1} while (y >=j){j=j + l;x = x* z ; } {I a —>(y>=j)}
{/A^(y >= j)} => {x = zy}
Tali lemmi, grazie alle regole IRi e IR2, permettono di concludere PA.
Sfruttando poi la regola IR4, ci riduciamo ai problemi
{y>0}x = l;j = 1; {1}
{ÌAy>=j} j = j + 1 ; x = x * z ; {1}
{/a—,(y>=j)} => {x = zy}
che, se dimostrati, dimostrano anche PA.
Rimane quindi il problema di identificare Tinvariante I, per la cui definizione,
purtroppo, non esiste un algoritmo, ma si può solamente sfruttare il proprio intuito
e la propria conoscenza del comportamento del programma.
Nel nostro coaso, osserviamo che per ogni iterazione del ciclo la variabile j
viene incrementata e x viene moltiplicato per z. Di conseguenza, poiché inoltre la
condizione del ciclo limita j a y, deve esistere ima relazione tra i valori di x, y e j.
Si osservi che aH’intemo del ciclo il valore di j è sempre minore o uguale al valore
di y, tranne nell’ultima iterazione in cui, incrementando j, si ottiene j = y + 1,
valore che interromperà l’esecuzione del ciclo. Quindi y > j-1 è un’invariante nel
287
La logica matematica in informatica
ciclo. Inoltre, poiché x viene moltiplicata per z ad ogni iterazione, anche x = z-'1'1 è
un’invariante del ciclo. Possiamo quindi considerareI = y > j-1 a x = zj-1.
Dobbiamo quindi dimostrare che le seguenti asserzioni sono teoremi
{y > 0} x = l;j = 1; {y > j-1 a x = zj-1}
{y> j-1 Ax = zj'1Ay>=j} j=j +1; x = x * z ; {y > j-1 a x = zj-1}
{y > j-1 a x = z-H a —i(y>=j)} => {x = zy}
Tali dimostrazioni sono facilmente ottenibili applicando la tecnica di sostituzione
all’indietro e vengono lasciate al lettore come esercizio.
■
L’Esempio 7.A.1, per quanto semplice, ha sottolineato un punto importantissimo
nell’applicazione del metodo di Hoare. Tale metodo richiede una forte conoscenza
del comportamento del programma in esame e abilità da parte di chi lo applica ogni
qualvolta è necessario identificare un’invariante per i cicli presenti.
Inoltre, in questa sezione ci siamo limitati non solo allo studio di programmi
semplici che non contengono variabili indicizzate, ma anche all’analisi di
asserzioni prive di quantificatori. Il metodo di Hoare propone regole che
permettono anche di gestire tali programmi e asserzioni, e questo ovviamente
complica la prova della correttezza di un programma. Nuovamente, si invita il
lettore interessato ad analizzare la bibliografia consigliata per eventuali
approfondimenti.
Nella Sezione 7.3 abbiamo visto che la logica può essere un utile strumento per
formalizzare le caratteristiche di un qualsiasi sistema, senza entrare nei dettagli del
suo comportamento. Inoltre, specificare formalmente i vincoli del sistema rende
spesso facile identificare debolezze nella descrizione che porterebbero il sistema a
comportamenti non desiderati. Infine, il caso di studio (Sezione 7.3.3) ha mostrato
che a partire da una specifica formale del sistema sotto analisi è possibile,
formalizzando in logica le proprietà che vogliamo valgano nel sistema, verificare
se tali proprietà valgono effettivamente. Intuitivamente l’idea è di mostrare che le
proprietà specificate si possono dedurre dalla specifica del sistema, cioè sono
conseguenza logica della specifica stessa.
In questa sezione vogliamo analizzare attraverso alcuni esempi come sia
possibile provare formalmente proprietà a partire da una specifica logica,
deducendo le proprietà dalla specifica stessa. Questa sezione ha solo lo scopo di
convincere maggiormente il lettore delTutilità di dedicare tempo e impegno alla
specifica formale di un sistema, mostrando che, una volta che si possiede una
descrizione formale del sistema, è possibile provarne formalmente la correttezza.
Purtroppo bisogna però osservare che il procedimento che porta alla prova di
correttezza richiede in generale molte conoscenze matematiche e molta attenzione
da parte di chi sta analizzando la specifica.
288 Informatica teorica
Iniziamo analizzando in modo più formale il caso di studio riportato nella Sezione
7.3.3.
Esempio 7.A.2
Il caso di studio affrontato nella Sezione 7.3.3 descrive le specifiche di un semplice
passaggio a livello. In tale esempio si sono identificati i seguenti assiomi (che
riportiamo in modo schematico per comodità, commenti e spiegazioni sugli
assiomi si possono trovare nella Sezione 7.3.3):
- Vincoli sugli intervalli
(II) (8 „ = d/r ) a (8. = h/ ) a (8
V / V R max //V min ' ' Imar //Vmin ' max rrV . '
min
(12) (5. . = —)a(8t . = h/ ) a (8 . = -^±A)
x / V R min ' \ Imin / JZ ' mm TZ 7
max max max
- Vincoli sul comportamento del treno
(Tl) \f t(Ar(t) => + <tl + ))
(S2) \ft(Ar(t) => + 5Rmn <t1 <t + 8rmx ) => Down(t J))
(S3) \ft(Down(t) => 3/\((* — 8^ < t-8^ ) a Ar(t J))
Esempio 7.A.3
Consideriamo le reti di Petri come strumento per descrivere sistemi (Sezione 4.5.2)
e, in particolare, le reti di Petri temporizzate, introdotte nella Sezione 4.5.3
(Definizione 4.33), ponendo però le seguenti limitazioni:
— Ciascun posto della rete può contenere al massimo un token (la rete è 1-
bounded);
— Non esistono cicli di transizioni che abbiano come minimo tempo di scatto 0.
290 Informatica teorica
Grazie a tali semplificazioni le nostre reti di Petri contengono solo frammenti come
quelli riportati in Figura 7.A.2. Si osservi che tale semplificazione permette
comunque di descrivere il problema del passaggio a livello, affrontato
nell’Esempio 4.30.
Per poter utilizzare un approccio basato sull’integrazione con la è
necessario introdurre gli assiomi che descrivono la semantica del nostro modello
(reti di Petri temporizzate con i limiti appena descritti). Gli assiomi di interesse
sono i seguenti:
(Ist) Il predicato Fire(r, t) che descrive lo scatto della transizione r al tempo t,
descrive un evento; formalmente
\/tVr(Fire(r, Z) => (<7 > 0 a VZi(Z - <7<ZivZi<Z + <7=> -^Fire(r, Z0))
(Mar) La marcatura di un posto P (Mar(P)), che ha come unica transizione
entrante s e come unica transizione uscente v (Figura 7.A.2(a)) è definita
come segue:
^f^P(Mar(P, t)o3d (d>0 a Fire(s, t - d) a
VZi(Z - <7 < Zi < Z => —Flre(v, Zi)))
Inoltre i seguenti assiomi formalizzano le relazioni di scatto per i frammenti in
Figura 7.A.2(a) e 7.A.2(b):
(LI.a) Fire(v, Z) => VZi(Z - mv < <t^> Mar(P, Zi))
(LS.a) VZi(Z - < Zi < Z => Mar(P, Zi)) =i> Fire(y, Z)
(LLb) Fìre(v, t) => VZi(Z - < Zi < Z => Mar(P, Zi) a Mar(Q, Zi))
(LS.b) VZi(Z - Mv < Zi < Z => Mar(P, Zi) a Mar(Q, Zi)) => Fire(y, t)
Sfruttando gli assiomi appena scritti e utilizzando il medesimo schema utilizzato
nell’Esempio 7.A.2 è possibile derivare alcuni lemmi, quali ad esempio,
considerando il frammento di Figura 7.A.2(a),
La logica matematica in informatica 291
Note bibliografiche
L’applicazione della logica matematica in informatica è un argomento molto vasto.
Panoramiche abbastanza dettagliate sull’argomento possono essere trovate in
Burris (1997), Mordechai (2003) e Hunt e Ryan (2004).
Il lettore interessato poi ad analizzare logiche non trattate in questo libro può
dedicarsi allo studio della logica descrittiva, spesso usata in intelligenza artificiale,
e della logica modale e temporale, utilizzata generalmente in ingegneria del
software per specificare proprietà di sistemi. Baader et al. (2003) raccolgono i
contributi più significativi sulle logiche descrittive e sulle loro applicazioni.
Emerson (1990) propone una dettagliata introduzione della logica modale e in
particolare della logica temporale. Un altro possibile approfondimento
sull’argomento è proposto in Venema (2001).
Il lettore interessato ad analizzare tecniche di verifica per specifiche descritte
in logica matematica può concentrarsi sullo studio delle tecniche per le
dimostrazioni di teoremi (theorem proving), riferendosi, ad esempio, a Duffy
(1991), e su tecniche di verifica completamente automatiche, come il model
checking, di cui il libro Clarke et al. (1999) dà una descrizione esaustiva. Per una
lettura più concisa il lettore può riferirsi a Peled et al. (2009). Esistono molte altre
tecniche per l’analisi di specifiche e non è tra gli obiettivi di questo testo fornire
una bibliografìa completa.
Lo studio dell’analisi di precondizioni e postcondizioni può essere
approfondito analizzando le tecniche per verificare le postcondizioni a partire dalle
precondizioni, Hoare (1969), oppure studiando linguaggi ad hoc per particolari
linguaggi di programmazione, come, ad esempio, JML (Java Modeling Language)
per Java.
Il caso di studio del passaggio a livello è stato molto usato in letteratura come
“benchmark” per valutare formalismi adatti alla specifica, analisi e verifica di
sistemi critici in tempo reale. Heitmeyer e Mandrioli ( 1996) presenta una raccolta
di contributi di diversi autori che si “cimentano” con questo benchmark a diversi
livelli di approfondimento e sfruttando diversi formalismi. Infine si possono
approfondire le applicazioni a casi reali, ad esempio in Abrial et al. (1995).
Capitolo 8
b{x{ + Z)2X2 = C2
Notiamo poi che è possibile far corrispondere biiettivamente Z, e quindi Z6, con
N. Lo stesso vale per Q2, poiché ogni numero razionale si può descrivere come
coppia di interi: per ogni r e Q, r = m / n, per qualche m,n e Z. In questo modo il
problema precedente viene ridotto al problema del calcolo di un’opportuna
funzione/ N N.
ESERCIZI
cioè il linguaggio delle stringhe formate da una stringa su V\*, seguita dalla sua
traduzione; la stringa e la sua traduzione sono separate dal simbolo speciale “$”.
Un dispositivo che riconosce ZT può essere usato come trasduttore che calcola
r; per ogni x, infatti, è possibile enumerare tutte le y g V2* e verificare se x$y g
o no: se ciò avviene g Zt), si può concludere che la stringa y è la traduzione
rispetto a r della stringa x, cioè r(x) = y. Si noti che questo processo ha termine se e
solo se t(x) risulta definita. Infatti, qualora per x non fosse definita una traduzione,
si proseguirebbe nell’enumerazione delle je V2*. senza mai trovare una stringa x$y
che appartiene a ZT.
ESERCIZI
Come annotazione finale, ricordando il Teorema 4.19, che dimostra che ogni MT è
equivalente ad un’opportuna MT avente un alfabeto con due soli simboli, si può
affermare che, diversamente dagli altri automi, la classe di problemi risolvibili
dalle MT risulta indipendente dall’alfabeto scelto per la rappresentazione, purché
contenga almeno due elementi.
Tutta la discussione svolta finora conduce ad una importante conclusione: le
MT, e i formalismi ad esse equivalenti, sono i risolutori meccanici di problemi più
La risoluzione automatica dei problemi 299
potenti fra quelli incontrati finora, indipendentemente dalla codifica del problema.
Questo fatto consente di concentrare l’attenzione, d’ora in poi, sulle MT intese
come risolutori di problemi, senza preoccuparsi della formalizzazione scelta per la
nozione di problema.
ESERCIZI
1 Si ricordi che in questo contesto per “potenza di calcolo” intendiamo la classe di problemi
risolvibile mediante un certo formalismo, ma non facciamo riferimento allo “sforzo”
impegato dalla macchina astratta per il calcolo della soluzione; abbiamo già notato ad
esempio che una MT a nastro singolo può aver bisogno di un notevole numero di mosse per
simulare una sola mossa della macchina a k nastri; ancor più significativa è la differenza tra
il meccanismo di scansione della memoria rigorosamente sequenziale tipica delle varie
famiglie di automi esaminate nel Capitolo 4 e l’accesso diretto alle celle di memoria che
caratterizza le architetture di calcolo che fanno riferimento al classico schema di von
Neumann. Queste osservazioni saranno approfonditamente riprese nel Capitolo 9 dedicato
appunto al “costo” per il calcolo della soluzione meccanica dei problemi.
La risoluzione automatica dei problemi 301
I
302
Informatica teorica
il medesimo algoritmo, ma, a causa delle particolari rigidità dei diversi linguaggi,
nessuno dei tre implementa completamente la filosofia dell’algoritmo descritto in
Figura 8.1.a, come appare chiaro soprattutto nel caso di P2SORT.
(a)
La risoluzione automatica dei problemi 303
(b)
C P2SORT
PARAMETER (N = 20)
INTEGER X
INTEGER A(21)
DO 73 1 = 2, N + 1
READ(5,75)A(I)
73 CONTINUE
DO 77 1 = 3, N+ 1
X = A(I)
A(1) = X
J 0 1-1
78 IF(X.GE.A(J)) GO TO 79
A(J+1)=X
J = J-l
GO TO78
79 A(J+1)=X
77 CONTINUE
75 FORMAT(I5)
DO 74 J = 2,N+ 1
WRITE(6,75)AtJ)
74 CONTINUE
STOP
END
(c)
304 Informatica teorica
(d)
quando il calcolo lo richieda, si vedrà nel prossimo capitolo che vi sono molte
altre ragioni per cui parecchi calcoli che possono essere effettuati da un
automa astratto non possono venire implementati in pratica.
8. Non esiste limite al numero di passi discreti richiesti per effettuare un calcolo
e possono quindi aversi computazioni infinite2. Ciò si accorda perfettamente
con il fatto che le computazioni delle MT possono anche non fermarsi mai:
questo aspetto cruciale della teoria della computazione sarà approfondito nella
Sezione 8.6.
ESERCIZIO
8. 10 Si scriva un programma per calcolatore che simuli un AP che riconosce il
linguaggio L = {anbn\ n > 1}. Il programma deve anche riconoscere quando
non è in grado di simulare propriamente l’automa e avvertire l’utente in
corrispondenza di ciò.
2 Altri autori impongono il requisito che gli algoritmi terminino dopo un numero finito di
passi discreti, qualunque sia il valore dei dati di ingresso ma ciò, come vedremo, limita le
capacità di calcolo dei formalismi.
307
La risoluzione automatica dei problemi
Definizione 8.1
Ogni funzione (o, equivalentemente, problema) per cui esiste una MT che la calcoli
(risolva) si dice computabile o calcolabile (o risolvibile). Un problema risolvibile
la cui risposta è booleana ed esiste per ogni valore del dominio di definizione (ossia
è formalizzato da una funzione calcolabile e totale) si dice decidibile.
Esempio 8.1
Si consideri l’insieme {a, b}* delle stringhe sull’alfabeto {a, b}. Tale insieme è
algoritmicamente enumerabile. Infatti è possibile associare ad ogni numero
naturale una stringa su {a, b} e viceversa, in modo algoritmico.
Un semplice modo per ottenere lo scopo consiste nell’ordinare le stringhe per
lunghezza crescente e, a parità di lunghezza, assegnare un ordine tra gli elementi
dell’alfabeto su cui sono definite. Perciò, se poniamo a < b, otterremo il seguente
ordine tra le stringhe di {a, b}*: e < a < b < aa < ab < ba < bb < aaa < aab < aba <
abb < baa < ... In questo modo possiamo associare ad ogni stringa il numero
naturale che corrisponde alla sua posizione nell’ordinamento. Simmetricamente,
dato un numero naturale, possiamo ritrovare la stringa che corrisponde a quella
posizione. Per cui la biiezione sarà definita come segue: e <-> 0, a 1, b <-> 2, aa
<-> 3, ab <->4, ...
A questo punto è un facile esercizio di programmazione scrivere un
programma che, ricevendo in ingresso una stringa su {a, b}* ne calcoli il
corrispondente numero nell’ordinamento così definito e viceversa; sulla base della
tesi di Church questo algoritmo può poi essere “codificato” nel linguaggio di
qualsiasi macchina astratta che sia equipotente alle MT.
■
Analogamente a quanto fatto per l’insieme di stringhe {a, b}* nell’Esempio 8.1, è
possibile enumerare algoritmicamente T insieme delle MT. Per semplicità fissiamo
un alfabeto A e consideriamo l’insieme {MT^} delle MT a nastro singolo e senza
stati finali, aventi A come insieme di simboli. Le MT in {MT^} accettano una
stringa se e solo se arrivano in uno stato di halt e compiono infinite mosse
altrimenti.
Si osservi che le semplificazioni precedenti, cioè aver fissato l’alfabeto A,
aver considerato solo le macchine a nastro singolo e aver cambiato la condizione di
accettazione senza considerare gli stati finali, semplificano solamente la notazione,
ma non costituiscono una perdita di generalità in quanto un procedimento analogo
può essere applicato anche su altri tipi di MT; inoltre, qualsiasi problema e
qualsiasi algoritmo per la sua soluzione, se esiste, possono essere descritti mediante
un alfabeto fissato di almeno due caratteri e una MT a nastro singolo con la
condizione di accettazione descritta precedentemente.
La risoluzione automatica dei problemi 309
Mostriamo quindi come {MT^} possa essere enumerato, ossia come si possa
stabilire una biiezione effettiva «P: M <-> {MT4}. Osserviamo in primo luogo che
per ogni intero k, esiste un numero finito di MT, aventi A come insieme di simboli
ed esattamente di k stati. Infatti, il numero di modi diversi in cui si può definire la
funzione di transizione 8 fissato l’alfabeto e il numero di stati risulta finito, poiché
8 ha dominio e codominio finito.
Più in generale, data una funzione f: D R, con D e R finiti vi sono
esattamente |7?||/J| funzioni totali f diverse. Seguendo lo stesso ragionamento per le
MT, poiché la funzione di transizione 8 di un MT a nastro singolo è una funzione
parziale, definita come 8: Q x A->Qx A x {R, L, S}, esisteranno esattamente (1
+ 3 • |2| ■ [A|)lel MT aventi A come insieme dei simboli e Q come spazio degli
stati. Infatti 8 può assumere qualunque valore appartenente a Q XA X {R,L,S},
oppure può risultare indefinita, nel qual caso si scriverà ò(q,i) = ±. Se chiamiamo h
la cardinalità dell’insieme A, allora esistono (1 + 3 • h • k')h'k MT dotate di k stati.
Per poter enumerare le MT in {MT4} è ora necessario ordinare le
(1 + 3 • h • k)h 'k MT con k stati seguendo un preciso criterio sistematico, ad esempio
in base all’ordine lessicografico. Dapprima bisogna imporre un ordinamento
all’interno degli insiemi Q, A e {R, L, 5}, stabilendo, ad esempio, che:
< 7o < 1> $ = ao< ai < ... < ah-\, R< L < S
Successivamente, per q, q e Q, a, a e A m, m' e {R, L, S},si definisca:
- {q, a) < {q , a') se e solo se (q' < q') V (fiq = q) A (a < a')), ossia
{q, ) < {qi, ai), {qo, afi < (qh «I ), (q!, H ) < {qh a^ ecc.
- ± < (q, a, mfidq e Q, 'da g A, 'dm e {R, L, 5}
- (q, a, m) < (q , a , ni) se e solo se
(q < q) V ((q = q) A (a < a')) V ((q = q) A (a = a') A (m< m'fi
La Figura 8.2 chiarisce il significato dell’ordinamento lessicografico.
Infine, si definisca M< M', dove Me M' sono due MT a singolo nastro e a. k stati,
se e solo se esiste una coppia {q,d) tale che 8(g, a) < 5\q, à) e per ogni
{q, a} < {q, a} 5(q, a) = ò'(q', a'). In altre parole, M precede M' nell’ordine
lessicografico se, nella prima coppia {q, a) in cui le relative funzioni di transizione
differiscono, il valore di 8 risulta minore del valore di 8'. Sulla base di questo
ordinamento si possono effettivamente costruire, per ogni k, la prima, la seconda,
..., la (1 + 3 • h • kf 4-esima MT con k stati.
Esempio 8.2
Seguendo la procedura appena introdotta, ordiniamo le MT a nastro singolo con
due stati Q = {q0, qi} sull’alfabeto A = {b , a, b}. Secondo l’ordine lessicografico
avremmo cheq0<ql, b <a<b eR<L<S. Inoltre,
- {qo, b ) < {q0, a) < (q0, b} < {qx, b ) < {qh a) < (q1} b\
poiché {q, a} < {q', a’} se e solo se (q' <q) V ((q = q'} A (a < a')), ossia
- ± < {qh s, ni), Vi g {0, 1}, Vs g {b , a, b}, \/m g {R, L, 5}
- {q, a, m) < {q’, a, m’) se e solo se
(? < ?') V (iq = q') A (a < af) V ((q = qf A (a = a’) A (m < m'f)
Poiché l’ordine tra due MT è dato dal valore della funzione di transizione nel primo
valore rispetto all’ordine fissato tra le coppie {q, a}, si otterrà che la prima
b a b b a b
1 1 1 qi 1 1 1
Mi Mi + l
b a b b A b
41 1 1 1 qi 1 1 1
Mì + 2 M{+ 3
b a b b a b
41 1 1 1 qi 1 1 1
Mi + 4 Mi + 5
ESERCIZI
8.11 Si scrivano due programmi Pascal o C o lava che, per ogni sottoinsieme A
dei caratteri ASCII, calcolino le seguenti funzioni:
N {MXJ
^'1: {MXJ N
8.12 Si illustri a grandi linee la definizione di una MT che enumeri tutti i membri
di {TMj}, per un determinato alfabeto A. Non è necessario specificare tutti i
dettagli della costruzione di tale macchina, ma bisogna mostrare di conoscere
effettivamente in che modo si possa realizzare.
8.13 Si mostri schematicamente un’enumerazione effettiva di tutte le MT
multinastro aventi un determinato alfabeto di ingresso I, di memoria T (e di
uscita O). Si noti che il numero di nastri di memoria non è fissato a priori.
8.14 Mediante un ragionamento analogo a quello usato per enumerare
algoritmicamente {MXJ si mostri come si possono enumerare tutti i
programmi di un qualsiasi linguaggio di programmazione.
312 Informatica teorica
ESERCIZIO
8.15 Si mostri che, per ogni x e y prefissati, la funzione g, definita come la
composizione fx° fy, ovvero g(w) = fx(fy(w')), è computabile, ossia esiste un
indice z tale che g sia fz.
Si mostri inoltre che non solo g è computabile, ma esiste anche una funzione
computabile h: N x N —> N tale che, per ogni x e y, il valore z = h(x, y) è
tale che g =fz. In altre parole, date le MT (o i relativi numeri di Godei) che
calcolano due funzioni prefissate, si può effettivamente costruire una MT (o
il suo numero di Godei relativo) che calcoli la loro composizione.
Si noti infine che g(w) è definita se e solo se ^(w) è definita e fiffwy) è
definita: in altre parole, sia la computazione di My con ingresso w che la
computazione di Mx con ingresso ffw) devono terminare per assicurare la
terminazione di Mz.
Suggerimento', si progetti a grandi linee un algoritmo che riceve in ingresso
una descrizione di Mx e di My, producendo in uscita la descrizione di una
MT, M. che “concatena” le rispettive computazioni. Dapprima M simula My
su ogni ingresso. Poi, se e quando My termina la sua computazione, M simula
il comportamento di Mx sul risultato prodotto dalla simulazione di My. Infine
si calcola il numero di Godei di M, ossia z. Poiché tutto ciò viene svolto da
un algoritmo, la funzione h risulta computabile da una determinata MT.
Vediamo ora come si possa costruire una MTU, a sua volta in modo algoritmico. Si
considerino l’enumerazione discussa nella Sezione 8.5.1: No {MT^} e la
suddetta funzione g: N x N o N definita da g(x, y) =fy(x). Come già osservato la
funzione g(x, y) si può anche considerare come una funzione g : N —> N, purché
sia definita una opportuna biiezione calcolabile algoritmicamente da N x N a N.
Allo scopo di semplificare la notazione, si userà lo stesso simbolo g anche per g .
Un esempio di biiezione da N x N a N è dato dalla funzione
d(x,y) = + y^x + y + + x (si veja ia Figura 4.41 della Sezione 4.3.4), che
2
permette di associare biunivocamente e algoritmicamente a una coppia di numeri
naturali un numero naturale. Graficamente, è come visitare le coppie di punti nel
piano in un ordine prefissato, dove la posizione di un punto nella visita rappresenta
il numero naturale associato alla coppia che identifica il punto.
Si osservi che g è una funzione MT-computabile, ossia esiste uni e N tale che fi -
g ed è possibile calcolarla mediante i passi seguenti.
Passo 7: Si scelga un alfabeto finito A per codificare i numeri naturali ed ogni
altra informazione possibile richiesta per la computazione. E già noto che
qualunque^, con (4| > 2, è adatto a questo scopo.
Passo 2\ Si traduca la rappresentazione di n in un’opportuna rappresentazione
della coppia {x, y) corrispondente a n. La rappresentazione decimale di n
può essere tradotta nelle due rappresentazioni decimali di x e di y,
separate da un simbolo $. Ad esempio, se si sceglie la biiezione
<7: N x N N, definita precedentemente, allora n = 18 è tradotto in
“3$2”. .
Passo 3: Si traduca il numero y in un’opportuna codifica della MT j-esima nella
enumerazione (ossia My).
Passo 4: Si simuli la computazione di My su x.
È già nota la realizzabilità dei passi 1 e 2. Si esamini ora più attentamente come si
possa codificare My. La Figura 8.4a mostra la porzione di nastro che codifica la
transizione definita da
ò(p, a) = {q, b, m)
La Figura 8.4b illustra il caso in cui ò(p,a) è indefinita. Nella Figura 8.4 i simboli
sopralineati (come p, q , ...) indicano le codifiche delle corrispondenti entità della
MT (ossiap, q, ...). I simboli speciali $ e # vengono usati solo come separatori e
non possono apparire in alcun altro luogo. In particolare, una coppia di $ racchiude
la porzione di nastro che codifica ciascun valore di ò. 1 valori di ò vengono fomiti
in corrispondenza agli elementi Q x A, dove Q ed A sono, rispettivamente,
l’insieme degli stati e Tinsieme di ingresso di My.
1
La risoluzione automatica dei problemi 315
$ p # a # q # b f m $
(a)
$ q # a » b $
(b)
Figura 8.4 Codifica di My: (a) ò(p, a) = {q, b, ni); (b) ò(p, a) è indefinita.
Il passo 3 è dunque MT-computabile, ossia esiste una MT in grado di tradurre il (o
la codifica del) numero naturale y nella precedente descrizione di My.
Infine, anche il passo 4 può essere effettuato da una MT, come viene ora
mostrato per una MT multinastro. La MT considerata, come mostra la Figura 8.5,
si serve di un nastro per memorizzare la descrizione di My, di un nastro per
simulare lo stato corrente di My, per ciascun passo della computazione, e di un
nastro per simulare il contenuto del nastro di My, sempre per ciascun passo di
computazione. Il terzo nastro è infinito su entrambi i lati, come il nastro di My.
La computazione da parte del “simulatore” MT (SMT) consiste in una
sequenza di macro-passi. Ciascun macro-passo simula l’esecuzione di un
corrispondente passo di computazione di My ed è costituito dalla seguente sequenza
di azioni, da mi. a m4.
mi. Inizializzazione del macro-passo:
- Le testine di Ti e di T2 vengono posizionate sulle prime celle dei nastri.
Sia qc il contenuto di T2.
- La testina di T3 è posizionata sulla prima locazione della porzione di
nastro corrispondente alla locazione in cui la testina di My verrebbe
posizionata nel caso reale.
- qmiT e lo stato corrente del SMT.
m2. Il SMT cerca, all’interno di Tb una porzione di nastro racchiuso fra due $
consecutive, in modo tale che il primo elemento sia qc e il secondo sia ac,
dove ac è la codifica del simbolo che verrebbe letto da My. Una simile
porzione di nastro viene sempre, inevitabilmente, trovata. Quando ciò
avviene, la macchina entra in un nuovo stato qpouND-
m3. Quando SMT entra in qpouND, se la porzione di Tj trovata indica una
transizione indefinita, allora SMT entra in un nuovo stato quAtr e si ferma,
come farebbe My. Altrimenti, SMT effettua le seguenti azioni:
- Sostituisce qc in T2 con il terzo elemento della porzione trovata in Tb
ossia con la descrizione del nuovo stato di My, ad esempio sia qN .
- Sostituisce ac in T3 con il quarto elemento della porzione trovata in Tb
ossia riscrive T3 come farebbe My con il suo nastro di ingresso.
J16 Informatica teorica
Dispositivo
di controllo
ESERCIZIO
8.16 Si specifichino in dettaglio i macro-passi di un SMT mediante una
descrizione formale completa della macchina.
ESERCIZIO
8.17 Si mostri come una MTU possa simulare se stessa.
3 II termine “andare in loop” tuttavia è leggermente improprio: esso infatti suggerisce l’idea
che l’esecuzione del programma entri in un ciclo di operazioni che viene ripetuto in
maniera identica aH’infinito. Questa circostanza, tuttavia, non è l’unico modo in cui
potrebbe avvenire che l’esecuzione di un programma non termini (come risulterà
ulteriormente chiaro nel seguito); al contrario, se così fosse sarebbe possibile eliminarla
riconoscendo 1’esistenza di un tale ciclo durante l’esecuzione del programma e
interrompendo quindi la sua inutile ripetizione.
319
La risoluzione automatica dei problemi
Esempio 8.3
Vogliamo dimostrare che la funzione g così definita:
g(x, y) = if^(x)=l then 1 else 0
non è computabile, ossia che non esiste una MT che calcola g.
A partire da g, definiamo la funzione h con un solo argomento nel seguente
modo: h(x) = if g(x, x) = 1 then 0 else 1: ci siamo quindi posizionati sulla
diagonale del dominio di g. Se la funzione g fosse computabile, allora lo sarebbe
certamente anche h, cioè esisterebbe un qualche indice xh che rappresenta l’indice
di una MT che calcola h, cioè h = fx .
Calcoliamo allora il valore di h(xh), usando la sua definizione:
h(xh) = if g(xh, xh) = 1 then 0 else 1
Sfruttando la definizione di g, otteniamo
7z(x*) = if fx (x*) = 1 then 0 else 1
Ricordando ora che fx =h, possiamo riscrivere h(xh) come
h(xh) = if /z(x/,) = 1 then 0 else 1, che mostra evidentemente una contraddizione.
La risoluzione automatica dei problemi 321
4 Si noti che il Teorema 8.6 afferma che nessuna MT può decidere se, per un dato valore di
ingresso, una MT si fermerà in uno stato finale. Tuttavia ogni MT può sempre essere
costruita in modo tale da fermarsi se e solo se viene raggiunto uno stato finale.
322
Informatica teorica
Dimostrazione
La dimostrazione segue la traccia della precedente dimostrazione del Teorema 8;6.
Dapprima si definisca:
h(x) = if A(x) = 0 then 1 else ±
Si osservi, quindi, che h è computabile se k è computabile. Infatti, una volta
ottenuta una MT M in grado di calcolare k, sono sufficienti solo semplici modifiche
per adattarla al calcolo di h:. Sia ora x0 il numero di Godei di una determinata MT,
M , che calcola h: ossia h = f , cioè A è la funzione calcolata dalla x0-esima
MT. Si verifica quindi facilmente, tuttavia, che A(x0) = 1 implica f (x0) = ±,
mentre h(x0) = ± implica h(x0) = 1, ossia f (x0) = A(x0) = 1 : in entrambi i casi si
ottiene quindi una contraddizione.
■
Osserviamo che il Corollario 8.7 è impropriamente citato come un corollario del
Teorema 8.6, ma più correttamente esso ne è un lemma, infatti esso costituisce il
cuore sella dimostrazione del Teorema 8.6. L’enunciato di questo lemma, di per sé,
non ha un particolare significato pratico, ma è tuttavia importante menzionarlo per
sottolineare che il suo enunciato non può essere ricavato come conseguenza
immediata del Teorema 8.6, il cui enunciato è più generale.
Si osservi infatti che se un problema è irrisolvibile, può accadere che un suo
caso particolare diventi risolvibile, mentre una sua generalizzazione è
necessariamente irrisolvibile. Al contrario, se un problema è risolvibile, può
accadere che una sua generalizzazione diventi irrisolvibile, mentre un suo caso
particolare rimane sicuramente risolvibile. Nel nostro caso, il Corollario 8.7 è
evidentemente un caso particolare del Teorema 8.6 e sarebbe quindi scorretto
ricavare la sua asserzione semplicemente come conseguenza dell’enunciato del
teorema principale: è al contrario necessario dimostrarlo ex novo, pur
ripercorrendo l’essenza della dimostrazione originaria.
ESERCIZIO
8.18 Seguendo la traccia delle precedenti dimostrazioni per assurdo, si dimostri
che non esiste alcuna MT in grado di calcolare la funzione g definita da:
g(x, y, z) = iff(y) = z then 1 else 0
Dimostrazione
Una volta ancora, la dimostrazione procede per assurdo e in maniera diagonale,
anche se l’applicazione della tecnica dimostrativa richiede in questo caso un’analisi
più dettagliata. Si supponga dunque che k sia totale e computabile. Allora la
funzione g: N N, definita come:
g(x) = w, dove w è il numero di Godei della x-esima MT della enumerazione <£ che
calcola una funzione totale fw, risulta a sua volta totale e anche computabile. E
infatti possibile enumerare tutte le MT per mezzo di una MT. E quindi sufficiente
controllare, per ciascuna di esse, se la funzione calcolata è totale o meno, ottenendo
in questo modo una effettiva enumerazione di tutte le MT che calcolano funzioni
totali. Poiché, per ciascuna z, esiste sempre una z > z per cui f- risulta totale, anche
g(x) è totale.
Si consideri ora la funzione totale h definita da:
h(x) =fg(x)(x) + 1 =/w(x) +1
324 Informatica teorica
Poiché, per ogni x,f^ è totale e computabile, altrettanto risulta essere h. Essendo
poi g totale e strettamente monotona (ossia x' > x implica che g(x') > g(x)),
risulta definita sull’insieme W dei numeri di Godei delle MT che calcolano
funzioni totali e la sua computabilità discende ovviamente dalla computabilità di g.
Sia w0 il numero di Godei di una MT che calcola h. Poiché h è totale, g-1(w0) è
definita. Siax0 = g4w0); allora, per la definizione di Ir.
ESERCIZI
8.19 * Si dimostri che nessuna MT può decidere se, per ogni x, la funzione
calcolata da Mx sia costante o no. Ossia, si dimostri che la funzione g definita
da
g(x) = if4 è costante then 1 else 0
non può essere calcolata da alcuna MT.
8.20 * Si mostri che non esiste alcuna MT in grado di calcolare una delle seguenti funzioni:
■ gi(x, y)= ify G 1 f then 1 else 0
(Si ricordi, dalla Sezione 1.1, che // indica l’immagine di f)
- g2(x, y) = if fx coincide con fy (ossia Mx e My calcolano la medesima
funzione) then 1 else 0
■ gs(x) = if 1 f è finito then 1 else 0
8.21 Si mostri che, per ogni z0 prefissato, non esiste alcuna MT in grado di
calcolare la funzione g definita da
g(x) = if zoe I f then 1 else 0
Analizziamo ora alcune conseguenze pratiche dei risultati fin qui ottenuti. In primo
luogo si è definitivamente constatata l’esistenza di problemi non risolvibili
meccanicamente (o algoritmicamente). Ciò non esclude però la possibilità di
trovare una soluzione per tali problemi: osserviamo infatti che, se le MT (e quindi
gli algoritmi) falliscono, si può sempre sperare neH’intuito e nell’esperienza umani.
Ad esempio, chiunque risponderebbe positivamente alla domanda se la funzione x*2
sia totale e negativamente alla medesima domanda riferita alla funzione 1/x;
qualche riflessione e conoscenza matematica in più sarebbe necessaria per le
2 .
funzioni. x log2(x), log (2')• Nessuno però è in grado di garantire una
a/x2 + 1 22 •
risposta per qualsiasi funzione gli venga sottoposta, proprio per la mancanza di un
procedimento algoritmico.
In secondo luogo, la portata delle affermazioni e delle tecniche di
dimostrazione impiegate è molto più ampia degli scarni risultati matematici finora
enunciati e dimostrati. Infatti, il Teorema 8.6 si può riformulare, in un contesto più
generale, come l’impossibilità di decidere meccanicamente se un dato algoritmo,
indipendentemente dal linguaggio di codifica, si fermerà, prima o poi, per un dato
valore di ingresso. Analogamente, il Teorema 8.8 assicura che nessun algoritmo
può decidere se un dato programma si fermerà per tutti i possibili valori di
ingresso: ecco perché un compilatore ci può segnalare se abbiamo omesso una
parentesi in un nostro programma, ma non ci può avvisare del fatto che il nostro
programma è a rischio di andare in loop o, peggio, vi andrà sicuramente qualsiasi
dato gli venga fornito in ingresso.
Si noti anche che le tecniche di dimostrazione impiegate non sono
strettamente limitate al formalismo delle MT, ma possono venire applicate
direttamente, ad esempio, ai programmi Pascal, una volta fissata un’opportuna
enumerazione algoritmica ed una convenzione che stabilisca quale problema viene
risolto dall’x-esimo programma dell’enumerazione.
Infine, la considerazione che le MT definiscono funzioni parziali, porta con sé
alcune conseguenze. Infatti, la funzione g usata nella dimostrazione del Teorema
8.6 non è computabile solo perché è totale. Se invece si usa la sua restrizione g,
definita da:
g'(x, y) = iffy(x) A ± then 1 else ±
326 Informatica teorica
è facile verificare che g' risulta computabile, essendo solo una piccola modifica
della funzione calcolata da una MTU.
Tutte queste osservazioni vengono approfondite nella sezione seguente.
due funzioni costanti sia h, anche se è evidente che essa è computabile perché lo
sono entrambe le possibilità.
Questo tipo di risultato ricorda le dimostrazioni non costruttive spesso
utilizzate in matematica, dove si dimostra che una soluzione esiste, ma non per
questo è possibile fornirla: in questo caso siamo in grado di affermare che la
funzione h(w) è calcolabile, ma non sappiamo come calcolarla. Questo mostra che
per certi problemi possiamo arrivare ad affermare che il problema è risolvibile,
cioè esiste una MT che lo risolve, ma non per questo siamo in grado di fornire tale
MT.
Allo scopo di chiarire questo punto piuttosto intricato, consideriamo altri
esempi di problemi la cui risoluzione consiste nel rispondere a una domanda, la cui
risposta è certamente una risposta affermativa o negativa “secca”: “Sì” o “No”
indipendentemente dal valore di eventuali variabili in ingresso. Esempi di questi
problemi sono domande del tipo “La partita a scacchi perfetta terminerà? Con la
vittoria del bianco, del nero, o in parità?” oppure “Il numero di molecole
IO10
• IO19 '
dell’universo è pari a 10 ?”. In entrambi questi esempi, come nel caso della
funzione h(w), sappiamo a priori che la risposta è “Sì” o “No”, anche se non
sappiamo quale sia.
Il problema della irrisolvibilità algoritmica può presentarsi solo quando si
devono prendere in considerazione infiniti casi possibili (argomenti e valori di una
funzione, stringhe di un linguaggio), ma non di fronte al calcolo di una funzione
costante, che è il tipo di funzione associata ai problemi descritti in precedenza.
Infatti, codificando la risposta “Sì” come 1 e la risposta “No” come 0, i problemi
precedenti sono associabili o alla funzione fsi (x) = 1, Vx, oppure fno (x) = 0, Vx.
Entrambe le funzioni sono banalmente calcolabili, quindi, anche se non fosse noto
quale delle due funzioni associare al problema, se queste sono le uniche possibili
soluzioni associabili, il problema risulta banalmente risolvibile, pur non essendo
nota la soluzione.
Più in generale, ogni volta che un problema è formalizzabile attraverso ima
funzione definita su un dominio finito, il problema è certamente decidibile. In tali
casi, infatti, la soluzione è rappresentata da una tabella finita. L’esistenza di tale
tabella, però, non garantisce di saperla costruire..
Per chiarire ulteriormente questo delicato aspetto della computabilità, si
considerino i seguenti esempi.
Esempio 8.4
Si consideri la funzione g: N —> {0, 1, ..., 9} definita come g(x) = x-esima cifra
nella rappresentazione decimale del numero reale rr. Ci si potrebbe chiedere se g
sia computabile, visto che rr non è un numero razionale. L’analisi numerica
fornisce diversi algoritmi per calcolare un’approssimazione di n per ogni valore
s > 0 del limite di errore. Esistono cioè algoritmi che calcolano
JZ6 Informatica teorica
un’approssimazione decimale di tt in modo tale che la x-esima cifra sia esatta, per
ogni intero x. La funzione g(x) risulta allora computabile: esiste infatti una MT My
che calcola una funzione fy tale che g =fy. Inoltre è effettivamente possibile trovare
una tale y.
Si consideri ora una nuova funzione gy.
gi(x) = if esiste una sequenza di esattamente x “5” consecutivi nell’espansione
decimale di n then 1 else 0
In questo caso, i precedenti metodi numerici non consentono di concludere che gì
sia computabile. Infatti, per ogni x prefissato, si. può cominciare a calcolare
l’espansione decimale, peraltro infinita, di 7t. In un dato istante possono verificarsi
solo due situazioni: o si è trovata una sequenza di esattamente x “5” consecutivi
oppure non la si è trovata. Nel primo caso si può concludere che gi(x) = 1 e fermare
la computazione, ma nell’altro caso non si può trarre nessuna conclusione. D’altra
parte ciò non consente di concludere che gì sia non computabile. Potrebbe
accadere, infatti, che uno scienziato ingegnoso scopra un algoritmo per calcolare
g7. Potrebbe perfino succedere che venga dimostrato un teorema del tipo “per ogni
dato x esistono sempre x ‘5’ ” consecutivi nell’espansione di tt”. In questo caso
gi(x) sarebbe identicamente uguale a 1.
Molto tempo fa, lo stesso tipo di incertezza esisteva per la funzione h definita da:
h(x) = if esiste una sequenza di esattamente x “5” consecutivi nell’espansione di
741/2339 then 1 else 0
che oggi è noto essere computabile.
Si modifichi ora leggermente il problema, considerando la seguente funzione g2.
g2(x) = if esiste una sequenza di almeno x “5” consecutivi nella espansione
decimale di it then 1 else 0
In questo caso g2 è certamente computabile, poiché ricade necessariamente in uno
dei due casi seguenti:
a. esiste un k tale che
g2(x) = if x < k then 1 else 0 (si veda la Figura 8.6a)
b. g2(x) = 1 (ossia g2 è identicamente uguale a 1) (si veda la Figura 8.6b)
Ad esempio potrebbero esistere 13, 118, 30456 ‘5’ consecutivi e non altre sequenze
oltre tale limite: in tal caso si ricadrebbe nel caso (a) di figura con k = 30457;
oppure potrebbe valere la congettura precedente “per ogni dato x esistono sempre x
‘5’ ma non sussistono altre possibilità.
Nel caso (b), g2 è una funzione costante, quindi computabile. Anche nel caso
(a) essa è computabile, qualunque sia il valore di k. Il problema è che non è noto in
quale dei due casi ci si trovi, né, qualora g2 fosse del tipo 1, quale sia il valore
effettivo di k. È noto quindi che esiste un y tale che g2 =fy, ma non si sa quale sia.
Di nuovo, potrebbe accadere che, in futuro, si riesca effettivamente a trovare un y
opportuno. Finché ciò non accade, tuttavia, non bisogna cercare di dimostrare che
il problema di trovare un y siffatto sia meccanicamente insolubile.
Esempio 8.5
Vogliamo stabilire se dati due generici programmi Pi e P2, che calcolano un
polinomio di grado n fissato (ad esempio n = 324), è decidibile il problema di
decidere se Pi e P2 sono equivalenti. Questo è un caso particolare di un problema
che verificheremo essere indecidibile (si veda la Sezione 8.7.2), ossia stabilire se
due generici programmi Pi e P2, che calcolano due generiche funzioni computabili
/i sf2, siano equivalenti (cioè/i =f2) o no.
Si osservi però che un polinomio di grado n è individuato da n + 1 punti. Per
decidere l’equivalenza tra Pi e P2 è perciò sufficiente fornire in ingresso a entrambi
i programmi n + 1 valori diversi della variabile in ingresso: se (e solo se) i
corrispondenti valori prodotti da Pi e da P2 coincidono in tutti i casi i due
programmi sono equivalenti. In questo caso quindi il problema risulta risolvibile,
ma anche risolto, essendo stato trovato uno specifico algoritmo per la sua
soluzione.
■
Esempio 8.6
Consideriamo il problema di realizzare un archivio di 5MB mediante una tabella
hash, in cui i record hanno la chiave costituita da sequenze di al più 30 caratteri.
Qualora, nella definizione della funzione di hash h, si trovi ima funzione h
“perfetta”, cioè, tale per cui x y implica h(x) h(y), e non si riesca però ad
implementare un algoritmo per il calcolo di h, si può comunque essere certi che h
sia calcolabile. Infatti, poiché il dominio su cui è definita h è finito, h è certamente
calcolabile, anche se questa conclusione non aiuta a calcolarla.
Esempio 8.7
Il ben noto che l’ultimo teorema di Fermat afferma che non è possibile trovare
quattro numeri interi x, y, z, n, con n > 2, tali che xn + yn = z.
330
Informatica teorica
Definizione 8.3
Un insieme S è ricorsivo (o decidibile) se, e solo se, la sua funzione caratteristica è
computabile.
■
Si noti che, per ogni insieme S, la sua funzione caratteristica cs è totale, infatti, dato
un qualsiasi elemento x e N, esso appartiene (cfx) = 1) o non appartiene (c^x) =
332
Informatica teorica
enumerabili non risulta quindi superiore alla cardinalità della classe delle funzioni
computabili, ossia Ko. Come nel caso delle funzioni computabili, la maggior parte
dei sottoinsiemi di M non sono ricorsivamente enumerabili, poiché la cardinalità di
p(N) è 2X°. Il ragionamento corrisponde perfettamente all’analisi delle funzioni
computabili e non computabili.
Il prossimo risultato introduce un insieme non ricorsivamente enumerabile che
permette di approfondire ulteriormente il problema della terminazione del calcolo,
confermando la sensazione originaria che esso sia imprescindibilmente connesso al
raggiungimento della massima potenza di calcolo.
Teorema 8.10
Per ogni S, se
1. i e S implica che f sia totale e,
2. per ogni funzione f totale e computabile, esiste un i e S tale che f=f,
allora S non è ricorsivamente enumerabile.
■
Dimostrazione
Si supponga, per assurdo, che esista una funzione totale computabile gs tale che S =
Ig . Allora si può effettivamente enumerare i0 = gstty, ii = gs(l ), ... e perciò M ,
M , ... e è la funzione totale calcolata dalla MT M. .). Per
ipotesi, la sequenza {ft t , fi. , ...} contiene tutte le funzioni totali computabili.
Si definisca ora la funzione h nel modo seguente:
h(x) =Mx) + 1
Chiaramente h(x) risulta computabile e totale poiché, per ogni x, ftx(x) è definita e
computabile. Esiste quindi un i e S tale che ft, = h (per il quale, cioè,/?1, è identica a
h). Ciò implica, tuttavia, che y?,(z) = h(i) e h(i) + 1 per definizione: ancora
una volta, una contraddizione sulla “diagonale” <indice della MT, dato su cui essa
opera>.
■
Analizziamo l’impatto del Teorema 8.10 sulle capacità degli strumenti di calcolo.
Intuitivamente esso stabilisce che tutte le funzioni totali computabili non sono
ricorsivamente enumerabili (mentre le funzioni parziali computabili lo sono). Si
noti che l’insieme Stot = {x|/i è totale} soddisfa Tipotesi del Teorema 8.10, quindi
non è ricorsivamente enumerabile; tuttavia l’enunciato del teorema comprende
anche altri insiemi contenuti in Slol: infatti, un insieme soddisfa tale ipotesi se
contiene almeno un indice per ogni funzione computabile totale. Stot è dunque il
massimo insieme fra tutti quelli che soddisfano l’ipotesi del teorema.
La risoluzione automatica dei problemi 335
Teorema 8.12
Non esiste una funzione totale e computabile h che sia un’estensione della seguente
funzione
i
La risoluzione automatica dei problemi 337
2. Per un dato n, dapprima si calcoli l’unica coppia (x, y) tale che n = cl(x, y).
Successivamente si simulino non più di y mosse di M, con ingresso x. Se la
computazione termina entro s <y mosse, allora si ponga h (w) = x,
altrimenti si ponga h (ri) = k.
In virtù di questa definizione, h risulta chiaramente computabile, in quanto
la precedente procedura è effettiva e totale. Inoltre I~- Dh, per la
definizione di h .
ii. Parte relativa al “solo se ”
Se 5 = 0 allora sia h(x) indefinita per ogni x. Altrimenti 5 = Ig, dove g è una
funzione totale computabile.
Si definisca h per mezzo della seguente procedura. Per ogni x, si enumerino
g(0), g(l), ..., g(z), Se si trova un i tale che g(z) = x allora h(x) = 0.
Chiaramente h è computabile ma la procedura precedente può non terminare
mai, quindi h è parziale. Inoltre Dh = Ig.
Dimostrazione della parte (b)
i. Parte relativa al “se ”
È simile alla corrispondente di (a) ed è quindi lasciata al lettore per esercizio.
ii. Parte relativa al “solo se ”
La dimostrazione è banale, in quanto una funzione totale non è altro che un
caso particolare di funzione parziale.
■
Si noti che, come nel caso del Teorema 8.9, la dimostrazione del Teorema 8.13 non
è costruttiva poiché essa porta solo a concludere l’esistenza di una funzione h , che
garantisce la semidecidibilità di S, ma non fornisce un meccanismo per costruirla:
per ottenerlo sarebbe necessario un algoritmo per stabilire se h(x) è indefinita per
ogni x, ciò che non rientra tra le ipotesi del teorema.
Grazie al Teorema 8.13, si può far corrispondere una funzione
“semicaratteristica” ad ogni insieme 5 ricorsivamente enumerabile. La funzione c$
viene definita come:
Ci(x) = if x e 5 then 1 else 0 or ±
Per la precisione, la formula precedente non è una definizione della funzione
semicaratteristica, quanto piuttosto una sua proprietà. cs-(x) deve valere 1 se x è
contenuto in S, mentre può valere 0 o risultare indefinito se xeS. Quindi, gli
insiemi ricorsivamente enumerabili o semidecidibili hanno (almeno) una funzione
semicaratteristica computabile.
Giunti a questo punto, siamo in grado di mostrare un insieme semidecidibile
che non è decidibile:
K= {x|/(x)^L}
338 Informatica teorica
ESERCIZI
8.25 Si mostri che i linguaggi accettati dalle MT sono insiemi ricorsivamente
enumerabili ma, generalmente, non sono ricorsivi. Per un suggerimento si
veda il Teorema 8.17.
8.26 Si mostri che, se S = Ig per qualche funzione g totale e monotona, allora S è
ricorsivo (g è monotona se x <y implica g(x) < g(y)).
8.27 L’affermazione dell’Esercizio 8.25 vale nel caso in cui g è debolmente
monotona (ossia x <y implica g(x) < g(y))?
8.28 L’affermazione dell’Esercizio 8.25 vale se g è monotona ma non totale
(ossia, se x < y e se g è definita sia per x che per y, vale g(x) < g(y))?
fp ~f«p)
La funzione fp è chiamata punto fisso di t. perché t trasforma (una macchina che
calcola) fp in (una macchina che calcola) fp stessa.
■
Dimostrazione*
Sia u un qualsiasi numero naturale. Si definisca una MT che realizza la seguente
procedura applicata al valore in ingresso x.
1. Calcola z =fu(u)
2. Quando la computazione di fu(u) si ferma, se ciò avviene, calcola fz(x), che non è
detto sia definito.
La risoluzione automatica dei problemi 339
Si noti che g è totale, mentre f^uy non lo è necessariamente. Ora, sia t una
qualunque funzione computabile totale: poiché g è totale, la composizione t ° g è
totale e anche computabile (si veda TEsercizio 8.14).
Sia dunque v il numero di Godei di t ° g, cioè fv = t ° g. Utilizzando ora v al
posto di u nella costruzione precedente, si ottiene /^ =ffi(vy, poiché ffy) = t° g(v) è
definita. Quindi f^fx) =^(v)(x) per ogni x. Tuttavia/A(v) =/og(v). Quindi^ =f^V) e
g(v) è un punto fisso di t.
■
Sfruttando ora il Teorema 8.14, possiamo enunciare e dimostrare il Teorema di
Rice, che è un risultato fondamentale della teoria della computazione.
Teorema 8.15 (Teorema di Rice)
Sia F un insieme qualunque di funzioni computabili. L’insieme S = {x| /reF} degli
indici di MT che calcolano le funzioni di F è ricorsivo se e solo se F = 0 oppure F
è l’insieme di tutte le funzioni computabili.
■
Dimostrazione
Per assurdo, si supponga che 5 sia ricorsivo, che F # 0, e che F non coincida con
l’insieme di tutte le funzioni computabili.
Si consideri ora la funzione caratteristica cs di S.
cfx) = iffxeF then 1 else 0
Per ipotesi assurda, c$ è computabile.
Sempre per ipotesi, enumerando effettivamente tutte le MT Mh si può trovare il
primo i e S per cui
(«) fi e F
ed il primo j £ S per il quale
(P) fj^F.
Dunque la seguente funzione è anch’essa computabile e totale.
(y) cs (x) = iffx£ F then i else j
Ora, per il teorema di Kleene, esiste un x tale che:
(8) 4(r> = h
340 Informatica teorica
Supponiamo che cs (x ) = i; allora, per (y), segue che f- £ F. Tuttavia, per (5), si
ha che f- = f e, per (a), si ha che f g F; cioè una contraddizione. Si supponga
invece che cs (T ) =j; allora, per (y), risulta f- g F. Tuttavia, per (5), si ha che f- =
fi, e, per ([3), si ha che fiiF’, ottenendo di nuovo una contraddizione.
■
Il teorema di Rice ha un forte impatto pratico negativo; infatti, intuitivamente,
afferma che, in tutti i casi non banali, S non è decidibile. Ad esempio, si ponga F =
{g}, ossia F sia composto solo da una singola funzione g. Per il teorema di Rice,
non è possibile decidere se una data MT possa, o meno, calcolare g. Tuttavia, per la
tesi di Church, il risultato non è ristretto alle MT e al formalismo delle funzioni.
Non è quindi possibile stabilire, per mezzo di un algoritmo, se un dato algoritmo
sia in grado di risolvere un determinato problema, né se due programmi siano
equivalenti (ossia calcolino la medesima funzione). Si noti che quest’ultima
considerazione coincide con il risultato dell’Esercizio 8.19 (la funzione g2 non è
computabile). Un simile risultato non era facile da dimostrare senza l’aiuto del
teorema di Rice, mentre ora è immediato ricavarlo.
Come ulteriore esempio per illustrare la potenza del teorema di Rice nella
dimostrazione dell’irrisolvibilità dei problemi, si consideri l’Esercizio 8.18.
L’insieme delle funzioni costanti chiaramente soddisfa l’ipotesi del Teorema 8.15;
l’insieme dei loro indici non è perciò ricorsivo, da cui si ricava che la funzione g,
definita nell’Esercizio 8.18, non è computabile. Il lettore è invitato a paragonare
questa semplicissima dimostrazione con la sua dimostrazione e con la traccia di
soluzione fornita alla fine del capitolo.
Il grande impatto pratico del Teorema di Rice deriva dal fatto che il concetto
di sottoinsieme F di funzioni computabili è un’espressione formale del concetto
generale di proprietà di problemi risolvibili: una proprietà degli elementi di un
insieme è un sottoinsieme dell’insieme dato e una funzione computabile è una
formalizzazione del concetto di problema risolvibile; quindi il Teorema di Rice
afferma che non è possibile stabilire se un determinato algoritmo risolve un
problema pur risolvibile che goda di una qualsiasi proprietà non banale (le uniche
proprietà banali in questo caso sono l’appartenenza del problema a una categoria di
problemi inesistente o coincidente con tutti i problemi risolvibili).
Gli esempi citati precedentemente sono infatti solo alcuni degli innumerevoli
esempi di problemi la cui indecidibilità discende banalmente dal Teorema di Rice.
Allo scopo di comprendere meglio come applicare tale teorema nella pratica si
considerino anche i seguente esempi.
Esempio 8.8
Vogliamo analizzare la decidibilità del problema di stabilire se un generico
programma, scritto in un qualsiasi linguaggio di programmazione, calcoli la
funzione trigonometrica sin(x) con un’approssimazione migliore di IO-3.
La risoluzione automatica dei problemi 341
Esempio 8.10
Si considerino il Teorema 8.6 ed il Corollario 8.7. Essi affermano, mediante
dimostrazioni indipendenti, sebbene simili, che le due funzioni g e k,
rispettivamente definite da g(x, y) = iffy(x)^E then 1 else 0 e da k(x) = iffx(x) ±
then 1 else 0, non sono computabili. Intuitivamente, la prima affermazione sembra
più generale della seconda. Non può quindi accadere di saper risolvere il problema
generale se non si è in grado di risolvere quello particolare. Formalmente, ciò
significa che sarebbe possibile derivare facilmente un algoritmo in grado di
calcolare k, partendo da un algoritmo che calcola g (ossia k viene ridotto a g
semplicemente ponendo y = x).
Questo fatto rende la dimostrazione del primo teorema una conseguenza banale del
secondo. Dapprima bisogna dimostrare il Corollario 8.7; successivamente si
deduce il Teorema 8.6 osservando che la computabilità di g implicherebbe la
computabilità di k. In un certo senso, come quindi anticipato nella Sezione 8.5.1, il
Corollario 8.7 diventa il teorema (o lemma) principale.
• ■
Il prossimo risultato mostra l’indecidibilità del problema di stabilire se l’immagine
di fx, per qualche x, sia vuota. Questo risultato viene ottenuto riducendo il problema
originario a quello di stabilire se, fissato un numero z0, dato un generico x, z0 e p.
Quest’ultimo, a sua volta, è un problema indecidibile (si veda l’Esercizio 8.20).
Teorema 8.16
Il problema di stabilire, per un generico x, se 11. = 0 è indecidibile.
■
Dimostrazione
Si scelga un qualunque valore prefissato z0. Per un generico x, si calcoli un y tale
che fx(z) Zo implichi fy(z) = E,fx(z) = z0 implichi fy(z) = z0. Chiaramente,^ risulta
computabile ed y può essere effettivamente calcolato sulla base di una MT che
calcola^. Quindi I = 0 se e solo se z0 £ I f : se si fosse in grado di risolvere il
primo problema si potrebbe risolvere anche il secondo.
■
Si noti che il Teorema 8.16 si potrebbe anche dedurre come semplice conseguenza
del teorema di Rice (Teorema 8.15). Infatti, l’insieme delle funzioni computabili
totalmente indefinite non è né vuoto né coincidente con l’insieme di tutte le
funzioni computabili (in realtà è un “singleton”).
La risoluzione automatica dei problemi
Esempio 8.11
Si consideri il problema di decidere se durante l’esecuzione di un generico
programma P si acceda ad una variabile non inizializzata (trattasi di un ben noto
caso di “errore a run time”). Dimostriamo che tale problema non è decidibile,
riducendo ad esso il problema della terminazione di P come segue. Dato un
generico P ’ che riceve in ingresso generici dati D, costruisco un P come segue:
begin
var x, y: ...
P’;
y := x
end
avendo cura di usare identificatori x e y che non sono usati in P
L’assegnamento y : = x produce un acesso ad x che non è inizializzata perché x
non compare in P’. Quindi l’accesso ad una variabile non inizializzata accade in P
se e solo se P ’ termina. Allora se fosse possibile decidere il problema dell’accesso
ad una variabile non inizializzata, saprei decidere anche il problema della
terminazione del calcolo, che è assurdo.
■
Consideriamo ora un esempio che ci permette di riflettere su come si applica
correttamente la tecnica di riduzione, sottolineando un tipico errore in cui si può
cadere utilizzandola.
Esempio 8.12
Si consideri il problema di stabilire se, dato un generico sottoprogramma P, che ha
un parametro par di tipo intero e ritorna un intero, e dato un valore in input x, vale
P(x) = x.
Si consideri ora il seguente tentativo di dimostrazione di indecidibilità del
problema in questione, che fa uso della tecnica di riduzione: “A partire da un
generico sottoprogramma P che ha un intero come parametro e restituisce un
intero, costruiamo un sottoprogramma P' (utilizzando una sintassi ispirata a
quella del Pascal) che, a fronte di un input x, si comporta nel seguente modo:
procedure P'(x:integer)
begin
if (P(x) <> x)
while(1)
write("loop");
end.
Il sottoprogramma P' quindi termina su input x se e solo se P (x) = x. Poiché il
problema di stabilire se un programma C termina a fronte di un generico input non
è decidibile, allora non è decidibile neanche il problema di stabilire se P (x) =
346 Informatica teorica
Esempio 8.13
Analizziamo la decidibilità del problema di stabilire se, data una generica MT M, il
linguaggio riconosciuto da M è vuoto. Tale problema non è decidibile per il
teorema di Rice; infatti l’insieme delle MT che riconoscono il linguaggio vuoto
non è l’insieme vuoto, né è Tinsieme di tutte le MT.
Rimane ora da analizzarne la semidecidibilità, ricordando che, poiché il
problema non è decidibile, al più uno tra esso e il suo complemento può essere
semidecidibile. In questo caso, il problema non è neppure semidecidibile, in quanto
è semidecidibile il suo complemento, cioè il problema di stabilire se, data una
generica MT M, il linguaggio riconosciuto da M contiene almeno una stringa.
Infatti, enumerando opportunamente le stringhe in ingresso, con la solita tecnica
diagonale è possibile simulare le esecuzioni della MT in modo che, se una stringa
viene accettata, prima o poi questa viene trovata; in caso contrario, la
computazione prosegue all’infinito.
■
Concludendo, siamo ora in possesso di un potente insieme di strumenti per la
dimostrazione dell’irrisolvibilità dei problemi, e precisamente le dimostrazioni
diagonali, la riduzione dei problemi, ed un insieme di enunciati fondamentali come
il teorema di Rice. Siamo anche in grado di distinguere tra i vari problemi
indecidibili quelli semidecidibili da quelli che non godono neanche di questa
parziale proprietà: il caso <presenza-assenza> degli errori a run-time dei
programmi ne è uno tra gli esempi più significativi.
ESERCIZIO
8.32 Si dimostri Tirrisolvibilità dei problemi proposti negli esercizi dal 8.17 al
8.22, usando la tecnica di riduzione dei problemi e/o applicando il teorema di
Rice.
348 Informatica teorica
Giova infine rammentare (si veda la Sezione 8.5.1) che un caso particolare di
scorretta inversione della tecnica di riduzione di problemi è l’uso improprio della
<specializzazione-generalizzazione>: così come in realtà il Corollario 8.7 è in
realtà un lemma del teorema principale, alla stessa maniera, non è detto che
restringendo un problema indecidibile a qualche caso particolare, esso rimanga
tale.
Ad esempio, è ora ben chiaro che è stato possibile determinare
algoritmicamente se un programma termina, per un; dato valore di ingresso.
Abbiamo tuttavia osservato che se si restringe l’attenzione alla classe dei
programmi (ad esempio in linguaggio Pascal) che non impiegano le istruzioni
goto, while e repeat, né le chiamate ricorsive di procedure, allora è possibile
garantire la terminazione di tali programmi per qualunque valore di ingresso. Si
possono costruire programmi con queste caratteristiche per la risoluzione di molti
problemi utili e non banali. Ad esempio, molti problemi numerici sono risolvibili
da algoritmi che impiegano solo i cicli for. Analogamente, è possibile garantire a
priori che le funzioni ricorsive primitive sono funzioni totali.
In generale quindi, un problema irrisolvibile può diventare risolvibile, in modo
più o meno banale, restringendolo a opportuni casi particolari: la dimostrazione di
indecidibilità di un problema non deve perciò essere considerata un ostacolo
insormontabile e comportare necessariamente la rinuncia ad affrontarne la
soluzione con l’ausilio del calcolo automatico. Il problema del riconoscimento del
linguaggio fornisce, a questo proposito, alcuni esempi interessanti, che verranno
passati in rassegna nella prossima sezione.
8.33 Si dia una dimostrazione diagonale diretta del Teorema 2.17, considerando il
linguaggio L = {x,| x, e L(M)}.
8.34 Si mostri che i seguenti problemi sono indecidibili.
1. Data una MT M, L(M) = 0?
2. Data una MT M, L(M) = VT*?
3. Data una grammatica G ed una stringa x e VT*, x e L(G)1
4. Data una grammatica G, L(G) = 0?
5. Data una coppia di grammatiche Gb G2, L(G)) c L(G2)?
Si osservi ora che i linguaggi riconosciuti dagli AF sono ricorsivi, al contrario dei
più generali linguaggi riconosciuti dalle MT. Infatti, per ogni stringa x e per ogni
AF A, è banale decidere se ò*(q, x) e F. Basta infatti far funzionare A fino a che 8
non risulta più definita (caso (a)) oppure la lettura di x viene completata (caso (b)).
La procedura di decisione si ferma con risposta affermativa nel caso (b), se A è in
uno stato finale. Altrimenti la risposta è negativa. Si ottiene quindi il seguente
enunciato.
Enunciato 8.18
I linguaggi accettati dagli AF sono ricorsivi (ossia, per gli AF, il problema
dell’appartenenza è decidibile).
■
ESERCIZIO
8.35 Si mostri che i linguaggi riconosciuti dagli AP sono ricorsivi. Suggerimento'.
si sfrutti il Teorema 8.11.
ESERCIZIO
8.36 Si dia il procedimento di costruzione di AP che riconoscono L e LR, secondo
la definizione del Lemma 8.21.
Tabella 8.1 Un riassunto dei problemi classici di decidibilità nella teoria dei
linguaggi formali.
Problema
Classe di linguaggio —— L— 0 L\ — L2
Accettati da MT I I I I
Regolari D D D D
Liberi da contesto D* D* I* I
Accettati da AP D D* I
D: decidibile
I: indecidibile
Esempio 8.14
Si considerino i due insiemi
Si = {x| Dx è infinito}
52 = {x| Dx = M (ossia fx è totale)}
Come è noto dal Teorema 8.10, 52 non è ricorsivamente enumerabile. Si può
facilmente intuire che, in qualche modo, Si e S-, sono riducibili l’uno all’altro.
Infatti, si supponga di avere a disposizione un algoritmo per verificare se, per ogni
x,fx è totale (ossia, si supponga che S2 sia ricorsivo). Allora, per verificare se Dx è
infinito, si proceda nel modo seguente: si definisca una funzione h, totale e
computabile, tale che, per y = h(x'), Dx = Ix e tale che zi A z2 implichi /,(zi)A^(z2).
Ciò si può ottenere mediante una costruzione analoga a quella impiegata per h
nella dimostrazione del Teorema 8.13. In questo modo Dx risulta finito se e solo se
fy è totale.
D’altra parte, si supponga che esista un algoritmo per verificare se Dx è finito,
per ogni x. Allora, per verificare sefx è totale, si definisca una funzione h, totale e
computabile, tale che, per;y = h(x):
fy(z) = iffx(wy£l. per ogni w < z then 1 else ±
Quindi fx risulta totale se e solo se Dy è infinito. Poiché è effettivamente possibile
ottenere una simile funzione h, totale e computabile, ciò significa che si è riusciti
ad ottenere una procedura per decidere se /) è totale.
La costruzione precedente consente una dimostrazione della indecidibilità di
51, dopo aver stabilito l’indecidibilità di S2, ma anche il viceversa. La
dimostrazione è una reductio ad absurdum.
C’è un altro interessante punto di vista per interpretare questo risultato. Si
immagini di migliorare una MT con un dispositivo non algoritmico che sia in grado
di stabilire l’appartenenza ad 5b Si chiami tale dispositivo “oracolo’’'. Si può allora
impiegare una MT di questo tipo per risolvere anche il problema della
appartenenza di S2. Infatti, una tale MT potrebbe rispondere alla domanda
“x e S2?” nel modo seguente: dapprima si calcolerebbe y secondo la precedente
procedura; poi chiederebbe all’oracolo se y e 5i e uscirebbe la risposta per
risolvere il problema originario. Viceversa, un oracolo in grado di decidere
l’appartenenza di S2 si potrebbe usare anche per decidere l’appartenenza per 5b Si
può dunque affermare che lo stesso oracolo può essere impiegato per decidere sia
5i che 52.
354
Informatica teorica
Esempio 8.15
Si considerino i due insiemi:
5] = {x| Dx è finito}
Si può ridurre K a S,. Infatti, si supponga che un oracolo sia in grado di decidere il
problema di appartenenza per S). Il problema di appartenenza per K può essere
risolto mediante la seguente procedura. Si definisca, come al solito, una funzione
totale e computabile h tale che, per_y = /z(x):
fy(w) = if Mx, con ingresso x, non si ferma in meno di w mosse then 1 else ±
Quindi fx(x) risulta definita se e solo se Dy è finito.
Si vedrà in seguito che, in questo caso, la riduzione del problema non si può
applicare nell’altra direzione. Ciò conduce ad affermare, intuitivamente, che il
problema dell’appartenenza per K è “più risolvibile” del problema
dell’appartenenza per 5,. In breve: K è “più risolvibile” di S1. Simmetricamente, si
può affermare che è “meno risolvibile” di K. Infatti, si noti che K è
ricorsivamente enumerabile, sebbene non ricorsivo, mentre non lo è (si dimostri
quest’ultima affermazione per esercizio). Per usare altre parole, si potrebbe usare
un’oracolo in grado di decidere l’appartenenza per , anche per decidere
l’appartenenza per K, ma non viceversa. .
■
L’esempio precedente suggerisce l’opportunità di definire una misura del “grado di
(ir)risolvibilità”. Questa nozione viene qui presentata formalmente solo in uno dei
modi possibili, senza alcuna pretesa di completezza. Siano A e B due sottoinsiemi
di N e si definisca = N - ^4, B = N - B.
Definizione 8.6
A è riducibile a B (si indica A <r B) se e solo se esiste una finizione t, totale e
computabile, tale che, per ogni x, x e A se e solo se t(x) e B.
■
Ecco alcune proprietà della relazione <r.
Teorema 8.22
1. <r è riflessiva e transitiva.
2. A <rB implica A <r B .
3. Se A <rB e B è ricorsivo, allora A è ricorsivo.
La risoluzione automatica dei problemi 355
Dimostrazione
1. e 2. sono esercizi banali.
3. Sia t una funzione totale e computabile tale che x e A se e solo se t(x) e B,
(ossia A = f (B)). Siano cA e cB le funzioni caratteristiche di A e di B. Allora cA
= cB°t. Quindi, se B è ricorsivo, lo è anche cA.
4. Di nuovo, A <rB significa che A = fl(B), con t computabile e totale. Ora, se B
è ricorsivamente enumerabile, allora è il dominio di definizione di qualche
funzione computabile fx (ossia B = Dx). Tuttavia A = P(B') è il dominio di
definizione di /( ° t che è computabile.
■
ESERCIZIO
8. 37 Si riesaminino gli Esempi 8.3 e 8.4 alla luce del Teorema 8.22. Nel caso
dell’Esempio 8.3, si dimostri che 5) <r S2 e che S2 <r S\. Nel caso
dell’Esempio 8.4 si dimostri che K <r s{, ma —(Si <rK). In entrambi i casi,
si usi h per definire <r.
Definizione 8.7
A=rB significa che A <rB eB <rA.
■
Ovviamente =r è una relazione di equivalenza. Si possono così definire le classi di
equivalenza di =r come gradi di irrisolvibilità. Si noti che ogni grado che contiene
un insieme ricorsivo, contiene tutti e soli gli insiemi ricorsivi. Si può quindi parlare
del “grado ricorsivo”. Inoltre, ogni grado che contiene un insieme ricorsivamente
enumerabile, contiene solo insiemi ricorsivamente enumerabili (si può dimostrare
che vi sono diversi gradi ricorsivamente enumerabili).
Molte domande sorgono naturalmente quando si introduce l’ordinamento
parziale in una struttura matematica. Ad esempio,
- L’ordinamento è un ordinamento totale?
- L’ordinamento è un reticolo?
- Se A <rB e A 7= B esiste una o più C “fra A e'B”, tale che A <r C <rB7 (come
al solito <r significa <r A
Queste ed altre domande non hanno un interesse puramente matematico. Ad
esempio, se <r fosse un ordinamento totale, ciò implicherebbe che, dati due
problemi qualsiasi Pi e P2, può accadere che Pi sia più difficile di P2 o viceversa,
oppure che entrambi presentino un’uguale difficoltà. Una trattazione algebrica
356 Informatica teorica
Quindi un eventuale insieme C, r-completo, risulta massimo rispetto a <„ fra gli
insiemi ricorsivamente enumerabili. Intuitivamente, un insieme di questo tipo si
potrebbe chiamare “il problema semidecidibile più difficile”, poiché, una volta
ottenuta la soluzione di C, ad esempio mediante una macchina con oracolo, la
soluzione di ogni altro problema semidecidibile si potrebbe ottenere per riduzione
meccanica alla soluzione di C. Si noti anche che, se Q e C2 sono due insiemi r-
completi, allora Q =r C2. Se dunque esiste un grado massimo di irrisolvibilità, esso
è unico e si indica con [C]= .
Nel Capitolo 9 si comprenderà come la nozione di completezza abbia una
portata molto ampia e si possa applicare ad altri importanti aspetti della teoria della
computazione.
Il prossimo teorema afferma l’esistenza di insiemi r-completi.
Teorema 8.24
L’insieme H= {(x, x e Dy} è r-completo7.
■
Dimostrazione
H è l’insieme {(x,_y)| tale che My, con ingresso x si arresta in meno di z passi}.
Si può dimostrare che H è ricorsivamente enumerabile, mediante un ragionamento
simile a quello impiegato nella dimostrazione del Teorema 8.13.
Sia A un qualunque insieme ricorsivamente enumerabile. Allora A = D y per
qualche jo- Quindi x e A se e solo se (x,y0) e H e A <rHpex mezzo della funzione
f definita da/fx) = (x, yG\
■
Poiché si può anche dimostrare che H <rK, si ha K =r H e anche K è r-completo.
ESERCIZI
ALTRI ESERCIZI
8.41 Si dimostri che non si può decidere se, per un dato programma Pascal P e per
una data istruzione S, contenuta in P, esiste qualche dato di ingresso tale che
il flusso dell’esecuzione di P raggiunga, prima o poi, l’istruzione S.
8.42 Talvolta, in letteratura, la classe delle funzioni ricorsive totali viene definita
come la classe delle funzioni definite mediante funzioni base, composizione
e ricorsione e l’operatore totale p, ossia l’operatore p definito come nella
Sezione 2.4.2 (p(g(xi.. ,xm y) = 0)), con il vincolo che esista sempre una y
che soddisfi p.
Si può dimostrare, in modo non banale, che la classe delle funzioni ricorsive
totali coincide con la classe delle funzioni ricorsive parziali che sono totali.
D’altra parte, la classe delle funzioni ricorsive parziali coincide con la classe
delle funzioni calcolabili da una MT (si veda l’appendice 4.A). Questo
risultato contraddice il Teorema 8.10? Perché? Perché no? Si ricordi che le
La risoluzione automatica dei problemi
à
La risoluzione automatica dei problemi 301
Note bibliografiche
Nel capitolo precedente abbiamo mostrato che esistono problemi che, pur essendo
ben definiti e di interesse sia concettuale che pratico, non sono, purtroppo,
risolvibili, cioè problemi per i quali non esiste una MT in grado di risolverli, o
equivalentemente, problemi per i quali non è possibile scrivere un programma
eseguibile da un calcolatore che li risolva. La risolvibilità di un problema non è
però l’unico elemento da tenere in considerazione quando si affronta un problema
in cerca della sua soluzione. Infatti, poiché i calcoli, come molti altri servizi,
costano sotto diversi punti di vista, può capitare che un problema che sia
teoricamente risolvibile, non lo sia poi in pratica.
Si supponga di avere accesso al più potente calcolatore del mondo; anche in
questo caso rimarrebbe ugualmente un prezzo da pagare nella risoluzione di un
problema dato: il tempo impiegato dal programma per produrre la soluzione
richiesta. Appare chiaro che, se non è possibile ottenere una soluzione di un
problema entro un “ragionevole” intervallo di tempo, il problema diviene
praticamente intrattabile, anche se teoricamente risolvibile. Consideriamo, ad
esempio, il problema di stabilire il risultato di una “perfetta” partita a scacchi, ossia
di una partita in cui entrambi i giocatori giocano al meglio: tale problema è
certamente decidibile, infatti vi è solo un numero finito di stati sulla scacchiera.
Quindi, partendo dalla configurazione iniziale della scacchiera, un algoritmo ideale
potrebbe enumerare tutte le configurazioni raggiungibili e stabilire la sequenza che
verrebbe scelta da due giocatori “perfetti”. Si può tuttavia dimostrare che il
calcolatore più veloce che esista non completerebbe l’esecuzione di questo
algoritmo nel tempo di vita stimato dell’universo. Di conseguenza, il problema pur
risolvibile della “perfetta gara di scacchi” è intrattabile, ossia, pur essendo
disponibile un algoritmo per la sua soluzione, l’esecuzione di tale algoritmo
richiederebbe un tempo inaccettabile.
L’intrattabilità costituisce una limitazione notevole per le applicazioni
pratiche. Sfortunatamente, infatti, esistono molti problemi interessanti che, pur
essendo risolvibili, si rivelano praticamente intrattabili.
Questo capitolo è dedicato al concetto di intrattabilità. Prima di addentrarsi in
una rigorosa analisi dell’argomento, è necessario porre le fondamenta per questo
nuovo concetto ed illustrare ulteriormente le sue motivazioni di base.
Il concetto di “intrattabilità” è ovviamente correlato con quello di
“complessità”: un problema è intrattabile quando la sua complessità è troppo
elevata. Informalmente, la complessità può essere vista come la misura del prezzo
che bisogna pagare per risolvere il problema. Quindi il nostro obiettivo è definire la
complessità in modo formale e mostrare, fornendo adeguati strumenti, in che modo
si possa effettuare l’analisi di complessità.
364 Informatica teorica
Esempio 9.1
Si consideri la seguente funzione, che risolve il problema dell’appartenenza di un
intero ad un insieme. I parametri della funzione sono x (un insieme rappresentato
da un array) e y (l’elemento di cui bisogna decidere l’appartenenza all’insieme).
La funzione restituisce 1 se y appartiene a x, 0 altrimenti.
int ricerca (int x[N], int y){
\\N è una costante
for(int i = 0; i < N; i++)
if(x[i] == y)
return 1;
366 Informatica teorica
else
i = i + 1;
return 0;
}
Cerchiamo di analizzare intuitivamente sia la memoria necessaria (complessità
spaziale) che il tempo richiesto (complessità temporale) dalla funzione ricerca
per fornire la soluzione.
Dapprima si noti che il numero di celle di memoria e il numero di secondi
richiesti per eseguire la procedura dipendono daH’insieme x. Nel caso della
complessità spaziale, si può dire che il numero totale di celle richieste 'i/' è dato
dalla cardinalità dell’insieme x (ossia N) e da un numero costante k di celle, che
non dipende dalla cardinalità di x, cioè .9? = |x| + k. Intuitivamente, k corrisponde
al numero di celle usate per memorizzare tutte le altre variabili (i nel nostro
esempio) e il codice oggetto.
L’analisi della complessità temporale è leggermente più elaborata. Il numero
totale di secondi .^richiesti per eseguire la funzione ricerca si può esprimere
come: dT = + 57, dove .57 è il tempo speso fuori dal ciclo f or, mentre ,57 è il
tempo impiegato al suo interno. .57 è un valore costante (ad esempio /?), che non
dipende dall’insieme x, mentre .55 dipende da esso; si può quindi scrivere
= h + ,57(x)
Come si può notare, il tempo richiesto dalla funzione ricerca è molto
variabile e dipende dalla presenza o meno dell’elemento cercato nell’insieme x e,
nel caso di appartenenza, dalla sua posizione. Nel caso migliore, la procedura trova
un elemento uguale a y nella prima posizione del vettore: in questo modo il ciclo
viene eseguito una sola volta, in quanto la funzione termina restituendo il valore 1
(ramo “then” dell’if). Nel caso peggiore, cioè quando y non appartiene a x, la
funzione scandisce tutto il vettore prima di giungere ad una conclusione
sull’appartenenza. In questo modo il ciclo viene ripetuto |x| volte.
Che cosa si può dire del caso medio, cioè quanto tempo è necessario per
fornire la soluzione in media? Per rispondere a questa domanda, è necessario
conoscere statisticamente la distribuzione dei dati in ingresso. Sia p la probabilità
che la funzione ricerca venga chiamata con un valore y appartenente all’insieme
x. Si supponga inoltre che tutti i valori di questo tipo abbiano uguale probabilità di
comparire nelle chiamate a funzione. Allora (1 ~p) è la probabilità che y non sia
= 5-1 x | + — • p • r
2
dove s = r------p • r
2
■
Analizziamo ora un’altra soluzione del problema dell’appartenenza. Questa volta,.
però, supponiamo che gli elementi dell’insieme x siano memorizzati in un array
ordinato.
Esempio 9.2
Si supponga di dover nuovamente risolvere il problema dell’appartenenza per un
insieme, rappresentato da un array ordinato in ordine ascendente. Per risolvere
questo problema, si potrebbe impiegare la procedura ricerca, descritta
nell’Esempio 9.1, anche se, in questo modo, non sfrutteremmo il fatto che
l’insieme risulta già ordinato. Un’altra soluzione applicabile in questa situazione è
il ben noto algoritmo di ricerca binaria, ricerca_binaria.
int ricerca_binaria (int x[N]; int y) {
\\N è una costante
int i, j, k;
i = 0; j = N - 1;
while (ì j){
Wl'insieme dei candidati va x[i] a x[j] ; si
Wprende l'elemento centrale}
k = (i + j)/2;
if x[k] == y
return 1
else Wdimezza l'insieme dei candidati
if y < x[k]
' j = k - 1
else
i = k + 1
}
return 0 ;
}
368 Informatica teorica
ESERCIZIO
9.1 Si analizzi la complessità temporale di ricerca_binaria per il caso
medio, sotto le medesime ipotesi di probabilità viste per la funzione
ricerca nell’Esempio 9.1.
Suggerimento: si noti che, se y e x, la probabilità di trovare y nella prima
iterazione del ciclo è l/[x[. La probabilità di trovare y nella seconda
iterazione è (1 - l/|x))-l/[|x|/2] e così via. Si noti anche che, per x
sufficientemente grande, anche la complessità del caso pessimo di
369
La complessità del calcolo
per codificarlo in base k con k > 1. Bisogna quindi prestare attenzione alla reale
dimensione dell’ingresso nella soluzione considerata.
A differenza di quanto visto nel Capitolo 8 per la risolvibilità, la complessità
non è collegata solo al problema che si vuole affrontare, ma dipende dall’algoritmo
scelto per risolverlo. Come si è visto nell’Esempio 9.2, lo stesso problema (ricerca
di un elemento in un insieme ordinato) può essere risolto, con differenti
complessità, da due algoritmi diversi (ricerca e ricerca_binaria).
Finché si ragiona in termini di risolvibilità, un problema formalizzato mediante
una determinata codifica (ad esempio come un problema di traduzione) può essere
riformulato in modo equivalente - ossia senza cambiarne la proprietà di
risolvibilità o meno - cambiando tipo di formalizzazione tipo (ad esempio come
riconoscimento di un linguaggio o calcolo di una funzione il cui dominio è
l’insieme dei numeri interi). Per esempio, la traduzione y = r(x) può essere
codificata come il riconoscimento di x$y ($ £ x, $ £ y). In generale, però, questa
equivalenza non vale per la complessità temporale. Infatti, si supponga che una
computazione deterministica effettui la traduzione y = r(x) nel tempo t(x). Si può
allora decidere se x$y e LT = {zi$z2| z2 = fi^i)} nello stesso tempo t(x). Ciò non
vale, tuttavia, sull’altro versante. Se il problema x$y e L può essere deciso nel
tempo t(x$y) e se si usa l’algoritmo che riconosce L per calcolare y = r(x) bisogna
allora enumerare tutti i possibili {y,}, ad esempio in ordine crescente di lunghezza.
Per ciascun si richiede un tempo z‘(x$yI) per decidere se x$y,eZT. Quindi, il
tempo totale necessario al calcolo di r(x), nel caso pessimo, è dato da:
I y, l±frO)|
Questo ragionamento, ovviamente, non esclude la possibilità che un algoritmo più
efficiente riesca a calcolare r(x) in un tempo inferiore. In questo capitolo ci si
riferirà principalmente al problema della complessità delle decisioni, anche se, in
molti casi, verranno presi in considerazione altri tipi di problemi.
Infine, le stime di complessità dipendono dalla scelta del modello di calcolo,
come verrà mostrato nel resto di questo capitolo; verranno in particolare studiate le
macchine di Turing e macchine ad alto e basso livello che corrispondono, in una
certa misura, ai linguaggi di programmazione “tipo - Java” e “tipo - assembler”.
Questa osservazione esclude di poter ottenere per la complessità un risultato
equivalente alla Tesi di Church per la risolvibilità, in quanto la complessità
dipende dal modello scelto per la soluzione. Vedremo però che, anche se le
soluzioni proposte per modelli diversi portano spesso a complessità diverse, queste
possono essere correlate tra di loro in modo sistematico.
Ciò deriva dal fatto che il comportamento asintotico (ossia il comportamento per x
tendente all’infinito) di è dell’ordine di log2(|x|), mentre V 'p è dell’ordine di
|x|.
La notazione dell’ordine di grandezza di una funzione, nota sotto il nome di
notazione theta-grande, sottolinea i fattori dominanti che influenzano la crescita
della complessità, in funzione della dimensione dell’ingresso e per questo motivo
risulta particolarmente utile per lo studio della complessità di una soluzione.
Prima di analizzare formalmente la notazione theta-grande, introduciamo altre
due notazioni che possono risultare utili nella sua definizione: la notazione o-
grande e la notazione omega-grande.
Definzizone 9.1
Siano gef due funzioni aventi come dominio i numeri naturali e come codominio i
numeri reali positivi, R+. La funzione g è in O(/) se e solo se esistono due numeri
positivi c e «o tali che per ogni n > n0, g(n) < cflji). Alternativamente possiamo dire
che O(/) è il seguente insieme di funzioni O(/) = {g: N -à K+ | 3 c, h0 >0 e
V n>n0, gfn)<cfin)}.
Definizione 9.2
Siano gef due funzioni aventi come dominio i numeri naturali e come codominio i
numeri reali positivi, R+. La funzione g è in Q(/) se e solo se esistono due numeri
positivi ce H0 tali che per ogni n > n0, cfln) < g(n). Alternativamente possiamo dire
che Q(/) è il seguente insieme di funzioni Q(/) = {g: N —> IR+ | 3 c, n0 > 0 e
Vn>«0, c/(n)<g(n)}.
Esempio 9.3
Consideriamo la funzioni g(n) = n2 + 12w + 35. Tale funzione è in O(ù2), ma anche
in O(n2) ed è in Q(m2), ma anche in (fin) e in Q(log n). Osserviamo che, fra tutti i
limiti superiori ed inferiori che si possono trovare per fin), sono di particolare
interesse il minimo dei primi e il massimo dei secondi, che in questo caso
coincidono con la funzione fin) = n2.
■
Nonostante la somiglianza dei termini, il limite superiore della complessità di un
algoritmo e il caso pessimo non devono essere confusi. Infatti, mentre il primo
rappresenta una funzione che limita superiormente la complessità ottenuta per la
dimensione dell’ingresso che tende all’infinito, il secondo si riferisce
all’assegnamento dei valori in ingresso, che, tra i possibili assegnamenti per la
stessa dimensione dei dati, porta il programma a svolgere più operazioni rispetto a
tutti gli altri possibili assegnamenti.
Ora che abbiamo definito i limiti inferiore e superiore per una funzione data,
possiamo introdurre anche la notazione theta-grande in due modi distinti, ma
equivalenti, mediante le seguenti definizioni.
Definizione 9.3
Sianogef due funzioni aventi come dominio inumeri naturali e come codominio i
numeri reali positivi. La funzione g è in 0(/) se e solo se esistono tre numeri
positivi cb c2 e «o tali che per ogni n > n0, c1 fin) < g(n) e g(n) < c2 fin).
Alternativamente possiamo dire che ®(f) è il seguente insieme di funzioni Q(f) =
{g: N -> IR+ | 3 ci, c2, «o >0 e V n> n0, c^fin) < g(n) e g(n) < c2fin)}.
Definizione 9.4
Siano gef due funzioni aventi come dominio i numeri naturali e come codominio i
numeri reali. La funzione g è ®(f) se, e solo se, si può trovare una costante reale
c > 0 tale che
r g(«)
lim ----------= c
;^.co f (ri)
ESERCIZIO
9.2 Si dimostri formalmente che le Definizioni 9.3 e 9.4, che introducono la
relazione theta-grande, sono tra loro equivalenti.
Enunciato 9.1
Transitività:
- se fin) = &(g(ri)) e g(ri) = ©(h(n)) allora fin) = 0(7z(m));
- se fin) = ©(fin)) e fin) = ©(h(n)) allora/(«) = O(7?(w));
- se fin) = £ì (g(«)) e fin) = ©(h(n)) allora fin) = ©(h(n)).
Riflessività
- fin) = ©(fin));
- fin) = ©(fin));
- fin) = © (fin)).
Simmetria: fin) = ©(g(n)) se e solo se g(n) = ©(fin)).
Simmetria trasposta: fin) = ©(fin)) se e solo se fin) = ©(fin)).
■
In particolare, perciò, vale la seguente proprietà della notazione theta-grande.
Enunciato 9.2
La relazione 0 è una relazione di equivalenza.
■
Per ogni classe di equivalenza definita dalla relazione 0 sull’insieme delle funzioni
definite sui numeri naturali, è opportuno scegliere, come rappresentate dell’ordine,
una funzione caratterizzata da una formula semplice. Ad esempio, ci si riferisce a
©(nk) piuttosto che a ©(ai/ik + a*-xnk~1 + ... + cz0)-
Le notazioni introdotte per l’analisi asintotica della complessità sono
molteplici. Per una discussione approfondita delle molte notazioni alternative si
faccia riferimento alle note bibliografiche.
374 Informatica teorica
ESERCIZI
9.3 Siano date le funzioni/, con z = 1, 5, definite nel modo seguente: ffrì) =
m2*,/2(m) = M2-log2M,/3(«) = «MogioW, /4(m) = n2Jn ,f5(ri) = \sin(n)-n6\. Si
stabilisca sef è ®(f) oppure ®(^) < ®(f), per ogni ij = 1,5.
9.4 Si dimostri che le relazioni < e > sono ordinamenti parziali sull’insieme
delle funzioni definite sui numeri naturali. Come conseguenza si ottiene un
ordinamento sulle classi di equivalenza [/]0.
La notazione theta-grande tiene dunque conto dei fattori dominanti che influenzano
la crescita della funzione di complessità. Si può affermare, ad esempio, che un
algoritmo con complessità temporale 0(m2) sia peggiore di un algoritmo con
complessità temporale 0(wlog m): il comportamento asintotico del secondo è
infatti decisamente migliore di quello del primo. Si noti che, poiché la relazione
theta-grande non induce un ordinamento totale sulle sue classi di equivalenza, può
accadere che due algoritmi abbiano complessità non confrontabili.
Si osservi che però la notazione theta-grande non distingue fra due funzioni
appartenenti alla medesima classe di complessità. Tuttavia, che dire di 0(m2) e di
0(1 06m2)? Come si può metterle nella medesima classe di equivalenza quando è
evidente che la seconda è sempre IO6 volte peggio della prima? Il lettore troverà
una risposta rigorosa a questa domanda nel seguito di questo capitolo, quando
verrà presentato il teorema dell’accelerazione lineare (Teorema 9.12). Tale teorema
assicura che è sempre possibile accelerare di un fattore costante qualunque
computazione. Ad esempio, partendo da una macchina che risolve un problema in
un tempo 106m2, è possibile ottenere, almeno in linea di principio, una macchina
equivalente che esegua il medesimo calcolo in un tempo m2. La nuova macchina
richiederà ovviamente più “risorse” della precedente. Il fattore dominante della
complessità corrisponde quindi al ritmo di crescita, mentre i fattori costanti si
possono ignorare. Come ulteriore conseguenza, si può anche parlare di fattori di
complessità logaritmici senza preoccuparsi della base del logaritmo in questione.
E’ noto infatti che, per ogni bi, ò2 > 1 e per ogni funzione f
Dog 6i°/]0 =[log
Definizione 9.5
Sia Muna MT deterministica a k nastri e sia x e /*. Sia co '-m Ci *~m Cz l- ••• *~m cr
una computazione, ossia una sequenza di transizioni di M tale che c0 = (qo, 1x, TZ0,
..., TZ0) e e; = {qi, x^y,, ayT^i, ..., a^Tp^). cr è una configurazione di arresto di M,
se ne esiste una. Allora, la funzione complessità temporale TM, di M, è definita
come:
7m(x) = if la computazione è finita then r else oo
La definizione vale anche nel caso di una MT a k nastri con uscita, con solo
qualche differenza formale di scarsa importanza.
■
La complessità temporale viene quindi definita come una funzione che fornisce
l’esatto numero di passi richiesti da una MT per raggiungere una configurazione di
arresto, se esiste, a partire dalla configurazione iniziale, per una qualsiasi stringa di
ingresso x prefissata.
Analogamente, si può definire la complessità spaziale come il massimo
numero di celle del nastro di memoria utilizzate.
Definizione 9.6
Siano M, x, c0, ..., cr definiti come nella Definizione 9.5. La funzione complessità
spaziale SM di Avviene allora definita come:
376 Informatica teorica
k
SM <x)= ay \+l\i = l,...,r}
J=1
■
Notiamo che la definizione di Sm(x) prende in considerazione solo i nastri di
memoria, ignorando sia il nastro d’ingresso 17 che il nastro d’uscita Tq. Inoltre, è
importante osservare che Sm(x) può risultare finito anche se la computazione di M
non termina mai.
Al fine di capire meglio come si analizza la complessità delle MT,
consideriamo il seguente esempio.
Esempio 9.4
Si consideri una MT M che riconosce il linguaggio L = {wcwfl| M
riconosce tale linguaggio controllando l’uguaglianza dell’elemento z-esimo con
l’elemento (n - i +l)-esimo della stringa di ingresso, dove n è la lunghezza della
stringa e i = 1, 2, ... . Se tutte le verifiche di uguaglianza danno un risultato
positivo, la stringa viene accettata quando i = n - i + 1 e l’z-esimo elemento è una
c.
Escluso il nastro d’ingresso (il nastro Tz), a sola lettura, vi sono altri quattro
nastri, organizzati nel modo seguente:
Nastro T;: contiene una copia della stringa di ingresso.
Nastro T2: contiene il valore di z, codificato in forma unaria.
Nastro T5: contiene il numero di celle del nastro di ingresso non ancora
esaminate.
Nastro T4: contiene una copia dell’z-esimo elemento della stringa di ingresso.
La Figura 9.1 fornisce una descrizione formale di M, usando una
rappresentazione grafica condensata (già introdotta nel Capitolo 4), che consente di
rappresentare gli archi multipli mediante un unico arco dotato di un’unica etichetta.
La seguente descrizione dettagliata del comportamento di M si riferisce alla
descrizione formale mostrata in Figura 9.1.
«,<»,X,Y,ZO>I
e,<Zo,x,Y,zo>/
< »,X, Y,Z0>, < S,L,S,S,S>
<Z0.A,Y,Zq> ,<S,fì,L,L,S>
<Zo,Zo,Zo,Zo>, <S,R,R,XS>
(a)
La complessità del calcolo 377
D,<c,X,A,Zq>I
<c.X,V,Z0>,<S,S,S,L,S>
b,<z,Zo,Y,Zol>
<z,Z0, Y,Za>,< S.S.RS.S >
93
(b)
»,<H,X,Y.y>l b,<y.b,Yy>l
<a,X, Y.y > ,<S,L,R,S,S> <y>8, Y,Z0> ,<S,S,S,S,S>
le)
&,<£,&,A,Zo>/ »,<Z0,X,Y,Z>/
b,<c,X,Zo,Zo>l
<c,X,Z0,Z0> ,<S,S,S,S,S>
te)
Figura 9.1 Una MT che accetta L = {wcwR | w e {a,b}*}. (a) Passi 1, 2.
(b) Passi dal 3.1 fino al 3.4. (c) Passi 3.5 e 3.6. (d) Passi dal 3.7 al
3.9. (e) Passo 4. z corrisponde ad a, b o c. y corrisponde ad a o b.
X, Y, Z corrispondono ad A, Zo o V> .
378 Informatica teorica
Passo 1: La configurazione iniziale è c0 = (qn, Tx, TZ0, TZ0, TZ0, TZ0), dove x è la
stringa in ingresso da riconoscere.
Passo 2\ Poniamo il contenuto del nastro T] pari a x, del nastro T2 pari ale del
nastro T3 pari a n, scandendo la stringa di ingresso da sinistra a destra.
Successivamente si ritorni alla prima posizione della stringa che è stata
copiata sul nastro Tb allo scopo di far partire l’effettivo processo di
riconoscimento. Il simbolo A viene impiegato come codifica unaria per i
nastri T2 e T3. Dopo questo passo, /V/si trova nello stato q2.
Passo 3: Si ripetano le seguenti azioni, dalla 3.1 alla 3.9
3.1 Si effettuino i mosse (z è il contenuto di T2) su Tb da sinistra a
destra (M entra nello stato qì).
3.2 Se il valore correntemente letto su Ti è una c, si esca dal ciclo (M
entra nello stato qA-
3.3 Si decrementi il valore codificato in T3 (se T3 è vuoto, M si ferma
senza accettare);
3.4 Si memorizzi il corrente valore di ingresso in T4 (M entra nello stato
?5)-
3.5 Si sposti la testina di T) da sinistra a destra, fino al primo simbolo
vuoto che segue la stringa di ingresso.
3.6 Si effettuino i mosse da destra a sinistra sul nastro Tg dopo aver
controllato che il simbolo corrente sia uguale al simbolo contenuto
in T4, la macchina entra nello stato q2.
3.7 Si decrementi il valore codificato in T3 (se T3 è vuoto, M si ferma
senza accettare).
3.8 Si incrementi il valore codificato in T2.
3.9 Si muova la testina di Ti da destra a sinistra, fino al simbolo Zo che
precede la stringa di ingresso.
Passo 4: La stringa è accettata se il simbolo corrente è una c e il contenuto di T3 è
zero.
Qual é la complessità temporale del riconoscimento di L = {wcwÀ| wg{a,b}*}2
Cerchiamo dapprima di ottenere una risposta sulla base di considerazioni
informali, per poi analizzarla formalmente. M effettua una doppia scansione
iniziale della stringa di ingresso x, di lunghezza n, per predisporre i nastri Ti e T2.
Successivamente effettua una doppia scansione per ciascuna coppia di simboli
nella posizione (1, rì), (2, n - 1), ... fino a che viene raggiunto il simbolo mediano
c. Il numero di mosse, quindi, è circa 2-n + 2-n-(n~ l)/2, dove n è la lunghezza di
x.
Cerchiamo ora di ottenere la medesima conclusione in modo più formale,
esaminando il grafo che rappresenta M. Il numero di mosse effettuate sulla catena
di stati q2, q3, q5, q6, q2, qx, q2, è pari a 2-n + 5 (non importa quale sia il valore della
z). Inoltre, questa catena viene eseguita m = (n - l)/2 volte. Infatti, alla (m + 1)-
379
La complessità del calcolo
esima iterazione, la catena, da q2, diventa q2, q-ì, q^, qp, il che corrisponde a m + 3
mosse. In conclusione, se x = wcwÀ per qualche we {a,b}* en = |x|, si ottiene:
T^x) = 2-n + 3 + (2-n + 5)-(w- l)/2 + (n- l)/2 + 3 = (2-n + 6)-(w + l)/2
Rimane da considerare ciò che accade quando la stringa in ingresso x non
appartiene a L.
Caso 1. x = 8. Qui si ha Ty(x) = 0.
Caso 2. |x| = 1 e x c. Qui si ha Tm(x) = 7.
Caso 3. x = Wiw'w2w"wiÀ per qualche wbw2 e {a,b}*, w'e {a, b}, w"e {a, b, c},
w' w”. Qui si ha
Definizione 9.7
ESERCIZI
9.5 Si consideri un’altra MT M2 che riconosce L = | we {a,b}*}. M2 copia
il contenuto del nastro T/ sul nastro Tb fino a che non incontra ima c.
successivamente legge all’indietro T! mano a mano che legge T/ e controlla i
simboli letti per verificarne l’uguaglianza. Si noti che, in questo caso, il
nastro Ti simula il comportamento di una pila e che l’intero processo di
riconoscimento assomiglia al processo di riconoscimento effettuato mediante
un automa a pila (si veda l’Esercizio 4.2le l’Esempio 9.6). Si progetti M2 e
si descrivano TM> e SM^, in ogni dettaglio, sia nel caso in cui il dominio è I*
Esempio 9.5
Definiamo una MT M che risolve il problema di appartenenza (si veda l’Esempio
9.1) per un insieme di caratteri di alfabeto I. La stringa in ingresso è x = ay, dove y
è una rappresentazione in forma di stringa dell’insieme ed a è un singolo carattere.
M accetta x ogni volta che a e {c | c è un carattere di y}.
Oltre al nastro di ingresso T/, M ha un altro nastro, Tb in cui memorizza il
primo carattere di x. La soluzione è mostrata in Figura 9.2 nella consueta forma di
grafo condensato.
Qual è la complessità temporale, in questo caso? Non è difficile ricavare la
seguente formula:
T^x) = ifx = <awi<2w2, Mq6(/- {a})*, w2<=I* then |tnvia| else |x|
Quindi 7)w(n) = n.
382 Informatica teorica
z ?= t
Figura 9.2 Una MT che risolve il problema di appartenenza, z e t indicano
simboli qualunque contenuti in I.
ESERCIZI
9.8 La MT dell’Esempio 9.5 risolve un problema leggermente diverso dalle
funzioni degli Esempi 9.1 e 9.2. Infatti, in questo caso si cerca un singolo
carattere, mentre in precedenza si cercava un numero intero. Si modifichi la
MT M dell’Esempio 9.5 affinché cerchi numeri interi codificati in binario.
Più precisamente, la nuova macchina Mi deve riconoscere il linguaggio
L = {x|x = z$yi$...$ym, e 3z, l<i<m, tale che z = yt}
Per semplicità, si supponga che z e y, abbiano tutti la medesima lunghezza e
si calcoli Tm2 sia come funzione di x che come funzione del numero di
elementi m dell’insieme che si vuole esaminare.
9.9 * Si elimini l’ipotesi semplificatrice nel precedente esercizio e lo si risolva di
nuovo.
Esempio 9.6
Consideriamo ora una MT in grado di riconoscere il linguaggio L = {anbn | n > 1}.
Tale macchina può essere costruita facilmente simulando il comportamento di un
AP che riconosce lo stesso linguaggio: il numero-di a del nastro in ingresso viene
salvato in unario sul nastro di memoria e tale numero viene poi confrontato con il
numero di b. La complessità temporale risultante sarebbe &(n) (viene eseguita una
transizione per ogni simbolo in ingresso), che è facile capire essere la migliore
ottenibile. Ovviamente, poiché il numero di a viene salvato in unario, anche la
complessità spaziale risulta essere ®(n).
Qualora volessimo minimizzare la complessità spaziale, conviene contare in
codifica binaria (o equivalentemente, in altra base > 1) il numero di a ricevute e poi
decrementare il contatore binario per ogni b ricevuta. La complessità spaziale
sarebbe così 0(log n), ottenuta però al prezzo di un peggioramento di un fattore
logaritmico della complessità temporale (la verifica di quest’ultima affermazione
viene lasciata in esercizio al lettore).
■
384 Informatica teorica
ESERCIZIO
9.10 Si costruiscano MT che risolvono i problemi sotto elencati e si analizzi la
complessità delle loro computazioni. Si cerchi di stabilire se e come i
risultati ottenuti si possono migliorare.
1. Sottrazione di due interi codificati in base 2.
2. Sottrazione di due interi codificati in base unaria.
3. Riconoscimento del linguaggio L = {anbncn\ n > 1}
4. Riconoscimento del linguaggio L = {anbn2\ n > 1}
5. Riconoscimento del linguaggio L = {anbn\ n > 1} u {a"h2"| n > 1}
1 Questa convenzione è dettata dal fatto che per gli AF una 8 parziale può essere vista come
l’abbreviazione di una 8 totale che porti l’automa in uno stato di errore e ivi lo faccia
rimanere laddove la 8 parziale non fosse definita.
385
La complessità del calcolo
passo per ogni simbolo di ingresso, si può calcolare la complessità temporale nei
seguenti termini.
Enunciato 9.3
Per ogni AF e per ogni x, TA(x) = |x|
■
Vale la pena di puntualizzare l’importanza dell’Enunciato 9.3, che afferma che per
qualsiasi AF la complessità temporale cresce linearmente con il crescere della
lunghezza della stringa in ingresso. Diversamente dagli esempi precedenti, in
questo caso un’intera classe di modelli ha una formula di complessità determinata
(e molto semplice), indipendentemente dal particolare problema da risolvere.
Si noti anche che è immediato simulare gli AF mediante opportuni AP o MT,
in modo tale che valga ancora la medesima formula di complessità. Più
precisamente, una MT che simula un AF può impiegare |x| + 1 mosse per decidere
se x e L, poiché una MT può accettare la stringa di ingresso solo se si trova in una
configurazione di arresto, mentre un AF non richiede che uno stato finale sia uno
stato di arresto. Si ottiene quindi il seguente enunciato generale.
Enunciato 9.4
I linguaggi regolari possono essere riconosciuti da AF, AP e MT in un numero di
mosse pari a |x| o a |x| + 1, dove x è la stringa di ingresso da analizzare.
■
L’Enunciato 9.4 afferma che poiché la complessità temporale di un AF è sempre
pari alla lunghezza della stringa in ingresso è possibile simulare un AF con un AP
o con una MT senza cambiare la complessità dell’AF, a meno al più di una “extra
mossa” finale.
La complessità spaziale per gli AF è un problema molto semplice. È
sufficiente considerare che un AF non è altro che una MT a k nastri con k = 0. Si
ottiene quindi che SA(x) = 0 per ogni AF A e per ogni stringa di ingresso x. Questo
risultato sorprende solo in apparenza. Infatti gli AF sono realmente dispositivi a
memoria finita, potendo memorizzare solo una quantità finita e limitata a priori di
informazione attraverso gli stati, mentre S(x) si riferisce alla memoria illimitata
funzione della stringa di ingresso necessaria per la sua elaborazione (escludendo
quindi la memoria finita dell’unità di controllo).
9.2.2.2 La complessità delle computazioni degli automi a pila
Analizziamo ora la complessità temporale per un dato AP A, dapprima in funzione
della stringa in ingresso (T)(x)) e successivamente in funzione della sua lunghezza
Wj).
Come per gli altri tipi di automa, quando si calcola la complessità temporale
in funzione della stringa di ingresso, si contano i passi che portano da una
i
386 Informatica teorica
Definizione 9.8
Sia A un AP. Per ogni x e I*, sia c0 = (qr0, x, Zo) una configurazione iniziale, c0 >- cx
>- ... cr la sequenza di transizioni che partono da c0; e cr una configurazione di
arresto (di accettazione o di rifiuto per x), se ne esiste una. Se A si ferma, si ponga
TA(x) = r; altrimenti si ponga TA(x) = oo, se non esiste alcuna configurazione di
arresto.
TA(n) = max{7^(x) | |x| = n}
■
Analizziamo ora, considerando sia la stringa che la sua lunghezza come
possibili argomenti, la complessità spaziale.
Definizione 9.9
Sia Co = (qo, x, Zo) = (qh x,, y;)h-...,-cr la sequenza di transizioni effettuate da
un AP A quando opera su di un ingresso x e Z* (la sequenza può essere infinita se
l’AP non si ferma). Allora:
ó'/x) = max{|y,| | i= 1, ..., r}
SA(n) = max{ó)i(x) | |x| = n}
■
La complessità spaziale di un AP corrisponde quindi alla porzione della pila
necessaria per effettuare la computazione. Come per gli AF e le MT, la memoria
finita dell’unità di controllo non viene considerata.
Per capire meglio queste definizioni in pratica, consideriamo nuovamente
l’Esempio 9.4, studiandolo però dal punto di vista della complessità degli AP.
387
La complessità del calcolo
O.A/AA
Figura 9.3 Un AP che accetta {wcwA}.
Esempio 9.7
L’AP descritto in Figura 9.3 (si veda l’Esercizio 4.21) riconosce il linguaggio L =
itwcwR | w e {a,b}*}, che è stato esaminato anche nell'Esempio 9.4.
La determinazione di TXx) (e di TA(n)) è molto semplice, poiché A non
effettua alcuna s-mossa, se si eccettua l’ultima. Quindi TA(x) = |x| + 1 (cioè la
lunghezza della stringa in ingresso più la mossa necessaria per spostarsi nello stato
finale) se x e L(A) e, in generale, TA(n) = n + 1. Anche SA(n) è molto facile da
ottenere. I simboli di ingresso sono impilati fino a che si incontra c; essi vengono
successivamente disimpilati (se x e E). Quindi SA(x) = (|x| - l)/2 se x e L e, in
generale, SA(n) = n.
■
Questi risultati non sono assolutamente sorprendenti. In generale, è facile
dimostrare che, per ogni AP A, si può costruire una MT a 1-nastro che lo simuli e
che abbia le medesime formule di complessità spaziali e temporali2.
Diversamente dagli AF, gli AP possono però effettuare s-mosse. Per questo
motivo, la semplice formula che esprime la complessità temporale negli AF non
vale, in generale, per gli AP. Si intuisce tuttavia che è ugualmente possibile
esprimere la complessità di un qualsiasi AP mediante una formula abbastanza
semplice. Si noti dapprima che, se l’automa non presenta cicli, è possibile
supporre, senza alcuna perdita di generalità che TA(n) sia finita per ogni n. Grazie
al Teorema 4.13, che afferma che per ogni AP esiste un AP equivalente aciclico,
tale risultato può essere generalizzato per tutti i linguaggi non contestuali
deterministici.
2 Come accade per gli AF, una MT che simula un AP può richiedere un passo
supplementare per entrare in uno stato finale.
388 Informatica teorica
Teorema 9.5
Ogni linguaggio L, non contestuale e deterministico, può essere riconosciuto da un
AP A con complessità temporale TA(rì) = kA-n, dove n indica la lunghezza della
stringa di ingresso e kA è una costante opportuna.
■
Dimostrazione
Come si è detto, è possibile supporre, senza alcuna perdita di generalità, che A sia
privo di cicli. Per q e Q, Z e T, sia CqZ il massimo numero di mosse di una
sequenza di transizioni di A del tipo {q, e, Z'y-'lp, e, aZ), a e T*, ossia la lunghezza
della più lunga sequenza di s-mosse che non tolga Z dalla cima della pila. Poiché A
è privo di cicli, CqZ risulta finito per ogni q e per ogni Z.
Sia C = max{CgZ| q e Q, Z e T}, h = max{|a| | ò(q, a, Z)={q', a) V ò(q, e, Z) =
(q', a), per q e Q, Z e T}, ossia la massima lunghezza delle stringhe impilatali in
una sola mossa. Si noti che sia C che h sono effettivamente calcolabili.
Si osservi a questo punto che, nella sequenza {q0, x, Zo) l~*dA {q, e, y) vi sono
esattamente |x| transizioni del tipo (p, ay, y) >- (p',y, y')e, al più, C-|x| transizioni
del tipo Zyi) >- {p',y, yzy\). Tutte le altre transizioni sono del tipo
(p,y,Zyx}^(p',y, yj).
Le transizioni dell’ultimo tipo non possono quindi essere più di h ■ |x| + h ■ C- |x|.
In questo modo, la lunghezza totale della sequenza di transizioni è limitata da
(1 + h + h-C + C) ■ |x|.
■
Corollario 9.6
Ogni linguaggio Z, non contestuale e deterministico, si può riconoscere con una
complessità spaziale 0(n).
’ ■
La dimostrazione, banale, è lasciata al lettore per esercizio. Grazie al Teorema 9.5
e al Corollario 9.6 possiamo quindi concludere che sia la complessità temporale
che la complessità spaziale necessaria per riconoscere un linguaggio non
contestuale deterministico sono lineari rispetto alla lunghezza della stringa in
ingresso.
9.2.2.3 La complessità delle MT a nastro singolo
Studiamo adesso la complessità delle computazioni effettuate dalle MT a nastro
singolo. Si otterranno alcuni interessanti risultati ed alcune osservazioni in un certo
senso sorprendenti. Le complessità spaziale e temporale per le MT a nastro singolo
risultano ovviamente definite come per le MT multi nastro (Definizioni 9.6 e 9.7).
La complessità del calcolo 389
ESERCIZIO
Il risultato dimostrato nell’Esercizio 9.11 afferma che una MT a nastro singolo che
riconosce L ha la stessa complessità theta-grande della macchina multinastro
dell’Esempio 9.4.
Lo stesso problema però, risolto ancora con una MT multi nastro che opera
come la macchina M2, descritta nell’Esercizio 9.4, permette di arrivare a una
soluzione con una complessità lineare. Se il lettore ora provasse a simulare tale
macchina con una MT a nastro singolo, mantenendo lineare la sua formula di
complessità, scoprirebbe che tale problema non è affatto semplice; anche un
tentativo di ottenere una complessità lineare con una diversa macchina a nastro
singolo - nonostante ciò sia ottenibile mediante un AP e una macchina a più nastri-
sarebbe destinato al fallimento. Il seguente teorema, infatti, dimostra che tale
obiettivo non è proprio raggiungibile.
390 Informatica teorica
Teorema 9.7
Nessuna MT M a nastro singolo può riconoscere L = s,wcwR | w&{a,b}*} con
O(Tm) < ®(n2).
Dimostrazione *
La dimostrazione di questo teorema non è banale ed è basata sulla nozione di
sequenza di attraversamento, che ha consentito di ricavare molti risultati relativi
alla teoria della computazione. Intuitivamente, una sequenza di attraversamento
della computazione di una MT è la sequenza degli stati in cui la macchina
attraversa il confine fra due celle consecutive durante la computazione (si veda la
Figura 9.4). La Figura 9.4 mostra il nastro, il cammino seguito dalla testina, nonché
lo stato presente ogni volta che la testina attraversa il confine tra le celle z e z + 1.
Nel caso della Figura 9.4, la sequenza di stati qt ,qt + j , qt +k è la sequenza di
attraversamento del confine fra le celle z e z + 1. Formalmente, una sequenza di
attraversamento viene definita nel modo seguente.
Lemma 9.8
Se una MT M, a nastro singolo e deterministica, non ha nessuna mossa in cui
ò(q, i) = (q , i', S) per qualche q' e f, allora il tempo speso da M sulla stringa di
ingresso w è pari alla sommatoria delle lunghezze delle sequenze di
attraversamento di tutte le z. Nel caso generale, il tempo di computazione di M è
limitato da una funzione lineare di tale sommatoria, purché M non possa effettuare
una sequenza illimitata di mosse in cui la testina rimane ferma (5-mosse).
391
La complessità del calcolo
numero di mosse di M è al più kr. Notiamo che, per ogni MT M, si può facilmente
costruire una M' equivalente che effettua solo un numero limitato di S-mosse
consecutive, tale che T>An) > TM(n) per ogni n.
Lemma 9.9
Sia M una MT a nastro singolo deterministica. Si supponga che, al termine della
computazione, M si fermi sempre alla destra delle celle che originariamente
contenevano i dati in ingresso. Allora, se M accetta WiW2 e jSzdQwxl) = £4(|xi|),
quando M riceve in ingresso x,x2 (ossia quando la sequenza di attraversamento del
confine fra nj e w2 è la medesima che fra Xi e x2), allora M accetta xiw2.
Si noti che, almeno per la metà di tutte le parole w, lw z < 2a(z~) per ogni z. Infatti,
se per più di metà di tali parole Zw,z fosse maggiore di 2a(z), anche nel caso in cui la
rimanente Zwz fosse 0, si avrebbe
'-■2-a(z)-2m
k
induzione rispetto a k, poiché, per k = 1, n<«2 e < zz * +1 implica
Z=1
£+1 k
z v"1 ' k+1 . £+1 k+1 . k+ 2
E
z=l
n = 2, n + n
Z=1
< n +n < n
. 2-log2(|2|) 2
In virtù del Lemma 9.8, il tempo impiegato da A/per il riconoscimento di x = un/
è
394 Informatica teorica
m
'y', ^w,z
z = -co z=1
Quindi, il tempo medio speso da M per riconoscere tutte le stringhe x = -wcwR, con
|x| = n è pari a:
ym i
,V' z = \ w’z
E
\w\=m
?m
2
2m
iw z m
m
z
Zj z = l^J |w|=w z-1 m
2m 21og|g| 2
Z=1 Z=1
m
1 m m
2log \ Q\
Z-
Z=1
21og|g| 2
m(m -1) m 1
\Q |+ 2
4 log
2log iei
Esempio 9.8
ESERCIZI
9.12 * Si dimostri che nessuna MT a nastro singolo può riconoscere L = {wws}
con una complessità temporale minore di 0 (n2).
9.13 Si costruiscano MT a nastro singolo che risolvano i problemi elencati
nell'Esercizio 9.10 e si controlli se il loro comportamento asintotico sia
cambiato o meno rispetto alle MT multinastro.
Definizione 9.11
Sia M una MT multinastro non deterministica che accetta il linguaggio L. M ha
complessità temporale TM (e, rispettivamente, complessità spaziale SM) con
dominio I se, per ogni stringa di ingresso x, x e L se e solo se esiste almeno una
computazione di M che accetta x in T^x) mosse (rispettivamente, usando S^x)
celle di memoria) e nessun’altra computazione accetta x in meno di Z^x) mosse
(rispettivamente, usando meno di ST.x) celle del nastro di memoria). TJn)
(rispettivamente, viene definita come il massimo di Z«(x) (rispettivamente,
S>AXA su tutte le x e Z di lunghezza n.
Avvertimento *
Il lettore attento probabilmente non si è lasciato sfuggire alcuni punti cruciali della
definizione precedente. In primo luogo, la definizione si riferisce alle MT usate
come accettori di linguaggi, il che è una restrizione rispetto ai loro usi potenziali.
La definizione è coerente con la consueta modalità mediante la quale i dispositivi
non deterministici vengono utilizzati come riconoscitori di linguaggi. Fra le molte
computazioni possibili, siamo interessati a trovarne almeno una che conduca
all’accettazione. Sembra perciò naturale concentrare la definizione di complessità
su tale computazione.
La complessità del calcolo 397
Nel caso in cui, invece, si sia interessati alle MT come traduttori di linguaggi (ossia
al calcolo di tutti i valori di una traduzione a più valori r(x) effettuato da una MT
non deterministica), la filosofia del “caso pessimo” dovrebbe condurre alla scelta
della computazione più lunga fra quelle relative alTingresso x. Questa scelta, però,
comporterebbe qualche complicazione nel caso in cui alcune computazioni su x
non terminasssero. In ogni caso, qui focalizziamo l’attenzione sul riconoscimento
dei linguaggi, per uniformità con la letteratura esistente.
Un’altra spiacevole conseguenza della Definizione 9.11 è che essa non si
riduce alla Definizione 9.5 nel caso particolare in cui M è deterministica. Infatti, se
x g L, la definizione è soddisfatta da ogni valore di TM. Ad esempio, se T^n) = m2,
per qualche x £ L, M può impiegare più di |x|2 mosse ed entrare addirittura in
computazioni senza fine, secondo la Definizione 9.11. Ciò non è consentito,
invece, dalla Definizione 9.5.
Si può quindi adottare, in alternativa, la seguente definizione.
Definizione 9.1 la
Sia M una MT non deterministica. T^x) è tale che nessuna computazione
effettuata sull’ingresso x impiega più di T^x) mosse e almeno una ne impiega
esattamente TU-U S^x), T^n) e S^n) sono definite conseguentemente.
■
Tale definizione, però, potrebbe risultare in contrasto con le osservazioni
precedenti; per questo motivo si preferisce, generalmente, la Definizione 9.11.
Nella maggior parte dei casi interessanti, tuttavia, la differenza fra le due
definizioni non è molto grande. Si noti dapprima che, se TM è ima funzione totale
computabile, il linguaggio accettato da M è ricorsivo. Infatti, per stabilire se
x e L(M), è sufficiente prendere in considerazione tutte le computazioni di
lunghezza minore o uguale a T^n), in cui n = |x|. Tali computazioni sono
necessariamente un numero finito. Si può dunque supporre, senza perdita di
generalità, che M si fermi sempre. Analogo ragionamento vale se T^n) <fin) per
qualche finizione totale computabile f. Secondariamente, tutti i risultati presentati
in questo testo, concernenti la complessità computazionale delle MT non
deterministiche, non perdono la loro validità qualunque sia la definizione adottata,
come il lettore può verificare personalmente. Infine, si intuisce facilmente che, in
molti casi interessanti, le due definizioni sono praticamente equivalenti, come si
illustrerà successivamente, in questa stessa sezione, nel corollario del Teorema
della Accelerazione Lineare (Corollario 9.14).
Dopo aver associato una finizione di complessità ad una macchina, prendiamo
ora in considerazione la classe dei problemi risolvibili all’interno di un determinato
limite di complessità, ossia mediante una macchina la cui complessità sia limitata
superiormente da una determinata funzione. In termini di riconoscimento dei
linguaggi, ciò conduce alla seguente definizione.
398 Informatica teorica
Definizione 9.12
Sia f una funzione totale definita sui numeri naturali. DTIME(/) è la famiglia di
linguaggi riconosciuti da qualche MT deterministica multinastro con complessità
temporale limitata da f ossia tale che Tfin) < fin) per ogni n. Analogamente,
DSPACE(/) è la famiglia dei linguaggi accettati da una MT deterministica
multinastro con complessità spaziale limitata da f. NTIME(/) e NSPACE(/) sono
definite analogamente per i linguaggi accettati dalle MT non deterministiche.
■
Ad esempio, L = {wcwA} è in DTIME(m) e in DSPACE(log2 (fi)), come mostrano
gli Esercizi 9.4 e 9.6. Si noti però che ciò non implica che L possa essere
riconosciuto, dalla stessa MT, in tempo n e spazio log(n). Molto spesso, come già
osservato in precedenza, bisogna rinunciare all’efficienza temporale per quella
spaziale e viceversa.
ESERCIZI
9.14 Si dimostri che sefi(fi) <ffifi) per ogni n, allora DTIME(fj) c DTIME(^);
si estenda poi la dimostrazione anche a NTIME, DSPACE e NSPACE.
9.15 Si determinino le più piccole classi di complessità, deterministica e non
deterministica, temporale e spaziale, che contengano i seguenti linguaggi
Zi = {ww| w e {a,b}*}
L2 = {anxban2 ...ank | 3z,j, 1 < i *j < A tale che «,= nfi
fb)
Figura 9.5 (a) Un nastro di M. (b) Il corrispondente nastro di M.
399
La complessità del calcolo
Teorema 9.10
Se L è accettato da una MT multinastro (deterministica o non deterministica) con
complessità spaziale S allora, per ogni costante reale c > 0, L è accettato anche da
un’opportuna MT avente complessità spaziale c-S (c-S indica la funzione S' tale
che S'(n) = c-S(n) per ogni n).
■
Si consideri un intero r tale che r-c>2. Possiamo a questo punto “fondere” insieme
r celle adiacenti di un qualunque nastro della MT M, ottenendo un’unica cella, e
avere ancora una MT M' equivalente a quella originaria, mediante un’opportuna
codifica e una modifica di T, Q, 8. Chiaramente, la nuova MT ha la complessità
spaziale desiderata. La Figura 9.5 fornisce uno schema intuitivo della costruzione.
Allo scopo di codificare la posizione della testina di M, all’interno della r-upla
(ai,...,ar), lo stato di M' corrisponde ad una coppia (q, i), con 1 <i< r, nel caso di
una MT a nastro singolo, mentre corrisponde ad una (k + l)-upla, nel caso di una
MT a k nastri.
Figura 9.6 (a) Una MT a k nastri, M. (b) Una MT equivalente ad un nastro, M',
con la medesima complessità spaziale.
400 Informatica teorica
Teorema 9.11
Se L è accettato da una MT a k nastri con complessità spaziale S, allora è accettato
anche da un’opportuna MT ad un nastro M' con la medesima complessità S.
■
La dimostrazione è lasciata al lettore per esercizio. Come suggerimento, la Figura
9.6 indica la possibilità di impiegare alfabeti mutuamente disgiunti per ciascun
nastro di memoria. Le porzioni “significative” di ciascun nastro di memoria di M
(ossia le porzioni che contengono solo celle non vuote, nonché la posizione della
testina) vengono memorizzate consecutivamente nell’unico nastro di memoria M’.
Le posizioni delle k testine di M vengono memorizzate mediante opportuni simboli
speciali.
ESERCIZIO
9.16 Si dimostri che, se un linguaggio L è accettato da una MT con complessità
spaziale tale che S(n) > n per ogni n, allora è accettato da una MT a nastro
singolo con complessità spaziale S(n).
Definizione 9.13
Sia f una qualunque finizione definita sui numeri naturali. Si definisce sup f (»)
«—> co .
Per esempio,
sup n ■ (sin (w) + 1) = oo , inf n ■ (sin (ri) + 1) = 0 ,
La complessità del calcolo 401
taf
n—><x n
Allora, per ogni costante reale c > 0, si può costruire una MT a (k + 1) nastri M'
che accetta L con complessità temporale TM’, tale che TM (rì) = max {n + 1,
Dimostrazione
La dimostrazione si ispira all’analoga dimostrazione relativa alla riduzione lineare
della complessità spaziale (Teorema 9.10), in quanto consiste nella fusione di r
celle adiacenti di Min un’unica cella di M’, per un opportuno valore di r (si veda la
Figura 9.7). E tuttavia necessario prestare una maggiore attenzione ai dettagli per
ottenere l’espressione della complessità temporale di M'.
Durante la fase preliminare, M' copia il contenuto del nastro di ingresso Tj sul
suo nastro supplementare di memoria T7+;, fondendo insieme r celle adiacenti di 17
in un’unica cella di T7+7. Successivamente, la testina di TK7 viene posizionata di
nuovo sulla prima cella del nastro.
Questa fase preliminare richiede un tempo n + \ n/r J, dove n indica, come al
solito, la lunghezza della stringa di ingresso. Da questo momento in poi, M' simula
Musando TK7 come nastro di ingresso. La computazione di M’ consiste in una
sequenza di macro-mosse. Ciascuna macro-mossa, a sua volta, è costituita da due
gruppi formati rispettivamente da, al più, quattro e due mosse elementari.
402 Informatica teorica
Il primo gruppo è organizzato nel modo seguente. Per ciascun nastro T;, 1 <i < k +
1, M' visita le due celle alla destra e alla sinistra della cella precedentemente letta e
si riposiziona su di essa. Ad esempio, la M' mostrata in Figura 9.6 visita le celle
(ar...ar) effettuando un passo a sinistra, (ci...cr), con due passi a destra e ritornando
su {bi...br) con un passo a sinistra.
A questo punto, M’ “conosce” il contenuto delle 3-r celle di M, {aA...aX
(bi...br\ {ci...cr). Poiché tale contenuto può consistere in |r|3 r valori diversi, questi
ultimi potranno essere memorizzati da M’ mediante l’insieme dei suoi stati. Si noti
che, quando M opera sulla porzione di T; corrispondente alle 3 -r celle di cui sopra,
essa può:
1. Fermarsi, accettando o rifiutando.
2. Non lasciare mai la porzione di nastro sopra descritta, per tutti i nastri T;. In
questo caso, essa dovrà entrare, alla fine, in un ciclo chiuso di configurazioni
ripetute un numero infinito di volte, a causa del numero finito delle possibili
configurazioni diverse.
3. Effettuare una sequenza di almeno r + 1 mosse, tali che, per qualche Tz, la
corrispondente testina di lettura lasci, alla fine, la porzione di 3 ■ r celle sopra
citate.
I casi 1. e 2. possono essere decisi da M' senza alcuna mossa, semplicemente
ispezionando il suo stato. Infatti essi corrispondono ad un numero finito di possibili
alternative.
Nel caso 1., M' si ferma, cosi come farebbe M. Nel caso 2., M' si ferma
rifiutando la stringa, o, equivalentemente, entra in un ciclo, come farebbe M. Nel
caso 3., M' simula r mosse di M per ciascun T„ mediante il secondo gruppo
composto, al più, di due mosse. Questa situazione si articola nel modo seguente.
M' modifica il contenuto della cella corrente e (eventualmente) della cella
adiacente, come farebbe M nella corrispondente porzione di nastro, e lascia la
testina posizionata sulla cella corrispondente al gruppo di celle in cui la testina di
M si ritroverebbe dopo r mosse. Ad esempio, si supponga che r mosse di M
consistano nel visitare, da destra verso sinistra, b)...bs...blar...am cambiando i loro
valori in bf ...bs'...am' e ritornando a bs’. Si noti che, se un elemento di ax...ar viene
visitato da M, nessun elemento di c\...cr può essere visitato in una sequenza di r
mosse. Ciò può essere simulato da M' mediante due mosse, che sostituiscano
con {ai...am’ ...ar'} e (b1...br') con {b\ ...bs'..br), e lasciando la testina
posizionata su (bi'...br'), in uno stato che memorizza la posizione s per il nastro T>.
Come si può notare, quindi, r mosse di M sono state simulate da, al più, sei
mosse di M'. Ciò implica che, se M impiega T^ri) mosse per effettuare i suoi
calcoli, M' non ne impiega più di
r r r r
La complessità del calcolo 403
yr (fi )
Ora, si ricordi che inf ----- = 00 , il che significa che per ogni costante reale 8
n —> co n
esiste un «5 in corrispondenza del quale, per ogni n > n&, T(rì)ln > 8. Risulta quindi
molto facile verificare che, per ogni n > n& e n > 2, dove n + 2 < 2n,
n 6T(n) <6 2 1 >
fi H--------1----------------- F 2 < T’(ft) • 1— +
r r <r 8 r•8)
Chiaramente, per ogni c > 0 assegnato, si possono trovare un intero r ed una 8 tali
che:
6 2 1
— H------ H------------ < C
r 8 r■8
Resta da considerare l’insieme finito di parole la cui lunghezza è minore di max{2,
ns}. Questo non è però un problema, poiché un insieme finito di parole può sempre
essere riconosciuto da un AF, e quindi da una MT, in n + 1 mosse (si ricordi che
una MT ha bisogno, al più, di una mossa supplementare per entrare nello stato di
arresto dopo aver letto la fine della stringa di ingresso).
■
Basandosi sul Teorema 9.12, è banale dimostrare il seguente corollario, che viene
quindi lasciato al lettore per esercizio.
Corollario 9.13
1. Se inf ---------- = 00
n —> co n
calcolo più vicini alla classica architettura di von Neumann; il lettore è invitato a
verificare di persona questa affermazione in seguito alla lettura della Sezione 9.3.
Secondo il Teorema 9.12, tuttavia, il guadagno ottenibile mediante questo
approccio sistematico (aumentare le risorse di calcolo disponibili) è vincolato a
restare lineare. Questo risultato porta con sé un’interessante conseguenza. Si
supponga di eseguire un algoritmo con complessità temporale ©(/?) per risolvere
un problema P su di un piccolo personal computer. La velocità di esecuzione che si
può raggiungere passando ad un supercalcolatore che esegue il medesimo
algoritmo (per casi di P sufficientemente “grandi”) è molto minore del guadagno
ricavabile passando ad un algoritmo 0(nL9) eseguito dallo stesso personal
computer. In altre parole, l’intuito nel trovare buoni algoritmi dà migliori risultati
rispetto al calcolo fondato sulla sola potenza del calcolatore.
Un’altra conseguenza del Teorema 9.12 comporta la possibilità di colmare il
divario fra le definizioni di complessità 9.11 e 9.1 la, per le computazioni non
deterministiche.
Corollario 9.14
Sia funa funzione totale che:
□
a. • r -------- = oo
ini
«—> oc n
b. Per ogni n, il valore di fin) è computabile da una MT deterministica in un
tempo t, con t <fin).
Se una MT non deterministica M ha una complessità temporale fi secondo la
Definizione 9.11, si può costruire una MT equivalente M' con complessità
temporale/^ secondo la Definizione 9.1 la. Quindi, per ogni f che soddisfa l’ipotesi,
NTIME(/) non dipende dalla scelta di una delle due definizioni.
Dimostrazione
Si può costruire facilmente M' seguendo la traccia seguente.
Per ogni ingresso x assegnato, di lunghezza n, M' dapprima calcola fin) nel tempo
t, con t <firì). Non c’è perdita di generalità nel supporre che/(«) sia codificata in
base unaria su qualche nastro di M', poiché la conversione di un numero qualunque
m dalla base unaria ad una base k con k > 1, e viceversa, può essere effettuata in un
tempo 0(m).
405
La complessità del calcolo
M' simula M decrementando fin) di un’unità per ciascun passo; se non accetta x
prima di f(n) mosse, si ferma, rifiutando x. Chiaramente, esisterà qualche
computazione di M' che accetta x se, e solo se, M si comporta nello stesso modo.
Inoltre, il limite di tempo per tutte le computazioni di M' su stringhe di lunghezza n
è dato da 2 ■/(»). In virtù del Teorema 9.12, tali computazioni si possono accelerare
in modo tale da venire effettuate in un tempo limitato esattamente da /fw).
ESERCIZI
Esempio 9.9
Vogliamo fornire una maggiorazione, a meno della relazione 0, della relazione tra
le complessità temporali di una MT a k nastri e una a k + 1 nastri, quando si usa la
prima per simulare la seconda.
Si osservi che una MT a nastro singolo può simulare una MT a k nastri con
complessità ©(^(n)) < O(Tk(h)2). Informalmente, l’idea è di collassare i k nastri
della seconda sull’unico nastro della prima. In questo modo ogni mossa della MT a
£ nastri costa al più una scansione completa dell’unico nastro della prima.
Lo stesso ragionamento si può effettuare nel nostro caso, collassando il (£+1)-
esimo nastro della MT a k + 1 nastri sul £-esimo della MT a k nastri, ottenendo
dunque 0(Tk(n)) < 0(Tk+1(»)2).
Esempio 9.10
Consideriamo il problema di decidere la veridicità delle seguenti affermazioni:
Enunciato 9.15
Una MT a due nastri può effettuare la somma di due numeri naturali e n2 per
ogni base k, con k > 1, con una funzione di complessità temporale che è 0(m), dove
n = max{| logt + 1, (log^ m2J +1}- Nessuna MT Mmultinastro può effettuare
questa operazione con &(TM) < 0(m).
■
D’altra parte, è ben noto che ogni calcolatore digitale è dotato di un’istruzione
ADD che esegue in una unità di tempo (un ciclo macchina) la somma di due
numeri interi, i cui valori possono essere immagazzinati o nei registri o nella
memoria principale, e lascia il risultato o in un registro o in una cella della
memoria principale.
Ciò motiva la necessità di studiare modelli computazionali più pratici, in
modo che i risultati relativi alla complessità, dimostrati su quei modelli, abbiano
un’applicabilità pratica e immediata. In questa sezione si studiano due di tali
modelli: la macchina RAM (una astrazione di un calcolatore convenzionale) e
SMALG (un linguaggio di programmazione ad alto livello ispirato all’ALGOL),
già parzialmente introdotto nell’Appendice 7.A. In seguito, nella Sezione 9.5, si
confronteranno in termini rigorosi le analisi di complessità relative ai diversi
modelli computazionali (ricavandone risultati non del tutto scontati).
di una cella verso destra. Le celle di memoria, invece, sono indirizzate da numeri
naturali: M[i\ (con i > 0) indica la z-esima cella di memoria e A/[0] si riferisce ad
un registro speciale, l’accumulatore, che si usa per contenere il valore di uno dei
due operandi delle operazioni aritmetiche binarie che la macchina può effettuare.
Il programma, che definisce ciascuna RAM, è cablato nella macchina ed è quindi
fisso. Un programma è una sequenza di istruzioni, ciascuna formata dal codice
dell’operazione da effettuare e dall’operando (che in alcuni casi può essere
un’etichetta). Il repertorio delle istruzioni è un insieme molto semplificato di ciò
che è possibile trovare nei calcolatori reali: si possono eseguire operazioni di
lettura e scrittura sui nastri, assegnamenti, operazioni aritmetiche e istruzioni di
salto condizionato e non. Le etichette sono associate solo alle istruzioni di salto,
mentre tutte le altre istruzioni sono associate ad un operando.
Le istruzioni della RAM e la loro semantica sono descritte brevemente nella
Tabella 9.1, in cui si adotta una intuitiva notazione ispirata a linguaggio lava
nell’ipotesi che M si possa considerare come un vettore illimitato di interi. Il
contatore istruzioni si può vedere come una variabile intera CI, il cui valore è
contenuto nel sottoinsieme dove m è la dimensione, ossia il numero di
istruzioni, del programma.
Tutte le istruzioni dalla 1 alla 8 nella Tabella 9.1, oltre all’effettiva operazione
indicata dal codice, incrementano implicitamente il valore di CI di una unità. La
macchina si ferma in uno stato corretto quando viene raggiunta l’istruzione di
HALT. Essa si ferma invece in uno stato scorretto quando i valori sono al di fuori
dell’insieme di definizione o vengono incontrate istruzioni sintatticamente senza
senso (ad esempio READ= x) durante l’esecuzione.
Esempio 9.11
Si consideri la funzione è_primo definita sugli interi positivi nel modo seguente:
è_primo(n) = if n è un numero primo then 1 else 0
Un programma di Figura 9.9 implementa la funzione è_primo enumerando tutti i
valori da 2 a n fino a che il valore non uguaglia n o divide esattamente n. Nel
primo caso, il programma stampa in uscita un 1; nel secondo caso il valore di
uscita è uno 0.
411
La complessità del calcolo
Esempio 9.12
Il programma RAM di Figura 9.10 riconosce il linguaggio, ormai familiare, L =
{wcwÀ| wg {a,b} } utilizzando la seguente codifica per rappresentare i simboli
dell’alfabeto (a, b e c) attraverso l’uso di numeri naturali.
- a è codificata da 1.
- b è codificato da 2.
- c è codificato da 3.
- 0 è usato come marca di fine nel nastro d’ingresso.
Programma RAM Commento
READ 1 II valore letto in ingresso (ri) è memorizzato in Affi]-
LOAD= 1 II valore 1 viene caricato nell’accumulatore.
SUB 1 II valore in à/[0] (cioè 1) viene decrementato di n (il
contenuto di Af[O].
JZ YES Se n = 1 (cioè se 1-n è pari a 0), allora n è banalmente
primo e il resto del programma viene saltato.
LOAD= 2 II valore 2 viene caricato nell’accumulatore e
STORE 2 poi salvato in At[2] (cioè à/[2] è inizializzato a 2).
NO: WRITE= 0
HALT
SI: WRITE= 1
HALT
(Seconda parte)
9.21 Si scrivano programmi RAM che calcolano le funzioni definite nel modo
seguente:
1. primo(n) = k, dove n > 0 e k è l’z-esimo numero primo, cominciando
da 2.
2 tutti-primi(n) = {x| x è un numero primo e x < n}
3. fln\, n2, ■■■, n^) = 2”13”2 ... p™k , dove pi è l’z-esimo numero primo. Si
supponga che la stringa di ingresso contenga per primo il numero k,
seguito da nr, n2, ..., nk.
4. fl, dove fè la funzione del punto 3.
5. ordinato(n\,...,n^) = if < n2 < ...< nk then 1 else 0. La stringa in
ingresso è strutturata come nel punto 3 precedente.
9.22 Si scrivano programmi RAM che riconoscono i seguenti linguaggi
1. Li = {wwA| we {a,b}*}
2. L2 = {mv| M-e {a,b} }
414 Informatica teorica
3. £3 = {anbn\ n > 0}
In particolare, si scrivano due programmi RAM, Pi e P2, che
riconoscono Z,3. Pi si ottiene come simulazione diretta dell’AP che
riconosce £3. P2 conta le occorrenze di a, invece di memorizzarle nella
pila.
Possiamo ora usare il modello RAM per stimare la complessità delle computazioni
effettuate dai calcolatori reali. Infatti, il modello computazionale RAM si comporta
in modo molto simile ai calcolatori convenzionali, anche se vi sono alcune
differenze sostanziali. La differenza più evidente è che i calcolatori convenzionali
sono programmabili: i programmi sono immagazzinati in memoria e possono
modificare se stessi.
Un modello classico, che fa uso dello stesso insieme di istruzioni della RAM e
non presenta questa differenza con i colcolatori reali, è la macchina RASP
(Random Access Stored Program), che mantiene il programma in una parte della
memoria e permette di modificarlo. Tale macchina usa lo stesso insieme di
istruzioni della RAM, con l’unica eccezione che tutte le istruzioni del tipo “codice
operativo*”, cioè le istruzioni che utilizzano l’indirizzamento indiretto, non sono
consentite.
Si osservi che la macchina RASP rappresenta per la macchina RAM quello
che la MT universale rappresenta per la MT. Infatti, le prime sono macchine che
possono essere programmate e quindi prendono in ingresso sia il programma che i
dati su cui utilizzare il programma, le seconde sono macchine già programmate,
atte a risolvere uno specifico problema in modo prestabilito e ricevono in ingresso
solo i dati su cui operare.
Tornando al confronto tra la RAM e i calcolatori reali, altre differenze
risiedono nel repertorio delle istruzioni, poiché la nostra RAM è una versione
semplificata di quanto si può trovare nel mondo dei calcolatori reali. Ad esempio,
molti calcolatori prevedono una istruzione INC per incrementare un valore di
un’unità. Una istruzione “INC z” può essere simulata da una sequenza di istruzioni
RAM.
LOAD i
ADD= 1
STORE i
D’altra parte, la macchina RAM ha, come istruzioni primitive, la MULT e la DIV,
che possono non essere disponibili sui calcolatori più semplici, in quanto possono
essere simulate utilizzando la somma e la sottrazione, o, più probabilmente
ricorrendo ad un’apposito coprocessore matematico. In ogni caso, per eseguire
operazioni di tipo moltiplicativo su calcolatori reali, bisogna impiegare
un’opportuna sequenza di istruzioni, contenenti anche dei cicli, che difficilmente
può essere completata nello stesso tempo richiesto da un’istruzione elementare.
415
La complessità del calcolo
Esempio 9.13
Si consideri il programma RAM in Figura 9.11. Tale programma legge da tastiera
un numero n e, per tutti i numeri da 1 fino a n stampa a video un 1 se il numero è
dispari. Appare evidente che la parte che concorre maggiormente alla complessità
del programma è il ciclo (CICLO) che viene ripetuto n volte. Infatti, tutte le
istruzioni che lo precedono e lo seguono vengono ripetute esattamente una volta. Il
numero di operazioni ripetute all’interno del ciclo è costante e non dipende dal
valore di n, per cui possiamo dire che la complessità temporale del programma
considerato è pari a 0(«).
Si osservi che il dato in ingresso n non viene manipolato in alcun modo
durante l’esecuzione del programma e che l’unica altra variabile, utilizzata come
contatore e salvata in M[2], raggiunge al più il valore n. Questo significa che la
complessità dell’algoritmo è al più influenzata linearmente dalla dimensione di n
(che, poiché n è codificato in binario, è log ri) e quindi la complessità trovata, senza
considerare tale parametro, risulta realistica.
417
La complessità del calcolo
Esempio 9.14
Consideriamo il problema del calcolo del doppio fattoriale. Un semplice modo per
risolvere tale problema è riportato in Figura 9.12. La soluzione proposta, dopo aver
letto l’ingresso (n), fa uso di due cicli: il primo, che viene ripetuto n volte, calcola
n\, il secondo, che viene ripetuto ni volte, calcola («!)!.
Appare evidente che la complessità temporale è dominata dal secondo ciclo
(CICLO2), che viene ripetuto ni (ottenendo così una complessità pari a ©(«!)). In
questo esempio, però, i dati utilizzati all’interno dei cicli sono ottenuti
moltiplicando valori proporzionali a n, fino ad ottenere («!)!, la cui dimensione in
bit è &(nln log rìf. Risulta quindi irrealistico immaginare che la gestione di un
dato di tale dimensioni non influenzi la complessità temporale.
6 Si veda la Sezione 9.8 per una dimostrazione che log (zw!) è ©(w.log m). Si ponga quindi
m = ni per ottenere quanto affermato.
418 Informatica teorica
i =0
WRITE= X /(x)
WRITE X /(x) + /«x])
WRITE* X /(x) + /«x]) + /«Mx]D
JUMP lab 1
JGZ lab /«od
JZ lab /«od
HALT 1
7 Si noti che attribuire alle operazioni moltiplicative lo stesso costo di quelle additive è
alquanto ottimistico perché non sono noti algoritmi che eseguano queste operazioni in
tempo proporzionale alla lunghezza dei loro operandi. Ciò conferma l’osservazione che un
ragionamento rigoroso dovrebbe escludere queste operazioni dall’insieme di quelle assunte
come elementari.
420 Informatica teorica
Esempio 9.15
Consideriamo nuovamente il problema del calcolo del doppio fattoriale, la cui
soluzione è riportata in Figura 9.12. Come osservato nell’Esempio 9.14, in cui
abbiamo analizzato la complessità di tale soluzione con il criterio del costo
uniforme, il programma, dopo aver letto l’ingresso (m), fa uso di due cicli: il primo,
che viene ripetuto n volte, calcola ni, il secondo, che viene ripetuto ni volte,
calcola («!)!.
Appare evidente che anche in questo caso la complessità temporale è dominata
dal secondo ciclo (CICLO2), che viene ripetuto ni e all’interno del quale vengono
svolte operazioni sui dati fino al calcolo di («!)!. Le operazioni dominanti
all’interno di tale ciclo sono:
LOAD 1
MLTLT 3
STORE 1
che, facendo riferimento ai costi in Tabella 9.2, hanno rispettivamente i seguenti
costi:
Z(l) + Z«l])
/«OD + 1(3) + Z«3])
Z«O]) + Z(1)
Il dato che viene immagazzinato nella cella 1 è quello che domina la complessità
spaziale e, ad ogni iterazione, è pari a i!, fino a valere (n!)!. Perciò la complessità
spaziale del programma risulterà 0(n!n log n), cioè la dimensione in bit di (n!)!.
Poiché la complessità temporale, a parità di criterio di costo, è sempre maggiore o
uguale alla complessità temporale, la complessità temporale con il criterio del
costo logaritmico risulterà molto superiore alla complessità temporale valutata con
il criterio del costo uniforme (0(n!)), mostrando quindi che tale critero risulta
irrealistico quando il programma in analisi gestisce dati di grandi dimensioni. Si
lascia al lettore come esercizio la valutazione esatta di tale complessità
■
Non è dunque sorprendente che i risultati dell’analisi di complessità siano molto
diversi, a seconda del criterio di costo adottato. Il criterio del costo uniforme è
semplice da applicare, ma può essere impiegato con sicurezza solo se si prevede
con certezza che ogni valore che comparirà nel corso della computazione potrà
essere immagazzinato in una sola cella di memoria. Altrimenti, bisogna riferirsi al
criterio di costo logaritmico. Infatti, come visto negli Esempi 9.14 e 9.15, il criterio
di costo uniforme risulta anche gravemente inadeguato per analizzare la
complessità di un programma che calcola la funzione doppio fattoriale per valori di
ingresso non piccolissimi (basti pensare al valore di (10!)!).
In pratica, si potrebbe tener conto di entrambi i criteri nel modo seguente. Sia
k la lunghezza della parola del calcolatore impiegato (in generale k vale 8, 16, 32,
421
La complessità del calcolo
64 o 128). Per ogni intero positivo i, sia s l’intero definito dalla seguente
disuguaglianza:
2k■ s-1 < . < 2^(5 + 1)_i
Esempio 9.16
Si consideri il programma RAM mostrato in Figura 9.9. Per valutare la sua
complessità temporale (nel caso pessimo) T, secondo il criterio di costo uniforme,
si conta semplicemente il numero massimo di esecuzioni di istruzioni.
E immediato comprendere che:
a. Le prime sei istruzioni vengono eseguite al più una volta.
b. Due delle ultime quattro istruzioni sono eseguite una sola volta.
c. Le istruzioni contenute fra “CICLO: LOAD 1” e “JUMP CICLO” vengono
ripetute al più À/[l] - 2 volte, dove A/[l] = n (n è il valore di ingresso).
d. La sequenza di tre istruzioni che comincia da CICLO viene eseguita ancora
un’altra volta.
Costo di b.: 2
Costo di c.:
Istruzione Costo______________________________
CICLO: LOAD 1 1 + Z(m)
SUB 2 Z(») + 2 + Z(VZ[2])
a: JZ Sì W])
LOAD 1 1 + Z(m)
DIV 2 Z(») + 2 + Z(ÀZ[2])
MULT 2 Z(n/M[2]) + 2 + Z(ÀZ[2]) < Z(») + 38
SUB 1 Z(ÀZ[O])+ 1 + Z(»)<2-Z(») + 1
JZ NO Z(A/[0]) < Z(rz)
LOAD 2 2 + Z(ÀZ[2])
ADD= 1 Z(ÀZ[2]) + 1
STORE 2 Z(AZ[2] + 1) + 2 < Z(AZ[2]) + 3
JUMP CICLO j
Totale parziale arrotondato 17 + 8- l(n) + 5 ■ Z(ÀZ[2]) + Z(À/[0])
Si noti che LZ[2] assume i valori 2, 3,..., n - 1; A/[0] assume i valori n - 2, n - 3,
1. Quindi, il totale parziale dovuto a n - 2 iterazioni è
n-1 n-2
1. {i = 5 ; j = 10; x = 3 ;
if(i != j){a[2] = x + i;} else{a[j] = 6;}}
2. {while(5 == 5){x = 3;
if(x < 3){x = x + 1;}
else(x = x-1;}}}
3. {read(n);
if (n <= 0){write(n);}
elsefz = n; c = n-1;
while(c > 0){z = z * n; c = c -1;}
write(z);}}
Il lettore avrà probabilmente già compreso, durante l’analisi delle macchine a stati
(AF, AP e MT) e delle RAM, che il problema della definizione rigorosa delle
trasformazioni di stato (ossia delle computazioni) compiute da macchine astratte o,
“programmi”, diventa molto più difficile quanto più potenti ed astratte diventano le
macchine. Infatti, mentre le funzioni di transizione degli AF sono immediatamente
descrivibili mediante una semplice tabella, le transizioni delle MT richiedono
maggiori dettagli per la loro definizione formale e le trasformazioni di stato delle
RAM sono ancora più complicate (ad esempio quando si ha a che fare con
l’indirizzamento indiretto). Quando si raggiunge il livello di astrazione dei
linguaggi di programmazione di alto livello, sorge qualche difficoltà. Poiché lo
studio della semantica formale, operazionale o denotazionale che sia, non rientra
negli scopi di questo libro, ci limiteremo a definire lo spazio di stato di SMALM e
le trasformazioni operate dai programmi SMALG in modo piuttosto informale ma
sufficientemente preciso da permettere un’analisi rigorosa della loro complessità.
Lo spazio di stato di SMALM consiste di:
1. Una locazione di memoria che contiene un valore intero per ciascuna variabile
semplice. La locazione associata alla variabile semplice x sarà indicata con
Mx.
2. Una sequenza illimitata di locazioni di memoria contenenti valori interi per
ciascuna variabile vettoriale. Una variabile indicizzata a [ i ] è associata a:
2.1 La i-esima locazione nella sequenza associata ad a, se i è una costante
intera di valore maggiore di zero.
2.2 La j -esima locazione nella sequenza associata ad a, con j > 0, se i è una
variabile semplice e j è il valore memorizzato nella locazione M±.
2.3 In tutti gli altri casi a [ i ] è indefinita.
3. Un nastro di ingresso e di uscita, come nel caso della RAM.
La Figura 9.15 fornisce una descrizione grafica dello spazio di stato di SMALM
per il programma SMALG numero 1 di Figura 9.14. Oltre ai nastri di ingresso e di
uscita, sono presenti tre locazioni (AL, Mj e AQ, associate alla variabili i, j e x, e
le locazioni di memoria necessarie per memorizzare l’array a.
427
La complessità del calcolo
una quantità di tempo limitata, secondo il criterio di costo uniforme. Quindi, finché
si considera la notazione theta-grande, non bisogna preoccuparsi molto del valore
esatto delle costanti che denotano le complessità temporali delle singole istruzioni
di assegnamento.
2.1. Se (StatList) è la lista di istruzioni vuota, allora SMALM non effettua alcuna
operazione e T<statList> = 0.
2.2. Se (StatList)> è una (Stat) seguita da una (StatList), allora SMALM esegue
l’istruzione secondo le regole da 1 a 5 e, successivamente, esegue la lista di
istruzioni secondo la regola 2, applicata ricorsivamente. In questo caso,
T/statList) = T(stat) + ^statListy dove T(StatListy denota il tempo richiesto per eseguire
la lista di istruzioni nella parte destra della produzione.
La complessità del calcolo
Le regole per valutare 7)Cond> sono simili a quelle date nella Tabella p.3 per 7^^.
Un limite superiore per 7)CondStat> è dato da
7}cond) + max{ 7}cond)', 7}Cond) "}•
dove T (Whiiestat) è il tempo richiesto per calcolare la stessa istruzione while, dopo
l’esecuzione della lista di istruzioni.
Esempio 9.17
Applichiamo le regole precedenti ai programmi molto semplici di Figura 9.13.
1. L’esecuzione del programma SMALG numero 1, secondo il criterio di costo
uniforme, impiega un tempo
I\ = (1 + 1 + 1) + (1 + 1 + 1) + (1 + 1 + 1) + (1 + 1 + 1) + (1 + 1 + 1 + 1 + 1)
Secondo il criterio di costo logaritmico, impiega un tempo
7) < (1 + Z(5) + Z(5)) + (1 + /(IO ) + /(IO )) + (1 + Z(3 ) + 1(3)) + (1 + 1(5) + 1 +
Esempio 9.18
Si consideri il problema di verificare se, dato un array di n interi A e un intero x,
esistono in A due elementi che sommati diano x.
Consideriamo prima la seguente soluzione banale, che non fa nessuna ipotesi
suH’ordine in cui i valori appaiono in A:
{
output = 0;
i = 1;
while(i <= n){
j = 1;
while ( j <= n){
if(i != j){
if(A[i] + A[j] == x){
output = 1;
}
}
j = j + i;
}
i = i + 1;
}
}
La complessità temporale di tale algoritmo è, banalmente, 0(n2), se valutata con il
criterio di costo uniforme e diventa invece 0(n2log n), se valutata con il criterio di
costo logaritmico (in questo caso bisogna considerare oltre ai due cicli annidati
anche la dimensione dell’indirizzo delle celle in cui vengono memorizzati i valori
di A).
432 Informatica teorica
{
output = 0;
i = 1 ; j = n;
while(i != j){
if<A[i] + A[j] == x){
output = 1 ;
i = j;
1
else{
if (A [i] + A[j] < x) {
i = i + 1; '
1
else{
j = j - 1;
1
1
1
1 ,
Tale algoritmo ha al suo interno un solo ciclo che scorre tutto l’array, per cui la sua
complessità sarà 0(n), valutata con il criterio di costo uniforme, e 0(n log n),
valutata con il criterio di costo logaritmico.
Nella Sezione 9.4.1 si discuterà approfonditamente il problema
dell’ordinamento, mostrando che tale problema richiede almeno 0(n log n)
(criterio del costo uniforme) per essere risolto e che esistono algoritmi con tale
complessità. Questo suggerisce, che anche quando non si possono fare ipotesi
sull’ordine dei dati in A, è più conveniente ordinare l’array e poi cercare la coppia
di elementi nell’array ordinato, che cercare tale coppia direttamente.
■
ESERCIZIO
9.28 Si codifichino i programmi SMALG di Figura 9.13 come programmi RAM
e si faccia l’opposto per il programma RAM dell’Esempio 9.6 e 9.7 e
l’Esercizio 9.27.
Sia PR il programma RAM corrispondente al programma SMALG P. Si
verifichi che, se P ha complessità temporale 7>, allora TPR è 0(T?) e
viceversa.
433
La complessità del calcolo
{read(n)
while (i <= n){
read(a[i]);
i = i + 1;
1
while(i <= n){
x = a [i] ;
a [ 0] = x;
j = i - 1;
while(x <= a [ j]) {
k = j + 1;
a [k] = a [j ] ;
j = j - i;
1
k = j + 1;
a [k] = x;
i = i + 1;
1
i = 1;
while(i <= n){
print(a[i]);
i = i + 1;
1
Come annotazione preliminare, bisogna aver presente che tutte le unità di costo
esaminate sono “astratte”, poiché non si riferiscono ad alcun specifico ciclo
macchina reale. Quindi, se si desidera determinare il tempo assoluto di esecuzione,
bisogna avere a disposizione maggiori informazioni sull’implementazione delle
singole istruzioni e sulla velocità fisica del calcolatore. Abbiamo già osservato,
tuttavia, che la notazione theta-grande fornisce utili risultati di validità generale
sulla complessità; in particolare essa mette in luce il comportamento asintotico
dell’algoritmo. Cerchiamo quindi, come primo passo, una descrizione di T che in
prima approssimazione ne definisca l’ordina di grandezza. In un secondo passo, si
potrebbe decidere di raffinare l’analisi per ottenere almeno un limite alle costanti
contenute nell’espressione di T. Fondiamo l’analisi dell’algoritmo sulla sua
descrizione SMALG illustrata in Figura 9.16, riferendoci alla SMALM come
modello computazionale.
Il passo successivo è la scelta di un criterio di costo. Una breve occhiata al
programma rivela che i dati non aumentano significativamente le loro dimensioni
nel corso dell’esecuzione. Sia m = max{n, a[l], ..., a[n]}; se le celle di
memoria possono immagazzinare m, allora saranno in grado di memorizzare ogni
altra variabile del programma durante l’esecuzione. Inoltre, il programma non
contiene alcuna moltiplicazione. Il criterio di costo uniforme sembra quindi
un’ipotesi piuttosto ragionevole.
Siamo ora pronti per cominciare la vera analisi di complessità. Dapprima
osserviamo che, secondo il criterio di costo uniforme, tutte le istruzioni di
assegnamento, di lettura, di scrittura e di valutazione di condizione si possono
eseguire in un tempo limitato da una costante opportuna, come riportato nella
Tabella 9.4.
Seguiamo ora i passi dell’esecuzione del programma.
1. Viene speso il tempo = Ci prima di entrare nel primo ciclo.
2. Il primo ciclo viene eseguito esattamente n volte e richiede un tempo
ti — fi = n ■ (ù2 + C3) + Ci
3. Il secondo ciclo comincia all’istante fi = fi + c4.
4. Il secondo ciclo viene eseguito esattamente n - 1 volte.
Quindi, all’uscita del secondo ciclo, il tempo è
n
G = t3 + (c2 + c5 + tj + C8 ) + c2
i= 2
n
= t3 + (n- l)(c2 + c5 + c8) + c2 + fi7
i=2
dove t? è il tempo richiesto per eseguire il ciclo più interno all’i-esima
iterazione del ciclo esterno.
435
La complessità del calcolo
Per valutare t- , si noti che la condizione del ciclo interno può essere vera
al più i volte, poiché j è inizializzato ai- le viene decrementato a
ciascuna iterazione fino a quando raggiunge lo 0. A quel punto x = a [ 0 ]
e la condizione diventa falsa. Quindi, per ogni i, si ottiene
{i - z ■ (c6 + c7 ) + c6
Cosicché
n
n +1 ]
- <c6 + c7 ) • -------- «-1 +c6 '(«-!)
2 )
i=2
ESERCIZI
9.29 Si schematizzi una MT multinastro che implementa l’algoritmo di
ordinamento per inserzione diretta. Qual é il suo ordine di complessità?
9.30 Si può ottenere un ordine di complessità migliore impiegando, per il
problema dell’ordinamento, un’altra MT (senza necessariamente seguire la
traccia dell’algoritmo precedente)?
9.31 * L’esempio della Sezione 9.4.1 supponeva che n (la lunghezza del vettore
da ordinare) e m (il massimo dei valori immagazzinati nel vettore) fossero
valori indipendenti. Analogamente, l’Esempio 9.1 supponeva che n (la
lunghezza del vettore in cui effettuare la ricerca) e m (come prima) fossero
437
La complessità del calcolo
{ j = 1;
while(j <= n){
if(R[i, j] = 1) {
k = 1;
while(k <= n){
if (G[j,k] == 1) {
R[i,k] = 1;
}
k = k + 1;
}
}
j = i + i;
1
}
{ t = 1;
while(t <= mm){
i = SP[t] ;
j = TP[t];
while(h <= mm){
if(SP[h] == j){
k = TP[h];
inserire <v7, vk> in SP e TP
}
h = h + 1;
}
t = t + 1;
}
}
Figura 9.18 Una implementazione alternativa del passo 2.
440 Informatica teorica
{ r = 1;
found = 0;
while(r <= mm){
if(SP[r] == i){
if(TP[r] == k){
found = 1 :
}
}
r = r + 1;
}
if(found == 0){
mm = mm + 1 ;
SP[mm] = i;
TP [mm] = k;
}
}
Figura 9.19 Un’implementazione ulteriormente dettagliata del passo 2.
ESERCIZI
seguito di questa sezione, come sia possibile fornire un quadro molto generale
aH’intemo del quale si possono valutare e confrontare le complessità dei vari
modelli formali.
Cominciamo ad analizzare eventuali relazioni fra i risultati sulla complessità
ottenuti per i modelli RAM e MT (deterministica). A tale scopo, mostriamo come
sia possibile simulare una MT a k nastri mediante una RAM. Il modo più naturale
(si veda la Figura 9.20) consiste nel considerare la memoria della RAM come
divisa in blocchi, tutti di dimensione k, ad eccezione del blocco 0, che ha
dimensione k + 1, Il blocco 0 memorizza lo stato della MT, e le posizioni delle k
testine dei nastri di memoria. I successivi blocchi di k celle di memoria ciascuno
(blocco 1, blocco 2 ecc.) vengono impiegati per contenere i valori contenuti nelle
posizioni 1, 2 ecc. di ciascuno dei k nastri di memoria della MT. Quindi, il valore
rappresentato nella /-esima cella del /-esimo nastro della MT è contenuto nella
locazione c + k-j + i, dove c è una costante opportuna della memoria della RAM.
Inoltre, per accedere, in un dato istante, al valore presente sotto la testina di lettura
del nastro /«-esimo, è necessario compiere un accesso indiretto attraverso il blocco
0 per trovare il valore della posizione corrente della «z-esima testina. Infine,
l’esecuzione della funzione di transizione 8(7, i, Si,..., sk) e della funzione di uscita
q(<y, i, si,..., sk), richiedono un numero prefissato di accessi alla memoria della
RAM per accedere a q, sb ..., sk, un’operazione di lettura per accedere a z ed un
numero finito di test su questi valori per determinare 8 e q. Ciò conduce
direttamente al seguente teorema:
La complessità del calcolo 443
Enunciato 9.16
Una MT multinastro con complessità temporale TM può essere simulata da una
macchina RAM con complessità temporale TR = 0(Tw), secondo il criterio di costo
uniforme, o TR = &(TM - log TM), secondo il criterio di costo logaritmico.
■
La simulazione di una RAM mediante una MT è leggermente più complessa da
analizzare. Illustreremo il caso del criterio di costo logaritmico, che risulta molto
più ampiamente applicabile del criterio di costo uniforme, come si è visto nella
Sezione 9.3.1. Ulteriori commenti sul criterio di costo uniforme verranno fomiti in
seguito, dopo il Teorema 9.17.
Teorema 9.17
Sia L un linguaggio accettato da una RAM con complessità temporale TR secondo
il criterio di costo logaritmico. Se il programma RAM non usa le istruzioni MULT
e DIV, allora L può essere riconosciuto, da un’opportuna MT multinastro, in un
tempo limitato da una funzione TM = 0 (T/).
Dimostrazione
Si faccia corrispondere una RAM ad una MT nel modo seguente.
a. I nastri di ingresso delle due macchine sono isomorfi. Infatti, il nastro di
ingresso della RAM contiene una sequenza di interi appartenenti ad un
insieme limitato poiché, per ipotesi, la macchina opera come riconoscitore di
linguaggi. Il corrispondente nastro di ingresso della MT contiene, quindi, una
sequenza di simboli appartenenti ad un insieme di ingresso finito.
b. Poiché si stanno considerando le macchine in qualità di riconoscitori di
linguaggi, si ignorano, per il momento, i nastri di uscita.
c. La MT ha tre nastri (oltre al nastro d’ingresso 17).
c.l. Il primo nastro, Tb codifica i valori contenuti nella memoria RAM
secondo la seguente convenzione:
Sia I = {ij | j = 1 ,...,A} l’insieme degli indici tali che, ad un dato istante,
M[ij] risulti esplicitamente inizializzato, cioè l’insieme degli indici che
identificano celle di memoria per cui vi è stata almento un’operazione di
STORE. Il contenuto del nastro Ti della MT è mostrato in Figura 9.21.
Tale nastro contiene tutti gli elementi in I, ciascuno seguito dal contenuto
della cella di memoria corrispondente. Una cella di memoria viene,
quindi, rappresentata sul nastro Ti (si veda la simulazione descritta qui di
seguito) solo se, in essa, è già stato immagazzinato un valore in qualche
istante precedente. Il simbolo ‘$’ è utilizzato come delimitatore; in
particolare ‘$’ è usato per dividere un indice dal contenuto della cella
corrispondente, mentre “$$” è utilizzato per separare tra loro le diverse
444 Informatica teorica
$ $ ij $ M(ii] $ $ ‘k $ Af[it] $ $ «
Figura 9.21 Nastro che codifica i valori contenuti nella memoria di una RAM.
Lemma 9.18
La lunghezza della porzione non vuota del nastro Ti della MT è limitata da una
funzione 0(7}?).
Dimostrazione
Dapprima si noti che, all’inizio della computazione, sia la memoria della RAM che
i nastri di memoria della MT sono tutti vuoti.
Ciascuna istruzione della RAM modifica, al più, ima cella di memoria, ad esempio
M[h\, e il costo di questa operazione è almeno l(h) + (si veda la Tabella
9.2; può essere maggiore nel caso di un indirizzamento indiretto). Inoltre, la stringa
$$/z$Af[/z]$$ compare nel nastro Ti della MT solo se almeno un valore è stato
esplicitamente immagazzinato nella /z-esima cella di memoria della RAM. La
lunghezza di tale stringa è uguale a l(h) + l(M[h]) + 5 ed è minore di cx-th, dove th è
il tempo richiesto dalla RAM per memorizzare un valore in M[h] e cx è
un’opportuna costante. In conclusione, la lunghezza Li della porzione non vuota
k
un valore in Af[z}] (si veda la Figura 9.21) e dove c è una costante opportuna.
k
d è una costante opportuna. Ciò è dovuto al fatto che, per simulare un’istruzione
RAM, bisogna, nel caso pessimo, scandire l’intero nastro.
Poiché un’istruzione RAM costa almeno un’unità di tempo, se TR è la
complessità temporale della RAM, il numero di istruzioni RAM necessarie alla
simulazione non è maggiore di TR(n). Quindi, la complessità totale della
simulazione è limitata da una funzione ®(TR)-
■
Per quale motivo abbiamo limitato la dimostrazione del Teorema 9.17 (l’opposto
del Teorema 9.16) al caso particolare in cui viene applicato alla RAM il criterio del
costo logaritmico? Come si è detto, il criterio di costo logaritmico ha una validità
più ampia, rispetto al criterio di costo uniforme. Inoltre, il teorema vale solo nel
caso di costo logaritmico. Infatti, secondo il criterio di costo uniforme, una RAM
può calcolare numeri come 22 , per ogni n>0, in un tempo ®(rì). Una MT richiede
2” celle solo per memorizzarli e leggerli: la computazione richiede quindi almeno
0(2”) passi. Come conseguenza, non esiste alcuna relazione polinomiale fra le
complessità della RAM e della MT nel caso del criterio di costo uniforme.
Tuttavia, in tal caso è l’adozione del criterio di costo uniforme a risultare
irrealistica.
Per riassumere e generalizzare il precedente ragionamento, si stabiliscono i
seguenti enunciati.
Enunciato 9.19
La complessità della RAM, secondo il criterio di costo logaritmico, e quella della
MT multinastro sono correlate polinomialmente (ossia, se la complessità temporale
di un modello è 0(7), la complessità dell’altro è ®(P°T), dove P è una funzione
polinomiale9).
■
La dimostrazione è lasciata al lettore per esercizio.
Suggerimento-, Dapprima si generalizzi il Teorema 9.17 al calcolo di una
qualunque funzione intera. Successivamente si progettino i sottoprogrammi per la
MT che implementano le istruzioni MULT e DIV usando i sottoprogrammi di
ADD e SUB. Si verifichi che la loro complessità è correlata polinomialmente al
costo logaritmico di MULT e DIV.
Un risultato simile vale per la complessità spaziale ed è lasciato al lettore per
esercizio.
Esempio 9.19
Si consideri il linguaggio L = {vvclT w, JV e {a, è}* e IL la stringa che differisce
dalla stringa riflessa di w, w®, per al più 3 caratteri}. Tale linguaggio è chiaramente
cella di indirizzo i costa log(z). Questo esempio dimostra quindi che non sempre il
meccanismo di accesso diretto tipico della RAM risulta superiore, in termini di
complessità, al meccanismo di accesso sequenziale proprio della MT.
■
Correliamo ora le funzioni di complessità del modello SMALM con quelle dei
modelli RAM e MT. Come primo passo mostriamo come sia possibile tradurre un
generico programma SMALG in un programma RAM equivalente.
Sia Ps un programma SMALG. Esso può essere tradotto in un programma
RAM equivalente PR mediante la seguente procedura.
Come prima cosa, si definisce una biiezione fra la memoria della SMALM e
la memoria della RAM. Per motivi di semplicità, si supponga di conoscere a priori
che nessun indice di nessun vettore eccederà mai un valore N nel corso
dell’esecuzione. Successivamente si associa ciascuna variabile semplice di Ps con
una cella di memoria della RAM e ciascuna variabile vettore con una sequenza di
N celle di memoria. L’associazione viene fatta lasciando libere le celle Affi],
M[2] e M[3], che vengono utilizzate come memoria temporanea. Si indicherà con
i l’indirizzo della cella corrispondente alla variabile semplice i di SMALG. Si
indicherà con a l’indirizzo della prima cella della sequenza associata al vettore a.
Quindi, se due vettori a e b vengono immagazzinati consecutivamente, allora
b = a + N . Per ogni variabile x di Ps, x è un intero noto a priori.
Diamo allora un insieme di regole per costruire un programma RAM PR
equivalente ad un dato programma SMALG Ps. Sia X un non terminale della
X X
grammatica SMALG e sia Ps una porzione di programma tale che Ps .
La corrispondente porzione di PR si ottiene applicando le seguenti regole.
1. Valutazione delle espressioni.
• *
1.1. Se (Expr) =^> (SimpleVar) => x, dove x è un identificatore di variabile
semplice, allora si genera la sequenza
LOAD x
STORE 1
* *
1.2. Se (Expr) =^> (Const) =^> k, dove k è una costante, allora si genera la
sequenza
LOAD=k
STORE 1
» *
1.3. Se (Expr) =^> (ArrayVarld)[(Const)] =^> a\k\, dove a è un array
identificatore e k una costante, allora si genera la seguente sequenza
LOAD h
La complessità del calcolo 449
STORE 1
dove h è l’intero a +k-\.
Di nuovo, la traduzione degli altri casi per (AssStat) è lasciata al lettore per
esercizio.
3. Traduzione di istruzioni condizionali.
Se (CondStat) if f(Cond^) {(StatList^2}else{(StatList/}, allora si
genera la sequenza
P (Cond)
JZERO F
P \cond)
JUMP C
F: P 2(Cond)
C:
dove
450 Informatica teorica
ESERCIZI
9. 40 Si modifichi la precedente costruzione eliminando l’ipotesi che la
dimensione dei vettori sia limitata staticamente.
Suggerimento: Se un programma SMALG usa j vettori, allora si usano
blocchi di j celle consecutive della macchina RAM per memorizzare gli
elementi dei vettori che hanno lo stesso indice.
9. 41 Si traducano i programmi SMALG di Figura 9.13 nei corrispondenti
programmi RAM.
9. 42* (La soluzione di questo esercizio richiede qualche precedente esperienza
sulle tecniche di compilazione). Si trasformino le precedenti regole per la
traduzione di Ps in PR in un programma per calcolatore.
Un breve esame delle regole di complessità ricavate per SMALG nella Sezione 9.4
e delle precedenti regole di traduzione chiarirà al lettore le seguenti affermazioni.
Enunciato 9.20
Se un problema può essere risolto da un programma SMALG con complessità
temporale T$, allora esiste un programma RAM che lo risolve con una complessità
Tr = ®(TS).
451
La complessità del calcolo
Enunciato 9.21
Tutti i modelli computazionali, adottando ipotesi ragionevoli per le misure di
costo, hanno funzioni di complessità spaziale e temporale correlate
polinomialmente.
■
In altre parole, ogni problema risolubile da un modello computazionale con
complessità temporale T può essere risolto da ogni altro modello computazionale
con una complessità temporale ®(P°T), dove P è una funzione polinomiale. Questa
affermazione vale, ovviamente, solo se vengono impiegate ipotesi di costo
“ragionevoli”: come infatti si è osservato, il criterio di costo costante non è
ragionevole per il caso generale, in quanto suppone che sia possibile accedere ad
una quantità di informazione illimitata in un tempo prefissato.
In un certo senso, l’Enunciato 9.21 è il corrispettivo della tesi di Church per
quanto riguarda la complessità computazionale. Anche se non ci si può riferire ad
un unico modello computazionale per ottenere misure di complessità di validità
assoluta, si può perlomeno stabilire se un problema ha complessità polinomiale,
esponenziale o addirittura peggiore. Per convenzione, inoltre, si stabilisce che i
problemi aventi complessità maggiore della polinomiale siano, in pratica,
intrattabili. Come sempre, questa osservazione va considerata con una certa
cautela. Una complessità polinomiale di tipo nk, con k molto grande, si può
diffìcilmente considerare trattabile, nelle applicazioni pratiche. D’altra parte, vi
sono casi in cui, entro un intervallo di valori di n praticamente accettabili, Tip) =
k-n2 può risultare migliore di T-Jn) = h-n se h » k. Si ritornerà su questo punto al
termine della Sezione 9.9.
Esempio 9.20
Si consideri la versione deterministica gli automi a pila doppia, A2P, (si faccia
riferimento all’Esercizio 4.77), che sono come i tradizionali automi a pila
deterministici, ma sono dotati di due pile invece che di una. Una singola mossa di
tali automi dipende dal valore contenuto sulla cima delle due pile, oltre che dallo
stato corrente e dal simbolo in ingresso. L’automa, inoltre, opera sulle due pile
452 Informatica teorica
unaria per ri) per constatare che, rispetto a alla lunghezza della codifica del
dato in ingresso, la complessità dell’algoritmo risulta esponenziale.
Se si eliminano le operazioni MULT e DIV dal repertorio delle istruzioni
RAM, allora il Teorema 9.17 vale anche secondo il criterio di costo uniforme,
se si sostituisce ®(Tr) al posto di ®(Tr). Ciò si può dimostrare seguendo lo
stesso procedimento impiegato per il Teorema 9.17 e osservando che il
Lemma 9.18 rimane valido avendo cura di sostituire ®(7«2) al posto di ®(TR).
Questa osservazione conferma ulteriormente che MULT e DIV difficilmente
si possono considerare come operazioni elementari, almeno se si cercano
risultati di validità matematica generale.
I risultati precedenti (in particolare il Teorema 9.17 e le sue conseguenze)
sono stati ricavati considerando computazioni complete (ossia computazioni
che cominciano da una configurazione iniziale della macchina di calcolo in
cui la memoria è vuota). Ovviamente, per tali computazioni, T è almeno 0(«)
poiché, a parte i casi banali, bisogna leggere l’intera stringa di ingresso.
Quest’ipotesi, peraltro ragionevole, esclude tuttavia alcuni casi interessanti
illustrati nel seguente esempio.
La porzione di programma SMALG, presentata in Figura 9.22, risolve il
problema dell’appartenenza ad un vettore ordinato di lunghezza n (si veda
l’Esempio 9.2). Si usano i e j per delimitare la porzione x, del vettore,
attualmente in corso di esame. Il risultato della ricerca è z = 1 se esiste un
elemento del vettore uguale a y, altrimenti è z = 0. La complessità del
programma SMALG, secondo il criterio di costo uniforme, si può ricavare
facilmente: essa coincide, ovviamente, con il risultato ricavato informalmente
nel caso del programma Java dell’Esempio 9.2 (è 0 (log «)). Si analizzi ora la
complessità del programma precedente usando il criterio di costo logaritmico
e sotto l’ipotesi che, per ogni i, /(%[?]) < m, l(y) < m, per qualche costante
intera m. Si noti che l’esecuzione di k / 2 si può considerare come
un’operazione elementare, in quanto la sottostante SMALM può eseguirla
mediante uno scorrimento verso destra di una posizione della stringa di bit che
rappresenta k. Il tempo richiesto per eseguire il corpo del ciclo è ©(/(«)),
poiché i,j e k sono contenuti in mentre m è una costante. Il ciclo
viene eseguito al più /(«) volte, quindi la complessità temporale, secondo il
criterio di costo logaritmico, risulta pari a 0(log2(«)).
454 Informatica teorica
{ i= 1; j = n;
while(j <= j){
k = k + j;
k = k / 2;
if(y == x[k]){
i = k;
j = k - 1;
}
else{
if(y < x[k]){
j = k - 1;
}
else{
i = k + 1;
}
}
}
if(x == a[k]){ .
z = 1;
}
else{
z = 0;
}
}
Figura 9.22 Ricerca binaria in SMALG.
Teorema 8.22
Per ogni funzione totale e computabile T, esiste un linguaggio ricorsivo L che non
è in DTIME(T).
456 Informatica teorica
Dimostrazione
Anche la dimostrazione di questo teorema assomiglia alla dimostrazione del
Teorema 8.6: è una classica dimostrazione diagonale.
Dapprima si definisca un’enumerazione effettiva di MT multinastro, ad
esempio {Mi, i = 1,2,...}. Ciò si può ovviamente ottenere estendendo la tecnica di
enumerazione proposta nella Sezione 8.4.1. Analogamente, si consideri
*
un’enumerazione effettiva delle stringhe di VT .
Si definisca ora L = {x, | M, non accetta xf entro T(|x,-|) mosse}. Chiaramente L
è ricorsivo. Infatti, per stabilire se x, e L, è sufficiente simulare tutte le possibili
sequenze di computazione di M, la cui lunghezza non sia maggiore di T(|x;-|); tali
computazioni, fra l’altro, risultano finite.
Si supponga ora, per assurdo, che L sia in DTIME(T). Esisterà allora un z0 tale
che L = ), dove M,- ha una complessità temporale limitata da T. Ora, se
Xi e L , allora M accetta x - entro T(n^ passi, dove n0 = | x,- |. Quindi, per la
lo lo lo lo
definizione di L, x,- non è in L\ una contraddizione. D’altra parte, se x, g L,
allora M; non accetta x,- . Quindi, per definizione di L, Xj è in L: di nuovo una
lo lo lo
contraddizione. Entrambe le ipotesi conducono a contraddizioni, quindi la
complessità di M .■ non può essere limitata da T.
lo
■
I seguenti enunciati, anche se proposti come esercizi non troppo impegnativi al
lettore, stabiliscono alcune fondamentali proprietà nell’ambito della teoria della
complessità computazionale.
ESERCIZI
9.43 Si dimostri che il Teorema 3.22 sussiste anche per NTIME, DSPACE e
NSPACE.
9.44 Si dimostri che, per ogni/ DTIME(/) c DSPACE(/).
9.45 Si dimostri che, per ogni L in DSPACE(/), con fin)> log n, oppure in
NTIME(/), esiste una costante c tale che L sia in DTIMEfc^"/
Teorema 9.23
I linguaggi regolari sono una gerarchia infinita rispetto al numero di stati dei loro
AF riconoscitori. Più precisamente, per ogni n, esiste un linguaggio accettato da un
AF con n stati, ma da nessun AF con meno di n stati.
■
La dimostrazione del Teorema 9.23 è lasciata come esercizio per il lettore.
Prendiamo ora brevemente in considerazione la terza domanda sollevata in
precedenza, ossia se Tx(n) < T2(n), per ogni n>n, implichi la relazione
DTIME(Ti) c DTIME(T2). Si noti dapprima che, se per qualche c > 0,
T2(n) < c-T\(n), allora, per il Teorema 9.12, DTIME(Ti) = DTIMEfTV). Non ci
addentriamo ulteriormente in questo argomento. Informiamo soltanto il lettore
interessato che, per qualche T, può accadere che DTIME(T2) = DTIME(7), ma, “in
generale”, DTIME(7) c DTIME(TTog T). Per ulteriori informazioni su questo
argomento ci si può rifare alla bibliografìa consigliata alla fine del capitolo.
Rivolgiamoci, infine, all’ultima domanda sollevata all’inizio di questa
sezione, cioè chiediamoci come il non determinismo influenza la complessità. Tale
domanda verrà affrontata in una cornice specifica ma fondamentale. Si è affermato
che la complessità temporale polinomiale è stata convenzionalmente, ma
realisticamente, definita come il confine fra i problemi trattabili e quelli intrattabili.
Si definiscono ora:
00
NP = U NUME (n)
i=L
cioè la classe dei problemi risolvibili in tempo polinomiale da una MT
deterministica e la classe dei problemi risolvibili in tempo polinomiale da una MT
non deterministica, rispettivamente.
Ci si chiederà, a questo punto, se <P = 5V1P, cioè se il non determinismo non
influenza la complessità, almeno per la classe dei problemi considerati trattabili.
Questa domanda ha conseguenze enormi per la teoria della risoluzione di problemi.
Infatti, un gran numero di problemi di importanza pratica sono contenuti in 5MP.
458 Informatica teorica
quindi, 5V?Pse fosse uguale a <P, molti problemi interessanti risulterebbero trattabili.
Se ne fornisce un campione qui di seguito.
Teorema 9.24
Dimostrazione
Sia Wuna formula proposizionale contenente n occorrenze di m variabili logiche.
Quindi, m < n.
Si generi non deterministicamente una sequenza di m valori logici. Questa
operazione può essere compiuta in un tempo ®(zw) < ®(n) da una MT non
deterministica. Si sostituisca poi ogni occorrenza di A, con il suo valore. Ciò può
avvenire in un tempo ®(n-log rì), poiché bisogna leggere la stringa originale. Si
può tuttavia supporre che la stringa risultante, contenente solo i simboli T, F, -i,...,
), abbia lunghezza ®(n).
459
La complessità del calcolo
Se dunque <P fosse uguale a WL tutti questi problemi e molti altri si potrebbero
classificare come “trattabili”, rafforzando quindi la speranza di trovare, per essi,
algoritmi veramente efficienti. Sfortunatamente, anche se in letteratura gli sforzi di
dimostrazione in entrambe le direzioni si susseguono (il lettore interessato può fare
riferimento alle letture consigliate nelle note bibliografiche), la questione è ancora
aperta, ma il fatto che tutti i tentativi di trovare soluzioni polinomiali a tali
problemi siano finora falliti, suggerisce una risposta negativa alla domanda
generale. Inoltre, l’Esercizio 9.45 suggerisce, ma non dimostra, che il passaggio da
computazioni non deterministiche a deterministiche può richiedere, in generale, un
numero esponenziale di “tentativi”. L’importanza della questione viene
ulteriormente enfatizzata quando le si applica il concetto di riducibilità di un
problema, presentato qui di seguito.
Definizione 9.12
Un linguaggio Li è riducibile in tempo polinomiale ad un linguaggio L2 se e solo se
esiste una MT deterministica, di complessità limitata da un tempo polinomiale e
dotata di nastro di uscita, che, per ogni x, produce un’uscita r(x) tale che r(x) e L2
se, e solo se, x e Zi.
■
ESERCIZIO
9.46 Si mostri che la riducibilità in tempo polinomiale è una relazione transitiva.
Avvertimento: Se Li è riducibile a L2 in pfrì) e L2è riducibile a L3 in p2(n),
allora Li non è riducibile a L3 in pfri) + p2(n)l
Definizione 9.13
Sia L una classe di linguaggi. Un linguaggio L, non necessariamente in L, si dice
L-difficile rispetto alle riduzioni in tempo polinomiale se, e solo se, per ogni
L' e L, L' è riducibile in tempo polinomiale a L. Un linguaggio L è completo in L,
o L-completo (rispetto alle riduzioni in tempo polinomiale) se e solo se è in L ed è
L-difficile.
462 Informatica teorica
Teorema 9.25
SAT è W-difficile.
■
Dimostrazione
L’obiettivo della dimostrazione è di fornire una computazione deterministica che,
per ogni MT non deterministica M con complessità polinomiale p e per ogni
stringa x sull’alfabeto di M, tale che |x| = n, produca come uscita una formula
proposizionale W, in tempo polinomiale p'(ri), tale che W sia soddisfacibile se e
solo sex e L(M).
Il nocciolo della dimostrazione deriva dall’osservazione che, se x e L(M),
allora esiste una sequenza di mosse, la cui lunghezza non eccede p(ri), che conduce
ad uno stato di accettazione. Quindi, al più p(n) + 1 celle di memoria possono
essere utilizzate da M durante una simile computazione. Una volta compreso che
una configurazione di una MT ha uno spazio limitato, la si può descrivere mediante
un’opportuna formula proposizionale. Ad esempio, una variabile logica Qtyk può
stabilire se, all’istante t, lo stato di M sia qk. Un’altra variabile, CW£, può stabilire
se, all’istante t, la cella z-esima contenga il simbolo ak e così via. Inoltre, opportuni
connettivi logici possono imporre che, all’istante t = 0, la formula descriva una
configurazione iniziale, che la configurazione all’istante t + 1 derivi dalla
463
La complessità del calcolo
di variabili logiche, dove g è una funzione ®(p2). In breve, diremo che si sono
definite 0(p2(zz)) variabili.
Chiaramente, in ogni istante, M deve trovarsi esattamente in uno stato, la sua
testina deve essere esattamente sopra una cella e ciascuna cella deve contenere
esattamente un simbolo. In questo modo si ottiene un primo gruppo di
clausole (clausole di configurazione, CC) che le variabili logiche devono
soddisfare per descrivere le configurazioni di M.
Clausole di configurazione (CC):
464 Informatica teorica
A V Qt,k
0<t < p(n) ^0< £<|0|-1 ,
{M deve trovarsi in almeno uno stato alla volta}
A
A (-eU1v-gGÌ2)
0<t<p(n)
0<£,^2<|gH
A (~^Ct,i,h V ~'Ct,i,k}
0<t< p(n)
0<i< p(n)
0<h,k<\A\-l
h^k
{In ogni istante, ciascuna cella contiene esattamente un simbolo}
Riassumendo, CC contiene il seguente numero di clausole:
w«) + i)-iei + w«) + i)-iei-(iei -i)+
+ (p(n) + l)2 + (p(n) + l)2 ■ p(n) +
+ (p(n) + l)2 • \A\ + (p(n) + l)2 • \A\ ■ (|^| -1)
dove ciascuna clausola è l’“or” logico di un numero limitato a priori di
letterali, e ciascun letterale è o una variabile logica o la sua negazione.
Quindi, CC contiene 0(/23(n)) clausole e 0 (p3(fi)) letterali (si ricordi che |g| e
P<| sono costanti).
2. Descrizione della configurazione iniziale.
All’istante t = 0, M deve trovarsi in q0, la sua testina deve trovarsi nella
posizione 0 e x = 1) deve essere immagazzinata nelle prime n celle
del nastro. Tutte le restanti celle devono risultare vuote. Ciò produce un
secondo gruppo di clausole (Clausole della configurazione iniziale, IC), qui
elencate.
Qo,O A H0,0 A CO,O,ko A ••• A C0,77-1,k„_x A C0,7,0
77<7< p(77)
(si suppone che b sia a0)
IC ha ®(p(rìfi letterali.
3. Descrizione della configurazione di accettazione.
Si adotti la convenzione per la quale, se M si ferma all’istante tH < p(n),
allora mantiene la configurazione finale per tutti gli istanti t, tH < t < p(n).
Questa convenzione provoca conseguenze sulle transizioni della macchina che
verranno descritte fra poco, ma consente di stabilire che, all’istante t =p(ri), M
deve trovarsi in uno stato di accettazione. Ciò produce un’altra clausola
(Clausola di accettazione, AC) che è descritta di seguito:
@p(n},ix V V @p(n},is
dove {qn,...,qis} = F
AC ha 0(1) letterali.
4. Descrizione della relazione di transizione.
Infine, bisogna fornire le clausole che descrivono la transizione della
configurazione dall’istante t all’istante t + 1. La funzione di transizione sia del
tipo 8(qk,Sh) = {(qk-,Sh-Jd}}, con la convenzione che, ogni volta che la 5
originale di Mrisulta indefinita per qualche qk e per qualche s/,, si pone 8(qk,s/,)
= {(qk,Sh,S)}. Indichiamo con m la cardinalità di .
Tali clausole devono imporre:
4.1. Per ogni t e per ogni i, se M si trova nello stato qk, se la sua testina è nella
posizione i e se sta leggendo s^ allora, all’istante t + 1, M si trova, in
modo mutuamente esclusivo (utilizzeremo quindi il simbolo © per
indicare “OR esclusivo”), in una configurazione in cui lo stato è qk-, la
posizione i memorizza e la sua testina si trova nella posizione i,
oppure nella i + 1, oppure nella i - 1, in dipendenza da N, se e solo se la
tema (q^, s^, A).appartiene a 8(qk, sh).
Ciò è descritto dalla seguente formula logica:
466 Informatica teorica
®
fef+i.t"' A A Ct+i,i,h’" )
v t+i,i,h"' j
( —,Q,
^t,k. v —iHt,i
t . v-,C,.. ^~'t+l,K,„ v —,77,7 + 1,. z .„ v —iC,..
t ,J ,h v -,0,., *~'t+\,k A
. .„ v —,O
7 + 1,z,«
kvv ^<+1,;
(~>Q,.
z-'t,k v t,i ■ V -.C, .. v -.0
t,i,n z-'t + \,k. ... v —,777 + 1,7. .„ v —iC,,. . v ^t + lk „ ò
t + l,i,n
v -iH m v t+l,i
-iC t+l,i,h m . J
f^Q,
^t,kt v t,l• V -iC, .. v -,Q
t>l,h .,1 v-,C t+\,i>h „,v^g
^t+l,km 1 v —,77 t+l,i"' 1 ^t+\,km ò
0<t< p(n)
0<i< p(n)
0<k<\Q\-l
0< A<M|-1
che, ancora, si può riformulare nel modo seguente:
t,i v v ^t+l,i,h'
L’insieme TC di clausole relative alla transizione è definito come la
congiunzione delle formule derivate in 4.1 e 4.2. TC ha 0(p2(n)) letterali
(si noti che il numero di ‘ffi’ nelle clausole 4.1 è limitato a priori perché
così è la cardinalità degli insiemi {(qk-,sh',N)} e, di conseguenza, il
numero totale di clausole viene moltiplicato nella trasformazione in
forma normale congiuntiva per un termine che dipende - pur
esponenzialmente - solo da m).
Si pone, infine, W= CC a IC a AC a TC, che significa che W è la congiunzione di
tutte le clausole che appartengono agli insiemi precedenti. W ha quindi 0(p3(zz))
letterali.
468 Informatica teorica
Corollario 9.26
Il problema di stabilire la soddisfacibilità delle formule proposizionali in forma
normale congiuntiva è iNP-completo.
469
La complessità del calcolo
Dimostrazione
Se un problema è in W(P, ovviamente anche un suo sottoproblema si troverà in 5W.
Poiché la formula W, ricavata nella dimostrazione del Teorema 9.25, è in forma
normale congiuntiva, il corollario è già dimostrato.
■
La soddisfacibilità delle formule proposizionali è un risultato fondamentale
nell’ambito dei problemi W(P-completi. Da esso deriva che la -completezza di
una gran parte di questi problemi si può dimostrare, in modo naturale, riducendo
SAT ad essi, sia direttamente che indirettamente. Discutiamo ora un altro esempio
classico, cioè il problema dell’esistenza di un ciclo Hamiltoniano in un grafo (HC).
La dimostrazione dell’WCP-completezza di questo problema sfrutta la tecnica
appena descritta.
Teorema 9.27
HC è 5V?P- completo.
■
Dimostrazione
Poiché si è già affermato che HC è in %(P, bisogna solo mostrare che è %(P-
difficile. Ciò verrà ottenuto mostrando che SAT, in forma normale congiuntiva, è
riducibile in tempo polinomiale a HC. Per la transitività della riducibilità in tempo
polinomiale, ogni problema in sarà riducibile a HC. Naturalmente la riduzione
verrà ottenuta mediante una procedura che, per ogni formula proposizionale W in
forma normale congiuntiva, costruisce un grafo G che ammette un HC se e solo se
W risulta soddisfacibile.
Il procedimento consiste nel costruire G come aggregazione di due classi di
“pezzi”. I pezzi del primo tipo saranno associati a ciascuna variabile logica in W e,
in un certo senso, ne mostreranno tutte le occorrenze. I pezzi del secondo tipo
saranno associati a ciascuna clausola di IL e legati ai nodi che appartengono ai
pezzi del primo tipo, in modo tale che il loro attraversamento garantisca la verità
della clausola associata.
Prima di entrare nei dettagli formali della dimostrazione, illustriamone il
principio costruttore attraverso un semplice esempio. Si consideri la fbf W\
Ai a(—lTi v^2) e il grafo G di Figura 9.23.
I sottografi GAi e GA2 sono associati, rispettivamente, a Ai e A2. GCi e GC2
sono associati alle clausole C): Ai, C2: —Ai vA2. Chiaramente, Wrisulta soddisfatta
solo da Ai = T, A2 = T. Si consideri ora G. Un possibile HC per G deve
necessariamente attraversare IAi. Si noti che GC. impedisce ad HC la scelta di Fw
come nodo successivo, dopo aver visitato IAi. Infatti, dopo Fw, HC deve
raggiungere Lu (altrimenti diverrebbe inaccessibile) e poi . Tuttavia ciò rende
470 Informatica teorica
ESERCIZIO
9.47 Si costruiscano i grafi G, corrispondenti ai seguenti W,, tali che G, abbia un
HC se e solo se W, è soddisfacibile.
Wp. (AjvA2) a(AiV-A2)
fflp (Ai a A2v A-)) a(—A[VA2) a(—A2\/A-$)
W3'. (A] v —A2) a (—Ai v A2) a (—Ai v —A2) a (Ai v A2)
(a) (b)
(c)
Figura 9.24. La costruzione del grafo associato ad una fbf. (a) La parte
associata alla variabile logica Aj. (b) La connessione delle parti
{GAj}. (c) La parte GCj associata alla clausola C,.
474 Informatica teorica
Teorema 9.28
L’ordinamento di una sequenza di n elementi non ordinati richiede, nel caso
pessimo, almeno ®(n ■ log ri) confronti a coppie.
Dimostrazione
Sia A = la sequenza da riordinare. Un algoritmo di ordinamento deve
produrre una permutazione ordinata di A, ad esempio Ao = {a^,a;- },
effettuando un certo numero di confronti. Ad esempio, se A è già ordinata, sono
sufficienti n - 1 confronti, in quando è sufficiente stabilire che ax < a2, a2 < a3, ...,
-1 <
L’insieme di tutte le possibili esecuzioni di un algoritmo di ordinamento può
essere efficacemente rappresentato da un albero di decisione, in cui ciascun nodo
interno rappresenta un confronto, il suo figlio sinistro (rispettivamente, destro)
rappresenta la conseguenza del risultato positivo (rispettivamente, negativo), e
ciascuna foglia rappresenta la permutazione di A ottenuta come risultato dei
confronti. Quindi, un cammino dalla radice ad una foglia rappresenta tutti i
confronti effettuati daH’algoritmo per ottenere la foglia come risultato. La Figura
9.25 rappresenta un albero di decisione per l’ordinamento di 3 elementi,
applicando l’algoritmo di ordinamento per inserzione diretta fornito nella Sezione
8.3.
L’altezza dell’albero di decisione (ossia la lunghezza del più lungo cammino dalla
radice alle foglie) è il numero di confronti effettuati dall’algoritmo nel caso
peggiore.
Si noti ora che il numero di foglie per un simile albero è pari a ni, poiché
questo è il numero di possibili risultati diversi dell’algoritmo. L’albero di decisione
è un albero binario. Un albero binario di altezza h ha al più 2h foglie (si verifichi
questa affermazione come esercizio). Perciò, l’altezza di un albero binario con m
foglie è, almeno, uguale a log2 m. In conclusione, l’altezza di un albero di
decisione corrispondente all’esecuzione di un algoritmo di ordinamento deve
essere almeno pari a log(w!).
Infine 0(log ni) è almeno 0(wlog n) poiché, per n > 1,
n
( n) ( n)2
n\> n(n - l)(n - 2)... — > —
n I
e quindi log( /?!)>— log — , che è 0(w log n).
2 <2 )
D’altra parte, log( n!) = log n + log( n - 1) + ..., cosicché log(w!) < wlog(w).
Sono richiesti, quindi, almeno 0(wlog ri) confronti per ordinare n elementi. Se si
suppone che il tempo richiesto per effettuare un confronto sia costante e che la
quantità totale di tempo impiegata da un algoritmo di ordinamento sia
proporzionale al numero di confronti effettuati, allora si può stabilire il limite
inferiore 0(wlog ri) per gli algoritmi di ordinamento. Si noti che l’utilizzo di
confronti multipli, ma finiti, influenza solo la base del logaritmo.
Il lettore scettico potrebbe obiettare all’ipotesi che un algoritmo di
ordinamento debba necessariamente passare attraverso una sequenza di confronti.
In effetti quando ordiniamo un mazzo di carte possiamo usare anche un algoritmo
che non fa uso di confronti: ad esempio possiamo posizionare ogni carta “al suo
posto” (l’asso di cuori in posizione 1, il due di cuori in posizione 2 ecc.); tuttavia
estendere questa tecnica a insiemi in cui gli elementi da ordinare siano molti meno
delle “posizioni” ossia dei possibili valori degli elementi dell’insieme, già
preordinati (ad esempio un insieme di parole su un certo alfabeto) comporterebbe
un intollerabile spreco di spazio. Assumiamo perciò che un algoritmo di
ordinamento sia basato, tranne casi eccezionali, su un meccanismo di confronto.
Ciò giustifica l’affermazione che, in pratica, l’ordinamento richieda almeno un
tempo 0(wlog ri).
Si osservi che esistono diversi algoritmi, quali il Mergesort e l’Heapsort, che
sono in grado di risolvere il problema dell’ordinamento con complessità temporale
©(«■log ri). Il risultato del Teorema 9.29, garantisce che tali algoritmi non possono
essere migliorati e forniscono la soluzione migliore, in termini di complessità
asintotica, al problema dell’ordinamento.
479
La complessità del calcolo
Esempio 9.21
Si supponga di avere un array A contenente un insieme di n numeri interi tutti
distinti e disposti in un ordine non precisato. Consideriamo il problema di costruire
un albero di ricerca binario14, che contenga tutti gli elementi di A e sia bilanciato,
cioè abbia profondità minima.
Prima di provare a risolvere il problema, che non è di interesse per questo
testo, è piuttosto interessante chiedersi se sia possibile identificare un limite
inferiore alla complessità per risolvere il problema.
Si osservi che a partire da un albero di ricerca binario è possibile produrre una
sequenza ordinata del contenuto dell’albero mediante una semplice visita
dell’albero in pre-ordine sinistro. Tale visita ha costo lineare. È quindi intuitivo
dedurre che n log n costituisce un limite inferiore per il problema originale. Infatti
se si potesse costruire un albero binario di ricerca con costo inferiore a n log n,
sarebbe anche possibile risolvere il problema dell’ordinamento a costo inferiore,
ma abbiamo già dimostrato che ciò non è possibile.
14 Si ricordi che un albero binario di ricerca è un albero binario in cui per ogni nodo i valori
contenuti nel sottoalbero sinistro sono minori del valore del nodo stesso e quelli contenuti
nel sottoalbero destro sono maggiori.
480 Informatica teorica
dell’informatica teorica. Essi sono quindi al di fuori degli scopi di questo testo e
sono affrontati nell’ambito dell’ingegneria del software15.
ALTRI ESERCIZI
15 Ciò non significa che i vari modelli non abbiano radici matematiche in comune (ad
esempio la statistica) e che non possano o debbano essere usati in pratica in maniera
integrata.
482 Informatica teorica
3.2 0(/ì) < = 0(Zj) (ossiajS è ©(/))) < 0(4), fa non è confrontabile con ogni
z = 1, ..., 4.
3.17 Si consideri la costruzione schematizzata in Figura 9.6. Una MT a nastro
singolo M', che simula la MT 1-nastro M schematizzata in Figura 9.6b, può
avere il suo unico nastro organizzato come in Figura 9.26. La lunghezza
della porzione non vuota del suo nastro non eccede n + S!./n), con
S^n) < Tj^ri).
Quindi, la simulazione di una singola mossa di M da parte di M', richiede al
più n + S!./n) passi da parte di M', con Q(n + S^n)) < ©(T^ri)) se
IVn) >n. Quindi TM(rì) è 0 (T^- ).
Note bibliografiche
La complessità computazionale è un ramo relativamente giovane dell’informatica
teorica e non è stato ancora adeguatamente formalizzato in una cornice coerente e
sistematica. Mancano ancora molti anelli fondamentali e qualche risultato
matematico non presenta una validità assoluta, richiedendo un’interpretazione
piuttosto attenta. Tuttavia, la letteratura più recente sta facendo importanti
progressi in tutto il settore.
I risultati fondamentali, ormai classici, in questo campo sono presentati negli
scritti di Hartmanis e Stearns (1965) (Teorema dell’Accelerazione), Cook (1973)
(la gerarchia DTIME), Cook e Reckhow (1973) (il modello RAM), e Cook (1971)
484 Informatica teorica