Appunti di Elementi di Informatica Teorica

Transcript

Appunti di Elementi di Informatica Teorica
Appunti di Elementi di Informatica Teorica
by QuaDamge
A. A. 2006/2007
<ultima modifica 4 Novembre 2010>
si ringrazia Luke Bonham per gli errori segnalati e la realizzazione della dimostrazione del TEOREMA 3.2 (del contapassi)
–– INDICE ––
Linguaggi:
I Lezione (pag. 1) : Introduzione al Corso –– Alfabeti e Stringhe –– Automi
II Lezione
III Lezione
(pag. 5): Automi DFA –– Linguaggi Regolari –– Introduzione Automi NDFA
(pag. 8): Automi NDFA –– Relazione tra DFA ed NDFA (Teorema 2.1)
IV Lezione (pag. 14): fine Teorema 2.1 –– Proprietà di chiusura sui Linguaggi regolari
V Lezione (pag. 19): Altre Proprietà di chiusura –– Teorema di Kleene
VI Lezione (pag. 26): Espressioni regolari e teoremi
Seconda versione del Teorema di Kleene(prima parte)
VII Lezione (pag. 29): Seconda versione del Teorema di Kleene (seconda parte)
Pumping Lemma e teoremi conseguenti
VIII Lezione (pag. 34): Esercitazione sugli automi e le Espressioni regolari
Prima parte
Grammatiche:
VIII Lezione (pag. 37): Introduzione alle Grammatiche
Seconda parte
IX Lezione (pag. 39): Grammatiche C.F.: prime nozioni e teorema 1.2 (prima parte)
X Lezione (pag. 43): teorema 1.2 (seconda parte)
XI Lezione (pag. 46): Alberi di derivazione
XII Lezione (pag. 48): toremi sulle Derivazioni e gli Alberi di derivazione
Derivazioni estreme (a sx. e a dx.) –– Grammatiche Branching
XIII Lezione (pag. 52): teoremi sulla grammatica Branching e in Chomsky Normal Form –– Pumping Lemma
Proprietà di chiusura –– Grammatiche Ambigue e Grammatiche Regolari
XIV Lezione (pag. 57): Grammatiche Separatrici –– teorema sulla Grammatica Regolare –– Automi a Pila
XV Lezione (pag. 62): Esempi sugli Automi Pushdown e relativi teoremi
Prima parte
Calcolabilità:
XV Lezione (pag. 64): Introduzione ai Linguaggi di Programmazione –– S-programmi
Seconda parte
XVI Lezione (pag. 71): Ricapitolazione e seguito concetti sugli S-programmi
Funzioni parzialmente calcolabili –– estensione delle Macro
Predicati - composizione di Funzioni –– Ricorsione
XVII Lezione (pag. 79): Classi PRC –– Funzioni e Predicati primitivi ricorsivi
XVIII Lezione (pag. 86): Operazioni iterate e Quantificatori –– Minimalizzazione
altre Funzioni e Predicati primitivi ricorsivi
XIX Lezione (pag. 98): Codifica numerica dei Programmi
Interruzione di un Predicato e
problema dell’’insolvibilità dell’’arresto
XX Lezione (pag. 103): Teorema dell’’universalità –– Programma Universale
Insiemi ricorsivi, non ricorsivi e primitivi ricorsivi
XXI Lezione (pag. 112): Teorema della Forma Normale –– Minimalizzazione propria
Insiemi ricorsivamente enumerabili e relativi teoremi
Esercitazione finale (pag. 120)
Modifiche apportate (pag. 124)
Lettere greche utilizzate:
D alfa - E beta - J gamma - * gamma in maiuscolo - G delta - ' delta in maiuscolo H epsilon - Q ni - 3 pi in maiuscolo - V sigma - 6 sigma in maiuscolo - W tau ) phi in maiuscolo - \ psi - : omega in maiuscolo
Linguaggi
Prima Lezione
26/09/2006
Introduzione al Corso –– Alfabeti e Stringhe
Automi
Breve Introduzione
Il Corso di Elementi di Informatica Teorica si prefigge il compito di analizzare prevalentemente
problemi di:
DECISIONE
e di
GENERAZIONE
Al primo caso appartengono ad esempio problemi del tipo: ““x è un numero primo ?””, mentre al secondo appartengono problemi del tipo, ad esempio : ““qual è l’’ennesimo numero primo?””.
Nozioni di base –– Alfabeti e Stringhe
(rif. D.S.W. pag. 4)
DEFF.: l’’ALFABETO A è un insieme finito e non vuoto di simboli;
Dall’’alfabeto si generano le parole: la PAROLA o STRINGA su A: è una n-pla di simboli di A
Denotata così: a1 , a2 ,! , an o più semplicemente a1 a2 ! an .
Se u
a1 a2 ! an allora la LUNGHEZZA di u è n e si scrive:
u
n
e può essere vista come la funzione che, avendo come argomento u, restituisce la lunghezza di u.
PAROLA NULLA o STRINGA VUOTA: è la parola H o 0, la quale, come vedremo, è importante ad
esempio per le definizioni e dimostrazioni per induzione.
Risulta:
H
0 oppure 0
0
e
u0 0u u, u
(non bisogna fare confusione tra il simbolo 0, come stringa vuota, e 0, come numero zero).
L’’insieme di tutte le parole su A è denotato con
A
e si legge: ““A stella””, oppure ““A star””.
^a , b` allora A ^0, a , b , ab , ba , aa , bb , aab , bba , bbb ,...`
Il linguaggio A è infinito.
Se A
2
Con LINGUAGGIO si intende un sottoinsieme L di A :
L Ž A ,
quindi un linguaggio può essere infinito (a differenza dell’’alfabeto A).
Due linguaggi banali sono:
A e L
L
‡.
CONCATENAZIONE: se due stringhe u, v  A , con la scrittura:
l o semplicemente uv
uv
si indica la stringa che si ottiene ponendo (giustapponendo) la stringa v dopo la stringa u.
Un’’inferenza immediata (conseguenza della definizione appena data) è che:
uv
vu œ u v .
CONCATENZAZIONE REITERATA: se u  A , per convenzione si avrà:
u>1@
0 e u >n @
u , u >0@
uuu
!
uu , n t 0
n volte
n
(le parentesi quadre all’’apice [] possono anche essere omesse, avremo quindi u in luogo di u
u >n @
Risulta chiaramente:
SCRITTURA AL CONTRARIO: se u  A , u
uR
Risulta in particolare:
0R
>n @
).
n˜ u .
a1a2 ! an 1an , avremo:
an an 1 ! a 2 a 1 .
0 e, se u
a con a  A , u R
u.
Automi
(rif. D.S.W. pag 237)
Un AUTOMA finito, detto anche DFA (deterministic finite automaton), è una struttura matematica
che rappresenta un dispositivo (non necessariamente realizzabile nella pratica, non avendo infatti limiti,
essendo un concetto teorico) che ““prende in input”” una stringa, un simbolo alla volta, da sinistra a destra e cambia il suo stato interno, ovvero avvengono delle eventuali modifiche della struttura (nella pratica la dimensione dell’’input potrebbe essere un problema, data la complessità del problema in termini
di spazio e di tempo).
L’’esempio più semplice (e quello che si utilizzerà per i fini di questo corso) è quello di automa che
riconosce o meno un linguaggio, tale automa ““riceve in input”” parole di un determinato linguaggio e ““dà
in output”” due possibili valori: ““SI”” oppure ““NO”” (tali valori corrispondono allo stato in cui perverrà
l’’automa alla fine della lettura, tale concetto sarà chiaro a breve).
L’’input è rappresentato da una sequenza finita di simboli che può essere arbitrariamente lunga.
EDIT by Qd –– Linguaggi –– I Lez.
3
Formalmente
Q
un
^q1 , q2 ,!, qm ` ;
AUTOMA
FINITO
`
sull’’alfabeto
A
^s1 , s2 ,!, sn ` ;
con
Stati
F Ž Q detto Insieme degli Stati di Accettazione (o stati finali); q1 per convenzione
è lo Stato Iniziale; costituito dalla Funzione G detta di Transizione che associa ad ogni coppia qi , s j
uno stato qk :
G : Q u A o Q , con qi , qk  Q e
A,Q , F , q1 , G .
è la quintupla: `
1di dm
;
1d j dn
Nel caso dell’’esempio di automa che riconosce o meno una data stringa u, se alla fine della lettura
della stringa (partendo dallo stato iniziale), l’’automa si trova in uno stato q  F allora diremo che
l’’automa accetta la stringa u, se invece, alla fine della lettura di tutti i simboli di u, l’’automa perviene in
uno stato q  Q F , vorrà dire che l’’automa non ha accettato la stringa.
Esempio di automa finito ` :
A
^a , b ` , F
^q ` , Q ^q , q , q , q `
3
1
2
3
4
Dalla tabella di transizione (che rappresenta i possibili valori che assume la funzione di transizione) si
evince che se l’’automa si trova ad esempio nello stato q2 e riceve in input il
simbolo a, non cambia stato, analogamente succede quando si trova nello
a
b
G
stato q3 e riceve in input il simbolo b. Lo stato q4 invece rappresenta uno
q1
q2 q 4
stato trappola (o pozzo) in quanto, nel momento in cui l’’automa perviene
q2
q 2 q3
allo stato q4 ci resta per sempre, indipendentemente dal simbolo che legge.
q3
q 4 q3
q4
q4
a
q4
A destra la rappresentazione grafica dell’’automa `
appena descritto, mediante
grafi (la freccia sul cerchio dello stato q1 indica che quello è
lo stato iniziale, mentre il
doppio cerchio indica uno stato di accettazione:
a
q2
b
q1
q3
b
b
Ora che è stato definito
l’’automa ` verifichiamo, ad
esempio, che sia accettata la
stringa baba:
q4
a
G q1 , b q 4 , G q 4 , a q 4 , G q 4 , b q 4 , G q 4 , a q 4 .
Riscontriamo subito che q4  F , quindi baba non è accettata da ` .
EDIT by Qd –– Linguaggi –– I Lez.
b
a
4
Vediamo invece la stringa aabbb:
G q1 , a q 2 , G q 2 , a q 2 , G q 2 , b q 3 , G q 3 , b q 3 , G q 3 , b q 3 .
q3  F , quindi la stringa aabbb è accettata dall’’automa.
Nozione di G * :
Rappresenta un’’estensione della funzione G alle stringhe. È detta funzione delta stella ( o delta star) e
associa alla coppia qi , u lo stato qk  Q con qi  Q e u  A . Il simbolo qk rappresenta lo stato a cui
perverrà l’’automa su A dopo aver letto (partendo dallo stato qi ) tutta la stringa u simbolo dopo simbolo.
G :Q u A o Q da non confondere con G : Q u A o Q
A è l’’insieme delle stringe, mentre
A è l’’insieme dei simboli (alfabeto)
Definiamo ricorsivamente G :
x
passo base
G qi ,0 qi ;
ovviamente se l’’automa non riceve
nulla in input, cioè la stringa vuota,
il suo stato non cambierà, quindi
resta in qi
x
passo ricorsivo
G qi , v G G qi , u , s j se v
us j .
Per definire il passo ricorsivo per una generica stringa di lunghezza arbitraria non nulla, abbiamo spezzettato la stringa in due parti v us j dove u è una stringa (più piccola di v) ed s j è un simbolo
(l’’ultimo simbolo di v), se v
k, u
k 1.
Poiché G qi , u qk , possiamo benissimo sfruttare la G (che conosciamo) per passarle come argomen-
to G qi , u (il cui valore non è altro che uno stato) e il simbolo s j , quindi la scrittura G G qi , u , s j
è ben formulata, essa rappresenta in pratica lo stato a cui perverrà l’’automa quando avrà letto prima tutta la stringa u e poi il simbolo s j .
La definizione ricorsiva è ben posta in quanto ogni stringa può essere passata come argomento a G e,
nota la tabella di transizione dell’’automa, si sarà in grado di calcolarla ricorsivamente (la presenza di s j
ci assicura che G , nel passo ricorsivo, non riceva la stringa vuota).
EDIT by Qd –– Linguaggi –– I Lez.
Seconda Lezione
29/09/2006
Automi DFA –– Linguaggi Regolari
Introduzione Automi NDFA
Nell’’ambito degli automi, l’’aspetto implementativo non ci interessa, è invece importante approfondire l’’aspetto teorico, ci interessa studiare il funzionamento degli automi, ma non come potrebbero essere, nella pratica, realizzati.
Ricapitolando, un automa ` è costituito dall’’insieme A (alfabeto su cui opera), Q (insieme di
tutti i possibili stati dell’’automa, Q è un insieme finito), F (sottoinsieme -non proprio- di Q, rappresenta l’’insieme degli stati di accettazione, o finali, di ` ), uno stato iniziale q1  Q e una funzione G (di
transizione): Q u A o Q ,
q , s p
j
qk con q p , qk  Q e s j  A .
Ricordiamo che G qi , u (con u stringa di A ) denota lo stato al quale accede un automa finito
`
G , q1 , F Ž Q , A se si trova prima nello stato qi all’’estremità sinistra di u e poi quando ha completato la scansione di tutta la stringa (simbolo dopo simbolo), abbiamo:
G :Q u A o Q
x
passo base
G qi ,0 qi ;
x
passo ricorsivo
G qi , v G G qi , u , s j se v
us j
( G qi , u rappresenta lo stato di ` quando è stata letta tutta la stinga u).
Esempio sull’’uso di G :
G qi , v =
con v
s j , possiamo scrivere v come
stringa v
G qi ,0s j G G qi ,0 , s j Quindi :
0s j
G qi , s j G qi , v G qi , s j .
Linguaggi
L’’insieme L Ž A è detto linguaggio (in generale non è detto che A sia un linguaggio, un linguaggio a differenza del suo alfabeto può anche essere infinito, essendo un sottoinsieme di A ).
Si dice che un linguaggio è regolare se esiste un automa ` che lo accetta (cioè che accetta tutti e
soltanto i suoi elementi, ovvero tutte e soltanto le sue stringhe), un linguaggio accettato da ` si denota
con L ` e formalmente si scrive:
6
L `
^u  A
| G q1 , u  F `
G , q1 , F Ž Q , A .
con `
Ciò significa che il linguaggio L è accettato da ` se è costituito (soltanto) da tutte le stringhe u  A
per cui ` , partendo dallo stato iniziale q1 , giunge in uno degli stati finali di ` , qk  F .
Un linguaggio non è regolare se non esiste alcun automa che lo accetta. In pratica
L z L `
:œ u | G q1 , u  Q F
(quindi se vi è pure solo una stringa non accettata dall’’automa, il linguaggio L non è regolare.
TEOREMA: La regolarità di un linguaggio non dipende strettamente dall’’alfabeto, come mostrato da
quanto segue:
B
A
sia L Ž A e A Ž B allora vale la seguente equivalenza:
L è regolare, sia ` un automa che opera sull’’alfabeto A e che accetta L , abbiamo che L
œ ` c su B: L L ` c .
Ad esempio: se A
L `
^a , b` e B ^a, b, c` allora ` (su A): L ` œ L ` c , con ` c su B;
se chiaramente risulta L Ž A , F
^q2 `
abbiamo:
` c:
` :
a
a
q1
q1
q2
q2
c
b
b
c
a, b
a, b
q3
a, b
Vediamo un sistema generale per dimostrare la biiezione:
DIM.  : Vogliamo dimostrare che se ` c su B che accetta L Ž A Ÿ ` su A che accetta
L Ž A (restrizione di G su A). È banale mostrare che ` c accetta L Ž A se e solo se ` c perverrà
allo stato finale senza leggere simboli o stringhe che contengono simboli appartenenti a B A , altrimenti L z L ` , o anche L Ž A .
EDIT by Qd –– Linguaggi –– II Lez.
7
DIM. Ÿ : Vogliamo dimostrare che se ` su A che accetta L Ž A Ÿ ` c su B che accetta L.
Partendo da ` , basta trovare almeno un ` c su B che accetta L (espansione), quindi poniamo:
qi di `
G c qi , b q
e simbolo b  B A :
e
G c q , s q con q  F š s  B
Mentre le altre transizioni restano immutate rispetto a quelle dell’’automa ` .
q è un nuovo stato di ` c (che non deve essere di accettazione), esso rappresenta lo stato trappola a cui
perviene l’’automa ` c se prende in input un simbolo b  B A , quindi b  A (vedere esempio precedente). Di conseguenza ` c accetta lo stesso linguaggio di ` .
Automi Non Deterministici
(rif. D.S.W. pag. 242)
Partiamo con un esempio di Automa Non Deterministico (NDFA –– Nondeterministic Finite Automaton) per comprenderne la natura:
sia A
G
q1
q2
a
b
^q1 , q2 ` ^q1 , q3 `
^q `
^a , b` l’’alfabeto ed F
^q `
4
l’’insieme degli stati di ac-
cettazione, la funzione di transizione è un po’’ particolare ed è così descritta:
‡
Quando l’’automa NDFA perviene allo stato vuoto vuol dire
che non farà nulla, anche nell’’eventualità che la stringa venga letq3
^q4 `
‡
ta fino alla fine, però c’’è da dire che l’’NDFA ha la particolarità di
q4
^q4 ` ^q4 `
poter pervenire in nessuno, uno o più stati contemporaneamente,
cioè, se G è definita in un certo modo, l’’NDFA ha il potere di
percorrere più strade differenti allo stesso tempo. Quindi se ad un certo punto l’’NDFA perviene allo stato ‡ è probabile che possa proseguire per un’’altra strada. È importante notare che ‡ non è da confondere con il cappio visto nella rappresentazione grafica, in quanto l’’insieme ‡ indica che una determina4
ta strada dell’’automa è bloccata. Il cappio invece (ad esempio G ^q4 , a`
^q ` ) indica che l’’automa, ri4
cevendo in input il simbolo a, è rimasto sempre nello stesso stato, magari al passo successivo potrebbe
transitare in un altro stato, con un input differente.
EDIT by Qd –– Linguaggi –– II Lez.
Terza Lezione
3/10/2006
Automi NDFA
Relazione tra DFA ed NDFA (teorema 2.1)
Gli automi non deterministici sono un concetto teorico non realizzabile nella pratica, ma le sue
proprietà sono utili per risolvere dei problemi per i quali percorrendo certe strade lungo gli stati
dell’’automa, certi percorsi (rami) vengono scartati per prenderne altri (come si vedrà nelle dimostrazioni
di alcuni teoremi).
Diamo ora una definizione formale di Automa Non Deterministico:
su A con Q ed F è dato dalla funzione G (che è una funzione differente da quella utilizzata per gli automi deterministici DFA –– deterministic finite automata) definita così:
q , s o Q ,
i
j
con Qi Ž Q
i
G : Q u A o X
(quindi può essere anche ‡ )
X è l’’insieme delle parti di Q
^Qi | Qi Ž Q `
X
( X Ž Q , mentre Q  X ,
G qi , s j Ž Q , con Q i  X .
Se Q
^a , b` allora X ^‡, ^a` , ^b` , ^a , b`` .
Mentre prima, per i DFA, G qi , s j rappresentava uno stato, per gli NDFA G qi , s j rappresenta un insieme di stati. Quindi, in questo caso, una stringa sarà accettata dall’’NDFA se esso perverrà in almeno
uno degli stati di accettazione.
Formalizziamo quest’’ultimo concetto definendo prima la funzione G per gli NDFA, sempre ricorsivamente:
G : Q u A o Qi
x
G qi ,0 passo base
^qi `
ricevendo la stringa vuota l’’NDFA resta nello stato corrente (come il DFA) solo che dobbiamo sostituire a qi il suo singleton ^qi ` per come abbiamo definito G per l’’NDFA;
x
passo ricorsivo
G qi , w *
qG qi ,u G q, s j si prende l’’unione di tutti gli stati a cui perviene l’’NDFA alla fine della lettura di u con w
us j
( w k , u k 1 ). Dopodichè viene letto l’’ultimo simbolo. Alla fine della lettura di u l’’automa
non deterministico si troverà in uno o più stati, ecco perché è necessario l’’uso del simbolo di unione
* , per ogni stato a cui è pervenuto l’’NDFA viene letto l’’ultimo simbolo s j della stringa w, il risultato
finale è un sottoinsieme di Q, Q i Ž Q ( G
q ,u Ž Q
i
).
9
Analogamente ai DFA , stipuliamo q1 come stato iniziale dell’’NDFA.
Ora possiamo formalizzare che una stringa è accettata da un automa non deterministico su A se:
u  A , G q1 , u ˆ F z ‡
Ciò vuol dire che l’’automa non deterministico che accetta la stringa u alla fine della lettura dovrà trovarsi in almeno uno degli stati finali, ecco perché si richiede che l’’intersezione tra F e G q1 , u sia non
vuota (devono cioè avere almeno un elemento in comune).
Il linguaggio accettato da un
` (NDFA).
Da sottolineare che un
NDFA
DFA
è l’’insieme L `
costituito da tutte le stringhe accettate da
non è affatto un particolare tipo di
NDFA
differente: G DFA : Q u A o Q mentre G NDFA : Q u A o X , con X
in quanto la G ha condominio
^Q
i
| Qi Ž Q` .
TEOREMA 2.1 (rif. D.S.W. pag. 244): Un linguaggio L è accettato da un NDFA ` œ L è accettato da
un DFA ` ( L L ` ). Cioè L è accettato da un NDFA se e solo se L è regolare.
DIM.  : Vogliamo provare che se L è regolare allora L è accettato da un NDFA: ciò è immediato in
quanto si può definire la G NDFA ( qi , s j ) ^qk ` in luogo di G DFA ( qi , s j ) qk , possiamo anche scrivere
G
NDFA
( qi , s j )
^G
DFA
`
( qi , s j ) , l’’automa non deterministico avrà gli stessi stati (anche di accettazione)
dell’’automa deterministico. È chiaro che il linguaggio accettato dall’’automa deterministico è lo stesso
che accetterà l’’automa non deterministico.
DIM. Ÿ : Dimostriamo ora che se L è accettato da ` (dove ` è un NDFA), allora L è regolare,
cioè L L(` ) . Dobbiamo costruire un DFA che accetti il linguaggio accettato dal NDFA.
G è la funzione di transizione di ` , F è l’’insieme degli stati di accettazione
Q
^q1 , q2 , ! , qm ` l’’insieme dei suoi stati.
(F ŽQ ) e
Vogliamo provare che L(` ) L(` ) L .
Costruiamo un DFA ` sullo stesso alfabeto A di ` . ` avrà 2m stati, tale numero corrisponde a
tutte le parti di Q, cioè costruiamo un automa ` con gli stati, ognuno dei quali rappresenta un sot-
toinsieme di Q (insieme degli stati di ` ), incluso l’’insieme vuoto ‡ . Quindi l’’insieme degli stati di
` sarà Q ^Q1 ,Q2 ,!,Q2m ` ( Qi  X , X è l’’insieme delle parti di Q). Definiamo lo stato iniziale di
`
^q1` . Ora scegliamo l’’insieme degli stati di accettazione di ` ,
^Qi | Qi ˆ F z ‡` ( Y Ž Q ). Y è stato scelto in modo tale da contenere tutti quegli stati di DFA
come
Q1
Y
che contengono almeno un elemento (stato di NDFA) in comune a F (insieme degli stati di accettazione di ` ).
Definiamo ora la funzione di transizione di ` , G Q , s G q , s ( G : Q u A o Q , G ( q, s ) è un
i
*
NDFA
qQi
sottoinsieme di Q che quindi contiene nessuno, uno o più elementi (insieme di stati) di Q, a G(Q i , s ) viene associata
l’’unione degli stati a cui perviene `
EDIT by Qd –– Linguaggi –– III Lez.
quando questo si trova in uno degli stati q  Q i ).
10
A,Q , Y
`
Abbiamo dunque definito il seguente automa
, G,Q1 :
A è l’’alfabeto su cui opera anche ` ;
Q
^Q ,Q ,!,Q2 ` ;
1
m
2
^Qi | Qi ˆ F z ‡` ;
G Qi , s * G q , s ;
Y
qQi
Q1
^q1` .
Per continuare la dimostrazione è necessario enunciare il seguente
LEMMA 1 (il lemma è un teorema di importanza minore, o che comunque è utilizzato prevalentemente per la dimostrazione di teoremi più importanti): Sia R Ž Q (ricordiamo che Q è l’’insieme degli stati di `DFA ), si ha:
§
·
Qi , s ¸
*
¨ Q R
¸
© i
¹
G ¨
G Q , s *
Q R
i
i
Tale scrittura è corretta per il DFA da noi definito in quanto l’’unione di tutti gli elementi di R è ancora un elemento di Q (insieme degli stati di ` ).
Il lemma dice che il G dell’’unione di tutti gli elementi di R e di s è uguale all’’unione di tutti i G di
Qi  R e di s.
DIM.: poniamo:
Q * Qi
i R
Q
in pratica scegliamo R in modo tale che unendo
J
tutti i suoi elementi otteniamo l’’insieme Q
(R può assumere quindi varie conformazioni)
§
·
Possiamo quindi scrivere: G ¨ * Qi , s ¸ G Q , s ¨ Q R
¸
i
©
¹
D
Dalla definizione che abbiamo dato per G di ` DFA ( G Q i , s G Q , s * G q, s qQ
* G q , s ) possiamo scrivere:
qQi
stiamo applicando la definizione di G solo che al
posto di Q i scriviamo Q
EDIT by Qd –– Linguaggi –– III Lez.
11
Sfruttando J otteniamo:
G q, s * G q, s Q*R q*
Q
qQ
i
*
i
*
q
Qi
QiR
G q , s (l’’unione delle unioni di
G q , s con q  Q i e Q i  R
Riutilizzando la definizione di G si ha:
* * G q, s Q* G Q , s .
Qi R qQi
i
i R
E
Concludendo D
E ,ovvero:
§
·
Qi , s ¸ * G Qi , s .
*
¨ Q R
¸
© i
¹ Qi R
G ¨
Passiamo al LEMMA 2:
u  A ,
* G q, u .
qQ
G Qi , u i
Dc
Ec
Il lemma dice che, quando l’’automa DFA da noi definito si trova nello stato Qi e legge la parola u, la
funzione di transizione su stringhe G definita su ` DFA assumerà il valore corrispondente all’’unione di
tutti gli stati a cui perverrà l’’automa non deterministico ` NDFA quando si troverà in uno degli stati q
contenuti in Qi e quando legge la stringa u.
DIM.: il lemma si dimostra per induzione sulla lunghezza della parola u:
x
passo base: u
0 , quindi u
0 , si ha:
G ^Qi ,0` Qi
Dc
questa posizione è vera per la definizione del caso base di ricorsione della funzione G di un generico
automa finito (deterministico), si ha infatti;
possiamo esprimere Qi così: Qi
* ^q`
qQi
quest’’ultima è una banale inferenza, Q i è costituito dall’’unione di tutti i singleton degli elementi q appartenenti a Q i , da cui abbiamo:
G q ,0 * ^q` q*
qQ
Q
i
i
Ec
EDIT by Qd –– Linguaggi –– III Lez.
12
questa uguaglianza si ricava ricordando la definizione che si è data per G degli automi non determini
>
stico G
q , 0 ^q`@ , quindi l’’unione di tutti i
q  Q i sarà uguale all’’unione di tutte le G
q, 0 con
q  Qi .
Quindi per u
0 il lemma 2 è dimostrato:
G Qi ,0 * G q,0 .
qQ
Qi
i
Dc
Ec
Ipotizzando che il lemma 2 sia vero per u
x
passo d’’induzione: u
l (ipotesi di induzione), eseguiamo il seguente:
l 1 , poniamo u vs ( s  A ) dove v
G Qi , u G Qi , vs l , quindi è immediato scrivere:
Dc
e
G Qi , vs G G Qi , v , s si è applicata semplicemente la definizione di G per gli automi deterministici;
§
·
G q, v , s ¸
*
¨ qQ
¸
© i
¹
G G Qi , v , s G ¨
in quest’’ultima uguaglianza non si è fatto altro che sostituire G Q i , v con
* q, v , questi due
qQi
termini sono uguali per l’’ipotesi di induzione secondo la quale il lemma 2 è vero per v
l
(rammentiamo che dimostrare per induzione significa dimostrare il caso base, dopodichè presumendo vero
il passo k basta dimostrare che il passo k 1 è vero, quindi la dimostrazione è fatta).
Ora applichiamo il lemma 1 alla formula:
§
·
G q, v , s ¸
*
¨ qQ
¸
© i
¹
G ¨
nel lemma 1 abbiamo al posto di G
q, v G G q , v , s *
qQ
i
l’’insieme Q i , del resto G
q, v Ž Q
e risulta anche
G q , v  Q , proprio come Q i  Q , quindi Q i e G q , v fanno parte dello stesso insieme e quindi
su G
q, v è applicabile il lemma 1.
Ora, applicando la definizione di G per un DFA data nel teorema 2.1, otteniamo:
EDIT by Qd –– Linguaggi –– III Lez.
13
G G q , v , s *
*
qQ
qQ
*
i
i
rG q ,v G r , s r rappresenta uno stato, uno dei possibili stati raggiungibili dall’’automa non deterministico;
ricordiamo che G q , v Ž Q , G q , v  Q e G Q , s G q, s ,
*
i
qQi
per questo lemma applicare la G invece che a Q i a G q , v è legittimo in quanto G q , v come Q i
appartengono allo stesso insieme Q (sono della stessa natura);
applichiamo adesso (a ritroso) il passo di induzione della funzione di transizione G degli automi non
deterministici ( G q , us j * G q , s j ) si ottiene:
qG qi ,u *
qQ
*
i
rG q ,v G r , s * G q, vs ;
qQ
i
poiché avevamo posto u vs abbiamo:
G q, u .
* G q, vs q*
qQ
Q
i
i
Ec
Quindi:
G Qi , u Dc
* G q, u qQ
i
Ec
avendo dimostrato il lemma per u
EDIT by Qd –– Linguaggi –– III Lez.
l 1 , il teorema è dimostrato.
Quarta Lezione
10/10/2006
fine teorema 2.1
Proprietà di chiusura sui Linguaggi regolari
Al fine di dimostrare il teorema vediamo il terzo e ultimo lemma.
L `
LEMMA 3:
L `
In base a come abbiamo definito i due automi ` NDFA ed `DFA , il lemma 3 ci dice che il linguaggio accettato da ` è lo stesso che è accettato da ` .
DIM.: per come abbiamo definito l’’automa deterministico e per la definizione di stringa accetta da un
DFA abbiamo:
u  L ` :œ G Q1 , u  Y
Dal lemma 2 otteniamo:
G Q1 , u G ^q1` , u G q1 , u D cc
per come abbiamo definito lo stato iniziale di ` , Q 1 ^q1 ` ,
è a D cc che applichiamo il lemma 2: G Q i , u * G q , u , solo che in questo caso
Qi
Q1
^q `
1
qQi
che, essendo il singleton di q1 , è un unico elemento, quindi il simbolo * è inutile,
q1  Q 1 e q1 è l’’unico elemento appartenente a Q 1 .
Dobbiamo mostrare che u è accettato anche da `
niamo:
in modo biunivoco, dall’’ultima uguaglianza otte-
u  L ` œ G q1 , u  Y ,
u  L ` œ G q1 , u ˆ F z ‡
quest’’ultima biiezione è valida per come abbiamo definito ` e Y
^Q
i
| Q i ˆ F z ‡`
Dalla precedente biiezione, che è nient’’altro che la definizione di stringa accettata da un automa non
deterministico, deriva la seguente:
u  L ` œ u  L ` Ciò vuol dire che L `
rema 2.1.
L `
L il risultato che volevamo ottenere per la dimostrazione del teo-
15
Proprietà di chiusura (per i linguaggi)
(rif. D.S.W. pag. 249)
I linguaggi regolari sono chiusi rispetto a varie operazioni. Al fine di dimostrare alcuni teoremi relativi a queste proprietà definiamo il seguente:
DEF.: DFA Non Restarting (NRDFA), che è un automa finito deterministico che ha la seguente proprietà:
q , s | G q , s q1
In pratica l’’NRDFA non ripassa per lo stato iniziale (non esiste alcun stato q tale che l’’automa pervenga nello stato
iniziale q1 ).
TEOREMA 4.1: Dato un DFA `
si può costruire un NRDFA ` tale che L `
L ` .
Il teorema ci dice che un linguaggio regolare è accettato anche da un automa finito deterministico non
restarting.
DIM.: Costruiamo l’’NRDFA ` in modo che accetti L ` . Sia Q ^q1 , q2 ,! , qn ` l’’insieme degli
stati di ` con q1 lo stato iniziale, F l’’insieme degli stati di accettazione ( F Ž Q ) e G la funzione di
transizione.
Q è l’’insieme degli stati di ` (lo costruiamo con uno stato aggiuntivo rispetto a ` ):
Q ‰ ^qn 1 `
Q
con q1 lo stato iniziale,
La funzione di transizione di ` è così definita:
°­G q , s G q , s ®
°̄ qn 1
se
se
q  Q e G q , s z q1
e
q  Q e G q , s q1
G qn 1 , s G q1 , s L’’automa appena definito ha una funzione di transizione G che si comporta come la funzione G di
` , tranne che nei casi in cui l’’automa dovrebbe eventualmente transitare per lo stato iniziale q1 , infatti
se G q , s q la funzione G invece di far transitare ` in q , lo fa andare nel nuovo stato q .
1
1
n 1
Invece, quando ` si trova nello stato qn 1 si comporta come se stesse nello stato q1 , infatti si ha
G q , s G q , s .
n 1
1
Definiamo ora l’’insieme degli stati finali F di ` :
F
EDIT by Qd –– Linguaggi –– IV Lez.
se q1  F
­F
®
¯ F ‰ ^qn 1 ` se q1  F
16
Nel caso in cui `
ha tra gli stati di accettazione proprio lo stato iniziale q1 allora ` verrà indiriz-
zato verso qn 1 (ovviamente se, per ipotesi, abbiamo che `
dimostrato).
Da notare che non sarebbe corretto definire F
è non restarting, il teorema è banalmente
F ^q1 ` ‰ ^qn 1 ` in quanto è legittimo che ` pos-
sa avere tra gli stati finali proprio ^q1 ` , ad esempio quando viene letta la stringa vuota, nel caso questa
appartenga ad un linguaggio regolare, l’’automa non transita in alcuno stato e resta nello stato iniziale che
sarebbe anche quello di accettazione.
L’’automa ` così definito accetta lo stesso linguaggio di `
uno stato in più. Quindi L ` L ` c.v.d.
NRDFA
anche se non ripassa per q1 e ha
TEOREMA 4.2 * : se L e L sono due linguaggi regolari lo è anche L ‰ L .
DIM.: Senza perdere di generalità, per il teorema 4.1 si considerano per la dimostrazione due NRDFA
` ed ` che accettano rispettivamente L e L , tali automi operano sullo stesso alfabeto A, neanche
in questo caso si perde di generalità, infatti ricordiamo che il linguaggio riconosciuto da un automa non
dipende dall’’alfabeto utilizzato:
` NRDFA
A, Q , q 1 , F , G e
`NRDFA
A,Q , q , F , G ,
1
imponiamo inoltre che tali automi non abbiano stati in comune cioè (insieme degli stati disgiunti) :
Q ˆ Q ‡ .
Senza perdita di generalità (per il teorema 2.1) ora costruiamo un automa non deterministico che accetti
il linguaggio L ‰ L , `ˆˆ :
`ˆˆNDFA
Qˆˆ
l’’automa `ˆˆ ha gli stessi stati di `
stato iniziale qˆˆ1 ;
Fˆˆ
Qˆˆ , qˆˆ , Fˆˆ ,Gˆˆ, A 1
Q ‰ Q ‰ ^qˆˆ1 ` ^q1 , q1 `
ed ` tranne i loro stati iniziali q1 e q1 , `ˆˆ possiede un suo
­° F ‰ F ‰ ^qˆˆ1 ` ^q1 , q1 ` se q1  F o q1  F
®
altrimenti
°̄ F ‰ F
ed ` ad eccezione degli stati iniziali se presenti tra gli stati iniziali, questi due vengono rimpiazzati dallo stato iniziale di `ˆˆ
qˆˆ1 ;
l’’insieme degli stati finali F̂ di `ˆˆ è costituito da tutti gli stati finali di `
­°^G q , s ` se q  Q ^q1 `
Gˆˆ q , s ®
°̄^G q , s ` se q  Q ^q1 `
EDIT by Qd –– Linguaggi –– IV Lez.
17
la funzione Gˆˆ si comporterà come i due automi finiti non restarting ` ed ` , però essendo `ˆˆ
un automa non deterministico dobbiamo considerare i singleton nel condominio della funzione di transizione. Manca da definire la transizione dallo stato iniziale:
Gˆˆ qˆˆ1 , s ^G q , s ` ‰ ^G q , s `
1
1
quindi l’’automa `ˆˆ , leggendo s quando si trova nello stato iniziale transita contemporaneamente agli
stati in cui transiterebbero ` ed ` alla lettura di s partendo dagli stati iniziali q e q , graficamente
1
1
possiamo rappresentarlo così:
`
`ˆˆ
` ` `
È stato costruito un NDFA che è obbligato a seguire entrambe le strade di `
ed ` .
accetta entrambi (e soltanto) i linguaggi L ed L , quindi si può concludere che acL ‰ L , c.v.d.
cetta il linguaggio L `ˆˆ
L’’automa `ˆˆ
NDFA
Le condizioni Q ˆ Q ‡ e il fatto che gli automi da cui siamo partiti sono non restarting ci assicura
che `ˆˆ è obbligato a riconoscere unicamente L ‰ L .
TEOREMA 4.3: Se L Ž A ed L è regolare allora A L è regolare.
A
L
A L è il complemento di L rispetto ad A.
DIM.: Come al solito per dimostrare la regolarità di A L basta trovare un automa
finito che riconosca tale insieme. Partendo da un DFA ` su A con Q ed F scegliamo un DFA ` quasi identico a ` . ` accetta tutte le stringhe che ` rifiuta,
quindi abbiamo: F Q F (gli stati di accettazione di ` corrispondono a tutti gli stati che
non sono di accettazione per ` ), quindi il nuovo automa accetta A L .
EDIT by Qd –– Linguaggi –– IV Lez.
A L
18
Ad
F
` P Q ,q1 , G , F , A ,
esempio
^q ` , L ` ^b
3
^ a , b` ,
A
A
^0, a , b , ab , aab , !` , Q
`
>n @ > m @
^q , q , q ` ,
1
2
3
a b | n t 0, m ! 0
` :
a
b
q1
q3
q2
b
a
Mentre abbiamo: `
Q , q , G , F , A ,
1
Q F
F
^q , q ` :
1
2
` :
a
b
q1
q3
q2
b
a
`
È evidente che l’’automa
L `
A L
non accetta le stringhe del linguaggio L, ma accetta
^a , b , aa , bb , ba , baa , !`
^b
> n @ >m @
a
`
, n, m t 0 .
TEOREMA 4.4 : Se L1 ed L2 sono linguaggi regolari allora anche L1 ˆ L2 è regolare.
DIM.: Posto L1 , L2 Ž A , per le leggi di De Morgan vale:
L1 ˆ L2
(rif.D.S.W. pag. 2) R ‰ S
quindi,
applicando
L1 ˆ L2
A
A R ‰ S A A
L1 ‰ A L2 R ˆ S , nel nostro caso R L1 ed S
le
leggi
di
De
A > A
L1 ‰ A L2
@ .
L2 , R A L1 , S A L2
Morgan
abbiamo:
L1 e A L2 sono regolari per il teorema precedente (4.3, complemento); quindi, dal teorema
4.2 (unione) si ha che ª¬ A L1 ‰ A L2 º¼ è regolare; infine, riapplicando il teorema 4.3 otteniamo
che: A ª¬ A L1 ‰ A L2 º¼ è regolare. Quindi, essendo L1 ˆ L2 A ª¬ A L1 ‰ A L2 º¼ si
conclude che: L1 ˆ L2 L ` , c.v.d.
EDIT by Qd –– Linguaggi –– IV Lez.
Quinta Lezione
13/10/2006
altre proprietà di chiusura
teorema di Kleene
TEOREMA 4.5: ‡ e ^0` sono linguaggi regolari.
DIM. ‡ : Un automa che accetta L ‡ non ha stati di accettazione ( > L ‡ L ` @ œ > F ‡ @ ),
quindi qualsiasi stringa letta da un siffatto automa non verrà accettata perché non esistono stati di accettazione, quindi il linguaggio accettato è L ‡ .
DIM. ^0` : Per quanto riguarda L
proprio lo stato iniziale: F
^0` un automa che lo accetta è quello che ha come stato finale
^q1` , l’’automa non ha bisogno di leggere nulla per trovarsi nello stato di
accettazione, in quanto lo stato q1 , di partenza, è già di accettazione, quindi se legge la stringa vuota 0
non fa nulla e resta in q1  F . Chiaramente affinché l’’automa accetti solo la stringa vuota e nient’’altro
deve essere non restarting.
^u` è regolare.
TEOREMA 4.6: Se u  A allora L
DIM.: Se u 0 , dal teorema precedente abbiamo la dimostrazione.
Per un generico u a1a2 ! al al 1 con a1 , a2 ,! , al , al 1  A costruiamo un
la stringa u. Possiamo definire la funzione di transizione così:
­°G qi , ai ®
°̄ G qi , a ^qi 1`
‡
G qi , a con i
a1
q1
‡,
i z k ^ql 2 `
al 1
a2
q2
che riconosce soltanto
1,2,! , l 1 e a  A ^ai `
‡ œ G qi , a k F
NDFA
q3
ql 1
ql 2
L’’automa ““abortisce”” la computazione ( o ‡ ) se legge un simbolo che non è letto al momento giusto
ovvero quando i z k , mentre prosegue la computazione se i k fino allo stato finale ql 2 .
L’’NDFA appena costruito accetta il linguaggio ^u` , quindi ^u` L `
.
COROLLARIO 4.7: Ogni sottoinsieme FINITO di A è un linguaggio regolare.
20
DIM.: Per il teorema 4.5 se L ‡ allora L è regolare; se invece L è un qualsiasi sottoinsieme di A non
vuoto, L ^u1 , u2 ,!, un ` con u1 , u2 ,!, un  A allora, applicando il teorema 4.6 e 4.2, si ottiene la dimostrazione del corollario.
Infatti per il teorema 4.6 gli insiemi ^u1 ` , ^u2 ` ,! , ^un ` sono regolari; poi, per il teorema 4.2 si ha
che ^u1 ` ‰ ^u2 ` ‰ ! ‰ ^un ` è regolare, quindi il corollario è dimostrato.
Teorema di Kleene
(rif. D.S.W. pag. 253)
Esistono altre proprietà di chiusura di cui godono i linguaggi regolari rispetto ad operazioni nuove
che andiamo a definire:
DEF. (Concatenazione di linguaggi) < : siano L1 , L2  A , con la scrittura L1 <L2 indichiamo il linguaggio ottenuto dalla giustapposizione delle stringhe di L1 con L2 , quindi:
L1 <L2
^uv | u  L1
e
v  L2 `
Se L1 ed L2 sono insiemi finiti, ovviamente L1 < L2 è un insieme finito. Mentre se L1
h , L2
k al-
h ˜k .
lora L1 < L2
^u1u2 !un | n t 0, u1 , u2 ,!, un  L` .
DEF. L : sia L  A scriviamo: L
L chiaramente è sempre infinito e 0  L in quanto n può essere anche uguale a 0. Chiaramente se
L
A risulta L
A .
TEOREMA 5.1: se L ed L sono linguaggi regolari allora anche L <L è un linguaggio regolare.
DIM.: Coma al solito basta costruire un automa che accetti L <L per dimostrare il teorema.
Supponiamo che L L ` ed L L ` , quindi avremo due DFA:
` DFA
Q , q1 , F , G , A `DFA
Q , q , F , G, A e
1
con
Q ˆ Q
‡,
ricordando che la regolarità di un linguaggio non dipende dall’’alfabeto su cui opera l’’automa riconoscitore possiamo, senza perdere di generalità supporre che i due automi operino sullo stesso alfabeto A.
x
Sulla base degli automi ` ed ` costruiamo ora un automa non deterministico ` NDFA e facciamo
in modo che questo nuovo automa accetti il linguaggio L1 <L2 facendo sì che esso ““segua”” entrambe le
““strade”” degli automi `
EDIT by Qd –– Linguaggi –– V Lez.
x
ed ` . Definiamo le componenti dell’’automa ` :
21
x
Q ‰ Q ,
Q
x
q1
q1 ,
­^G q , s `
°°
®^G q , s ` ‰ G q1 , s ° °̄ G q , s x
G q, s ^
^
`
`
per q  Q F
per q  F
per q  Q
x
L’’automa ` NDFA in pratica, quando legge un simbolo, transita in altri stati ““seguendo il percorso”” di
` , nel momento in cui si trova in uno degli stati di accettazione di ` (cioè quando è stata letta tutta
una stringa appartenente a L ), il suo percorso si sdoppia, proseguendo eventualmente negli stati finali di
` e iniziando il percorso di ` sino al termine della lettura della stringa appartenente a L .
x
L’’automa `
quindi è stato costruito in modo da leggere prima le stringhe di L e poi quelle di L ;
x
dobbiamo però definire l’’insieme degli stati di accettazione di ` :
x
F
x
F
F ‰ F
se 0  L
F
se 0  L
Tale clausola è necessaria in quanto, ad esempio, parole del tipo u 0 con u  L e 0  L devono essere
x
riconosciute da ` , però per la definizione di G un NDFA (ma anche un DFA) non ““fa nulla”” se legge la
x
stringa vuota e poiché u 0
u, `
deve accettare anche parole di L, nel caso in cui L contenga la strin-
x
F ‰ F
se 0  L .
Mentre nel caso in cui 0  L , non ci saranno stringhe del tipo u 0 che l’’automa non deterministico do-
ga vuota, ecco perché F
x
vrà accettare, ecco perché è sufficiente imporre F
F
se 0  L .
x
` , per come è stato realizzato accetta il linguaggio L <L che quindi è regolare.
TEOREMA 5.2: Se L è un linguaggio regolare allora anche L è regolare.
DIM.: Ipotizziamo che L sia accettato da un NRDFA `
(per il teorema 4.1 l’’uso di un NRDFA non fa perdere di
generalità alla dimostrazione, inoltre l’’uso di un automa non restarting facilita la dimostrazione), con Q insieme degli
stati, q1 lo stato iniziale, F l’’insieme degli stati di accettazione ( F Ž Q ) e G la funzione di transizione,
costruiamo un automa non deterministico `
zione di transizione:
con Q
Q , q1
q1 ed F
^q ` , ora definiamo la fun
1
­°^G q , s `
se G q , s  F
°̄^G q , s ` ‰ ^q1 ` se G q , s  F
Gˆˆ q , s ®
In pratica laddove ` si ferma (quando finisce di leggere una stringa u  L ), `
per leggere ancora pezzi di stringa fatti da stringhe di L.
EDIT by Qd –– Linguaggi –– V Lez.
riparte d’’accapo
22
L’’automa ` appena realizzato accetta L , quindi tale linguaggio è regolare.
Abbiamo visto molti esempi per concludere che gli automi sono degli strumenti per dimostrare la
regolarità dei linguaggi.
TEOREMA 5.2 (di Kleene): Un linguaggio L è regolare œ L può essere ottenuto a partire da lin-
guaggi FINITI applicando un numero finito di volte le operazioni: *, <, .
DIM.  : la dimostrazione in questo senso è immediata. Bisogna infatti dimostrare che: se L è un linguaggio ottenibile da linguaggi finiti applicando un numero finito di volte gli operatori *, <, allora L
è un linguaggio regolare.
Dal teorema 4.7 si ha che ogni sottoinsieme finito di A è regolare, dai teoremi 4.2, 5.1 e 5.2 abbiamo
rispettivamente che l’’unione, la concatenazione e la stella sono operazioni che preservano la regolarità di
un linguaggio, quindi il teorema in questo verso è dimostrato;
DIM. Ÿ : Ora dobbiamo dimostrare che se L è regolare allora L è ottenibile a partire da linguaggi finiti
applicando un numero finito di volte le operazioni *, <, .
Supponiamo che L
L `
, sia ` un DFA con Q ^q1 , q2 ,! qm ` , stato iniziale q1 , insieme degli
stati di accettazione F, operante sull’’alfabeto A
^s , s ,!, s ` e G
1
2
p
la funzione di transizione.
Definiamo il seguente insieme:
Rik, j
^x  A
§ i, j ! 0 ·
| G q1 , x q j e tale che ` non transita attraverso stati ql | l ! k nell'esaminare x , ¨
¸
©k t0 ¹
`
Più formalmente possiamo dire che Rik, j è l’’insieme delle parole x
G qi , si1 q j1 ;
si1 si2 ! sir sir 1 tali che:
G q j1 , si2 q j2 ;
#
G q jr 1 , sir q jr ;
j1 , j2 ,!, jr d k
G q jr , sir 1 q j j ;
qi
In pratica l’’insieme Rik, j definisce tutte le
stringhe che fanno transitare un automa
dallo stato qi allo stato q j senza mai transitare per gli stati qk 1 , qk 2 ,! e così via.
qj
ql
l dk
- Interpretazione grafica del comportamento dell’’automa quando
legge una stringa di R -
EDIT by Qd –– Linguaggi –– V Lez.
Visto ciò possiamo dire che l’’insieme Ri0,i
è rappresentante di tutte quelle stringhe
che fanno transitare l’’automa dallo stato
qi allo stato qi stesso senza mai transitare
attraverso alcuno stato (visto che k 0 ). È
chiaro che esiste soltanto una stringa che
23
permette ad un automa di comportarsi in questo modo, la stringa vuota, quindi Ri0,i
0
i ,i
l’’automa non potrà transitare in alcuno stato, può solo stare in qi ), chiaramente R
0
i , j i z j Invece R
^0`
(poiché k
0
è un insieme finito.
è l’’insieme costituito da tutte quelle stringhe che fanno transitare l’’automa dallo stato
qi allo stato q j , ma poiché k
0 , l’’automa non potrà transitare in alcuno stato se non q j , quindi Ri0, j
sarà costituito da stringhe di lunghezza 1, cioè simboli (si ha di conseguenza che se
0
x  Ri , j i z j Ÿ x 1 š G q , x G q , s con x s  A ), quindi anch’’esso finito:
K è il q-
kappesimo
stato
R i z j ^a  A | G q i , a q j ` .
intermedio
Sottolineare che gli insiemi mostrati sono finiti è essenziale ai fini della dimostrazione del teorema,
come
0
i, j
vedremo a breve.
Da notare che con questa nuova notazione un automa potrebbe trovarsi, alla fine della lettura di una
stringa dell’’insieme Ri , j in uno stato q l con l ! k , il vincolo è riferito al fatto che l’’automa non deve
k
transitare durante la lettura dei simboli della stringa di R, ma all’’inizio e alla fine della lettura della stringa
potrebbe anche trovarsi in uno stato qualsiasi.
Possiamo scrivere una formula ricorsiva (avendo già visto il caso base Ri0, j ) che definisce Rik, j 1 in base a
insiemi di ““ordine minore””, abbiamo:
Rik, j 1
Rik, j ‰ ª« Rik,k 1 < Rkk 1,k 1 < Rkk 1, j º»
¬
¼
Tale formula può essere interpretata graficamente in questo modo:
qi
qj
Rkk1, j
k
i ,k 1
R
qk 1
R
k
k 1,k 1
Rik, j 1 può essere espresso mediante operazioni applicate a Rik, j che a sua volta può essere ricavato da
formule simili fino ad arrivare al caso base Ri0, j il cui contenuto è noto. Ribadiamo che Rik, j 1 rappresenta
l’’insieme di tutte quelle stringhe che fanno transitare ` dallo stato qi allo stato q j , ma che non transita attraverso stati qk 1 , qk 2 ,!
È utile sottolineare che non esiste un ordine tra gli stati, quindi j potrebbe benissimo essere minore di i,
è k che ci vincola a non scegliere stringhe che facciano transitare ` attraverso stati q k 1 , q k 2 , !
EDIT by Qd –– Linguaggi –– V Lez.
24
Rik, j invece rappresenta una parte dell’’insieme Rik, j 1 , infatti esso è costituito dalle stringhe che fanno
transitare `
dallo stato qi allo stato q j senza passare attraverso gli stati qk , qk 1 ,! Quindi Rik, j , a
differenza di Rik, j 1 , non farà passare l’’automa attraverso lo stato qk , stato invece consentito per Rik, j 1 .
Non bisogna fare confusione su quali sono gli strumenti necessari a costruire un insieme R, infatti è
dall’’automa, con la funzione di transizione, gli stati e l’’alfabeto che si parte per costruire l’’insieme R e non
viceversa.
In generale `
transita una volta attraverso qi e q j e un numero arbitrario di volte attraverso ql , con
l d k . In quanto, se k i j sicuramente `
dovrà transitare una sola volta per qi q j , mentre po-
trà transitare un numero arbitrario di volte attraverso stati ql con l d k .
Poiché manca lo stato qk 1 al fine di costruire l’’insieme Rik, j 1 , ottenibile mediante Rik, j , dobbiamo aggiungere a Rik, j un altro pezzo costituito da quelle stringhe, anzi da quei pezzi di stringhe che fanno
transitare l’’automa da qi a q j passando eventualmente anche per qk 1 . Possiamo dunque immaginare
la stringa x  Rik, j 1 divisa in tre parti: x u ˜ v ˜ w , dove u rappresenta la sottostringa di x che fa transitare mediante un numero finito di passi ` da qi a qk 1 ; mentre v fa transitare ` da qk 1 in se stesso
un numero arbitrario, ma finito, di volte (ecco perché si fa uso della stella); e infine w fa transitare ` da
qk 1 a q j sempre mediante un numero finito di passi (letture di simboli di w).
Il fatto che non si fa uso della stella nelle altre parti della formula dipende dal fatto che per la definizione
k 1
che abbiamo dato di Ri , j , se esistono, le stringhe di tale insieme devono far transitare l’’automa necessariamente dallo stato q i allo stato q j , più formalmente, rispettando la formula, da q i a q k 1 e poi da q k 1
k
q j , se applicassimo la stella a Ri ,k 1 e a
R k
k 1, j
Rkk1, j sarebbe consentito dire che
R k
i ,k 1
^0` e
^0` , ma in questo modo l’’automa non potrebbe mai transitare dallo stato qi allo stato q j .
Mentre è necessario l’’uso del simbolo di unione di Ri , j con Ri ,k 1 < Rk 1, k 1 < Rk 1, j perché potrebbero
k 1
k
k
k
esistere stringhe che non passano per q k 1 , facendo transitare l’’automa da qi direttamente in q j .
Dalla formula ricorsiva vista abbiamo il seguente:
LEMMA: Ogni insieme Rik, j può essere ottenuto da linguaggi finiti applicando un numero finito di
volte gli operatori *, <, .
DIM.: La dimostrazione deriva da quanto affermato poco fa. Procediamo per induzione su k :
x
k=0 : abbiamo visto prima che l’’insieme Ri0, j è finito;
x
k=r+1, presumendo che il lemma sia vero per k=r : la tesi del lemma è di nuovo data dalla
formula che abbiamo visto prima, si ha: Rir,j 1 Rir, j ‰ ª« Rir,k 1 < Rkr 1,k 1 < Rkr 1, j º» che è pro¬
¼
prio la tesi, infatti l’’insieme è dato dall’’uso di un numero finito di operazioni, ovvero una
volta l’’unione e la stella e due volta la concatenazione sull’’insieme Rir, j , che per ipotesi di
induzione è ottenibile da un numero finito di operazioni su linguaggi finiti.
EDIT by Qd –– Linguaggi –– V Lez.
25
Ritornando al teorema di Kleene, ricordiamo che dobbiamo dimostrare che se il linguaggio L è regolare,
allora esso è ottenibile da linguaggi finiti applicando su di essi un numero finito di volte le operazioni di
unione, stella e concatenazione.
Adoperando l’’insieme R visto prima, possiamo esprimere un linguaggio regolare L così:
L
L `
*
j !0 | q j F
R1,n j
Cioè stiamo considerando tutte le stringhe che fanno transitare l’’automa `
stati finali q j , n è una quantità che dipende dal numero di stati e risulta n t F .
dallo stato iniziale q1 agli
Ricorrendo al lemma precedente otteniamo la dimostrazione, infatti R1,n j è ottenibile da linguaggi finiti
applicando un numero finito di volte le operazioni di unione, stella e concatenazione, ciò è dato anche
dal fatto che l’’unione su R1,n j viene applicata un numero finito di volte, in quanto F è un insieme finito.
EDIT by Qd –– Linguaggi –– V Lez.
Sesta Lezione
20/10/2006
Espressioni regolari e teoremi
seconda versione del teorema di Kleene (prima parte)
Espressioni regolari
Il teorema di Kleene visto nella lezione precedente mette in relazione i linguaggi regolari con linguaggi finiti e le operazioni *, <, ; è possibile dunque dare, grazie ad esso, dei nomi ai linguaggi regolari. Ogni linguaggio è ““nominabile”” secondo quanto segue:
fissiamo un certo alfabeto A
^s1 , s2 ,!, sk ` ;
si vanno a considerare tutti i linguaggi regolari L ` , L Ž A ;
s , s ,! , s ,0, ‡, *, <, ,(, )
definiamo il seguente insieme: A
^
1
2
k
`
In pratica abbiamo definito l’’insieme A mediante elementi che rappresentano i simboli di A e le varie
operazioni, abbiamo dato un nome a tali simboli e a tali operazioni ( s1 si chiama s1 , ……, 0 si chiama 0 ,
ecc……).
Definiamo ora la classe delle espressioni regolari (rif. D.S.W. pag. 256):
per induzione diciamo che essa è un sottoinsieme di A con le seguenti clausole:
x
passo base:
1) ‡,0, s1 , s2 ,!, sk sono espressioni regolari;
x
passo induttivo:
2) se D e E sono espressioni regolari, allora lo è anche D ‰ E ;
3) se D e E sono espressioni regolari, allora lo è anche D < E ;
4) se D è un’’espressione regolare, allora lo è anche D ;
x
passo di chiusura:
(serve a escludere
tutti gli altri casi)
5) nient’’altro è un’’espressione regolare se non è stato ottenuto applicando
le clausole 1,2,3,4 un numero finito di volte.
per praticità omettiamo i trattini posti sotto alle parentesi ‘‘ ( ‘‘ e ‘‘ ) ’’
Quella appena data è una definizione sintattica, abbiamo inventato dei nomi (espressioni regolari)
adoperando i simboli: s1 , s2 , !, sk , 0, ‡, *, <, , (, ) . Ora diamo una denotazione semantica a quelle che
abbiamo battezzato: espressioni regolari:
sia J un’’espressione regolare, con l’’uso delle parentesi angolari ‘‘<’’ e ‘‘>’’ definiamo J ! che rappresenta un linguaggio regolare. Ecco che il simbolo J acquisisce un vero significato mediante l’’uso delle parentesi angolari ( J ! viene anche detto valutazione di J ).
27
Ecco alcuni esempi adoperando questa notazione:
^a , b, c` vengono definite mediante l’’insieme
le espressioni regolari sull’’alfabeto A
^a, b, c ,0, ‡, *, <, , (, )`
, 0 ‰ a < b , c < b .
A
e sono ad esempio: a < b ‰ c Si ha in base alle definizioni date per la classe delle espressioni regolari:
si
è un’’espressione regolare, mentre
si
è il linguaggio regolare denotato
dall’’espressione regolare si .
se J
si
^si ` , se J
allora si
0 allora 0
^0` ; se J ‡ allora ‡
^‡`
(si ottengono dalla clausola 1 della definizione di espressioni regolari);
D ‰ E se J
allora
D ‰ E D ‰ E
(si ottiene dalla clausola 2 della definizione di espressioni regolari);
D < E allora D < E se J
D < E
(si ottiene dalla clausola 3 della definizione di espressioni regolari);
D allora D se J
D
(si ottiene dalla clausola 4 della definizione di espressioni regolari, in questo caso le parentesi tonde non
sono necessarie in quanto la stella è un’’operazione unaria);
Quando J
L , sappiamo che J rappresenta L (cioè L ha il nome J , mentre J
L ).
Altri esempi (rif. D.S.W. pag. 257):
1)
a < b
‰c a < b ‰ c ^a` < b ‰ c ^a ` < b ‰ c
^a` < ^b` ‰ ^c` (nell’’ultima uguaglianza le parentesi angolari non sono più necessarie in quando non vi è alcuna espressione regolare da denotare)
Risulta:
^a` < ^b` ‰ ^c` L ` 2)
^ab> @ , n t 0` ‰ ^ac > @ , m t 0` ^w | w
n
m
`
ab >n@ , n t 0 › ac >m @ , m t 0 ;
0 ‰ a < b 0 ‰ a < b ^0` ‰ a < b ^0` ‰ a < b
^a`<^b`
(la stringa vuota può essere omessa in quanto è già inclusa nella stella nell’’espressione a destra
dell’’unione)
EDIT by Qd –– Linguaggi –– VI Lez.
28
Risulta:
3)
^a`<^b`
L `
^ ab >n @
`
|n t 0 ;
c < b c < b
Risulta: ^c` < ^b`
c < b
L `
^c` < ^b`
^c > @b> @ , n, m t 0` .
n
m
TEOREMA 5.4 (rif. D.S.W. pag. 257): Se L è un linguaggio finito allora c’’è sempre un’’espressione regolare
per L tale che J
L
DIM.: Dimostriamo il teorema per induzione sulla cardinalità del linguaggio, per le definizioni semantiche date prima valgono le seguenti biiezioni, rappresentanti i passi base dell’’induzione:
1.a) L
1.b) L
‡œL ‡ ;
^0` œ L 0 ;
1.c) L
^ x` , x
si1 si2 ! sim œ L
§s < s < s ! s ! · .
¨ i1 i2 i3
¸
im
©
¹
Ora, assumendo che il teorema valga per L
L k 1.
k (ipotesi di induzione), dimostriamo che vale anche per
L1 ‰ ^ x ` , con x  A ( L L1 ^ x` k 1 ), per l’’ipotesi
d’’induzione si ha che per L1 k esiste un’’espressione regolare D tale che D L1 , si ha inoltre che,
per il passo base (1.c) ^ x ` E , con E espressione regolare. Quindi, poiché L L1 ‰ ^ x ` possiamo otD ‰E tenere un’’espressione regolare J tale che J
L ( J
D ‰ E
L1 ‰ ^ x ` L ).
Quindi il teorema è dimostrato, infatti mediante il passo induttivo può essere costruito qualsiasi linguaggio regolare finito da cui ottenere un’’espressione regolare che lo denota.
Posto L1
k , possiamo scrivere L
TEOREMA 5.5 (seconda versione del teorema di Kleene –– rif. D.S.W. pag. 258): In base alle definizioni
sintattiche e semantiche date prima e in base al teorema precedente, il teorema di Kleene può essere
scritto in questo modo: Un linguaggio (non necessariamente finito) L Ž A è regolare œ vi è
un’’espressione regolare J tale che J
L.
DIM.  : È facile dimostrare il teorema da destra a sinistra, infatti, facendo uso del teorema di Kleene,
si ha che se esiste un’’espressione regolare J tale che J
L allora L è un linguaggio regolare. Infatti
J denota un linguaggio regolare ottenibile da linguaggi regolari finiti a cui sono applicate le opera-
zioni *, <, un numero finito di volte (è proprio ciò che ci dice il teorema di Kleene). Quindi J
guaggio regolare.
è un lin-
La dimostrazione segue alla lezione successiva
EDIT by Qd –– Linguaggi –– VI Lez.
Settima Lezione
24/10/2006
seconda versione del teorema di Kleene (seconda parte)
Pumping Lemma e teoremi conseguenti
DIM. Ÿ : Nell’’altro senso dobbiamo dimostrare che se L è regolare allora vi è un’’espressione regolare J
tale che J
L . Consideriamo l’’implicazione nel caso in cui L sia un insieme finito e poi nel caso in
cui sia infinito.
Se L è finito, per il teorema precedente esiste un’’espressione regolare J , tale che J
L , con L regolare.
Nel caso in cui L è infinito, si ricorre nuovamente al teorema di Kleene per il quale si ha che ogni linguaggio L (non necessariamente finito) può essere ottenuto dalla costruzione di linguaggi finiti ai quali
si applicano le operazioni *, <, un numero finito di volte. Quindi L può essere rappresentato da espressioni regolari e le relative operazioni, da cui deriva la dimostrazione del teorema.
Un grosso limite dei linguaggi regolari è che ne esistono vari che sono riconoscibili da un algoritmo,
ma non da un automa (in riferimento all’’entità di automa finito studiata fino ad ora, infatti esistono altri tipi di automa
più potenti che sono capaci di riconoscere una classe più vasta di linguaggi e non solo di quelli regolari visti sino ad ora, come
vedremo nella sezione delle grammatiche), quindi non sempre la costruzione di un automa ci aiuta a verificare
la regolarità di un linguaggio. Ecco che il PUMPING LEMMA ci viene in aiuto (rif. D.S.W. pag. 260):
TEOREMA 6.1: Sia L L ` , dove ` è un DFA con n stati. Posto x  L e x t n allora si può
scrivere x nella forma uvw, con v z 0 e il linguaggio L conterrà tutte le stringhe della forma:
x
uv >i @w  L, i
mo
0,1,2,! .
>0@
Da notare che è sì vero che v z 0 ma può succedere che compaia v , questo perché x può essere espresso come uvw, uvvw, uvvvw, ecc……, quindi avremmo u0w, u00w, u000w, ecc…… per un i arbitrario, se
v
>i @
0 la stringa u 0 w si potrebbe ““pompare”” all’’infinito indipendentemente dal valore assunto da i, ot>i @
tenendo sempre lo stesso risultato e cioè u 0 w
uw .
Da notare anche che poiché per ipotesi Q n e x t n , ` nella lettura di x transiterà per almeno
n 1 stati, non necessariamente distinti, anzi, sicuramente non potrà transitare per n 1 stati tutti distinti, in quanto ne ha solo n a disposizione, quindi ` transiterà almeno due volte per uno stato, questo
fatto rappresenta la chiave di volta per dimostrare il lemma.
DIM.: Il pumping lemma si basa sul principio della piccionaia (accennato poco fa), cioè, se abbiamo
n 1 lettere da distribuire in una piccionaia di n cassette, è ovvio che almeno una cassetta dovrà contenere almeno due lettere.
Le n 1 lettere corrispondono ai simboli della stringa x, mentre le n cassette della piccionaia corrispondono agli n stati dell’’automa ` . Dire che due lettere saranno poste in una cassetta corrisponde a dire
che l’’automa ` , nella lettura di x, transiterà almeno due volte in uno dei suoi stati.
In base a tale principio possiamo dunque scrivere il comportamento dell’’automa `
nella lettura di x:
30
­G q1 , u q
° ® G q, v q
°G q , w  F
¯
w
u
`
q1
q
qF
v >i @
qF  F
L’’automa leggerà prima la sottostringa u, che dopo una serie di transizioni, arriverà nello stato q alla fine
della lettura di u; nello stato q inizierà a leggere la stringa v, alla fine della lettura di v, l’’automa ` si
ritroverà nuovamente in q; da q l’’automa ` leggerà l’’ultima parte di x, cioè la sottostringa w che lo
farà transitare dallo stato q in uno degli stati di accettazione. Il teorema è dimostrato mediante tale
comportamento, infatti per v >i @ , con i
pre in uno stato di accettazione.
0,1,2,! il tragitto di `
nella lettura di x si concluderà sem-
Il pumping lemma è uno strumento molto utile a verificare la NON regolarità di un linguaggio, infatti non possiamo affermare che non esiste alcun automa che riconosce il linguaggio (è semplice trovare
uno o più automi che riconoscono un dato linguaggio regolare, per la precisione se esiste un automa ne esistono infiniti che
riconoscono un dato linguaggio regolare; cosa molto più complicata invece sarebbe quella di esibire gli infiniti automi che
NON riconoscono un dato linguaggio, al fine di dimostrare che esso non è regolare; è chiaro quindi che nel dimostrare che
un linguaggio non è regolare l’’automa non è uno strumento adatto al nostro fine).
Per dimostrare che un linguaggio non è regolare lo si fa per assurdo. Se il metodo diretto è il seguente: se (ipotesi) L ^! !` allora L non è regolare (tesi), la dimostrazione per assurdo prevede che neghiamo la tesi, quindi assumiamo che L sia regolare. A questo punto possiamo applicare a tale linguaggio il pumping lemma, esibendo delle stringhe del tipo x
uv >i @w con v z 0 e i t 0 . La contraddi-
zione si ottiene soltanto quando per tutte le stringhe u, v , w esiste almeno un i tale che uv >i @w  L . Da
cui si può affermare con certezza che L non è regolare. Tale risultato non può essere confermato nel caso
in cui non si riesca a trovare una terna di stringhe u, v , w tali che esista un i tale che uv >i @w  L (in tal
caso il pumping lemma non è più sufficiente a dimostrare la regolarità o la non regolarità del linguaggio, bisogna dunque ricorrere ad altri metodi). Il metodo appena descritto sarà chiarito più avanti con
un esempio molto importante.
TEOREMA 6.2 (rif. D.S.W. pag. 261): Sia `
ga x  L ` tale che x n .
un DFA con n stati, allora se L `
z ‡ esiste una strin-
Il linguaggio costituito da tutte le stringhe x con x n è ovviamente finito.
DIM.: Supponiamo che x sia la parola più piccola (lunghezza minima) accettata da `
( x  L ` | x n ). Dimostriamo il teorema per assurdo, negando la tesi, supponiamo quindi che se
L ` z ‡ allora esiste una stringa x  L ` tale che x t n . Ci sono dunque i presupposti per
applicare il pumping lemma, possiamo dunque scrivere x uvw , con v z 0 , e, se i 0 , esiste una
stringa uv >0@w uw  L ` , segue che uw uvw , cioè uw x e quest’’ultima disuguaglianza rappresenta un assurdo in quando avevamo ipotizzato che x fosse la stringa più piccola accettata da ` e
invece il pumping lemma ci dice che esiste una parola, più piccola di x, uw che è accettata da ` , cioè
appartenente a L ` , quindi il teorema è dimostrato.
EDIT by Qd –– Linguaggi –– VII Lez.
31
È utile mostrare un metodo che ci permetta di stabilire se un linguaggio accettato da un automa
` 1 è incluso nel linguaggio accettato da un automa ` 2 , cioè ci stiamo chiedendo se esiste un metodo che ci permetta di sapere se L ` 1 Ž L ` 2 . Per verificare ciò basta mostrare che un dato linguaggio L ` sia vuoto esprimendolo così:
L ` 1 ˆ A L ` 2 L `
Graficamente possiamo esprimere L `
A
L `
quindi si ha:
‡ œ L ` 1 Ž L ` 2 così:
A L ` 2 L ` 2 L ` 1 Come si può osservare A L ` 2 e L ` 1 sono disgiunti quindi L `
L ` 1 Ž L ` 2 .
Caso limite è L ` 1 L ` 2 , in questa circostanza abbiamo comunque L `
Al contrario, se avessimo scritto L ` 2 Ž L ` 1 , avremmo avuto L `
dal grafico:
A
è vuoto, difatti
‡.
z ‡ , come si può vedere
A L ` 2 L ` 1 L ` 2 TEOREMA 6.3 (rif. D.S.W. pag. 261): Se L
L `
u, v , w  A con v z 0 , tali che uv >i @w  L con i
è un insieme infinito allora vi sono stringhe
0,1,!
A differenza del pumping lemma, ci siamo ora svincolati dal numero di stati di ` e dalla lunghezza di
x. Tale teorema è utile per verificare se certi linguaggi infiniti non sono regolari. Infatti basta cercare delle
stringhe del tipo x che non appartengono al linguaggio come visto prima.
TEOREMA 6.4: Sia ` un DFA con n stati, si ha che L `
contiene parole x (ne contiene almeno una) tali che n d x 2n .
EDIT by Qd –– Linguaggi –– VII Lez.
è un insieme infinito œ L ` 32
DIM.  : La dimostrazione in questo senso è banale e si ottiene mediante il pumping lemma. Si deve
dimostrare che se L ` contiene parole x, tali che n d x 2n allora L ` è un insieme infinito.
Sussistono le ipotesi per applicare il pumping lemma, infatti abbiamo un linguaggio regolare L ` ,
un DFA con n stati e la stringa x ha lunghezza pari o maggiore di n. Esiste dunque stringhe x uv >i @w ,
con v z 0 e i 0,1,2,! La non finitezza di L ` è diretta conseguenza del pumping lemma, infatti
se esiste una x uv >i @w , con v z 0 e i 0,1,2,! x si può pompare a piacere al variare di i, quindi
L ` conterrà stringhe (non sono tutte così) del tipo uw, uvw, uvvw, uvvvw, …… quindi L ` è
infinito.
DIM. Ÿ : Ora dobbiamo dimostrare che: dato un L ` infinito allora L ` conterrà parole
x | n d x 2n . Abbiamo che, poiché L ` per ipotesi è infinito, esisteranno certamente parole
x | x t 2n , scegliamo una stringa di lunghezza minima lunga almeno 2n, essendo tale stringa x t 2n
la si può certamente scomporre in due pezzi (è chiaro che ` ha almeno uno stato, quindi n t 1 ). Quindi
x x 1 ˜ x 2 , posto x 1 n abbiamo di conseguenza x 2 t n poiché abbiamo fissato x t 2n , allora, per il
principio della piccionaia visto per la dimostrazione del pumping lemma, abbiamo che x 1 uvw .
Nel pumping lemma non è specificato, ma u e w possono essere anche stringhe vuote, è soltanto su v
che c’’è il vincolo di v z 0 .
­G q1 , u q
°
Possiamo dunque scrivere: ®G q , v q
°G q , w ˜ x  F
2
¯
w ˜ x2
u
`
q1
q
qF
con 1 d v d n .
Quindi, poiché la lettura di v genera un cappio, possiamo dire che uwx 2 è una stringa accettata da ` ,
uwx 2  L ` , G q1 , uwx 2  F . Certamente risulterà
uwx 2 t x 2 t n , poiché x 2 t n . Inoltre, poiché abbiav
mo costruito x x 1 x 2 , con x 1 uvw e 1 d v d n , ovqF  F
viamente risulterà uwx 2 x (strettamente minore in quanto
nella parte sinistra della disuguaglianza, manca la v che certamente non è una stringa vuota). Ricordando che si era ipotizzato x quale stringa più piccola, di lunghezza non minore di 2n ( x t 2n ), risulterà dunque
uwx 2 2n e uwx 2 è una parola accettata da ` , ma x avevamo stabilito che fosse la più piccola parola di lunghezza non minore di 2n e di conseguenza una stringa più piccola di x deve necessariamente risultare di lunghezza strettamente minore di 2n e poiché uwx 2 x e uwx 2 t n avremo che
n d uwx 2 2n . In definitiva uwx 2 rappresenta la stringa appartenente al linguaggio L che soddisfa la
tesi.
Il teorema appena mostrato rappresenta un valido metodo (algoritmo) per verificare che un dato linguaggio regolare sia finito o meno, basterà infatti trovare una stringa x tale che, se ` ha n stati,
n d x 2n .
>i @
Il pumping lemma fornisce come avevamo già detto un metodo per verificare la non regolarità di un
linguaggio. Ad esempio (rif. D.S.W. pag. 262) si può dimostrare che il linguaggio L
EDIT by Qd –– Linguaggi –– VII Lez.
^a > @ ˜ b> @ | n ! 0` non
n
n
33
è regolare (cioè non esiste nessun automa che accetta esclusivamente le stringhe di tale linguaggio e null’’altro, inoltre a e b
devono essere visti come stringhe costituite da un solo simbolo).
L ` . Supponiamo che ` abbia m stati. Per il pumping
lemma L è infinito, inoltre esiste una stringa x, con x t m , x uvw e v z 0 , abbiamo che
DIM.: per assurdo supponiamo che L
^uv > @w | i t 0` Ž L . Posto
i
che x
uvw
x
a >l @ ˜ b >l @ , risulta a >l @ ˜ b >l @
2l e, poiché x t m , 2l t m . Quindi dire
a >l @ ˜ b >l @ vuol dire che v deve essere della forma a >l1 @ oppure della forma a >l1 @ ˜ a >l2 @ oppure
ancora b >l2 @ con, necessariamente, l 1 , l 2 d l . In tutti è tre i casi la stringa x  L `
, in quanto essa
non può avere lo stesso numero di a e di b. Infatti, nel caso in cui v a >l1 @ , per il pumping lemma, avremmo u ˜ v ˜ w  L ` , ma anche u ˜ v ˜ v ˜ w  L ` , che non potranno mai avere lo stesso numero di a e di b (se ce l’’ha la prima, non può averle la seconda e viceversa); analogamente succede per v
invece, nel caso in cui v
b >l 2 @ ;
a >l1 @ ˜ b >l2 @ si avrebbero stringhe del tipo u ˜ a >l1 @ ˜ b >l2 @ ˜ w , ma anche
u ˜ a >l1 @ ˜ b >l2 @ ˜ a >l1 @ ˜ b >l2 @ ˜ w che certamente non sono stringhe accettate da ` .
Avendo esibito tutti i possibili casi in cui x può presentarsi e (per ciascun caso) esiste almeno un valore di l per cui x  L , si conclude che certamente L
^a > @ ˜ b> @ | n ! 0` z L `
n
n
.
È importante ribadire che esistono sì automi che accettano, tra le tante, stringhe del tipo visto poc’’anzi,
ma non esistono automi che accettano ESCLUSIVAMENTE tutte le stringhe appena viste, questo ci basta per dire che l’’automa non accetta il linguaggio. Un automa che riconosce un dato linguaggio L deve
appunto riconoscere le stringhe di tale linguaggio e soltanto quelle (non deve riconoscerne altre).
EDIT by Qd –– Linguaggi –– VII Lez.
Ottava Lezione –– prima parte
27/10/2006
esercitazione sugli Automi e sulle Espressioni regolari
Esercizi proposti tratti dal libro di testo:
(rif. D.S.W. pag. 241, esercizio 1 b)
Mostrare che il linguaggio L è regolare costruendo un automa finito `
^a , b` , L consiste in tutte le stringhe che terminano per bbab.
L ^bbab , a ˜ bbab , b ˜ bbab , ab ˜ bbab , ba ˜ bbab , !`
A
A,Q , q1 , F ,G Costruiamo l’’automa in questo modo `
dove Q
che lo accetti.
^q , q ,!, q ` ,
1
2
5
F
^q ` e la
5
funzione di transizione è la seguente:
G
a
b
q1
q1
q2
q2
q3
q1
q4
q3
q4
q1
q5
q5
q1
q3
q3
b
a
a
b
b
q2
q1
b
q4
q3
a
q5
b
a
a
(rif. D.S.W. pag. 241, esercizio 1 h)
Mostrare che il linguaggio L è regolare costruendo un automa finito `
che lo accetti.
^a , b` , L consiste in tutte le stringhe che contengono 3 a consecutive.
L ^aaa , b ˜ aaa , aaa ˜ b , ab ˜ aaa , aaa ˜ b ˜ aaa ˜ aaa , !`
A
A,Q , q1 , F ,G Costruiamo l’’automa in questo modo `
dove Q
^q , q , q , q ` ,
1
2
3
F
4
funzione di transizione è la seguente:
G
a
b
q1
q2
q1
q2
q3
q3
q1
q4
q1
q4
q4
q4
a
b
a
a
a
q1
q3
q2
b
q4
b
b
^q ` e la
4
35
(rif. D.S.W. pag. 241, esercizio 1 i)
Mostrare che il linguaggio L è regolare costruendo un automa finito `
che lo accetti.
^a , b` , L consiste in tutte le stringhe che NON contengono 3 a consecutive.
L ^a , aa , ba , aab , abaa , aababbba , !`
A
L’’automa ` i è simile a quello visto nell’’esercizio precedente (1.h) salvo che per l’’insieme Fi che
rappresenta il complemento rispetto a Q di F, quindi Fi
Q F
^q , q , q ` . In pratica tutte le strin1
2
3
ghe che accettava l’’automa ` non saranno accettate dall’’automa ` i . Questa soluzione è stata trovata in modo immediato partendo dall’’esercizio precedente (ciò è dato dal teorema 4.3, è chiaro che possono esistere anche soluzioni alternative, a patto che il linguaggio sia regolare, e perché sia tale basta mostrare almeno un automa che lo
accetti).
(rif. D.S.W. pag. 241, esercizio 2.a)
Mostrare che il linguaggio L è regolare costruendo un automa finito ` che lo accetti.
A ^ A, B,!, Z ,0,1,! 9` , L consiste in tutte le stringhe w con 1 d w d 8 e che cominciano con
uno dei simboli A, B,!, Z .
L ^w |, w s ˜ v , s  ^ A, B , ! , Z ` , v  A , 0 d v d 7`
Costruiamo
F
l’’automa
in
questo
modo
A,Q , q1 , F ,G `
^q , q ,!, q ` e la funzione di transizione
2
3
dove
Q
^q1 , q2 ,!, q10` ,
9
G
A,!, Z
0,!,9
q1
q2
q10
q2
q3
q3
q3
q4
q4
q4
q5
q5
q5
q6
q6
q6
q7
q7
q7
q8
q8
q8
q9
q9
q9
q10
q10
q10
q10
q10
EDIT by Qd –– Linguaggi –– VIII Lez. - I parte
A, ! , Z
0,! , 9
q2
q1
0,! , 9
A, ! , Z
0,! , 9
q10
A, ! , Z
0,! , 9
q4
q3
A, ! , Z
0,! , 9
q9
A, ! , Z
A, ! , Z
0,! , 9
A, ! , Z
A, ! , Z
0,! , 9
q8
q5
A, ! , Z
0,! , 9
q7
A, ! , Z
0,! , 9
q6
36
(rif. D.S.W. pag. 251, esercizio 3.a)
Siano L ed Lc due linguaggi regolari, dimostrare che anche L Lc è regolare.
Basta scrivere L Lc L ˆ A Lc A
Lc
Quindi, poiché Lc per ipotesi è regolare, per il teorema 4.3, lo è anche
A Lc , mentre per il teorema 4.4 abbiamo che anche L ˆ A Lc è rego-
A
L
lare, quindi L Lc è regolare.
L Lc
L ˆ A Lc A Lc
(rif. D.S.W. pag. 258, esercizii 2.a, 2.b)
Siano D e E due espressioni regolari, con la scrittura D { E indichiamo che D
la definizione appena data dimostrare le identità seguenti:
E . In base al-
2.a) D ‰ D { D
Dobbiamo mostrare che
2.b)
D
D ‰ D D , quindi basta scrivere: D ‰ D D .
˜ E ‰ D ˜ J { D ˜ E ‰ J Mostriamo come D ˜ E ‰ D ˜ J Scriviamo:
D ˜ E ‰ D ˜ J ^u ˜ v | u  D
Mentre:
D ‰ D
D ˜ E ‰J ,v  E
D ˜ E ‰J D ˜ E ‰ D ˜ J ` ‰ ^u ˜ w | u  D
D ˜ E ‰J Quindi possiamo concludere che
EDIT by Qd –– Linguaggi –– VIII Lez. - I parte
D
D ˜ E ‰ D ˜ J
,w  J
D ˜ E ‰ J
` ^u ˜ z | u  D
,z  E › z  J
^u ˜ z | u 
D ,z  E › z  J
˜ E ‰ D ˜ J { D ˜ E ‰ J è vera.
`.
`.
Grammatiche
Ottava Lezione –– Seconda parte
27/10/2006
Introduzione alle Grammatiche
Introduzione alle Grammatiche
Gli argomenti trattati fin ora (automi e linguaggi regolari) sono inerenti a quella classe di problemi
detti di decisione: abbiamo studiato delle strutture astratte (gli automi) che ci hanno permesso, ad esempio, di stabilire se un certo linguaggio è o non è regolare, ma tale problema si può estendere ad un insieme molto più vasto di argomenti. Nel
caso specifico degli automi c’’è da dire però
x B
che essi hanno dei limiti, ad esempio essi
non riconoscono linguaggi come:
x
`
?
^a > @b > @ | n ! 0`
n
x B
n
.
B  Set
Ora ci prestiamo ad affrontare un’’altra classe di problemi, quelli inerenti alla GENERAZIONE, studieremo cioè dei metodi che permettono di generare dei linguaggi, regolari e non regolari. Usando due macchine (algoritmi), una per generare degli elementi y  B , un’’altra per la generazioni di elementi differenti dai precedenti y  B . Facendo un confronto tra i due elementi si potrà stabilire di che tipo è il linguaggio generato. Le strutture generative che vedremo a breve permetteranno di
generare e quindi di identificare una classe
più vasta di linguaggi (non solo regolari).
x
y B
`
Chiameremo tali macchine GRAMMATICHE.
Di seguito vengono elencate le prime
nozioni riguardanti le grammatiche (rif.
x
` c
D.S.W. pag. 269).
y B
Tratteremo esclusivamente grammatiche
CONTEXT FREE o anche C.F. (cioè libere
Macchine generatrici
dal contesto, in seguito si chiarirà tale termine).
DEFF.: Dati due alfabeti i e T disgiunti ( i ˆ T ‡ ), gli elementi di i saranno chiamati variabili, mentre gli elementi di T li chiameremo terminali. Con il termine produzione context-free indichiamo un’’espressione su i e T di questa forma:
i
o i ‰ T con X i e h  i ‰ T X è un simbolo mentre
h è una stringa
X oh
38
Da sottolineare che in generale h non è un terminale, ovviamente perché è una stringa e i terminali non
sono stringhe ma simboli, sebbene h potrebbe in taluni casi contenere terminali o coincidere con un terminale.
Ora sia P una produzione X o h e siano u e v due stringhe tali che u, v  i ‰ T allora con la
notazione:
u Ÿv
indichiamo che esistono parole p, q  i ‰T P
tali che u
pXq
ev
phq
i ‰ T o i ‰ T In altre parole v si ricava partendo da u, sostituendo al simbolo X la parola h.
Con la scrittura X o 0 indichiamo la produzione nulla (che equivale ad una contrazione, una sorta di STOP
per le grammatiche, e ha una sua utilità come vedremo. X o 0 fa collimare ogni simbolo di V nella stringa vuota).
Con il termine grammatica libera dal contesto indichiamo il simbolo * , caratterizzato dalle variabili
(simboli) di i e dai terminali (simboli) di T; tale grammatica è data da un insieme FINITO di produzioni libere dal contesto su i e T e da un simbolo designato S i (Start) detto simbolo iniziale o
assioma. L’’insieme i ‰ T viene chiamato alfabeto di * .
Una grammatica C.F. * viene detta positiva se nessuna delle sue produzioni è la produzione nulla.
EDIT by Qd –– Grammatiche –– VIII Lez. - II parte
Nona Lezione
31/10/2006
Grammatiche C.F.: prime nozioni e teorema 1.2 (prima parte)
Ricapitolazione concetti base Grammatiche C.F.
Il termine context-free sta a indicare che l’’unico vincolo che hanno p e q è che devono essere delle
stringhe; a eccezione di questo vincolo, le produzioni C.F. non dipendono da un contesto particolare o
non devono sottostare a regole dipendenti dal contesto in cui vengono adoperate (contrariamente a quanto
succede ad esempio per grammatiche sensibili al contesto le quali sono costituite da produzioni del tipo D o E e deve ri-
sultare D d E ).
Se * è una grammatica C.F. con variabili in i e terminali T, se u, v  i ‰ T , scriveremo
u Ÿ v per indicare che esiste una produzione P di * tale che risulti u Ÿ v .
*
P
Mentre la scrittura u Ÿ v rappresenta una sequenza di produzioni arbitrariamente lunga (ma pur
*
sempre finita). Quindi esiste una successione di stringhe u1 , u2 ,!, um con u1 u , um v e risulta
ui Ÿ ui 1 con 1 d i m (m è arbitrario ma finito; si può dire che * potrebbe pure avere meno regole di produzione del
*
numero m).
La sequenza u1 , u2 ,!, um con u1
u e um
v è detta derivazione di v da u in *.
Con m si indica la lunghezza della derivazione. È ovvio che la derivazione di lunghezza minima è 2,
quindi m t 2 (in alcuni libri di testo la lunghezza si indica con m 1 , quindi la lunghezza minima della derivazione in tal
caso sarà pari a 1).
Nelle derivazioni del tipo u Ÿ v o anche u Ÿ v , eccetto che nei casi ambigui, il simbolo * può esse*
*
re omesso, quindi in luogo di u Ÿ v o u Ÿ v potremo scrivere u Ÿ v e u Ÿ v . Inoltre la scrittura
*
*
u Ÿ v può essere vista come una derivazione di v da u di lunghezza 2, una notazione alternativa a quelm
la vista può essere u Ÿ v , con m la lunghezza della derivazione, che se è pari a 2, il simbolo m può essere
*
omesso.
Diamo la seguente definizione: sia * una grammatica C.F., con la scrittura L * indichiamo il linguaggio generato da * e lo definiamo così: L * :
^u T | S Ÿ u` e rappresenta l’’insieme di tutte le
*
stringhe u costituite da simboli terminali derivanti da S mediante un numero finito di produzioni.
Un linguaggio è detto C.F. se esiste una grammatica C.F. che lo genera (discorso simile a quello fatto per i
linguaggi regolari e i rispettivi automi riconoscitori).
Esempio di grammatica *es .1 :i
T
^S , SN , SV ,Verbo _Transitivo,Verbo _ Intransitivo, Articolo, Nome` ;
^il , un, gatto, topo, rincorre , mangia , dorme , canta` ;
SN viene detto sintagma nominale;
SV viene detto sintagma verbale.
40
Data u Ÿ v , con u u1
*es .1
S, v
il gatto rincorre un topo , vediamo se esiste una successione di pro-
duzioni tali che S Ÿ il gatto rincorre un topo mediante le seguenti produzioni:
*es ,1
S
SN
SV
SV
Verbo _ Transitivo
Verbo _ Transitivo
Verbo _ Intransitivo
Verbo _ Intransitivo
Articolo
Articolo
Nome
o SN SV ;
o Articolo Nome ;
o Verbo _Transitivo SN ;
o Verbo _ Intransitivo ;
o rincorre ;
o mangia ;
o dorme ;
o canta ;
o un;
o il ;
Partendo da u1 S e applicando una sola produzione alla volta si ha:
u1 S ;
u2 SN SV ;
u3 Articolo Nome SV ;
o topo ;
Nome o gatto
u4
il Nome SV ;
u5
il gatto SV ;
u6
il gatto Verbo _ Transitivo SN ;
u7
il gatto rincorre SN ;
u8
il gatto rincorre Articolo Nome ;
u9
il gatto rincorre un topo
(m 10)
Altro esempio (rif. D.S.W. pag. 270): * è dato da: i
^S ` , T ^a , b` , con le due produzioni
S o a S b e S o a b (es.: S o ab , a S b , aa S bb , aaa S bbb , ! ) da cui segue:
TEOREMA 1.1: il linguaggio generato da * è L * ^a > @ ˜ b > @ | n ! 0` il quale è C.F. ma non è regon
n
lare. Questo teorema ci fa comprendere le potenzialità delle grammatiche rispetto agli automi, le grammatiche C.F. possono generare anche linguaggi non regolari.
Terzo esempio riguardante le grammatiche è il seguente: dimostrare che la stringa aaabbb appartiene ad un linguaggio generato da una grammatica C.F. :
basta scrivere le sequenza: SN Ÿ1 aSb
N Ÿ2 aaSbb
N Ÿ3 aaabbb
.
u1
u2
u3
u4
Nel caso delle grammatiche * C.F. positive, 0  L * , in quanto non può contenere produzioni
nulle X o 0 e 0 potrebbe essere un terminale se 0  L * e ciò significherebbe che esiste X o 0 e ciò
non è permesso per come è stato definito *.
TEOREMA 1.2 (rif. D.S.W. pag. 273): L è un linguaggio C.F. œ esiste una grammatica * C.F. positiva
tale che L L * oppure L * ‰ ^0` .
Questo teorema ci mostra che le produzioni nulle non sono necessarie e adoperando un metodo algoritmico che vedremo a breve ne possiamo fare a meno.
EDIT by Qd –– Grammatiche –– IX Lez.
41
DIM.: La dimostrazione necessita della definizione di un insieme chiamato KERNEL (nocciolo) di * C.F.
e lo denotiamo con KER * il quale rappresenta l’’insieme dei simboli V i , variabili tali che
V Ÿ0 .
*
A titolo di esempio consideriamo la grammatica C.F. *0 che ha le seguenti produzioni:
S o XYYX , S o aX , X o 0, Y o 0
In generale più sinteticamente possiamo anche scrivere le produzioni in questo modo (adoperando la
barra orizzontale):
S o XYYX | aX , X o 0, Y o 0
Il nocciolo di *0 è KER *0 ^S , X ,Y ` . Da ogni variabile dell’’insieme, dopo un numero finito di
produzioni, si può giungere alla stringa vuota 0, infatti: S o XYYX o XYY 0 o XY 0 o X 0 o 0 ,
X o0 e Y o0.
Esiste un metodo algoritmico generale utile a costruire il KER * di una grammatica * C.F., costituito da un numero finito di passi:
1) Passo base (diretto): definiamo l’’insieme:
i0
^V | V
o 0 è una produzione di * C.F.` ;
2) Passo induttivo: definiamo l’’insieme:
i i 1 i i ‰ ^V | V o D è una produzione di * e D i i
`.
Cioè l’’insieme i i1 si costruisce in base all’’insieme i i unito alle variabili V tali che V o D ,
dove D i i
e per induzione i i contiene tutte le variabili D tali che D Ÿ 0 .
Facciamo un esempio riprendendo la grammatica *0 con le produzioni:
S o XYYX | aX , X o 0, Y o 0
Applicando il passo base dell’’algoritmo otteniamo: i 0
^ X ,Y ` ;
applicando il passo induttivo abbiamo: i 1 i 0 ‰ ^V | V o D , D i 0 `
^ X ,Y ` ‰ ^S ` ^ X ,Y , S ` ,
si è scelto S in quanto XYYX  ^ X ,Y ` quindi V S . Chiaramente in questo caso si ha che
i i i 1 , i ! 1 , cioè i i si satura in quanto i 2 ‰i 1 i 1 ,!,i i ‰ i 1 i 1 .
Quest’’ultimo concetto viene mostrato nel seguente:
LEMMA 1 (rif. D.S.W. pag. 271): se i k i k1 allora KER * i k . È chiaro che se i
inutile proseguire con la costruzione del kernel di *.
EDIT by Qd –– Grammatiche –– IX Lez.
k
i
k1
sarà
42
DIM.: Sotto l’’ipotesi che i k i k1 dobbiamo dimostrare che KER * i
KER * Ž i k e i k Ž KER * (se A, B  Set , A B œ A Ž B š B Ž A ):
k
e cioè che
i k Ž KER * è una conseguenza diretta del fatto che i k è stato definito in un certo modo, infatti i k contiene un certo numero di variabili che mediante le produzioni di * portano alla parola
vuota, mentre KER * è stato definito come l’’insieme di tutte le variabili tali che mediante
l’’applicazione di un certo numero di produzioni di * si giunge alla parola vuota, è chiaro quindi che se
V i k allora V  KER * .
Meno banale è dimostrare che KER * Ž i k , sotto le ipotesi che i k i k1 . Ciò equivale a voler
dimostrare che ogni elemento V  KER * appartiene anche a i k . Adottiamo un approccio induttivo
sulla lunghezza delle derivazioni:
x Passo base: (lunghezza minima della derivazione ( m 2 ) della parola vuota partendo dalla
variabile V in *) scrivere V Ÿ 0 con m 2 implica scrivere V o 0 (infatti V Ÿ 0 vuol dire
*
che p, q  i ‰ T | V
x
phq e quindi X o h , per essere corretta la corrispondenza deve ri-
. Scrivere V o 0 vuol dire che V  KER * e anche
^V | V o 0 è una produzione di *` ). Ovviamente vale anche V  i k , k t 0 .
sultare necessariamente X
V i 0 ( i 0
pXq e 0
V e h
0)
Passo induttivo: supponendo vero che, date tutte le derivazioni di lunghezza m r , costituite a sinistra da variabili V, se queste V appartengono a KER * , allora appartengono anche
a i k , vogliamo dimostrare che ciò vale anche per le derivazioni di lunghezza m t r . Poniamo V D 1 , D 1 Ÿ D 2 Ÿ " Ÿ D r 1 Ÿ D r e D r 0 , quindi V  KER * e
D 1 Ÿ D 2 Ÿ ! Ÿ D r 1 Ÿ D r è una derivazione di lunghezza r in *. Le stringhe
D 1 ,D 2 ,!,D r 1 sono necessariamente costituite da variabili in quanto la stringa finale deve essere D r 0 (ricordiamo che se D 1 Ÿ D 2 allora esiste una produzione del tipo pXq Ÿ phq , dove p e q sono
stringhe e possono anche essere vuote ma X è una lettera dell’’alfabeto i , quindi una variabile; per definizione KER * e i k contengono solo variabili e sicuramente V D 1 è una variabile per come abbiamo impostato la dimostrazione per induzione; il fatto che le stringhe D non debbano contenere terminali è perché se,
ad esempio, ci fosse D i Ÿ D i 1 con D i 1 abc e c simbolo terminale, tale simbolo rimarrebbe fino alla fine
delle produzioni e non si otterrebbe quindi la stringa vuota). Dalle ultime osservazioni possiamo dire
che D 1 ,D 2 ,!, D r 1 i
. Ora, posto D 2
V1V2 "VV , otteniamo che Vi Ÿ 0 con
*
successione di variabili
i
1,2,! , V (ciò è ovvio poiché abbiamo imposto D 1 Ÿ D 2 Ÿ ! Ÿ D r
0 , e quindi Vi Ÿ 0 ).
*
Più
formalmente Vi §¨Vi Ÿ 0 ·¸ , 1 d i d V , 2 d m d r 1 , tali derivazioni, poiché si parte da
©
¹
D 2 , avranno lunghezza al più pari a r 1 . Quindi tutte le variabili Vi  KER * . Ricordando l’’ipotesi di induzione (se derivazioni di lunghezza r 1 alla loro sinistra hanno variabili V, se appartengono a KER * allora appartengono anche a i k ), abbiamo che Vi i k e poiché in * c’’è una
produzione V o D 2 costruttivo di i i 1
V
o V1V2 "VV e V1V2 "VV
D 2 i k , ricordando l’’algoritmo
( i i ‰ ^V | V o D è una produzione di *, D  i i
`)
otteniamo che
V i k 1 ( i k ‰ ^V | V o D , D  i k ` ) , ricordando l’’ipotesi del lemma ( i k 1 i k ) si ottiene V i k .
EDIT by Qd –– Grammatiche –– IX Lez.
Decima Lezione
3/11/2006
teorema 1.2 (seconda parte)
Ricapitolazione teorema 1.2 e lemma 1, segue:
LEMMA 2 (rif. D.S.W. pag. 271): Vi è un algoritmo per trasformare una grammatica * C.F. in una
grammatica C.F. positiva * tale che risulti: L * L * oppure L * L * ‰ ^0` .
DIM.: dimostriamo il teorema elencando preliminarmente i passi dell’’algoritmo:
1. si calcola il KER * ;
2. all’’insieme di produzioni che si ottengono dagli elementi del nocciolo di * si aggiungono tutte
le produzioni di * cancellando dal loro lato destro una o più variabili appartenenti al KER * ;
3. dall’’insieme ottenuto si eliminano le produzioni del tipo V o 0 .
Il seguente esempio chiarisce i tre passi appena descritti: consideriamo la grammatica * 0 presa prima in
analisi, costituita dalle produzioni: S o XYYX | aX , X o 0, Y o 0 .
Per ottenere *0 applichiamo il passo 1. dell’’algoritmo del lemma poc’’anzi enunciato, allora l’’insieme
delle produzioni sarà ^S o XYYX , X o 0, Y o 0` ; passo 2. aggiungiamo tutte le possibili produzioni
ottenibili da * 0 cancellando alla destra una o più variabili presenti nel nocciolo, otteniamo:
^S o XYYX ,
X o 0, Y o 0` ‰ ^S o YYX | XYX | XYY | XY | YY ,
S o YX | XX | X | Y | aX | a
`;
al passo 3. dobbiamo eliminare dall’’insieme ottenuto le produzioni nulle ottenendo:
^S o XYYX , S o YYX , S o XYX , S o XYY , S o XY , S o YY ,
S o YX , S o XX , S o X , S o Y , S o aX , S o a ` .
Riprendendo la dimostrazione del lemma 2, inizialmente dobbiamo far vedere che L * L * ,
quindi bisogna dimostrare che se una produzione appartiene a L * allora essa appartiene anche a
L * . Consideriamo la produzione V o E1 E2 " EV di * ma non di *, E1 , E 2 ,!, EV  i ‰T ,
vogliamo far vedere che V o E1 E2 " EV è stata ottenuta da una produzione di
* :V o u0 E1u1 E 2 " EV uV con u0 , u1 ,!, uV  KER * , poiché stiamo adoperando l’’operatore unario
stella, le stringhe u potrebbero essere anche vuote ( u 0 ). Chiaramente essendo ui  KER * con
0 d i d V , si ha ui Ÿ 0 . È facile dedurre che V Ÿ u0 E1u1 E2 " uV 1 EV uV Ÿ E1 E2 " EV . Ciò mostra che un
*
*
*
elemento appartenente a L * appartiene anche a L * (usando la grammatica C.F. * e le sue produzioni, costituite anche da produzioni nulle, abbiamo costruito una derivazione che genera lo stesso elemento generato dalla gramma-
tica C.F. * positiva mediante l’’applicazione di una serie di produzioni) quindi L * Ž L * .
Ora bisogna dimostrare che se un elemento v  L * con v z 0 , allora v  L * (ricordando che gli
elementi di un linguaggio generato da una grammatica C.F. sono stringhe fatte di terminali), quindi dobbiamo dimo-
44
strare che L * Ž L * oppure (nel caso in cui 0  L * ) L * Ž L * ‰ ^0` . Dobbiamo dunque
*
*
provare che: V , se V Ÿ w, w z 0 e w T allora V Ÿ w , dimostriamolo per induzione:
x
passo base: derivazione di lunghezza minima m
2 (quindi Ÿ senza *) ; se V Ÿ w allora *
*
contiene la produzione V o w (poiché m 2 e V è una variabile) che è contenuta anche in *
(poiché w è fatta tutta di terminali che necessariamente * produrrà, si vedano i due passi per la costruzione
della grammatica positiva della prima parte della dimostrazione di questo lemma) ;
x
passo di induzione: derivazione di lunghezza maggiore di 2 ( Ÿ ); se V Ÿ w tale derivazione
*
la si può scrivere come V Ÿ w0V1w1V2 "VV wV Ÿ w (non si è fatto altro che scomporre la derivazio*
*
ne) con le variabili V1 ,V2 ,! ,VV i
e le stringhe di terminali w0 , w1 , w2 ,! , wV T (com
presa 0 per via della stella). A questo punto poniamo w
w0v1w1v2 " vV wV dove Vi Ÿ vi ,
*
1,2,! , V , allora si può applicare l’’ipotesi di induzione, considerando che ogni Vi Ÿ vi
i
*
ha lunghezza minore di V Ÿ w
*
Ÿ w 0 v 1 w 1v 2 w 2 " v V w V
*
(infatti
V Ÿ w 0V1w1V2 "VV wV
*
Ÿ w 0v 1w1V2 w 2 "VV wV Ÿ
*
w , la derivazione V Ÿ w contiene le derivazioni, più corte, Vi Ÿ v i ). Per
*
*
*
*
l’’ipotesi di induzione si ha quindi che se Vi Ÿ vi allora Vi Ÿ vi di conseguenza anche la de
*
*
rivazione, più lunga, V Ÿ w esisterà per V Ÿ w (poiché w w0v1w1v 2 " vV wV dove le stringhe vi
con i
1, 2, ! , V , sono prodotte da * e le stringhe w i con i
1, 2, ! , V sono fatte di terminali anch’’essi
prodotti da * per come abbiamo costruito l’’algoritmo (passo 2) nella prima fase di dimostrazione del lemma
2.
Dunque il lemma è dimostrato, ma non del tutto, infatti la dimostrazione per induzione, non sod
disfa il caso in cui vi
0 . Se vi
0 allora Vi Ÿ 0 quindi Vi  KER * a questo punto definiamo il se*
­0 se vi 0;
, in questo modo abbiamo escluso da * le produzioni nulle, sosti®
¯Vi altrimenti
tuendo ad esse stringhe vuote e ciò basta per concludere la dimostrazione del lemma 2, infatti avremo:
V o w0V10w1V20 "VV0wV che è in ogni caso una delle produzioni di * , infatti si ha
guente simbol: Vi 0
V Ÿ w0V10w1V20w2 "VV0wV Ÿ w0v1w1v2 "vV wV
*
*
w.
Ritornando alla dimostrazione del teorema 1.2 (rif. D.S.W. pag. 273) affermiamo che un linguaggio è
C.F. se e solo se esiste una grammatica C.F. positiva * tale che L L * › L L * ‰ ^0` :
L ' allora si applica l’’algoritmo descritto nel lemma 2 (con l’’ausilio del lemma 1 per la costruzione del kernel di *) e si costruisce una grammatica * C.F. positiva che soddisfi il teorema ( L L * › L L * ‰ ^0` );
DIM. Ÿ : Se L è C.F. e ' è una grammatica C.F. tale che L
EDIT by Qd –– Grammatiche –– X Lez.
45
DIM.  : Viceversa, data una grammatica * C.F. positiva, se L L * allora L è un linguaggio C.F.,
tale implicazione è ovviamente vera e dimostrata immediatamente in quanto, se L L * , L è chiaramente un linguaggio C.F.; nel caso in cui L L * ‰ ^0` si crea un nuovo simbolo (o assioma) S e si
aggiungono alla grammatica * (ricavata da *) due nuove produzioni: S o S e S o 0 . Chiaramente si
ha che L è un linguaggio C.F.: L * L * ‰ ^0` .
N N
S oS
EDIT by Qd –– Grammatiche –– X Lez.
S o0
Decima Prima Lezione
7/11/2006
Aberi di derivazione
Ricapitolazione lemma 2 e conclusione teorema 1.2.
ALBERI
Gli alberi sono delle strutture matematiche che servono a descrivere degli insiemi tra i cui elementi ci sono delle relazioni (gli
alberi di cui discuteremo più precisamente sono detti alberi finitari e cioè degli alberi in cui ogni nodo ha un numero finito di
successori).
Radice
DEF. (rif. D.S.W. pag. 273): Un albero è detto *-albero se:
Padre
1. la radice (root) è etichettata con una variabile;
2. ogni nodo (vertex o vertice) che non è una foglia (leaf ) è
etichettato con una variabile;
3. se un vertice ha etichetta X e i suoi immediati successori
hanno etichette D 1 ,D 2 ,!,D k (letti da sinistra a destra) allora questo vertice è una produzione di *.
Figlio
Foglia
Foglia
Foglia
DEF.: Sia g un *-albero e v un nodo (vertice) di g etichettato con X, allora g v è detto sottoalbero determinato dal nodo v. Tale sottoalbero avrà radice v e i
figli della radice saranno gli immediati successori di v e così via sino alle foglie.
DEF.: Se g è un albero allora g è la parola che consiste nelle etichette delle foglie di g lette nell’’albero da sinistra
a destra.
S
DEF.: Se la radice di g ha etichetta S e w
g è detto albero di derivazione per w in * (da S).
c
w
d
abcd
g
g
allora
Vediamo un altro esempio di albero di derivazione: sia
*es ,2 : S o a X bY , X o a X | a , Y o bY | b . Tale grammatica genera il linguaggio L *es ,2 guaggio, nel caso in cui m
^a > @ b > @, n,m ! 0`
n
n
(tale lin-
n non è regolare ma risulta pur sempre C.F.).
Costruiamo l’’albero di derivazione di una stringa generata dalla
a
b
Esempio di albero di derivazione
grammatica corrente, ad esempio w aaaabbb a >4 @ b >3@ . Per
costruire l’’albero dobbiamo seguire le regole di produzione della grammatica. Da notare che non è unica la derivazione di w
da S, infatti (rif. D.S.W. pag. 274) si possono avere tre derivazioni
differenti che portano allo stesso risultato:
47
1. S Ÿ1 a X bY Ÿ2 a >2@ X bY Ÿ3 a >3@ X bY Ÿ 4 a >4 @ bY Ÿ5 a >4 @ b >2@ Y Ÿ6 a > 4 @ b >3@
2. S Ÿ1 a X bY Ÿ2 a >2@ X bY Ÿ3 a >2@ X b >2@ Y Ÿ 4 a >3@ X b >2 @ Y Ÿ5 a >3@ X b >3@ Ÿ6 a >4 @ b >3@
3. S Ÿ1 a X bY Ÿ2 a X b >2@ Y Ÿ3 a X b >3@ Ÿ 4 a >2@ X b >3@ Ÿ5 a >3@ X b >3@ Ÿ6 a >4 @ b >3@
(le variabili sottolineate indicano che su esse avviene la successiva produzione)
È importante sottolineare che l’’albero di derivazione di w è unico, indipendentemente dalle differenti derivazioni adoperate per ottenere w. L’’albero di derivazione risultante è il seguente:
S
X
a
a
X
b
a
X
b
a
EDIT by Qd –– Grammatiche –– XI Lez.
Y
b
Y
Decima Seconda Lezione
14/11/2006
Tremi sulle Derivazioni e gli Alberi di derivazione
Derivazioni estreme (a sx. e a dx.) –– Grammatiche Branching
TEOREMA 1.3 (rif. D.S.W. pag. 274): Se * è una grammatica C.F. positiva e risulta S Ÿ w allora vi è un
*
albero di derivazione per w in *.
DIM.: Si dimostra per induzione sulla lunghezza della derivazione di w da S in *.
x
Passo base: m 1 , ciò corrisponde a dire che S w (per m 1 non ci sono produzioni) e
l’’albero di derivazione richiesto è rappresentato da un unico vertice etichettato con S;
N.B.: A lezione, nel passo base della dimostrazione per induzione, è stato considerato, giustamente, il
caso m 2 , si ha quindi S o w , cioè in * ci deve essere una produzione S o D 1 ˜ D 2 " D n w e
*
l’’albero sarà fatto cosi:
S
D1
D2
˜˜˜
Dn
Seguendo la dimostrazione del libro il passo in cui m 2 può essere visto come passo successivo (secondo caso base) a m 1 , dove le foglie D rappresentano sottoalberi.
x
Passo induttivo: ipotizzando che per derivazioni di w da S di lunghezza q è noto l’’albero di derivazione, dimostriamo che ciò vale anche per derivazioni di w da S di lunghezza q 1 in *, cioè
che esiste l’’albero di derivazione di w da S in * per derivazioni di lunghezza m
q 1 . Si ha
quindi: S Ÿ v Ÿ w , con v , w  V ‰T . Applicando l’’ipotesi di induzione su S Ÿ v si ha che
*
*
*
m q
m 1
esiste un albero di derivazione di v da S in *. Scrivendo ora v Ÿ w (ricordando la definizione
*
data per u Ÿ v rif. D.S.W. pag. 269) si ha che v
*
x˜X ˜ y e w
x ˜ D 1D 2 "D k ˜ y ( X V ,
h
h  V ‰ T ). * contiene la produzione X o D 1D 2 "D k , come già detto l’’albero di derivazione di v è noto per l’’ipotesi di induzione, mentre l’’albero di derivazione di w si costruisce a partire dall’’albero di derivazione di v aggiungendo un sottoalbero rappresentante la derivazione
v Ÿ w che sappiamo costruire sempre per l’’ipotesi di induzione ( m q 1 , per la precisione
*
m 2 , che come abbiamo poco fa visto nella nota riguardante il caso m 2 , a fortiori sappiamo costruire). Tale sottoalbero ha chiaramente radice etichettata con X. Il teorema è dunque
dimostrato.
49
Graficamente abbiamo:
S
x
X
X
y
"
Dk
x
y
v
D1
D2
w
DEF.: con la scrittura u Ÿl v indichiamo che esiste una produzione in * X o z , con u
ev
x˜X ˜ y
x ˜ z ˜ y , y  V ‰ T e x T .
Mentre la sequenza u1 Ÿl u2 Ÿl ! Ÿl un è detta derivazione estrema a sinistra.
Tale tipo di derivazione si ottiene applicando produzioni solo alle variabili che si trovano all’’estrema sinistra della stringa del tipo u xXy , abbiamo dunque: x ˜ X ˜ y Ÿ l x ˜ z ˜ y , dove xzy v . Poiché z deriva da X, è ovvio che x non può essere una variabile altrimenti si otterrebbe una derivazione qualsiasi, invece, essendo una derivazione estrema a sinistra, deve essere prodotta la prima variabile a sinistra, che nel
nostro caso è X  V ( x  T e y  V ‰ T ), se z è un terminale allora le successive derivazioni estreme a sinistra si applicheranno a y che potrebbe contenere variabili. Una derivazione estrema a sinistra è
(rif. D.S.W. pag. 274, 1):
S Ÿ l a X bY Ÿ l aa X bY Ÿ l aaa X bY Ÿ l aaaab Y Ÿ l aaaabb Y Ÿ l aaaabbb
L’’archetto identifica la prima variabile alla sinistra della stringa sulla quale si applica la produzione.
DEF.: Viceversa la scrittura u Ÿr v indica che esiste una produzione in *
u
X o z , con
x ˜ X ˜ y e v x ˜ z ˜ y , ma, rispetto alla definizione precedente, risulterà: x  V ‰ T e y T .
Analogamente la sequenza: u1 Ÿr u2 Ÿr ! Ÿr un è detta derivazione estrema a destra.
Dualmente rispetto a prima, in questo caso, vengono prodotte le variabili che si trovano all’’estrema destra della stringa come si può evincere dall’’esempio analogo a quello visto prima:
S Ÿr aXb Y Ÿ r aXbb Y Ÿ r a X bbb Ÿr aa X bbb Ÿ r aaa X bbb Ÿr aaaabbb
Come si può evincere vengono prodotte soltanto le variabili all’’estrema destra.
Per completezza vediamo un terzo esempio di derivazione:
S Ÿ l ,r a X bY Ÿ l aaXb Y Ÿ r aa X bbY Ÿ l aaaXbb Y Ÿ r aaa X bbb Ÿ l aaaabbb
Questa derivazione non è né estrema a sinistra né estrema a destra, essendo costituita sia da derivazioni
estreme a sinistra che estreme a destra. Da notare che, come nei due esempi precedenti, la prima derivazione ( S Ÿ l ,r a X bY ) è estrema sia a sinistra che a destra.
TEOREMA (rif. D.S.W. pag. 275) Dato un albero di derivazione g
rivazione estrema a sinistra (a destra) di w da S, quindi w g .
per w T si può ottenere una de-
DIM.: Si costruisce una dimostrazione per induzione sulla lunghezza della derivazione.
EDIT by Qd –– Grammatiche - XII Lez.
50
v0 ˜ X 1v1 ˜ X 2 " X r vr
Con la stringa:
(con v0 , v1 ,!, vr T e X 1 , X 2 ,! , X r V )
(notazioni alternative indicano q in luogo di r)
indichiamo la parola che si legge da sinistra a destra lungo l’’albero di derivazione nei vertici successori
immediati della radice S.
Come già definito i simboli v rappresentano stringhe terminali, mentre i simboli X sono le etichette dei
vertici Q 1 ,Q 2 , ! ,Q n immediati successori della radice S di g (da non confondere il simbolo v con il
simbolo Q ).
g
S
Dn
v01 v02 ! v0n
v0
v11 v12 ! v1m
X1
g1
x
X2
v1
g2
˜˜˜˜˜˜
Xr
vr1 vr2 ! vr p
vr
gr
Passo base: r q 0 , produzione priva di variabili. Stiamo ipotizzando il caso in cui non esistano derivazioni con lunghezza maggiore di 2 e cioè che le derivazioni di lunghezza 2 non generino stringhe che contengano
variabili ma soltanto terminali.
Ovviamente in questo caso si ha immediatamente S o w , con w T , w
v0 e r
0 (è facile
evincere ciò osservando l’’albero appena mostrato, escludendo i nodi etichettati con le variabili X , in quanto assenti nella produzione del passo base, e chiaramente le stringhe v 0 , v 1 , ! , v r devono essere viste come un’’unica stringa
che in questo caso è indicata con v 0 ).
In questo caso è facile osservare che S Ÿl w , ma anche S Ÿr w , la derivazione è dunque estrema sia a sinistra che a destra. Il caso base è dunque dimostrato;
x
Passo induttivo: ipotizzando r q ! 0 , cioè che la produzione contenga almeno una variabile
Q
X . Consideriamo gli alberi g i g i con i 1, 2,!, r . Con questa notazione indichiamo le
grammatiche *i che hanno come assiomi X i , rappresentano in pratica sottoalberi di g le cui
radici sono etichettate con X i e le cui foglie sono etichettate con wi0 , wi1 ,!, win
( wi0 ˜ wi1 "win
w
wi ). La parola che si ottiene dalla derivazione dell’’albero principale sarà
v0w1v1w2 " wr vr .
Presupponendo vero il teorema per un certo r ! 0 , partendo da X i si ha X i Ÿl wi e X i Ÿr wi ,
con 1 d i d r , ipotizzando vera l’’ultima affermazione fatta (ipotesi di induzione) possiamo giun-
EDIT by Qd –– Grammatiche - XII Lez.
51
gere alla tesi del teorema (su una lunghezza della derivazione maggiore di r) e cioè che S Ÿl w e
S Ÿl vo X 1v1 X 2 " X r vr
S Ÿr vo X 1v1 X 2 " X r vr
S Ÿr w , e più esplicitamente che
Ÿl vo w1v1 X 2 " X r vr
e
Ÿl vo w1v1w2 " X r vr
Ÿr vo X 1v1 X 2 "wr vr
#
Ÿr vo X 1v1w2 "wr vr
#
Ÿl vo w1v1w2 "wr vr
w
Ÿr vo w1v1w2 "wr vr
w
Da S si ottiene una derivazione estrema sia a sinistra che a destra. Tale conclusione del
teorema si ottiene applicando ricorsivamente i due passi dell’’induzione.
TEOREMA 1.4 (non dim.): Sia * una grammatica C.F. positiva con simbolo iniziale S e terminali T, allora i seguenti enunciati sono equivalenti:
1. w  L * ;
2. esiste un albero di derivazione per w in *;
3. c’’è una derivazione estrema a sinistra di w da S in *;
4. c’’è una derivazione estrema a destra di w da S in *;
DEF.: Una grammatica C.F. positiva è detta branching (ramificata o ramificante di Chomsky) se non
ha produzioni della forma X o Y , con X ,Y V .
L’’albero di derivazione di tale grammatica ha vertici che, se non sono foglie, non sono unici, nel senso
che ogni vertice non può avere un solo figlio, ammenoché questo figlio non sia una foglia.
TEOREMA 1.5: Vi è un algoritmo per ottenere, da una grammatica * C.F. positiva, una grammatica ' C.F. positiva e ramificante tale che si ha l’’invarianza L * L ' .
La dimostrazione segue alla lezione successiva.
EDIT by Qd –– Grammatiche - XII Lez.
Decima Terza Lezione
17/11/2006
teoremi sulla grammatica Branching e in Chomsky Normal Form
Pumping Lemma –– proprietà di chiusura
Grammatiche Ambigue e Grammatiche Regolari
DIM.: Supponiamo prima il caso in cui * contenga delle produzioni cicliche del tipo: X 1 o X 2 ,
X 2 o X 3 ,! , X k o X 1 , chiaramente con X 1 , X 2 ,! , X k V , k ! 0 .
1. Il primo passo consiste nell’’eliminare le produzioni cicliche, e sostituendo, ad ogni variabile X i
rimanente, il nuovo simbolo X V .
Da notare che facendo queste sostituzioni il linguaggio generato non cambia, in quanto ad esempio:
Y o X 1 e X 1 o X 2 , ! , X k o X 1 , tale sequenza dà gli stessi risultati di Y o X 1 , possiamo dunque eliminare il ciclo e rimpiazzare X 1 con X .
Se una variabile X i
S (cioè se è un assioma) allora porremo X
S.
Ora supponiamo il caso in cui * non contenga produzioni cicliche, in tal caso si passa al secondo passo.
2. Per ottenere da * una grammatica branching * non deve contenere produzioni del tipo X o Y
tali che Y o Z (cioè Y non deve essere una variabile, ma un terminale ).
Là dove risulta Y o x e X o Y con x  V ‰ T , si eliminano tali produzioni e le si rimpiazza con X o x , si ripete tale procedura fintantoché x 1 e x V , proprio perché si vuole
ottenere, non modificando il linguaggio generato, una grammatica branching ( X o Y non
ammesse, mentre sono ammesse ad esempio X o YZ ).
Ripetendo il passo 2 più volte si otterrà una grammatica C.F. positiva e ramificata.
DEF.: con la dicitura Chomsky Normal Form (forma normale di Chomsky) si indica una grammatica
C.F. * con variabili V e terminali T e ogni sua produzione ha una delle forme seguenti: X o YZ oppure X o a , con X ,Y , Z V e a T .
TEOREMA 3.1: Vi è un algoritmo che permette di trasformare una grammatica C.F. positiva in una
grammatica C.N.F. (Chomsky Normal Form) ', tale che il linguaggio generato non cambia, quind
L * L ' .
DIM.: Per il teorema precedente possiamo supporre che * sia una grammatica branching senza che la
dimostrazione perda di generalità.
1.1. Per ogni simbolo a T , si introduce la variabile X a ;
53
1.2. Si modifica * rimpiazzando ogni produzione X o x (dove x non è un singolo terminale)
con la produzione X o x c , tale x c si ottiene da x sostituendo ad ogni terminale a la variabile X a ;
Quindi se si ha X o x e x aa si ottiene X o x c, x c X a X a .
2.
Si aggiungono tutte le produzioni X a o a .
Chiaramente il linguaggio generato dalla grammatica ottenuta dai passi appena descritti è la stessa di
L * e avrà produzioni del tipo (ma non è ancora una grammatica in C.N.F.):
I)
II)
X o X 1 X 2 " X k con k ! 1 (del resto avevamo ipotizzato * branching) più precisamente si ha X o x c
con x c X 1 X 2 " X k , x c non è un singolo terminale per questo k t 2 ;
X oa.
X , X 1 , X 2 , ! , X k sono variabili mentre a è un terminale.
Al fine di ottenere una grammatica in C.N.F. bisogna eliminare tutte le produzioni I) con k ! 2 , infatti
la C.N.F. deve avere produzioni con (soltanto) due variabili, a tal fine si introduce un nuovo tipo di variabile: Z che utilizzeremo in questo modo:
X
o X 1Z1 ;
o X 2 Z2 ;
Z1
#
Z k 3 o X k 2 Z k 2 ;
Z k 2 o X k 1 X k
Con questo stratagemma otteniamo una grammatica C.N.F. ' tale che L * L ' .
DEF. (accenno, rif.: D.S.W. pag. 287, ex. 3): Si dice grammatica C.F. in forma normale di Greibach una
grammatica che ha ogni produzione nella forma: X o aY1Y2 "Y k con k t 0 , a T e
X , Y 1 , Y 2 ,! , Y k  V .
TEOREMA 4.1 –– Pumping Lemma (non dim.): tale lemma visto per i linguaggi regolari può essere esteso alle grammatiche C.N.F. in questo modo, sia * una grammatica C.N.F. con n variabili e sia
L L * , allora x  L tale che x 2n si ha che x r1 ˜ q1 r q2 ˜ r2 dove:
mxo
1. q1 r q2 d 2n ;
2. q1 ˜ q2 z 0;
3. i t 0 r1 q1>i @ r q2>i @ r2  L
TEOREMA 4.2 (rif. D.S.W. pag. 290 –– non dim.): Il linguaggio L
^a > @ ˜ b > @ ˜ c > @ | n ! 0` non è C.F.
n
n
n
Chiaramente se n avesse un limite superiore allora L sarebbe C.F., ma qui stiamo considerando il caso in
cui n possa assumere qualsiasi (tutti) valore positivo non nullo.
EDIT by Qd –– Grammatiche - XIII Lez.
54
Risolvendo il seguente esercizio (rif. D.S.W. pag. 290, ex. 1) si scopre che anche le grammatiche C.F. hanno dei limiti: mostrare che L
^a > @ | i
i
`
è un numero primo non è C.F. Tale fatto si può dimostrare i-
potizzando che L sia C.F., possiamo applicare il pumping lemma, si ha che (punto 3. del lemma): k t 0
r1q1>k @rq2>k @r2  L , ma ciò non è possibile k t 0 in quanto non avremmo sempre ripetizioni di a pari ad
un numero primo. La contraddizione ci conduce ad affermare che L non è C.F.
PROPRIETÀ DI CHIUSURA
per i linguaggi C.F.
Mostriamo tali proprietà analogamente a come si è fatto per i linguaggi regolari.
‰ TEOREMA 5.1: se L1 ed L2 sono due linguaggi C.F. allora L1 ‰ L2 è un linguaggio C.F.
DIM.: Supponiamo che L1 sia un linguaggio generato dalla grammatica C.F. *1 ed L2 il linguaggio generato dalla grammatica C.F. *2 , si ha quindi L1 L *1 ed L2 L *2 , inoltre supponiamo che *1
e *2 abbiano insiemi di variabili disgiunti fra loro, si ha quindi V1 ˆ V2 ‡ (con quest’’ultima posizione non
vi è perdita di generalità della dimostrazione del teorema in quanto ciò che interessa come risultato finale sono i terminali e
cioè i linguaggi e non le parti costituenti le grammatiche).
Ora supponiamo che S1 ed S2 siano rispettivamente i simboli iniziali di *1 e *2 . Definiamo una
grammatica * C.F. che ha come insieme di variabili V1 ‰ V2 ‰ ^S ` e simbolo iniziale S.
Questo modo di dimostrare il teorema si basa sullo stesso approccio utilizzato per i teoremi sui linguaggi
regolari, in quel caso cercavamo di costruire automi (riconoscitori) mentre adesso cerchiamo di costruire
grammatiche (generatrici).
Aggiungiamo due nuove produzioni a *: S o S1 e S o S2 . In conclusione la grammatica costruita è
generatrice sia di L1 che di L2 , infatti L * L *1 ‰ L *2 da cui L1 ‰ L2 L * .
Ricordiamo che dire che un dato linguaggio è C.F. vuol dire che esiste una grammatica che la genera,
quindi nel caso di questa dimostrazione è bastato trovare un’’opportuna grammatica che generasse il linguaggio L *1 ‰ L * 2 .
ˆ TEOREMA 5.2: Ci sono linguaggi C.F. L1 ed L2 tali che L1 ˆ L2 non è un linguaggio C.F. In altre parole il teorema ci assicura che la classe dei linguaggi C.F. non è chiusa rispetto all’’intersezione.
DIM.: la dimostrazione consiste nel trovare (almeno) un esempio di linguaggio che non è C.F. che è stato ottenuto dall’’intersezione di due linguaggi C.F., quindi consideriamo:
*1 , grammatica C.F. con le produzioni:
S o Sc | Xc , X o aXb | ab
tale grammatica genera il linguaggio C.F.: L1
*2 , grammatica C.F. con le produzioni:
n
n
m
L *1 ;
S o aS | aX , X o bXc | bc
tale grammatica genera il linguaggio C.F.: L2
EDIT by Qd –– Grammatiche - XIII Lez.
^a > @b > @c > @ | n,m ! 0`
^a > @b> @c > @ | n,m ! 0`
m
n
n
L *2 .
55
È chiaro che il linguaggio L1 ˆ L2
^a > @b > @c > @ | n ! 0` non è C.F. (teorema 4.2, conseguenza del pumping lemn
n
n
ma), tale risultato ci è sufficiente per ritenere dimostrato il teorema.
COROLLARIO 5.3: non vi è chiusura, per la classe dei linguaggi C.F., neanche per l’’operazione di
complemento, infatti: vi è (almeno) un linguaggio C.F. L Ž A tale che A L non è C.F.
DIM.: Si adoperano le leggi di De Morgan (rif. D.S.W. pag. 2 - R ‰ S
ˆ
L1 ˆ L2
L1 ‰ L2
A ª¬ L1 ‰ L2 º¼
R ˆS
‰
) e possiamo scrivere:
A ª¬ A L1 ‰ A L2 º¼
con l’’ausilio del teorema 5.1 ‰ e del teorema 5.2 ˆ se ne deduce che il complemento di un linguaggio
C.F. non è C.F. infatti, se (per assurdo) neghiamo la tesi del teorema, cioè assumiamo che A L sia C.F.
allora, per il teorema 5.1 potremmo affermare che, posto H
A
L1 ‰ A L2 , H è C.F. Prose-
guendo la dimostrazione per assurdo potremmo affermare anche che A H è C.F., ma A H , come
visto poco fa è uguale a L1 ˆ L2 che, per il teorema 5.2 non è C.F. (contraddizione), quindi il complemento di un linguaggio C.F. non è, in generale, C.F.
DEF. (rif. D.S.W. pag. 280): Una grammatica C.F. è detta regolare se ogni sua produzione ha una delle
due forme: U o aV oppure U o a , con U e V variabili e a terminale.
TEOREMA 2.1. (non dim.): Se L è un linguaggio regolare, allora vi è una grammatica regolare * tale
che L L * oppure L L * ‰ ^0` .
TEOREMA 2.2. (non dim.): Se * è una grammatica regolare allora il linguaggio L * generato da
gamma è regolare.
COROLLARIO 2.4 (non dim.): Ogni linguaggio regolare è C.F. È chiaro che il contrario non vale (non è vero
che ogni linguaggio C.F. è regolare).
DEF. (rif. D.S.W. pag. 300): Una grammatica C.F. * è detta ambigua se esiste una parola u  L * che
ha due derivazioni estreme a sinistra. Una grammatica C.F. che non è ambigua è anche detta non ambigua.
Esempio (rif. D.S.W. pag. 303): consideriamo la grammatica * con le seguenti produzioni:
S o XY | YX , Y o ZZ , X o a , Z o a
consideriamo la parola aaa  L * , tale parola ha due derivazioni estreme a sinistra, infatti, si ha:
1. S Ÿl XY
Ÿl aY Ÿl aZZ
Ÿl aaZ Ÿl aaa
2. S Ÿl YX
Ÿl aZX
Ÿl ZZX
Ÿl aaX Ÿl aaa
EDIT by Qd –– Grammatiche - XIII Lez.
56
Le due derivazioni hanno i seguenti alberi di derivazione:
g1
g2
S
X
Y
Y
Z
a
a
Z
Z
a
S
a
X
Z
a
a
Tale ambiguità viene risolta mediante l’’utilizzo delle parentesi, per mezzo delle quali è possibile risalire in maniera univoca alla derivazione. In effetti i due alberi coincidono. Quindi la stringa prodotta
dalla derivazione 1. verrà indicata come a aa , mentre la stringa della derivazione 2. verrà indicata come aa a . In questo modo l’’albero di derivazione (unico) può essere utilizzato per risalire univocamente alla derivazione.
EDIT by Qd –– Grammatiche - XIII Lez.
Decima Quarta Lezione
21/11/2006
Grammatiche Separatrici –– teorema sulla Grammatica Regolare
Automi a Pila
Riprendendo dall’’esercizio della lezione precedente, possiamo riscrivere le produzioni della grammatica * in questo modo: S o X Y | >Y @ X , Y o ^ Z ` Z , X o a , Z o a . Le produzioni che possono indurre ad ambiguità devono essere provviste di parentesi distinte (differenti tra loro). La stringa aaa
si otterrà nei due casi visti prima così:
1.
S Ÿ X Y Ÿ a Y Ÿ a ^ Z ` Z Ÿ a ^a` Z Ÿ a ^a` a
2. S Ÿ >Y @ X Ÿ ª¬^ Z ` Z º¼ X Ÿ ª¬^a` Z º¼ X Ÿ ª¬^a` a º¼ X Ÿ ª¬^a` a º¼a
Il risultato è concettualmente identico, ma non è ambiguo, in questo modo ogni stringa può essere
prodotta da un’’unica derivazione. I relativi alberi di derivazione sono i seguenti:
g 1
g 2 S
X a ^a `
>Y @
Y
^Z `
Z
a
S
[^Z `
[^a`
X
Z]
a
a]
L’’uso delle parentesi è essenziale per evitare ambiguità, un esempio è dato nell’’ambito algebrico dei connettivi logici in cui a š b › c z a š b › c .
Partendo dal concetto di grammatica ambigua e l’’uso delle parentesi si arriva alla seguente:
DEF. (rif. D.S.W. pag. 303): Sulla base di una grammatica * C.N.F. con terminali T e produzioni:
X i o Yi Z i e V o a
con i 1,2,! , n e a T
Costruiamo una nuova grammatica *S tale che i suoi terminai siano i terminali di * assieme ad altri
2n simboli ( i e )i , quindi il nuovo insieme ricavato da T è TS
T ‰ ^ ( i , )i | i
1,2,!, n` .
Le produzioni della nuova grammatica *S saranno identiche a quelle di * se della forma V o a , mentre le produzioni di * del tipo X i o Yi Z i , in *S assumeranno la forma: X i o ( i Yi )i Z i per
i 1,2,!, n .
58
La grammatica *S appena definita prende il nome di grammatica separatrice (si dice anche che *S è il
separatore *, ogni sua produzione ha una coppia distinta di parentesi ).
È ovvio comprendere che da una grammatica *S è possibile ricavare la grammatica *, basta, infatti, eliminare dalle sue produzioni i simboli delle parentesi ( i e )i .
Ora che conosciamo la nozione di grammatica separatrice. Aggiungendo alla grammatica *es .1 , mostrata nella IX lezione, le produzioni:
S o S connettivo S ;
connettivo o e ;
connettivo o oppure ;
connettivo o ma
Possiamo ottenere la stringa: v = un gatto corre e un topo canta oppure un gatto canta ottenibili non
da un’’unica derivazione e trasformando tale grammatica in una grammatica separatrice otterremmo una
derivazione univoca.
TEOREMA 2.3 (rif. D.S.W. pag. 282 –– non dim.): Un linguaggio L è regolare se e solo se œ vi è una grammatica * regolare tale che L L * oppure L L * ‰ ^0` .
Tale teorema rappresenta una caratterizzazione dei linguaggi regolari in termini generativi (per gli automi tale caratterizzazione era fatta in termini di riconoscimento).
Ora viene mostrato uno schema che illustra e ““localizza”” gli argomenti studiati sin ora e alcuni non
ancora trattati:
Algoritmi:
Riconoscimento
Generazione
Automi Finiti
Automi a Pila
Grammatiche Regolari C.F.
Grammatiche C.F.
Linguaggi:
Regolari
Context Free
Le grammatiche regolari C.F. generatrici di linguaggi regolari hanno produzioni con una sola variabile e
un solo terminale (questo fatto fa intuire come una grammatica di questo tipo riesca a simulare in qualche
modo il comportamento dell’’automa finito).
È dimostrato che la classe dei linguaggi regolari è inclusa propriamente (propriamente perché esiste almeno un linguaggio C.F. che non è regolare) nella classe dei linguaggi C.F.: C R  C C.F. . Del resto il corollario 2.4
dice proprio che ogni linguaggio regolare è anche C.F., ma il viceversa non vale come dimostrato dal teorema 1.1 (rif. D.S.W. pag. 270) in cui viene fatto un esempio di linguaggio C.F. che non è regolare.
Si introduce ora il concetto di automa a pila (o pushdown) che è un’’entità matematica (più potente
degli automi finiti) in grado di riconoscere i linguaggi C.F. (quindi anche i linguaggi regolari, per quanto
detto poco fa), che, oltre ad avere le proprietà degli automi finiti (tradizionali) possiede una memoria
(pila o stack) per memorizzare i dati (push) o eliminarli (pop) durante la lettura dell’’ipotetico nastro.
Formalmente diamo la seguente:
EDIT by Qd –– Grammatiche - XIV Lez.
59
DEF.: L’’automa a pila è rappresentato da un insieme di stati Q
^q1, q2 ,! qm ` , con
q1 stato inizia-
le, F Ž Q insieme degli stati finali (o di accettazione), A l’’alfabeto usuale (il nastro è costituito da parole di
questo alfabeto), un altro alfabeto detto alfabeto pila (pushdown) : . Introduciamo un nuovo simbolo 0 il
quale non appartiene né all’’insieme A, né all’’insieme : , scriveremo quindi 0  A e 0  : con
A A ‰ ^0` e : : ‰ ^0` .
DEF. (rif. D.S.W. pag. 310): Per transizione di un automa a pila si intende la quintupla: qi a h :i q j
con a  A e h ,i  : . La transizione si interpreta in questo modo:
1. qi rappresenta lo stato in cui si trova l’’automa a pila prima della lettura del simbolo a ;
2. a è il simbolo che viene letto dall’’automa se a z 0 , altrimenti non viene letto nulla;
3. h è il simbolo che viene estratto (pop) dalla pila se h z 0 , altrimenti non viene estratto nulla;
4. i è il simbolo che viene inserito (push) nella pila se i z 0 , altrimenti non viene inserito nulla;
5. q j è lo stato in cui transiterà l’’automa dopo la transizione.
Come detto se a 0 non verrà letto alcun simbolo sul nastro (ovvero l’’automa non si sposterà lungo il nastro per leggere il simbolo), il fatto che a 0 non vieta all’’automa di eseguire eventuali operazioni di pop e di push e di transitare eventualmente in un altro stato.
DEF.: Un automa a pila viene specificato da un numero finito di transizioni.
Il simbolo 0 rende, in qualche modo, l’’automa a pila non deterministico. Difatti se a 0 l’’automa
potrebbe comunque transitare in un altro stato, anche più di una volta, imitando, in questo modo, ciò
che avviene negli automi finiti non deterministici (i quali possono leggendo un solo simbolo transitare
in più stati contemporaneamente).
DEF.: Date le seguenti transizioni: qi a h : i q j
e qi b j : k qk se distinte tra loro (ovvero se c’’è
almeno un elemento delle due quintuple che le distingue), esse vengono dette incompatibili se si verifica una delle
seguenti condizioni:
1.
a
b e h
j
(in questo caso viene letto due volte lo stesso simbolo e viene fatto
il pop dello stesso simbolo due volte);
2. a
3. h
4. a
b e h
j
0 oppure j
e a
0 (viene letto due volte lo stesso simbolo e in una delle due transizioni
non viene fatto il pop);
0 oppure b
0 oppure b
0 e h
0 (viene fatto il pop due volte dello stesso simbolo e in una delle due
transizioni non viene letto alcun simbolo);
0 oppure j
0 (in una delle due transizioni non viene letto
alcun simbolo e in una delle due transizioni
non viene effettuato il pop);
DEF.: Un automa a pila si dice deterministico se non possiede coppie di istruzioni incompatibili.
EDIT by Qd –– Grammatiche - XIV Lez.
60
La definizione appena data è giustificata dal fatto che con istruzioni incompatibili non è assicurato il determinismo dell’’automa.
DEF.: Posto u  A ed ` un automa pushdown. Con il termine u-configurazione per ` indichiamo la tripla ' k , qi ,D dove k è un intero 1 d k d u 1 , qi uno stato di ` ed D  : è una
stringa del linguaggio pushdown ( D è una sequenza di simboli contenuti nella pila, che in caso può anche essere vuota, per via della stella), mentre u rappresenta la stringa letta dall’’automa.
Intuitivamente una u-configurazione rappresenta una situazione nella quale:
x
x
x
u è scritto nel nastro di ` ;
` osserva il k-mo simbolo della stringa u;
Se k u 1 la computazione di ` è terminata durante la u-configurazione ' ;
x
x
x
durante la u-configurazione ' ;
D è la stringa di simboli nella pila dell’’automa durante la u-configurazione ' ;
Se D 0 allora la pila è vuota nella u-configurazione ' .
qi è lo stato in cui si trova `
DEF.: Nel caso dell’’automa a pila non deterministico, per una coppia di u-configurazioni scrivere-
mo: u : k , qi ,D |` l , q j , E
se `
contiene una transizione qi a h : i q j , dove D h J e
E i J , con J  : e:
l k e a 0;
oppure
2. l k 1 e il k-mo simbolo di u è a .
1.
Da notare che il push (pop) viene fatto inserendo (estraendo) nella stringa della pila un simbolo alla volta da sinistra, ad esempio, inserendo B nella pila in cui c’’è A, si ha: B A.
Chiaramente se h
0 oppure i
0 si avrà rispettivamente D
J oppure E
J.
In effetti il simbolo |` serve a descrivere il ““passaggio”” da una configurazione all’’altra di un automa pushdown nella lettura di un simbolo ( 0 compreso).
DEFF.: una successione '1 , ' 2 ,!, 'm è detta u-computazione di ` se valgono le seguenti condizioni:
1. '1 1, q ,0 (per un q  Q , lo stack è vuoto e viene letto il primo simbolo di u,
lo stato non è necessariamente quello iniziale);
2. 'm u 1, p, J con p  Q e J  :
3. u : ' i |` ' i 1 con 1 d i m .
La prima condizione rappresenta il passo iniziale della u-computazione, la seconda condizione rappresenta il passo finale, mentre la terza condizione rappresenta i passi intermedi della u-computazione.
La u-computazione appena vista è detta di accettazione se:
1. lo stato p a 'm è uno stato di accettazione;
2. lo stato q a '1 è lo stato iniziale q1 ;
3. la pila a 'm è vuota.
EDIT by Qd –– Grammatiche - XIV Lez.
61
Diremo che u è accettata da `
Con L `
` : L `
se vi è una u-computazione di accettazione di ` .
indichiamo l’’insieme di stringhe accettate da ` ovvero il linguaggio accettato da
^u | u  A , `
accetta u` (rif. D.S.W. pag. 320).
Nell’’esempio che segue si mostra come gli automi a pila siano capaci di riconoscere linguaggi non
regolari.
Esempio 1 (rif. D.S.W. pag. 312 –– ex.1): sia ` 1 un automa a pila, l’’alfabeto dell’’automa ^a , b` e quello
dello stack è
F
^ A`
(non confondere A con l’’usuale simbolo dell’’alfabeto), insieme degli stati Q
^q2 ` , le transizioni sono le seguenti: q1a 0 : Aq1,
^q1, q2 ` ,
q1bA : 0q2 , q2bA : 0q2 .
` 1 è deterministico infatti non ci sono coppie di istruzioni incompatibili tra loro; fin quando ` 1
legge il simbolo a viene fatto il push nello stack del simbolo A, questo sistema permette all’’automa di tenere traccia del numero di a lette, invece quando vengono lette b viene effettuato il pop dallo stack del simbolo A e si transita nello stato q2 .
Il linguaggio riconosciuto da questo automa è L ` 1 ^a > @b > @ | n ! 0` e lo si può verificare facenn
n
do degli esempi (facendo leggere delle stringhe del linguaggio all’’automa e verificando che l’’automa, alla fine della lettura
si trova in uno degli stati, in questo caso q2 , di accettazione).
Come si può notare da questo primo esempio di automa a pila, il linguaggio riconosciuto è proprio uno
di quei linguaggi non riconoscibili da automi finiti tradizionali (visti nella prima parte del corso), questo
per evincere subito la potenza di questo nuovo strumento, quale l’’automa pushdown.
Proviamo a far leggere all’’automa pushdown la stringa u ab da cui si ha la u-computazione:
'1 , ' 2 , ' 3 con '1 1, q1 ,0 , ' 2 2, q2 , A e ' 3 3, q2 ,0 , possiamo anche scriverla in questo modo:
u : 1, q1 ,0 |` 1 2, q1 , A |`
1
3, q2 ,0 .
Come possiamo notare, nella terza u-configurazione, lo stato è di accettazione e lo stack è vuoto, ciò
vuol dire che la stringa ab è stata accettata dall’’automa pushdown.
Inizialmente lo stack è vuoto, alla lettura del simbolo a, l’’automa pushdown resta nello stato iniziale q1 ,
mentre viene caricato il simbolo A nello stack. Alla lettura del simbolo b, l’’automa pushdown transita nello stato q2 e viene fatto il pop del simbolo A dallo stack.
Adesso facciamo un esempio con la stringa v aab che porta alla u-computazione:
'1 1, q1 ,0 , ' 2 2, q1 , A , ' 3 3, q1 , AA , ' 4 4, q2 , A che non è di accettazione in quanto in
' 4 l’’automa pushdown è sì pervenuto in uno stato di accettazione ma lo stack non è vuoto.
Ultima stringa su cui testare ` 1 è w aabb dalla quale otteniamo la sequenza:
w : 1, q1 ,0 |` 1 2, q1 , A |` 1 3, q2 , AA |` 1 4, q2 , A |` 1 5, q2 ,0 Dunque la stringa aabb è accettata da ` 1 .
EDIT by Qd –– Grammatiche - XIV Lez.
Decima Quinta Lezione –– prima parte
24/11/2006
esempi sugli Automi Pushdown e relativi teoremi
Esempio 2: sia ` 2 con AT
phabet), Q
^q1, q2 ` ,
F
^q2 ` ,
^a , b, c`
( AT sta per Tape alphabet), AP
^ A, B`
( AP sta per Pushdown al-
le transizioni seguono il seguente schema: q1a 0 : Aq1 , q1b 0 : Bq1 ,
q1c 0 : 0q2 , q2 aA : 0q2 , q2bB : 0q2 .
Anche in questo caso
loro.
` 2 è deterministico in quanto non ci sono coppie di istruzioni incompatibili tra
Il linguaggio riconosciuto da ` 2 è L ` 2 ^u ˜ c ˜ u
R
| u  ^a , b`
` (quindi stringhe del tipo, ad esempio,
a ˜ c ˜ a , ab ˜ c ˜ ba , aab ˜ c ˜ baa , ! ).
Proviamo a far leggere la stringa w abcba , otteniamo la sequenza di u-configurazioni:
w : 1, q1 ,0 |` 2 2, q1 , A |` 2 3, q1 , BA |` 2 4, q2 , BA |` 2 5, q2 , A |` 2 6, q2 ,0 .
Non è complicato capire il meccanismo di questo automa pushdown, alla lettura di simboli a o b allo
stato q1 vengono caricati nello stack rispettivamente i simboli A o B, mentre allo stato q2 vengono tolti
dallo stack rispettivamente i simboli A o B. Il cambio di stato avviene soltanto alla lettura del simbolo c.
Durante la prima parte nella lettura della stringa lo stack viene caricato, tenendo traccia della stringa u,
R
una volta letto c viene scaricato lo stack fin quando la stringa u non viene letta tutta.
Esempio 3: Sia ` 3 un automa pushdown con AT ^a , b` , AP ^ A, B` , Q ^q1 , q2 ` , F ^q2 ` ,
le transizioni sono le seguenti: q1a 0 : Aq1 ,. q1b 0 : Bq1 , q1aA : 0q2 , q1bB : 0q2 , q2 aA : 0q2 , q2bB : 0q2 .
Questo è il caso di un automa pushdown non deterministico infatti le coppie di transizioni prima-terza
e seconda-quarta non sono compatibili tra loro (stesso stato, stesso simbolo letto, ma uno dei pop per ciascuna coppia è 0 , cioè viene fatto un pop e un push contemporaneamente). In tal caso ` 3 ha la capacità di seguire più strade contemporaneamente quando si trova nello stato q1 nel leggere a o b .
` 3 riconosce il linguaggio L ` 3 ^u ˜ u
R
`
| u  ^a , b` š u z 0 (quindi stringhe del tipo, ad esempio,
a ˜ a , ab ˜ ba , b ˜ b , abb ˜ bba , ……).
aa : 1, q1 ,0 o |`
Nella lettura della parola aa si ottiene:
2
|`
3
2, q1 , A 2, q2 ,? 3
o |`
2
|`
3
3, q1 , AA 3
3, q2 ,0 .
Come si può notare ` 3 in più punti segue contemporaneamente strade differenti, ma, come accadeva per gli automi non deterministici tradizionali, non sempre certe strade vengono prese in considerazione, ma scartate, in questo caso due u-configurazioni vengono scartate, 2, q2 ,? perché non ha senso
effettuare il push da uno stack che è vuoto, 3, q1 , AA è sì accettabile come u-configurazione ma non
permette all’’automa pushdown di accettare la stringa aa, quindi viene anch’’essa scartata.
I linguaggi riconosciuti dagli automi pushdown ` 1 ` 2 , ` 3 sono tutti e tre C.F.
63
Come abbiamo visto gli automi a pila offrono grosse potenzialità, tuttavia esistono altri tipi di linguaggi che neanche gli automi a pila sono in grado di riconoscere, per cui esistono entità matematiche
ancora più potenti.
TEOREMA 8.3 (non dim. –– rif. D.S.W. pag. 316): Sia * una grammatica in forma normale di Chomsky, al-
lora vi è un automa a pila `
che riconosce il linguaggio generato da * , si ha quindi L `
TEOREMA 8.4 (non dim.): Per ogni linguaggio C.F. L, vi è un automa a pila `
linguaggio, si ha quindi L L ` .
TEOREMA 8.6 (non dim.): Per ogni automa a pila ` , L `
EDIT by Qd –– Grammatiche - XV Lez. - I parte
L * .
che riconosce tale
è un linguaggio C.F.
Calcolabilità
Decima Quinta Lezione – Seconda parte
24/11/2006
Introduzione ai Linguaggi di Programmazione
S-programmi
Introduzione ai Linguaggi di Programmazione
(rif. D.S.W. pag. 17)
Il linguaggio che andiamo a studiare ha istruzioni che operano su un alfabeto con apparenti limitazioni A # !0,1,2,!,9" , come vedremo linguaggi che agiscono su questo alfabeto hanno in realtà grosse
potenzialità per la soluzione dei problemi.
Attualmente si pensa che se non è possibile risolvere un problema con i mezzi che abbiamo oggi a disposizione (pratici e teorici), allora il problema in questione non potrà mai essere risolto, il problema è di fatto
irrisolvibile. Ovviamente tale affermazione non è dimostrata, ma fino ad ora è risultata vera.
DEFF.: Il concetto teorico di computabilità si basa su uno specifico linguaggio di programmazione
f (o S ). L’alfabeto di tale linguaggio è stato poco fa definito, le variabili avranno valori interi non negativi, in particolare denotiamo con i simboli:
X1 X2 X3 !
variabili di input (ingresso);
Y
è la variabile (unica) di output (uscita);
inoltre con i simboli:
Z1 Z2 Z3 !
denotiamo le variabili locali.
In qualche caso le variabili potranno essere denotate in minuscolo e il pedice 1 è spesso omesso, quindi
in luogo di X 1 ad esempio, scriveremo X.
A differenza dei linguaggi di programmazione effettivamente utilizzati, il linguaggio S non ha un limite
superiore (riferito ai valori che possono assumere le variabili) per via della sua natura teorica, tuttavia lavorare con questi linguaggi è piuttosto semplice, soprattutto per chi ha già un minimo di esperienza con la
programmazione.
Le istruzioni scritte e riconosciute dal linguaggio f sono sostanzialmente tre:
V $V % 1
V $V &1
IF V ' 0 GOTO L
incremento della variabile V;
decremento di V (se V # 0 il valore di V resta invariato);
condizionale (se V # 0 si passa all’istruzione successiva,
altrimenti si passa all’istruzione etichettata da L).
In aggiunta alle variabili viste fino ad ora utilizziamo i simboli: A1 B1 C 1 D1 E 1 A2 B2 ! (anche in
questo caso il pedice 1 può essere omesso). Questi simboli servono ad etichettare le istruzioni, racchiudendo tali simboli tra parentesi quadre [ ] , come mostrato nel seguente esempio:
65
(L) V $ V % 1
Il simbolo V viene considerato come una meta variabile, cioè un simbolo che
rappresenta un dato, nel nostro caso un numero intero non negativo.
L’uso delle etichette è indispensabile, soprattutto per le istruzioni condizionali.
Sulla base e sulla composizione delle istruzioni appena viste possiamo definire gli S-programmi, successioni finite e ordinate di istruzioni (ovviamente, a differenza degli insiemi, qui l’ordine con cui vengono scritte le
istruzioni è essenziale).
Per convenzione la variabile d’uscita Y e le variabili locali Z i con i * 1 inizialmente hanno valore
nullo 0.
Vediamo un primo esempio di S-programma (a):
( A)
X $ X &1
Y $Y %1
IF X ' 0 GOTO A
in questo caso X è l’unica variabile d’ingresso, Y quella di uscita, e come
definito, inizialmente Y # 0 .
Tale S-programma copia il valore di X in Y, formalmente scriveremo:
-1
fa +x , # .
/x
se x # 0
altrimenti
X viene decrementato e Y incrementato fintantoché X ' 0 ad ogni
passo del ciclo; se però inizialmente X # 0 , dopo la prima istruzione, X
varrà sempre 0, dopodichè Y verrà incrementato diventando 1, poiché
X # 0 durante l’istruzione condizionale IF il programma terminerà.
Vediamo un altro esempio di S-programma (b):
( A)
IF X ' 0 GOTO B 0
1
- Z $ Z %1
1c
3 . IF Z ' 0 GOTO E 1
/
2
&&&&&&&&&&&&&&
(B )
X $ X &1
0
1
Y $Y %1
1t
1
Z $ Z %1
1
IF Z ' 0 GOTO A 2
In questo caso risulta:
fb + x , # x, 4 x * 0
Se inizialmente X # 0 , Y rimane a 0 e si esce dal programma.
La variabile Z viene utilizzata come flag per uscire dal programma al
momento opportuno.
Le istruzioni denotate con * rappresentano quello che viene chiamato
salto incondizionato.
Il programma è suddiviso in due parti c e t . Il primo gruppo di
istruzioni è di controllo, mentre il secondo gruppo è quello che si
occupa del trasferimento vero e proprio dei valori numerici dalla
variabile X alla variabile Y.
L’etichetta E, non facendo riferimento a nessuna istruzione esistente,
fa terminare il programma (E sta per Exit).
EDIT by Qd – Calcolabilità – XV Lez. - II parte
66
L’esempio appena visto rappresenta un perfezionamento dell’S-programma precedente, il quale presentava un grave difetto e cioè di non restituire il risultato corretto nell’eventualità che X fosse nulla, infatti con X # 0 in uscita avremmo avuto Y # 1 e non Y # 0 . Nell’esempio corrente invece, per qualsiasi valore non negativo di X avviene la copia di X in Y (in verità non si tratta di una vera e propria copia, ma di un
trasferimento in quanto al termine del programma il valore iniziale di X va perduto diventando 0 – una sorta di taglia e incolla quindi).
Analizziamo ora le due istruzioni contrassegnate con *: Z $ Z % 1 e IF Z ' 0 GOTO E . Esse rappresentano il salto incondizionato perché indipendentemente dai valori che può assumere Z, l’esecuzione
di queste due istruzione porta alla terminazione del programma. Difatti Z non sarà mai non nulla e
quindi si salterà all’istruzione etichettata con E che, non esistendo, fa terminare il programma. La prima
istruzione ci assicura che, anche se Z fosse nulla, comunque porterebbe alla terminazione del programma, essendo incrementata a 1. Il salto incondizionato è stato realizzato a posta nel caso in cui si volesse
far terminare prematuramente il programma.
DEFF: Le due istruzioni viste poc’anzi, assieme a tante altre, sono molto utilizzate, è utile quindi
raggruppare queste istruzioni in un’unica entità che chiameremo macro (il cui significato è concettualmente
simile a quello adoperato per i linguaggi di programmazione effettivamente utilizzati sui calcolatori). È cioè una sequenza di istruzioni che può essere richiamata più volte all’interno di un S-programma indicando semplicemente il nome dato alla macro, senza dover, ogni volta riscrivere tutte le istruzioni di cui è composta la
macro.
La sequenza di istruzioni costituenti la macro viene chiamata espansione della macro.
Nel caso del salto incondizionato utilizzato nel precedente S-programma denotiamo la macro semplicemente così: GOTO L e la sua espansione è:
I nomi delle variabili e delle etichette non sono importanti, è necessario però far
corrispondere le variabili del programma chiamante con le istruzioni
dell’espansione della macro.
Z $ Z %1
IF Z ' 0 GOTO L
( A)
IF X ' 0 GOTO B
&&&&&&&&&&&&&&
GOTO C
(B ) X $ X & 1
Y $Y %1
Z $ Z %1
&&&&&&&&&&&&&&
GOTO A
(C )
IF Z ' 0 GOTO D
&&&&&&&&&&&&&&
GOTO E
(D ) Z $ Z & 1
X $ X %1
&&&&&&&&&&&&&&
GOTO C
Come avevamo già fatto notare i programmi (a) e (b) trasferiscono
il contenuto di X in Y , ma distruggendo (azzerando) il valore iniziale di
X. Usualmente si vuole che (durante una copia o assegnazione) il valore
di X resti intatto, come accade normalmente nelle istruzioni di assegnazione della maggior parte dei linguaggi di programmazione, quindi andiamo ad illustrare, facendo uso delle macro, il seguente S-programma
(c):
Analizzando le varie istruzioni ci si accorge che se inizialmente X è nullo allora il programma (dopo alcuni controlli e GOTO) restituirà il corretto valore (nullo) di Y (se
X # 0 5 GOTO C , se Z # 0 5 GOTO E , X # Y # 0 );
mentre se X ' 0 , prima si trasferisce il suo contenuto in Y e poi si ripristina il valore
iniziale di X in modo da ottenere dal programma i risultati desiderati (se
X ' 0 5 GOTO B , avviene il trasferimento da X a Y e anche a Z, mediante la reiterazione di alcune istruzioni);
si perde però il contenuto di X , il quale viene ripristinato contenuto della variabile d’appoggio Z nuovamente in X .
EDIT by Qd – Calcolabilità – XV Lez. - II parte
GOTO
D - trasferendo il
67
Chiaramente la funzione computata è la stessa del programma precedente: f c + x , # x , 4 x * 0 .
Si è fatto uso di macro che snelliscono il codice, è importante far corrispondere i nomi delle variabili
e le etichette delle istruzioni, ad esempio, GOTO C ha come espansione le due istruzioni: K $ K % 1
e IF K ' 0 GOTO C (l’uso della variabile K ci assicura, non essendo mai stata utilizzata, che altre variabili del programma chiamante non vengano compromesse, ovviamente la variabile C all’interno dell’espansione della macro corrisponde
alla variabile C usata per richiamare la macro, se ci fosse stata un’altra variabile nella chiamata, allora nell’espansione avremmo trovato lo stesso nome della variabile menzionata nella chiamata).
Anche se nell’espansione della macro si usassero nomi di variabili uguali a quelli utilizzati esternamente,
bisognerebbe distinguere le variabili locali dalle altre variabili e non fare confusione con ambiguità che
sporcherebbero il risultato.
Abbiamo visto nel terzo esempio di S-programma come una semplice operazione di assegnazione
non sia così immediata da realizzare con le operazioni atomiche che abbiamo a disposizione, oltretutto
sappiamo che l’assegnazione è un’operazione largamente usata nei linguaggi di programmazione, è molto utile quindi trasformare in macro il programma (c), tuttavia quest’ultima, se utilizzata in un altro
programma potrebbe non funzionare correttamente in quanto, per essere sempre corretta, le variabili Y
e Z inizialmente devono essere nulle, e non è detto che sia sempre così, in quanto la variabile Y in particolare potrebbe essere stata utilizzata dal programma chiamante e contenere dei valori non nulli al
momento della chiamata della macro di assegnazione. Bisogna quindi, prima di richiamare tale macro,
azzerare il valore della variabile a cui verrà assegnato il dato. Risolviamo il problema con la seguente macro di inizializzazione V $ 0 la cui espansione è:
(L) V $ V & 1
IF
V ' 0 GOTO L
Con l’ausilio dell’ultima macro vista possiamo riscrivere, in termini di macro, il programma (c) che
denoteremo con la scrittura V $ V 6 la cui espansione è la seguente:
V $0
( A)
IF
V 6 ' 0 GOTO B
GOTO
C
(B ) V 6 $ V 6 & 1
V $V %1
Z $ Z %1
GOTO
(C )
IF
A
Z ' 0 GOTO D
GOTO
E
(D ) Z $ Z & 1
V 6 $V 6%1
GOTO
C
EDIT by Qd – Calcolabilità – XV Lez. - II parte
(rif. D.S.W. pag. 21) Da notare che Z non è stata inizializzata a 0 in quanto è
considerata variabile locale (se nel programma chiamante viene utilizzata una
variabile con lo stesso nome Z allora questo nome deve essere cambiato), il
cui valore iniziale non viene ereditato dal programma chiamante né il suo
valore finale verrà restituito al programma chiamante, più precisamente la
variabile Z utilizzata nella macro non deve essere la stessa che,
eventualmente, verrà utilizzata nel programma chiamante, il discorso è
diverso invece per V (il cui nome e valore devono essere ereditati dal
programma chiamante, come visto prima nella macro GOTO L ).
È dunque buona norma, per evitare confusione, utilizzare per le variabili
locali nomi differenti da quelli utilizzati nel programma chiamante, analogo
discorso vale per le etichette delle istruzioni.
68
Vediamo ora un altro importante S-programma (d) che, ricevendo in input due valori, computa la
funzione f d + x 1 , x 2 , # x1 % x 2 .
Viene fatto uso della macro del salto incondizionato e dell’assegnazione.
Il programma effettua la somma di X 1 e X 2 ponendo il risultato in Y , ecco le istruzioni:
Y $ X1
Z $ X2
(B )
IF
Z ' 0 GOTO A
E
GOTO
( A)
L’uso della variabile Z ha lo scopo di preservare il valore di X 2 , il programma infatti funzionerebbe anche senza l’utilizzo della variabile
temporanea Z, ma alla fine il valore di X 2 andrebbe perso e, per lo stesso
principio per cui è stata progettata la precedente macro di assegnazione,
anche in questo caso si vuole che le variabili di entrata restino intatte.
Z $ Z &1
Y $Y %1
B
GOTO
Inizialmente viene posto il valore X 1 in Y;
dopodichè, mediante una variabile temporanea Z, Y viene incrementato di
una unità X 2 volte.
Proseguiamo col mostrare un altro S-programma (e) (rif. D.S.W. pag. 22) che esegue il prodotto di due
interi e che computa la funzione f e + x 1 , x 2 , # x1 7 x 2 :
Z2 $ X 2
(B )
IF
Z 2 ' 0 GOTO A
E
GOTO
La moltiplicazione viene interpretata come una sequenza di somme, vengono infatti eseguite X 2 somme di X 1 : X 1 % X 1 % ! % X 1
"##$##
%
X2
volte
( A) Z2 $ Z2 & 1
L’uso dell’etichetta E 2 , apparentemente non necessario, verrà spiegato a
3
breve. Come si può notare viene fatto uso della macro Z 1 $ X 1 % Y la cui
espansione è, in sostanza, il programma precedente. Ci sono però da fare
alcune riflessioni, il programma precedente sommava X 1 e X 2 e poneva il
risultato in Y , se volessimo utilizzarlo come macro, così com’è, nel contesto
di questo programma avremmo il seguente codice:
Z1 $ X 1 % Y
(E2 ) Y $ Z 1
B
GOTO
Y $ X1
Z $Y
(B )
IF
Z '0
GOTO
( A)
GOTO
E
Z $ Z &1
Y $Y %1
GOTO
B
A
Se osserviamo con attenzione i nomi delle variabili possiamo accorgerci che
utilizzando questo codice non otterremo il risultato sperato nel programma
chiamante, per via di ambiguità nell’uso delle etichette e delle variabili. L’uso del
GOTO E ad esempio porterebbe alla terminazione prematura del programma (e
non solo della macro come si potrebbe pensare), invece si vuole che, una volta
terminata la macro si ritorni al programma chiamante. Quindi è necessario fare
uso di un’altra etichetta ( E 2 ) sia nell’espansione della macro che nel programma
chiamante. Altro problema è rappresentato dalla variabile Y che, nel contesto del
programma chiamante, è confusa con la variabile Z 1 (abbiamo Z 1 $ X 1 % Y e
non Y $ X 1 % X 2 ). Quando nel programma chiamante scriviamo l’istruzione
Z 1 $ X 1 % Y ci aspettiamo che i valori di X 1 e di Y, dopo l’esecuzione della ma-
cro restino immutati e la loro somma venga memorizzata in Z 1 , ma ciò non avviene nell’espansione qui mostrata, oltre al problema dell’etichetta E. Quindi vanno cambiati i nomi di alcune variabili ed etichette.
EDIT by Qd – Calcolabilità – XV Lez. - II parte
69
Vediamo ora la corretta espansione da utilizzare per il programma chiamante con gli accorgimenti
appena suggeriti:
( B2 )
Z1 $ X 1
Z3 $ Y
IF
Z 3 ' 0 GOTO A2
GOTO
( A2 )
E2
Z3 $ Z3 & 1
Z1 $ Z1 % 1
GOTO B2
Vediamo l’ultimo S-programma ( f ) che, seppur con qualche limitazione, effettua la sottrazione di
due interi, ponendo il risultato nella variabile di uscita:
Y $ X1
(C )
Z $ X2
IF Z ' 0 GOTO A
GOTO E
( A)
IF Y ' 0 GOTO B
GOTO A
(B )
Y $Y &1
Z $ Z &1
GOTO C
Analizzando il programma si scopre che esso computa la seguente funzione: f f + x1 , x 2 , # x1 & x 2 se x 1 * x 2 mentre dà un
risultato indeterminato se x 1 8 x 2 , infatti il programma entra in
un ciclo infinito (loop), tale condizione viene indicata mediante
il simbolo 9
Il loop avviene quando in A la variabile Y è nulla, in tal caso si ritorna
(GOTO A) nuovamente all’istruzione A e questo processo si ripete all’infinito.
Formalmente possiamo scrivere la seguente funzione computata
- x1 & x 2 se x1 * x 2
.
dal programma : f f + x1 , x 2 , # .
altrimenti
/9
La funzione appena descritta prende il nome di funzione parziale il cui concetto è importante per
apprendere che non tutte le funzioni possono essere computate dagli S-programmi. Formalmente abbiamo:
DEFF. (rif. D.S.W. pag. 3): Se una funzione f ha come dominio di definizione un sottoinsieme di &
(sottoinsieme improprio A : & ) diremo che f è una funzione parziale sull’insieme & dei naturali.
Nel caso in cui la funzione parziale & abbia come dominio & stesso ( & : & ), allora tale funzione è
detta totale (cioè è sempre definita per tutti i valori di & ).
(rif. D.S.W. pag. 25) Con il termine asserzione (statement) indichiamo un’istruzione che può avere una
delle seguenti forme:
1.
2.
3.
4.
V $V %1
V $V &1
V $V
IF V ' 0 GOTO L
EDIT by Qd – Calcolabilità – XV Lez. - II parte
70
La terza istruzione è detta istruzione pigra (dummy) in quanto la sua esecuzione all’interno di un
programma non porta ad alcun effetto.
Formalmente un’istruzione è una delle quattro asserzioni viste, precedute o meno da ( L ) che è
un’etichetta generica data all’istruzione.
Un S-programma è una successione finita di istruzioni.
La lunghezza c
di un S-programma c è il numero delle sue istruzioni.
Un S-programma di lunghezza 0 è detto programma vuoto (è privo di istruzioni da cui f + x , # 0 4x ).
Come abbiamo visto, le variabili di un programma, durante l’esecuzione dello stesso, possono assumere valori differenti, ciò suggerisce la seguente definizione:
Lo stato di un problema c è una lista di equazioni nella forma V # m , con V nome della variabile
ed m il suo valore, tale che:
1. vi è un’equazione per ogni variabile di c ;
2. non vi sono due equazioni con la stessa variabile.
Quindi uno stato indica i valori che possono assumere in certi istanti, non necessariamente iniziali,
le variabili del programma.
Se ; è uno stato del programma c , il valore di V allo stato ; è il numero q tale che V # q è
una delle equazioni di ; .
Un’istantanea (snapshot) di un programma c è una coppia ordinata + i , ; , con 1 < i < n % 1 , il simbolo n corrisponde alla lunghezza (numero di istruzioni) del programma, mentre ; e uno stato ad un
certo istante dell’esecuzione del programma, in altre parole + i ,; , rappresenta il valore delle variabili
nell’istante precedente l’esecuzione della i-ma istruzione di c .
EDIT by Qd – Calcolabilità – XV Lez. - II parte
Decima Sesta Lezione
01/12/2006
Ricapitolazione e seguito concetti sugli S-programmi
funzioni parzialmente calcolabili - estensione delle macro
predicati - composizione di funzioni - ricorsione
Ricapitolazione concetti preliminari sugli S-programmi.
Data l’istantanea + i ,; , di c , i è il numero di istruzione corrente, mentre ; è l’assegnazione corrente di valori delle variabili.
DEFF.: Un’istantanea + i , ; , di c è detta terminale se i # c % 1 .
+ i,; , è detta non terminale se vi è un’istantanea + j ,= , che è successore di + i,; , .
Diamo una definizione per casi (in base alle asserzioni) di istantanea successore + j ,= , di + i , ; , :
1. la i-ma istruzione di c è V $ V % 1 e ; contiene tra le equazioni V # m , allora j # i % 1 e = si
ottiene da ; rimpiazzando V # m con V # m % 1 ;
2. la i-ma istruzione di c è V $ V & 1 e ; contiene tra le equazioni V # m , allora j # i % 1 e , se
m ' 0 , allora = si otterrà da ; rimpiazzando V # m con V # m & 1 , altrimenti (se m # 0 ) = # ; ;
3. la i-ma istruzione di c è V $ V , allora j # i % 1 e = # ; ;
è IF V ' 0 GOTO L allora = # ; (essendo un’asserzione di controllo e non di
modifica delle variabili, lo stato non cambia, ma il numero di istruzione potrebbe cambiare, se si effettua il salto), distinguiamo due sottocasi:
4. la i-ma istruzione di c
4.1.
se V # 0 , ; contiene l’equazione V # 0 , allora j # i % 1 (il salto non avviene e si prosegue con la successiva istruzione);
4.2.
se V ' 0 , ; contiene l’equazione V # m e, se l’etichetta L non fa riferimento a nessuna istruzione allora j # n % 1 (il programma termina, in questo caso l’istantanea successore di + i , ; , è un’istantanea
terminale + n % 1,= , ). Mentre se fa riferimento a una o più istruzioni, j sarà il più piccolo numero
tale che la j-ma istruzione è etichettata con L (ovvero la prima che si incontra dall’alto verso il
basso -per evitare diramazioni non deterministiche non facenti parte della natura degli S-programmi).
L’ultimo caso visto spiega anche il comportamento del programma in situazioni nelle quali ci sono
più istruzioni contrassegnate con la stessa etichetta, in tal caso si fa riferimento sempre alla prima che
si incontra (le altre verranno ignorate come se non esistessero).
(rif. D.S.W. pag. 29): Un calcolo (computation) di un S-programma
tanee s1 , s2 ,! , sk (l’ordine dei pedici non deve essere casuale) tale che si %1
ed sk è un’istantanea terminale.
c è una successione finita di istancon i # 1,2,!, k & 1 è successore di si
72
Un processo di calcolo non terminale (da non confondere con l’omonimo stato) di c
infinita di istantanee s1 , s2 ,! , tale che si %1 con i # 1,2,! è successore di si .
è una successione
DEFF. (rif. D.S.W. pag. 28) Sia c un S-programma e siano r1 , r2 ,!rm > & con m * 1 (m indica il numero
di variabili della funzione computata da c ), con lo stato ; di c
dato dalle equazioni X 1 # r1 ,
X 2 # r2 , ! , X m # rm , Y # 0 e dalle equazioni V # 0 per ogni altra variabile di c (variabili locali, in ogni
e con + 1,; ,
caso che non siano variabili di ingresso X i ,1 < i < m o di uscita Y ) denotiamo lo stato iniziale di c
istantanea iniziale, con tali condizioni possono verificarsi due casi:
1. vi è un calcolo di c : s1 , s2 ,!, sk (non si confonda s con r), allora con la scrittura
?c( m ) + r1 , r2 ,!, rm , indichiamo il valore di Y all’istantanea terminale sk con s1 # + 1,; , ;
? # 0 se il programma è terminante.
2. non vi è un calcolo di c (se l’istantanea iniziale è + 1,; , ) (ciò non vuol dire che il
programma non sta girando, ma che entra in un loop infinito). In tal caso
?c( m ) + r1 , r2 ,!, rm ,
assume un valore indefinito 9 .
In effetti con la definizione appena data si è formalizzato il comportamento di c
computazione e a partire dall’istantanea iniziale di c .
al termine della
Esempio 1: prendiamo in analisi il programma (b) che copiava il contenuto della variabile X in Y:
?c + x , # x chiaramente ( m # 1 in quanto la variabile d’ingresso è soltanto X ; X # x ; non dimentichiamo che è im(1)
b
plicito considerare il valore di ? cb presupponendo l’istantanea iniziale + 1, ; , ).
(1)
X $ X %1
, la cui istantanea iniziale, con ; stato iniziale,
X $ X %1
è: + 1,; , # + 1, ! X # r1 ,Y # 0" , . Dopo l’esecuzione della prima istruzione abbiamo + 2,! X # r1 % 1,Y # 0" ,
Esempio 2: consideriamo il programma:
e, dopo la seconda istruzione abbiamo + 3,! X # r1 % 2,Y # 0" , che è l’istantanea terminale. La variabile Y
non viene menzionata nelle istruzioni del programma, quindi il suo valore resta immutato e cioè nullo,
abbiamo dunque: ?c(1) + r1 , # 0 .
Esempio 3 (rif. D.S.W. pag. 31): consideriamo il programma c con le seguenti istruzioni:
( A) X $ X % 1
IF
X ' 0 GOTO A
(loop infinito)
Abbiamo la seguente istantanea iniziale
+1,! X # r % 1,Y
1
+1,! X # r ,Y
1
# 0" ,
e poi
+ 2,! X # r % 1,Y
1
# 0" , , + 2,! X # r1 % 2,Y # 0" , , ! da cui chiaramente ?c(1) + r1 , #9 , 4r1 * 0 .
# 0" , ,
DEFF. (rif. D.S.W. pag. 30): Per ogni c e per ogni intero positivo m, la funzione ?c( m ) + x 1 , x 2 ,!, x m , è
la funzione di m argomenti calcolata dal programma c .
EDIT by Qd – Calcolabilità – XVI Lez.
73
Da notare che m è un numero che si riferisce al numero di argomenti della funzione calcolata dal
programma e non dipende (o non si riferisce) al numero di variabili di input del programma, ovvero il
numero di argomenti della funzione calcolata dal programma non è legato al numero di variabili di input del programma. Ciò si evince da due casi particolari: abbiamo c con n variabili di input con
m 8 n (cioè nella funzione ?c( m ) compaiono meno argomenti del numero di variabili di input dell’S-programma c ), nel
calcolo della funzione risulterà: r1 # X 1 , r2 # X 2 ,!, rn # X n , rn %1 # 0,!, rm # 0 , cioè le variabili che non
fanno riferimento ad argomenti della funzione calcolata verranno considerati nulli anche se magari non
è effettivamente così;
viceversa, se m @ n (quindi abbiamo più argomenti della funzione che variabili di input del programma) i valori degli
argomenti non facenti riferimento a variabili del programma verranno semplicemente ignorati.
Per comprendere meglio i concetti appena descritti facciamo degli esempi di funzioni il cui numero
di argomenti non corrisponde al numero di variabili di input del relativo programma. Facciamo riferimento ai programmi (c) e (d ).
Come ricordiamo il programma (c) effettuava un’assegnazione, ha una sola variabile di input e abbiamo
?c(1)c + r1 , # r1 , qui abbiamo fatto combaciare il numero di argomenti della funzione con il numero di va-
riabili di input che è pari a 1. Mentre se volessimo conoscere il valore della funzione calcolata da (c) che
ha però due argomenti avremmo ?c(2)c + r1 , r2 , # r1 , chiaramente il valore r2 viene ignorato non essendo
corrispondente di alcun valore di variabile di input.
Ora riferiamoci al programma (d ) che effettuava la somma di due interi contenuti nelle due variabili di
input e la trasferiva nella variabile di uscita Y, abbiamo ?c(2)c + r1 , r2 , # r1 % r2 , mentre ?c(3) + r1 , r2 , r3 , # r1 % r2 ,
l’argomento r3 viene ignorato.
Vediamo ora il caso opposto ?c(1)c + r1 , # r1 % 0 # r1 , in questo caso lo 0 rimpiazza in qualche modo la va-
riabile del programma che non ha corrispondenza con alcuna variabile ( r2 non esiste, mentre X 2 si).
DEFF.: Sia g una funzione parziale (con una o più variabili) su & , allora g si dice parzialmente calcolabile se esiste un S-programma c che la calcola e cioè se per ogni m-pla + r1 , r2 ,!, rm , > S m : &m risul-
ta g + r1 , r2 ,!, rm , # ?c( m ) + r1 , r2 ,!, rm , .
Da sottolineare che nel caso in cui g + r1 , r2 ,!, rm , #9 e ?c( m ) + r1 , r2 ,!, rm , #9 non si può concludere
assolutamente che g # ?c( m ) in quanto il simbolo 9 non è numericamente esprimibile.
Una funzione è detta calcolabile se è totale ed è parzialmente calcolabile (una funzione totale è definita in
tutto il suo dominio, cioè per ogni m-pla di argomenti r1 , r2 ,! , rm ).
Le funzioni parzialmente calcolabili vengono chiamate anche ricorsive parziali, analogamente le funzioni calcolabili, cioè sia totali che ricorsive parziali, vengono anche dette ricorsive.
Ad esempio, dal programma visto prima:
( A) X $ X % 1
IF
X ' 0 GOTO A
EDIT by Qd – Calcolabilità – XVI Lez.
si ha ?c(1) + x , #9 che è una funzione indefinita per ogni
74
valore di x, possiamo dunque affermare che il dominio della funzione è l’insieme vuoto A che è pur
sempre un sottoinsieme di & (rif. D.S.W. pag. 3), quindi possiamo affermare che la funzione del programma suindicato appartiene alla Classe delle funzioni ricorsive parziali è quindi una funzione ricorsiva parziale (o anche parzialmente calcolabile) pur non essendo definita per alcun naturale (è quindi scorretto affermare che la funzione vista nell’esempio non è calcolabile).
Estensione delle macro
(rif. D.S.W. pag. 32)
Facendo riferimento all’uso delle macro, la seguente scrittura
W $ f +V1 ,V2 ,!,Vn ,
Rappresenta il trasferimento del valore di f +V1 ,V2 ,!,Vn , , calcolato da qualche S-programma, nella
variabile W. In effetti l’espansione della macro è una sequenza di istruzioni che calcola
?c( n ) +V1 ,V2 ,!,Vn , # f +V1 ,V2 ,!,Vn , , quindi f è una funzione calcolabile o parzialmente calcolabile e
W rappresenta una variabile generica (che potrebbe anche essere uno degli argomenti Vi di f ) .
Ricorrendo a regole generali per quanto riguarda l’uso appropriato dei nomi delle variabili e delle etichette delle istruzioni, si può ottenere uno schema generale per costruire espansioni di macro inserite
in programmi chiamanti (per il dettaglio vedere D.S.W. pagg. 32-33).
Un caso particolare si presenta quando risulta W $ f +V1 ,V2 ,!,Vn , e f +V1 ,V2 ,!,Vn , #9 , allora
anche la funzione calcolata dal programma chiamante la macro darà luogo ad un valore indeterminato.
Ad esempio, il seguente programma fa uso di macro le cui estensioni calcolano funzioni che assumono valori indeterminati per certi elementi del dominio:
Z $ X1 & X2
Y $ Z % X3
Poiché la macro Z $ X 1 & X 2 che fa riferimento al programma (f )
- x 1 & x 2 se x 1 * x 2
computa la funzione f f + x 1 , x 2 , # .
che per certi valori è indeterminata, questa indealtrimenti
/9
terminazione verrà in qualche modo tramandata alla funzione chiamante che infatti computa la funzio-B+ x 1 & x 2 , % x 3 se x 1 * x 2
ne ?c(3) + x 1 , x 2 , x 3 , # .
.
altrimenti
B/9
Per ovviare a questi inconvenienti possiamo arricchire il nostro linguaggio di programmazione, oltre
che con l’uso (opportuno) delle macro, anche con l’uso dei predicati (più articolati del tradizionale
V ' 0 ) all’interno dei costrutti selettivi IF.
DEF.: Un predicato P su un insieme S è una funzione totale tale che 4a > S risulta:
EDIT by Qd – Calcolabilità – XVI Lez.
75
- P + a , # 1 + vero ,
B
.oppure C
B P + a , # 0 + falso ,
/
(in realtà P può avere anche più di un argomento).
Un’osservazione interessante è che l’uso dei predicati non può essere adoperato per realizzare metodi algoritmici capaci di prevedere se un algoritmo andrà in loop oppure no (si può apprendere che un algoritmo è
entrato in loop esclusivamente quando entra in loop e non prima, vale ovviamente il contrario e cioè che non si può sapere a
priori se un algoritmo non andrà mai in loop o meno, ma ciò non basta per affermare, in generale, che un programma non si
arresterà mai, in quanto un programma entrato in un ipotetico loop potrebbe anche fermarsi da un momento all’altro, ammenoché noi non conosciamo le istruzioni del programma. Un’ ipotetica macchina che esegue un programma non può prevedere se questo avrà un calcolo (finito) o meno, tale certezza si ha solo se il programma termina). Conseguenza di que-
sto concetto si vedrà più avanti quando si esibirà un predicato che non è calcolabile mediante un Sprogramma.
Altro concetto da sottolineare è che facilmente si fa confusione tra predicato e funzione parzialmente
calcolabile. Un predicato è una particolare funzione che ha vita propria indipendentemente dagli Sprogrammi, un predicato è una funzione che, per come è stata definita, è sempre totale (e può assumere
solo e soltanto i vaori 1 e 0) al di là del fatto che possa o non possa essere calcolata da un S-programma
(potrà capitare di incontrare funzioni che a prima vista sembrano predicati per come sono strutturati, ma nel momento in
cui ci si accorge che tali presunti predicati assumono valori indeterminati o differenti da 0 o da 1, possiamo subito affermare
che non sono predicati, ma funzioni, poi se tali funzioni sono calcolabili o parzialmente calcolabili questo è un altro discorso).
Con l’uso delle macro la forma generale che assume il costrutto di selezione è:
IF P +V1 ,V2 ,!,Vn , GOTO L
D
la cui espansione è la seguente:
Z $ P +V1 ,V2 ,!,Vn ,
IF Z ' 0 GOTO L
Viene calcolato P è memorizzato il risultato in Z;
se P è vero alloro Z ' 0 quindi si va all’istruzione L;
altrimenti Z # 0 e la macro termina.
Vediamo ora l’esempio con un predicato largamente utilizzato:
IF V # 0 GOTO L
D
ecco la sua espansione (non si è badato all’uso corretto dei nomi delle variabili
e delle etichette delle istruzioni):
IF X ' 0 GOTO E
Y $Y %1
EDIT by Qd – Calcolabilità – XVI Lez.
in questo caso il valore del predicato è memorizzato in Y e X corrisponde a V ;
si ricordi che Y inizialmente è nullo;
se X ' 0 la macro termina (GOTO E) e il valore di Y
resta nullo, il programma chiamante passa all’istruzione successiva;
se invece X # 0 allora Y # 1 e il programma chiamante passa all’istruzione L;
Nell’esempio quindi, se il predicato "V # 0" è vero assumerà un valore
non nullo, quindi si passerà all’istruzione L.
76
DEF. (rif. D.S.W. pag.34-35) : Essendo P una particolare funzione, ha senso dire che P è o non è calcolabile, quindi si parla di predicato calcolabile o non calcolabile in base alle definizioni date prima di funzioni calcolabili (essendo i predicati funzioni totali, non ha senso parlare di parziale calcolabilità, abbiamo dunque che se esiste un S-programma che calcola il predicato P, allora P è calcolabile).
Mediante una generalizzazione possiamo fornire un esempio di predicato calcolabile che è il seguente:
IF
V @0
GOTO
L
Il quale è chiaramente una generalizzazione dell’istruzione
IF
V '0
GOTO
L.
Composizione di funzioni
(rif. D.S.W. pag. 39)
Mostriamo un metodo per combinare l’output di una o più funzioni all’input di un’altra funzione
(ad una o più variabili) sulla base delle funzioni composte del tipo: h + x , # f + g + x , , . Diamo pertanto
la seguente definizione per formalizzare e generalizzare il concetto:
DEF.: Sia f una funzione di k variabili e siano g 1 , g 2 ,!, g k funzioni di n variabili. Se scriviamo
3 h + x 1 , x 2 ,!, x n , # f + g 1 + x 1 , x 2 ,!, x n , , g 2 + x 1 , x 2 ,!, x n , ,!, g k + x 1 , x 2 ,!, x n , , allora si dice che h è ottenuta per composizione da f e g 1 , g 2 ,!, g k .
Attenzione a non confondere il numero n di variabili di h con il numero di variabili k di f , si sarebbe
portati a pensare che essendoci un’uguaglianza tra h ed f il numero di argomenti di h debba coincidere
con quello di f , ma h è una funzione composta i cui argomenti sono x 1 , x 2 ,! , x n e non g 1 , g 2 ,! , g k ,
quindi l’uguaglianza definita poc’anzi è ben posta.
Del resto ha senso scrivere ad esempio che f j + x 1 , # f k + x 1 , x 2 , se si applica la diagonalizzazione
dell’argomento, cioè si impone x 1 E + x 1 , x 2 , con x 1 # x 2 , le funzioni sono uguali sebbene f j ha un argomento mentre f k ne ha due.
Ovviamente le funzioni f , g 1 , g 2 ,! , g k non sono necessariamente totali e h sarà calcolata quando tutte le funzioni g 1 + x 1 , x 2 ,! , x n , # z1 , g 2 + x 1 , x 2 ,! , x n , # z 2 , … ,
g k + x 1 , x 2 ,! , x n , # z k ed f + z1 , z 2 ,! , zn , saranno calcolate. Tale imposizione può essere
giustificata facendo uso delle macro e verificando la correttezza dell’uguaglianza 3 in
questo modo:
Z 1 $ g 1 + X 1 , X 2 ,! , X n ,
Z 2 $ g 2 + X 1 , X 2 ,! , X n ,
33
'
Z k $ g k + X 1 , X 2 ,! , X n ,
&&&&&&&&&&&&&
Y $f
+ Z 1 , Z 2 ,! , Z k ,
EDIT by Qd – Calcolabilità – XVI Lez.
durante la computazione vengono calcolate
prima tutte le funzioni g 1 , g 2 ,!, g k
e memorizzati i valori rispettivamente
in Z 1 , Z 2 ,!, Z k ;
dopodichè le variabili Z vengono adoperate
per il calcolo di f il cui valore viene
memorizzato in Y
77
La macro vista è utile per dimostrare il teorema seguente:
TEOREMA 1.1 (banale – rif. D.S.W. pag 39): Se h è ottenuta per composizione delle funzioni (parzialmente) calcolabili f , g 1 , g 2 ,!, g k allora h è (parzialmente) calcolabile.
DEF.: dobbiamo dimostrare che se f , g 1 , g 2 ,!, g k sono (parzialmente) calcolabili allora anche h è (parzialmente) calcolabile, ciò è immediato osservando la macro 33 , infatti per dimostrare che h è (parzialmente) calcolabile dobbiamo fornire un S-programma che la calcola utilizzando le funzioni (parzialmente) calcolabili (per ipotesi) f , g 1 , g 2 ,!, g k . È ovvio che se Z i $ g i + X 1, X 2 ,!, X n , , con 1 < i < k , e
Y $ f + Z 1, Z 2 ,!, Z k , sono (parzialmente) calcolabili, ne deriva che h è (parzialmente) calcolabile.
Ricorsione
(rif. D.S.W. pag. 40)
h +0, # k
h + t % 1, # g + t , h + t , ,
DEF.: Supponiamo che k sia una costante e h una funzione definita
in questo modo:
g è una funzione totale di due variabili, allora diremo che h
è ottenuta da g per ricorsione primitiva o semplicemente per ricorsione .
TEOREMA 2.1: Se h è ottenuto da g per ricorsione primitiva e posto g calcolabile (g per definizione è totale), allora h è anch’essa calcolabile (quindi totale anch’essa).
DIM.: È facile provare che una funzione costante del tipo f + x , # k è calcolabile, infatti essa è calcolata
ad esempio dall’S-programma:
Y $Y %1 F
Y $ Y % 1 BB
G k volte
'
B
Y $ Y % 1 BH
queste istruzioni rappresentano l’espansione della macro Y $ k .
La macro appena vista la utilizziamo per calcolare la funzione h ottenuta da g per ricorsione primitiva:
( A)
Y $k
si calcola prima k e si memorizza il risultato in Y;
IF X # 0 GOTO E
se l’argomento di h è 0 allora si esce dal programma e h + 0 , # k # Y ;
altrimenti (per hp. g è calcolabile quindi il suo valore viene
calcolato e memorizzato in Y ) viene effettuato il calcolo di h + t % 1 , # g + t , h + t , ,
un passo alla volta incrementando il parametro t partendo da 0, cioè seguendo la
sequenza:
Y $ g + Z ,Y ,
Z $ Z %1
X $ X &1
GOTO A
EDIT by Qd – Calcolabilità – XVI Lez.
78
h +0, # k # Y
h + 1 , # g + 0, h + 0 , , # g + 0, k ,
h + 2 , # g + 1, h + 1 , ,
'
h + x & 1 , # g + x & 2, h + x & 2 , ,
h + x , # g + x & 1, h + x & 1 , ,
Avendo fornito un S-programma che calcola h abbiamo dimostrato il teorema.
Complichiamo un po’ il concetto appena visto in modo da dare una definizione più generale di ricorsione.
DEF.: Sia:
h + x 1 , x 2 ,!, x n ,0 , # f + x 1 , x 2 ,!, x n ,
h + x 1 , x 2 ,!, x n , t % 1, # g + t , h + x 1 , x 2 ,!, x n , t , , x 1 , x 2 ,!, x n ,
allora la funzione h a n % 1 variabili si dice ottenuta per ricorsione primitiva o semplicemente per ricorsione dalle funzioni totali f (di n variabili) e g (di n % 2 variabili).
TEOREMA 2.2: Sia h ottenuta dalle funzioni a più variabili f e g per ricorsione primitiva (secondo
la definizione appena vista), se f e g sono calcolabili allora h è anch’essa calcolabile.
DIM.: Come per il teorema precedente, basta trovare un S-programma che calcola h (questa strategia ricorda
quella adoperata per dimostrare teorema sui linguaggi regolare e C.F. per i quali si esibivano rispettivamente automi riconoscitori e grammatiche generatrici). Ricordiamo che per ipotesi g ed f sono calcolabili, il seguente S-
programma calcola h, il cui schema è del tutto simile a quello dell’S-programma utilizzato per la dimostrazione del teorema precedente :
( A)
Y $ f + X 1 , X 2 ,!, X n ,
IF X n %1 # 0 GOTO E
viene memorizzato il valore di f in Y
il parametro t della funzione h è rappresentato dalla variabile X n %1
Y $ g + Z ,Y , X 1 , X 2 ,!, X n , se risulta h + x 1 , x 2 ,! , x n , 0 , il programma termina e il suo valore di
Z $ Z %1
X n%1 $ X n%1 & 1
GOTO A
EDIT by Qd – Calcolabilità – XVI Lez.
uscita sarà Y $ h + x 1 , x 2 , ! , x n , 0 ,
altrimenti parte il ciclo che calcola la funzione ricorsiva partendo
da t # 1, ! , t # X n %1
Decima Settima Lezione
5/12/2006
Classi PRC
Funzioni e Predicati primitivi ricorsivi
Classi PRC
(rif. D.S.W. pag. 42)
DEFF.: Sia data una classe V di funzioni totali, si dice che essa è una classe PRC ( primitive recursively clo-
sed ) se:
1. V contiene le funzioni iniziali (che definiremo tra poco);
2. V contiene funzioni ottenute da funzioni, che appartengono a V , mediante composizione e ricorsione primitiva.
Le seguenti funzioni sono chiamate funzioni iniziali :
s +x , # x %1
n+x , # 0
funzione successore ;
u + x 1 , x 2 ,!, x n , # x i con 1 < i < n
n
i
funzione nulla ;
funzioni di proiezione .
TEOREMA 3.1: La classe delle funzioni calcolabili è una classe PRC.
DIM.: Dobbiamo dimostrare che le funzioni iniziali e le funzioni ottenute mediante composizione e ricorsione primitiva da funzioni della classe PRC sono calcolabili. I teoremi 1.1 (composizione di funzioni), 2.1
(ricorsione con una variabile) e 2.2 (ricorsione con più variabili) dimostrano parte del teorema, manca da verificare che le funzioni iniziali siano calcolabili, quindi bisogna esibire degli S-programmi che le computino. La funzione successore s + x , # x % 1 è calcolata dal programma Y $ X % 1 , mentre la funzione
n+x , # 0
è calcolata dal
programma vuoto , infine le (infinite) funzioni di proiezione
uin + x 1 , x 2 ,!, x n , # x i sono calcolate dai programmi Y $ X i .
Quindi possiamo concludere che la classe delle funzioni calcolabili è una classe PRC.
DEF.: Una funzione è detta primitiva ricorsiva (il concetto di funzione primitiva ricorsiva è diverso da quello
di funzione appartenente ad una classe PRC sebbene i due concetti siano strettamente connessi fra loro) se può essere ottenuta dalle funzioni iniziali applicando un numero finito di volte composizione e ricorsione primitiva,
da cui abbiamo:
COROLLARIO 3.2: La classe delle funzioni primitive ricorsive è una classe PRC, la cui dimostrazione è
immediata.
DEF.: Si distinguono tre sottoclassi:
I
V1 : classe PRC di funzioni totali calcolabili da S-programmi;
I
V2 : classe di funzioni primitive ricorsive;
I
V3 : classe di tutte le funzioni totali su & .
80
TEOREMA 3.3 (rif. D.S.W. pag. 43): Una funzione è primitiva ricorsiva se e solo se J appartiene a tutte
le classi PRC (quindi l’insieme delle funzioni primitive ricorsive rappresenta il nucleo di ogni classe PRC, intersezione di
tutte le classi PRC).
DIM. K : Dimostrare che se una funzione appartiene a tutte le classi PRC allora è una funzione primitiva ricorsiva è una cosa abbastanza semplice, in quanto per il corollario 3.2 la classe delle funzioni primitiva ricorsive è una classe PRC (una funzione che appartiene a tutte le classi PRC per il corollario 3.2 apparterrà anche
alla classe PRC delle funzioni primitive ricorsive, quindi deve essere necessariamente una funzione primitiva ricorsiva).
DIM. 5 : Vogliamo ora dimostrare che se una funzione è primitiva ricorsiva allora appartiene ad ogni
classe PRC (e non solo alla classe PRC delle funzioni primitive ricorsive). Sia f una funzione primitiva ricorsiva e
V una classe PRC qualsiasi, vogliamo dimostrare che f >V . Essendo f primitiva ricorsiva essa deriva
(è ottenuta) da una serie di funzioni f 1 , f 2 ,!, f n , dove ogni funzione o deriva dalle precedenti mediante
composizione o ricorsione, oppure è una funzione iniziale. Le funzioni iniziali (per la definizione data di
classe PRC) appartengono alla classe PRC V e (sempre per definizione) vi appartengono anche tutte le
funzioni ottenute per ricorsione o per composizione, quindi f >V da cui (avendo considerato V come una qualunque classe PRC) abbiamo che f appartiene alla classe PRC, più precisamente f appartiene
a ogni classe PRC.
COROLLARIO 3.4: Ogni funzione primitiva ricorsiva è calcolabile (ciò non vuol dire necessariamente che
ogni funzione appartenente ad una classe PRC qualsiasi è calcolabile, si ribadisce il fatto che il concetto di funzione primitiva
ricorsiva è differente da quello di funzione appartenente ad una classe PRC). Il contrario non è sempre vero, infatti esistono
funzioni calcolabili che non sono primitive ricorsive.
DIM.: La dimostrazione è immediata, osservando il teorema precedente si ha che ogni funzione primitiva ricorsiva appartiene ad ogni classe PRC e ciascuna classe PRC è costituita da funzioni calcolabili (per la
definizione di classe PRC e per il teorema 3.1).
Dagli ultimi concetti visti si può affermare che una qualsiasi classe PRC deve contenere almeno le
funzioni primitive ricorsive, in più può contenere altre funzioni totali purché soddisfino le proprietà di
cui devono godere le funzioni appartenenti ad una classe PRC (si richiede cioè che siano totali e ottenute
dalle funzioni iniziali o da altre funzioni appartenenti alla classe mediante composizione e ricorsione, da
cui si può intuire che una classe PRC potrebbe contenere anche funzioni iniziali non calcolabili,
l’importante è che il gruppo di funzioni iniziali sia almeno rappresentato dalle infinite funzioni successore, nulla e di proiezione, ma ciò non vieta che possano esistere classi PRC costitute da funzioni iniziali
aggiuntive). È importante fissare bene i concetti visti fino ad ora, in quanto molto di ciò che seguirà si
baserà su questi concetti.
Diamo ora un elenco di funzioni primitive ricorsive (e quindi calcolabili):
1)
x%y
E
f1 + x, y , # x % y
Vediamo come ricavare la funzione adoperando solo le operazioni di ricorsione e composizione:
EDIT by Qd – Calcolabilità – XVII Lez.
81
f 1 + x ,0 , # x ,
f 1 + x , y % 1, # f 1 + x , y , % 1
f 1 + x ,0 , # u11 + x , ,
da cui ricaviamo: 3
+
con g 1 + x 1 , x 2 , x 3 , # s u23 + x 1 , x 2 , x 3 ,
,
f 1 + x , y % 1, # g 1 + y , f 1 + x , y , , x ,
# x2 % 1
Per comprendere meglio l’uso della ricorsione primitiva riscriviamo la formula 3 utilizzando le lettere
adottate per la definizione di ricorsione primitiva per funzioni a più variabili, abbiamo:
h + x 1 ,0 , # u1 + x 1 , ,
1
h + x 1 , t % 1, # g + t , h + x 1 , t , , x 1 ,
dove chiaramente h corrisponde a f 1 , x 1 a x,
t ay
g a g1 .
e
Abbiamo ottenuto tali equazioni adoperando le operazioni di composizione (in particolare g 1 è stata ottenuta componendo le funzioni iniziali proiezione e successore) e ricorsione primitiva.
La funzione 1) è quindi ricorsiva primitiva dunque calcolabile (sebbene già sapessimo che tale funzione era
calcolata dal programma (d) ora sappiamo che è anche primitiva ricorsiva).
Vediamo ora un altro esempio di funzione primitiva ricorsiva:
2)
x7y
h2 + x , y , # x 7 y
E
ottenibile da:
h2 + x ,0 , # 0,
h2 + x , y % 1, # h2 + x , y , % x
da cui:
h2 + x ,0 , # n + x , # 0,
h2 + x , y % 1, # g 2 + y , h2 + x , y , , x ,
+
,
con g + x 1 , x 2 , x 3 , # f 1 u23 + x 1 , x 2 , x 3 , , u33 + x 1 , x 2 , x 3 , , dove chiaramente f 1 è la funzione somma vista prima.
Si ha difatti:
+
,
f 1 u2 + x 1 , x 2 , x 3 , , u3 + x 1 , x 2 , x 3 , # f 1 + x 2 , x 3 , # x 2 % x 3
3
3
# h2 + x , y , % x .
Le formule viste, osservando la natura delle funzioni utilizzate, portano ad affermare che la funzione
h2 è primitiva ricorsiva.
3)
x!
(fattoriale) E
0! # 1,
+ x % 1, ! # x ! 7 s + x ,
più precisamente se x ! # h3 + x , abbiamo:
,
h3 + 0 , # 1,
h3 + t % 1, # g 3 + t , h3 + t , ,
con g 3 + x 1 , x 2 , # s + x 1 , 7 x 2 che è primitiva ricorsiva in quanto può essere scritta così:
EDIT by Qd – Calcolabilità – XVII Lez.
82
g 3 + x 1 , x 2 , # s + u12 + x 1 , x 2 , , 7 u22 + x 1 , x 2 , (chiaramente il prodotto usato è una funzione primitiva ricorsiva),
quindi la funzione fattoriale è una funzione primitiva ricorsiva.
Le funzioni che abbiamo visto sono state costruite mediante le funzioni iniziali che possono essere
immaginate come dei mattoni, mentre la ricorsione primitiva e la composizione sono il cemento con il
quale costruire le funzioni primitive ricorsive; ogni volta che viene aggiunta una funzione al nostro bagaglio di funzioni ricorsive primitive possiamo adoperarla a mo’ di mattone per costruire funzioni primitive ricorsive più complesse, proprio come abbiamo fatto per la funzione g 3 , per costruire la quale
abbiamo adoperato il prodotto visto in precedenza, mentre è sottinteso che la funzione h3 + 0 , è ottenuta da s + 0 , . Osservando tale principio si ottengono le seguenti funzioni potenza e predecessore:
x 0 # 1,
4)
xy E
5)
p5 + 0 , # 0,
- x & 1 se x ' 0
p5 + x , E p5 + x , # .
da cui abbiamo:
se x # 0
p5 + t % 1, # t
/0
x
y %1
(da notare che in questo caso 0 # 1 );
0
# x 7x
y
In questo caso la funzione p5 può essere computata dalla singola istruzione: X $ X & 1 , risulta
+ 1,
p5 + x , # ? c5 + x , con c5 : X $ X & 1 .
In termini di funzioni iniziali le due funzioni appena viste si ottengono come segue:
4)
5)
h4 + x ,0 , # s + n + x , , # 1,
h4 + x , t % 1, # g 4 + t , h + x , t , , x ,
p5 + 0 , # 0,
p5 + t % 1, # g 5 + t , p5 + t , ,
+
,
con g 4 + x 1 , x 2 , x 3 , # h2 u23 + x 1 , x 2 , x 3 , , u33 + x 1 , x 2 , x 3 , # x 2 7 x 3 ;
con g 5 + x 1 , x 2 , # u12 + t , .
Proseguiamo la rassegna di funzioni primitive ricorsive:
6)
-x & y
x &( y (differenza tra x e y) E x &( y # .
/0
se x * y
se x 8 y
il puntino serve a distinguere tale funzione
da quella vista in precedenza x & y il cui valore per x 8 y è indefinito, mentre in questo caso non lo è, la funzione 6 è
dunque totale (altrimenti non ci sarebbero neanche i presupposti per affermare che essa è primitiva ricorsiva).
In termini di ricorsione primitiva la 6 diventa:
x &( 0 # x ,
x &( + t % 1, # p5 + x &( t ,
EDIT by Qd – Calcolabilità – XVII Lez.
e in termini di funzioni iniziali abbiamo:
83
h6 + x ,0 , # u11 + x , # x ,
h6 + x , y % 1, # g 6 + y , h6 + x , y , , x ,
+
con g 6 + x 1 , x 2 , x 3 , # p5 u23 + x 1 , x 2 , x 3 ,
,
7) x & y (valore assoluto della differenza tra x e y), tale funzione può essere scritta in termini di funzioni primitive ricorsive precedentemente definite: x & y # + x &( y , % + y &( x , .
Se x * y + x &( y , % + y &( x , # + x & y , % 0 # x & y , mentre se x 8 y si ha
+ x &( y , % + y &( x , #
# 0 % + y & x , # y & x . In entrambi i casi otteniamo il valore assoluto della differenza tra x e y .
-1 se x # 0
8) L 8 + x , (rivelatore dello 0) E L 8 + x , # .
la quale può essere espressa in questo mo/0 se x ' 0
do: L 8 + x , # 1 &( x (se x # 0 , L 8 + x , # 1 & 0 # 1 , mentre se x ' 0 ( * 1) si ha L 8 + x , # 1 & x # 0 ).
Alternativamente si può esprimere la funzione 8 in termini di ricorsione primitiva in questo modo:
L 8 + 0 , # 1,
L 8 + t % 1, # 0
.
Oltre alle funzioni primitive ricorsive mostriamo due predicati primitivi ricorsivi (rif. D.S.W. 49):
9)
-1
x # y E d9 + x, y , # .
/0
x#y
la quale si può ottenere così: d 9 + x , y , # L 8 + x & y ,
se x ' y
se
Se x # y , si ha d 9 + x , y , # L 8 + x & y , # L 8 + 0 , # 1 , altrimenti si ha d 9 + x , y , # L 8 + x & y , # 0
poiché x & y ' 0 .
10)
-1
x < y E h10 + x , y , # .
/0
se
x<y
altrimenti
ottenibile da: L 8 + x &( y , .
Se x < y , si ha h10 + x , y , # L 8 + x &( y , # L 8 + 0 , # 1 , altrimenti si ha h10 + x , y , # L 8 + x &( y , #
# L8 + x & y , # 0 .
TEOREMA 5.1: Sia V la classe PRC. Se P e Q sono predicati appartenenti a V , allora lo sono anche
) P , P CQ e P &Q .
DIM.: Basta ricondurre tali predicati a equazioni primitive ricorsive, si ha: ) P # L 8 + P , ,
P & Q # P 7 Q e, utilizzando le leggi di De Morgan, P C Q # ) + ) P & ) Q , # L +L + P , 7 L +Q , , .
Il teorema appena visto è importante perché la tesi è uno strumento essenziale per costruire un vastissimo numero di predicati primitivi ricorsivi.
EDIT by Qd – Calcolabilità – XVII Lez.
84
COROLLARIO 5.2: Sia V la classe di tutte le funzioni primitive ricorsive. Se P e Q sono predicati
primitivi ricorsivi, allora lo sono anche ) P , P C Q e P & Q .
COROLLARIO 5.3: Sia V la classe di tutte le funzioni calcolabili. Se P e Q sono predicati calcolabili,
allora lo sono anche ) P , P C Q e P & Q .
Dagli ultimi risultati visti mostriamo un altro predicato primitivo ricorsivo:
11)
-1
x 8 y E h11 + x , y , # .
/0
se
altrimenti
x 8 y J + x < y ,& ) + x # y ,
x 8 y J ) + y < x,
x8y
ottenibile così:
(minore e non uguale) oppure così:
(non maggiore e non uguale).
TEOREMA 5.4 (definizione per casi – rif. D.S.W. pag. 50): Sia V una classe PRC, siano g e h funzioni appartenenti a V e sia P un predicato anch’esso appartenente a V . Se:
if P # 1
then
!
g
x
,
x
,
,
x
se
P
x
+
,
+
B
1
2
n
1 , x 2 ,!, x n ,,
f + x 1 , x 2 ,!, x n , # .
else
Bh + x , x ,!, x , altrimenti
1
2
n
/
allora f è una funzione primitiva ricorsi-
va, cioè appartenente anch’essa alla classe PRC V .
Ciò che abbiamo appena visto può essere interpretato con un costrutto selettivo, se il predicato P è vero
(cioè uguale a 1) allora la funzione f sarà uguale a g altrimenti la funzione f sarà uguale ad h .
DIM.: la dimostrazione è ovvia poiché basta scrivere f sottoforma di espressioni contenenti funzioni primitive ricorsive, si ha:
f + x 1 , x 2 ,!, x n , # g + x 1 , x 2 ,!, x n , 7 P + x 1 , x 2 ,!, x n , % h + x 1 , x 2 ,!, x n , 7 L 8 + P + x 1 , x 2 ,!, x n , , .
Se P è vero risulta:
f + x 1 , x 2 ,! , xn , # g + x 1 , x 2 ,! , xn , 7 1 % h + x 1 , x 2 ,! , xn , 7 L 8 + 1, #
# g + x1 , x 2 ,! , xn , % h + x1 , x 2 ,! , xn , 7 0 # g + x1 , x 2 ,! , xn , ;
se P è falso si ha:
f + x1 , x 2 ,! , xn , # g + x1 , x 2 ,! , xn , 7 0 % h + x1 , x 2 ,! , xn , 7 L 8 + 0 , #
# 0 % h + x 1 , x 2 ,! , x n , 7 1 # h + x 1 , x 2 ,! , x n , .
COROLLARIO 5.5: Sia V una classe PRC, siano g 1 , g 2 ,!, g m , h funzioni ad n variabili appartenenti,
assieme ai predicati P1 , P2 ,!, Pm anch’essi ad n variabili, alla classe V , posto:
Pi + x 1 , x 2 ,!, x n , & Pj + x 1 , x 2 ,!, x n , # 0 , 4x 1 , x 2 ,!, x n e 41 < i 8 j < m
(i predicati possono essere
o tutti falsi oppure al più
uno solo vero e gli altri falsi)
EDIT by Qd – Calcolabilità – XVII Lez.
85
Se:
- g 1 + x 1 , x 2 ,!, x n , se P1 + x 1 , x 2 ,!, x n , ,
B
B g 2 + x 1 , x 2 ,!, x n , se P2 + x 1 , x 2 ,! , x n , ,
B
f + x 1 , x 2 ,! , x n , # .'
B g x , x ,!, x
se Pm + x 1 , x 2 ,! , x n , ,
n,
B m+ 1 2
Bh + x 1 , x 2 ,!, x n ,
altrimenti
/
allora f appartiene a V .
Il fatto che uno solo dei predicati può essere vero è perché il valore di f deve essere univoco, infatti se
fossero veri due predicati, f dovrebbe assumere due valori contemporaneamente e ciò non è consentito.
Il corollario può essere interpretato come uno switch (o case, costrutto di selezione esteso dei linguaggi di
programmazione).
DIM.: La dimostrazione va fatta per induzione su m (numero dei predicati):
I
I
(passo base) m # 1 : il corollario è dimostrato perché si riduce al teorema 5.4;
(passo induttivo) m % 1 : presupponendo che il corollario sia vero per m. Basta ricondurre il caso
per m % 1 a quello di m in questo modo:
- g 1 + x 1 , x 2 ,! , x n ,
B
B g 2 + x 1 , x 2 ,!, x n ,
B
f + x 1 , x 2 ,! , x n , # .'
Bg
B m %1 + x 1 , x 2 ,!, x n ,
Bh + x 1 , x 2 ,! , x n ,
/
se P1 + x 1 , x 2 ,! , x n , ,
se P2 + x 1 , x 2 ,! , x n , ,
se Pm %1 + x 1 , x 2 ,! , x n , ,
altrimenti
ora se poniamo:
-B g m %1 + x 1 , x 2 ,!, x n , se Pm %1 + x 1 , x 2 ,! , x n , ,
h 6 + x 1 , x 2 ,! , x n , # .
altrimenti
B/h + x 1 , x 2 ,! , x n ,
dal teorema 5.4 possiamo affermare che h 6 >V , possiamo allora riscrivere f così:
- g 1 + x 1 , x 2 ,!, x n , se P1 + x 1 , x 2 ,!, x n , ,
B
B g 2 + x 1 , x 2 ,!, x n , se P2 + x 1 , x 2 ,! , x n , ,
B
f + x 1 , x 2 ,! , x n , # .'
B g x , x ,!, x
se Pm + x 1 , x 2 ,! , x n , ,
n,
B m+ 1 2
Bh 6 + x 1 , x 2 ,!, x n , altrimenti
/
Abbiamo dunque ridotto il problema a dimensione m che per ipotesi di induzione è vero, quindi il
corollario è dimostrato.
EDIT by Qd – Calcolabilità – XVII Lez.
Decima Ottava Lezione
12/12/2006
operazioni iterate e quantificatori limitati
minimalizzazione
altre funzioni e predicati primitivi ricorsivi
Operazioni Iterate e Quantificatori Limitati
(rif. D.S.W. pag. 52)
TEOREMA 6.1: Sia V una classe PRC. Se f + t , x 1 , x 2 ,!, x n , >V allora appartengono a V anche le
funzioni così definite:
y
y
t #0
t #0
g + y , x 1 , x 2 ,! , x n , # M f + t , x 1 , x 2 ,! , x n , e h + y , x 1 , x 2 ,! , x n , # N f + t , x 1 , x 2 ,! , x n , .
DIM.: Bisogna dimostrare il teorema adoperando le seguenti equazioni ricorsive:
g + 0, x 1 , x 2 ,! , x n , # f + 0, x 1 , x 2 ,!, x n , ,
e
g + t % 1, x 1 , x 2 ,! , x n , # g + t , x 1 , x 2 ,! , x n , % f + t % 1, x 1 , x 2 ,! , x n ,
h + 0, x 1 , x 2 ,!, x n , # h + 0, x 1 , x 2 ,!, x n , ,
h + t % 1, x 1 , x 2 ,! , x n , # h + t , x 1 , x 2 ,! , x n , 7 f + t % 1, x 1 , x 2 ,! , x n ,
Le funzioni g + t , x 1 , x 2 ,!, x n , e h + t , x 1 , x 2 ,!, x n , si ricavano da queste formule di ricorsione finché
non si risale a f + 0, x 1 , x 2 ,!, x n , , quindi il teorema è dimostrato.
di:
Qualche volta la sommatoria o la produttoria cominceranno da t # 1 e non t # 0 , scriveremo quiny
y
t #1
t #1
g + y , x 1 , x 2 ,! , x n , # M f + t , x 1 , x 2 ,! , x n , e h + y , x 1 , x 2 ,! , x n , # N f + t , x 1 , x 2 ,! , x n , .
Per la relativa dimostrazione bisogna sostituire i casi base delle formule ricorsive viste poco fa con queste:
g + 0, x 1 , x 2 ,!, x n , # 0 e h + 0, x 1 , x 2 ,!, x n , # 1 da cui, più formalmente, abbiamo il seguente:
COROLLARIO 6.2 (rif. D.S.W. pag. 53): Sia V una classe
tengono a V anche le due funzioni:
PRC,
se f + t , x 1 , x 2 ,!, x n , >V allora appar-
y
y
t #1
t #1
g + y , x 1 , x 2 ,! , x n , # M f + t , x 1 , x 2 ,! , x n , e h + y , x 1 , x 2 ,! , x n , # N f + t , x 1 , x 2 ,! , x n , .
TEOREMA 6.3 (teorema analogo al precedente, ma relativo ai predicati, rif. D.S.W. pag. 53 – si veda anche, per i quantificatori limitati, D.S.W. pag. 7): Se il predicato P + t , x 1 , x 2 ,! , x n , >V , con V classe PRC, allora appartengono a V anche i predicati:
+ 4t ,< y P + t , x1 , x 2 ,!, xn , e + Ot ,< y P + t , x1 , x 2 ,!, xn , .
87
Tali scritture indicano rispettivamente i predicati QU e Q E , in particolare le scritture + 4t ,< y e
+ Ot ,< y vengono chiamate rispettivamente quantificatore universale limitato e quantificatore esistenziale
limitato. “Limitato” indica il fatto che hanno significato soltanto per valori minori o uguali di y . Più esplicitamente il predicato QU può essere scritto così:
4t < y | P + t , x 1 , x 2 ,! , x n , QU + y , x 1 , x 2 ,!, x n ,
per ogni t < y se risultano veri tutti i predicati P allora QU è vero
e QU può essere espresso come segue:
QU + y , x 1 , x 2 ,!, x n , J P + 0, x 1 , x 2 ,! , x n , & P + 1, x 1 , x 2 ,! , x n , & ! & P + y , x 1 , x 2 ,! , x n ,
+P,
+P,
+P,
il predicato QU è vero soltanto se sono veri tutti i predicati P
;
Mentre il predicato Q E viene così espresso:
Ot < y | P + t , x 1 , x 2 ,! , xn , Q E + y , x 1 , x 2 ,!, xn ,
esiste almeno un t < y per cui è vero il predicato P allora Q E è vero
e Q E può essere espresso come segue:
Q E + y , x 1 , x 2 ,!, x n , J P + 0, x 1 , x 2 ,!, x n , C P + 1, x 1 , x 2 ,! , x n , C ! C P + y , x 1 , x 2 ,! , x n ,
+|,
+|,
+|,
il predicato Q E è vero soltanto se almeno uno dei predicati P è vero
.
Passiamo alla dimostrazione del teorema:
DIM.: In modo immediato si giunge a dimostrare il teorema osservando che:
QS y
0 R
+ 4t ,t < y P + t , x1 , x 2 ,!, xn , J TT VN P + t , x1 , x 2 ,!, xn , 1 # 1 UU
2 Y
X W t #0
affinché la produttoria valga 1 tutti i predicati devono essere veri
e
QS
y
0
R
2
Y.
+ Ot ,t < y P + t , x1 , x 2 ,!, x n , J TT V M P + t , x1 , x 2 ,!, xn , 1 ' 0 UU
X W t #0
affinché la sia non nulla, almeno un predicato deve essere vero
Avendo espresso i predicati mediante espressioni primitive ricorsive appartenenti alla classe
teorema è dimostrato.
Da notare che il predicato QU può essere anche espresso così:
S y
0
t
P
t
,
x
,
x
,
!
,
x
4
#
+ ,t < y + 1 2
V N P + t , x 1 , x 2 ,! , x n , 1
n,
W t #0
2
il predicato è uguale alla produttoria dei predicati P che se
risultano tutti veri rende la produttoria pari a 1 che
corrisponde a valore vero
EDIT by Qd – Calcolabilità – XVIII Lez.
PRC
il
88
Non si può esprimere in maniera analoga il predicato Q E in quanto il valore della sommatoria potrebbe essere 0, 1 o
anche valori maggiori di 1 (non ammessi per desumere il valore di un predicato, vero o falso, non sarebbe quindi più considerato un predicato, ma una funzione), mentre nel caso precedente la produttoria poteva assumere soltanto valori pari a 0 o
a 1.
Analogamente a quanto succedeva nel teorema 6.1 (in cui esisteva la variante in cui t partiva da 1 e non da 0),
nel caso attuale talvolta potremmo utilizzare le seguenti scritture:
+ 4t ,8 y e + Ot ,8 y
( “ 8 y ” e non “ < y ” )
Il teorema rimarrebbe valido se esprimiamo i quantificatori come segue:
+ Ot ,t 8 y P + t , x1 , x 2 ,!, x n , J + Ot ,t < y SWt ' y & P + t , x1 , x 2 ,!, xn , 02
esiste almeno una t < y tale che t ' y e P vero
e
+ 4t ,t 8 y P + t , x1 , x 2 ,!, xn , J + 4t ,t < y SWt # y C P + t , x1 , x 2 ,!, xn , 02
per ogni t < y risulta che se t # y allora P può anche essere falso,
mentre se t ' y , affinche il predicato QU sia vero, P deve essere
necessariamente vero
Vediamo ora altri esempi di predicati primitivi ricorsivi:
12) y | x
(y è un divisore di x)
( 3 | 12 E vero , mentre 3 | 13 E falso ).
Adoperando gli ultimi teoremi visti si scopre che questo predicato è primitivo ricorsivo infatti si può esprimere così:
y | x J + Ot ,< x + y 7 t # x ,
in effetti si cerca il primo valore non maggiore di x per cui y 7 t # x .
Lo si cerca non maggiore in quanto se t @ x si avrebbe y #
sore (intero) di x ;
13) Primo + x ,
x
t
e 0 < y 8 1 che non può essere un divi-
(x è un numero primo)
È un predicato primitivo ricorsivo anche questo, infatti:
Primo + x , J
x @1
*
un numero primo
deve essere >1
& + 4t ,< x !t # 1 C t # x C ) + t | x ," .
"###
#$####
%
EDIT by Qd – Calcolabilità – XVIII Lez.
a eccezione dell'1 e di se stesso
non deve avere divisori
89
Minimalizzazione
(rif. D.S.W. pag 55)
Dal teorema 6.1 sappiamo che se il predicato P + t , x 1 , x 2 ,!, x n , >V con V classe
funzione:
y
u
g + y , x 1 , x 2 ,! , x n , # M N L + P + t , x 1 , x 2 , ! , x n , ,
u #0 t #0
PRC,
allora la
appartiene a V .
Analizziamo la funzione supponendo per prima cosa che il predicato P per un valore t 0 < y sia:
P + t , x 1 , x 2 ,! , x n , # 0
per
t 8 t0
mentre si ha:
P + t 0 , x 1 , x 2 ,!, x n , # 1
In altre parole t 0 rappresenta il più piccolo valore che può assumere t che rende vero il predicato P. Per
valori di t 8 t 0 il predicato risulta falso, mentre per t # t 0 il predicato è vero (non ci interessa sapere il valore
del predicato per valori di t @ t 0 ) .
Da ciò possiamo affermare che:
3
u
1 se u 8 t 0
L + P + t , x , x ,!, x , , # .
N
0
t #0
1
Se u 8 t 0 abbiamo
u
/
se u * t 0
N L + P + t , x 1 , x 2 ,! , x n , , =
t #0
mentre se u # t 0 otteniamo
t
n
2
&1
t0
u
NL +0, =
t #0
u
N1 = 1
t #0
;
N L + P + t , x1 , x 2 ,! , xn , , #
t #0
S0
0
# V N L + P + t 0 & 1, x 1 , x 2 , ! , x n , , 1 7 L + P + t 0 , x 1 , x 2 ,! , x n , , # 1 7 L + 1, # 1 7 0 # 0 ;
W t #0
2
chiaramente per valori u @ t 0 il risultato rispetto al caso precedente non cambia, infatti si avrebbe una
produttoria in cui compare almeno uno 0, quindi l’espressione varrà sempre 0 da t 0 in poi.
Chiaramente, poiché lo 0 non porta contributo alla somma, possiamo riscrivere la funzione g in
questo modo:
g + y , x 1 , x 2 ,! , x n , #
M 1#t
u 8t 0
0
sommatoria di tutti i valori assunti dalla
produttoria a partire da 0 fino ad arrivare
a u 8 t0
y
L’espressione
u
viene fatto il conteggio di tutte le volte che l’espressione 3
risulta vera;
quindi la funzione g altro non è che il più piccolo valore
t 0 per cui P + t , x 1 , x 2 ,! , x n , è vero
MN L + P + t , x 1 , x 2 ,! , xn , , va interpretata come un contatore di predicati falsi.
u #0 t #0
EDIT by Qd – Calcolabilità – XVIII Lez.
90
DEF.: Definiamo ora la seguente scrittura:
-B g + y , x 1 , x 2 ,!, x n ,
min P + t , x 1 , x 2 ,!, x n , # .
t<y
B/0
se
+ Ot ,< y P + t , x1 , x 2 ,!, x n , ,
altrimenti
In pratica se esiste un minimo questo varrà almeno 1, se non esiste (alcun predicato vero) varrà 0.
Quindi min P + t , x 1 , x 2 ,!, x n , rappresenta il più piccolo valore che può assumere t + < y , per il quale il
t<y
predicato P risulta vero, questo se t esiste; se questo valore t non esiste la funzione assume valore nullo.
Utilizzando i teoremi 5.4 (it…then…else) e 6.3 (quantificatori limitati) abbiamo il seguente:
TEOREMA 7.1: Sia V una classe PRC, se P + x 1 , x 2 ,!, x n , >V e risulta
f + y , x 1 , x 2 ,! , x n , # min P + t , x 1 , x 2 ,! , x n , , allora f + y , x 1 , x 2 ,! , x n , >V .
t<y
DIM.: Come già anticipato la dimostrazione si ricava adoperando i teoremi 5.4 e 6.3, la quale è immediata.
Dal teorema 6.3 si dimostra che + Ot ,< y P + t , x 1 , x 2 , ! , x n , è primitiva ricorsiva, quindi con questa
ipotesi, dal teorema 5.4 (definizione per casi) si dimostra anche che min P + t , x 1 , x 2 , ! , x n , è primitiva
t<y
ricorsiva e che quindi appartiene ad una classe PRC.
DEF.: L’operazione min
viene chiamata minimalizzazione (limitata).
t<y
Grazie all’ultima definizione data, possiamo definire un’altra funzione primitiva ricorsiva:
14)
WV x y 21
(parte intera –base– del quoziente x y )
( WV 7 2 21 # 3, VW2 3 21 # 0 )
Mediante la minimalizzazione otteniamo:
VW x y 12 # min SW+ t % 1, 7 y @ x 02
t <x
da notare che compare min e non min , infatti se comparisse y, ad
t <x
t<y
esempio VW5 121 non darebbe il risultato corretto, in quanto y # 1
e min (+ t % 1 , 7 y @ x ) # 0 .
t<y
Quindi la 14 è una funzione primitiva ricorsiva.
L’uso della minimalizzazione funziona per tentativi, ovvero VW x y 12 è il più piccolo intero t < x tale che
+ t % 1, 7 y @ x . Facciamo un esempio WV5 2 21 # 2 , partendo da t # 0 , il predicato risulta falso:
+ t % 1, 7 y @Z x J 1 7 2 @Z 5 ; andiamo avanti con t # 1 , il predicato risulta ancora falso: + t % 1, 7 y @Z x J
J 2 7 2 @Z 5 ; proviamo per t # 2 , il predicato in questo caso è vero infatti si ha: + t % 1 , 7 y @ x J
J 3 7 2 @ 5 . Quindi VW5 2 12 # t # 2 . Il predicato in questo caso risulta vero 4t * 2 , ma la ricerca si inter-
EDIT by Qd – Calcolabilità – XVIII Lez.
91
rompe a 2, che, avendo adoperato la minimalizzazione limitata, rappresenta il minimo valore per cui risulta vero il predicato.
Importante notare che per come è stata definita la 14 il caso particolare di VW x 0 12 # 0 , (infatti
min (+ t % 1 , 7 y @ x ) # 0 , in quanto per tutti i valori di t < x il predicato risulterà sempre falso, non esistendo alcun valore
t <x
di t per cui sia vero il predicato, per come è stata definita la minimalizzazione limitata).
Dalla 14 ricaviamo la
R + x, y ,
15)
(funzione resto (remainder), della divisione tra x e y)
E possiamo esprimerla così: R + x , y , # x &( + y 7 VW x y 12 , che è chiaramente primitiva ricorsiva.
La formula si ottiene in quanto x # WV x y 21 7 y % R + x , y , J R + x , y , # x &( + WV x y 21 7 y , .
Anche per questa funzione c’è un caso particolare, risulta R + x ,0 , # x (infatti x &( + 0 7 WV x 0 12 , #
# x &( 0 # x ).
Altra funzione importante è la seguente:
pn con n @ 0 (n-mo numero primo)
16)
Stabiliamo che p0 # 0 , quindi avremo p1 # 2, p2 # 3, p3 # 5, p4 # 7, p5 # 11,!
Per esprimere pn ci serviamo delle equazioni di ricorsione, abbiamo:
p0 # 0,
pn %1 # min SPrimo + t , & t @ pn 0
t < pn ! %1 W
2
Per verificare la correttezza dell’uguaglianza dobbiamo verificare che valga la disequazione:
pn %1 < + pn , ! % 1 . L’ + n % 1,&mo numero primo si ricava utilizzando n & mo numero primo ricorsiva-
mente e corrisponde al più piccolo numero + t , che sia primo e sia (ovviamente) maggiore di pn , il valore + t , però non deve essere maggiore di pn ! % 1 .
Notiamo che vale l’uguaglianza:
Essendo
1
pi
+ pn , !
%1
pi
pi
>
Z & ( pi * 2 ) ed essendo
affermare che pi non divide
infatti
+ pn , ! % 1
#
+ pn , !
pi
%
1
pi
#K %
+ pn , !
pi
1
pi
con
K
intero e
08i <n
> & (risulta infatti
+ pn , ! % 1 , ovvero + pn , ! % 1
.
+ pn , !
pi
#
pn 7 + pn & 1 , 7 ! 7 pi 7 ! 7 3 7 2
pZ i
> & ) possiamo
non è divisibile per nessun numero primo p1 , p2 , ! , pn (risulta
che rappresenta la somma di una quantità intera per un’altra non intera, il cui risultato è una
quantità non intera). Da quest’ultima affermazione potrebbe risultare che:
a)
(out) o
+ pn , ! % 1
è un numero primo (un numero primo non è divisibile per numeri primi minori di es-
so e ciò basta per affermare che un numero primo non è divisibile per alcun numero minore di esso, mag-
EDIT by Qd – Calcolabilità – XVIII Lez.
92
giore di 1; numeri minori di esso non primi comunque non lo dividono, in quanto costituiti da numeri
primi che non lo dividono, insomma credo che ci siamo capiti !);
b) (out) oppure
+ pn , ! % 1
è divisibile per un numero primo maggiore di pn (questa è un’eventualità del
tutto possibile).
In entrambi i casi quindi possiamo affermare che esiste un numero primo q tale che:
pn 8 q < + pn , ! % 1
(infatti se vale a) allora
+ pn , ! % 1 @
pn e ciò non esclude che tra
+ pn , ! % 1
e
pn ci siano altri numeri primi; se invece vale b) deve esistere un numero
primo maggiore di pn che divide
+ pn , ! % 1 , appunto q).
Quindi abbiamo che pn %1 < + pn , ! % 1 (poiché se pn 8 q < + pn , ! % 1 allora pn 8 pn %1 < q < + pn , ! % 1 ), ciò assicura
la correttezza dell’uguaglianza pn %1 # min S Primo + t , & t @ pn 0 .
t < pn ! %1
W
2
Tale procedimento deriva dalla dimostrazione di Euclide circa l’inesistenza di un estremo superiore
dell’insieme dei numeri primi (insieme infinito), la quale si dimostra per assurdo.
Abbiamo dato per scontato che pn fosse una funzione primitiva ricorsiva, dimostriamolo:
SPrimo + t , & t @ y 02
sia: h + y , z , # min
t <z W
la quale calcola il più piccolo numero primo t tale che
y 8t <z e
sia: k + x , # h + x , x ! % 1, che calcola il più piccolo numero primo t tale che x 8 t < x ! % 1 .
Le funzioni appena definite sono primitive ricorsive e le possiamo adoperare per riscrivere la formula ricorsiva usata per definire pn , si ha:
p0 # 0,
pn %1 # k + pn ,
possiamo quindi concludere che pn è una funzione primitiva ricorsiva.
Tale funzione calcolabile è importante per farci capire che, ad esempio, linguaggi con stringhe di lunghezza p, con p numero primo, non sono C.F., mentre gli S-programmi hanno la capacità di generare numeri primi. Inoltre i numeri primi, per le loro proprietà, sono importanti (essenziali) per la numerazione di
Gödel che vedremo a breve.
Vale la pena notare che, utilizzando i vari teoremi visti e le macro in modo opportuno, possiamo effettivamente costruire un S-programma f che realmente calcoli pn , ma tale programma sarebbe estremamente inefficiente (per calcolare pn bisogna calcolare prima tutti i numeri primi precedenti pi
con 0 8 i 8 n ).
DEF.: Andiamo ora ad analizzare la minimalizzazione quando questa non è limitata, la rappresentiamo così:
min P + x 1 , x 2 ,! , x n , y ,
y
intendendo il più piccolo valore che può assumere y per cui
il predicato P + x 1 , x 2 ,! , x n , y , risulta vero.
EDIT by Qd – Calcolabilità – XVIII Lez.
93
Mentre nella minimalizzazione limitata veniva rappresentato il più piccolo valore t < y ( $ limite superiore) per cui valeva il predicato P.
Non avendo però limiti, in questo caso, se non ci dovesse essere alcun valore di y per cui sia vero il
predicato P + x 1 , x 2 ,! , x n , y , allora il valore che assume la minimalizzazione non limitata è indefinito,
in quanto non è in grado di stabilire se c’è un valore y per cui valga P ammenoché questo valore non esista.
Quindi si capisce bene che la minimalizzazione non limitata può produrre funzioni che non sono
totali. Chiaro esempio di questo concetto è il seguente:
x & y # min ( y % z # x )
la quale è indefinita se x 8 y (infatti la funzione continuerà a testare all’infinito
z
y % z # x che sarà sempre falso).
Il prossimo teorema formalizza il concetto secondo cui esistono predicati del tipo P + x , y , che sono
primitivi ricorsivi tali che min P + x , y , è una funzione che non è primitiva ricorsiva:
y
TEOREMA 7.2 (rif. D.S.W. pag. 58): Se P + x 1 , x 2 ,! , x n , y , è un predicato calcolabile e
g + x 1 , x 2 ,! , x n , # min P + x 1 , x 2 ,! , x n , y , allora g è una funzione parzialmente calcolabile (cioè non è detto
y
che sia totale).
DIM.: È semplice dimostrare il teorema, basta trovare un S-programma che calcola g + x 1 , x 2 ,!, x n , :
( A)
IF P + X 1 , X 2 ,! , X n ,Y
Y $Y %1
GOTO A
,
GOTO E
il programma cicla finché Y non soddisfa il predicato
Tale programma dimostra che g + x 1 , x 2 ,!, x n , è parzialmente calcolabile (ma non è detto che g sia anche totale, in quanto potrebbe assumere un valore indefinito 9 , se il predicato P risultasse falso per
qualsiasi valore di Y.
Un’osservazione, se volessimo realizzare un predicato mediante composizione di funzioni, del tipo ad e-
+
,
sempio: P0 min P + x 1 , x 2 , ! , x n , y , , questa è di fatto una funzione parzialmente calcolabile, non esseny
do totale (poiché min potrebbe assumere valore intederminato 9 ) non può essere considerata un predicato parzialmente calcolabile in quanto per definizione i predicati sono funzioni totali. Quindi P0 non è un
predicato.
Funzioni di Accoppiamento
e
Numerazione di Gödel
(per la codifica numerica dei programmi – rif. D.S.W. pag. 59)
Ora vediamo un metodo di codifica che ci permette di esprimere in modo biunivoco un dato Sprogramma mediante i numeri, tale codifica / decodifica è assicurata dall’utilizzo di particolari funzioni
primitive ricorsive, dette di accoppiamento e mediante l’uso dei numeri primi in modo opportuno (esiste
EDIT by Qd – Calcolabilità – XVIII Lez.
94
un’unica rappresentazione per fattori di numeri primi per ciascun numero naturale, dal teorema fondamentale
dell’aritmetica).
DEF.: Andiamo a definire le funzioni di accoppiamento (pairing functions - dette anche di angoletto). Tali
funzioni servono a codificare in modo univoco coppie di numeri naturali, mediante la rappresentazione
di un intero, come segue:
x , y # 2 x 7 + 2 y % 1, &( 1
tale funzione è primitiva ricorsiva.
Poiché risulta 2 x 7 + 2 y % 1, ' 0 , l’operazione &( non darà mai come risultato 0, se non quando
2 x 7 + 2 y % 1, # 1 , quindi possiamo trattare &( come una normale sottrazione (cioè le lacune di &( in questo caso non hanno effetto) e ci è consentito spostare l’1 al primo membro dell’uguaglianza:
x , y % 1 # 2 x 7 + 2 y % 1, .
Sia z un numero intero dato, allora l’equazione x , y # z avrà un’unica soluzione (rif. D.S.W. pagg. 59-60).
DEF.: Dalla funzione di accoppiamento posso definire altre due funzioni primitive ricorsive:
l +z , e r +z ,
(dette rispettivamente il sinistro di z e il destro di z) e risulta:
l +z , # x e r +z , # y
l +z , < z e r +z , < z
e dall’equazione di accoppiamento risulta:
poiché x , y 8 z % 1 .
Possiamo esprimere le due funzioni appena definite mediante funzioni primitive ricorsive, ricordando anche che x # l + z , e y # r + z , sono uniche, così:
l + z , # min SW+ Oy ,<z + z # x , y , 02
x <z
e
r + z , # min SW+ Ox ,<z + z # x , y , 02
y <z
.
Possiamo interpretare tali funzioni dicendo che l + z , + r + z , , è il più piccolo numero x
+ y,
per cui
vale l’equazione z # x , y , se esiste un y < z + x < z , che soddisfa tale uguaglianza.
Quindi, se la funzione di accoppiamento ci permette di ricavare z da x e da y, le funzioni sinistro e
destro ci permettono di ricavare rispettivamente x e y da z. Di conseguenza la seguente biiezione è vera:
x, y # z J x # l +z , & y # r +z , .
EDIT by Qd – Calcolabilità – XVIII Lez.
95
Ricapitoliamo le proprietà delle funzioni viste mediante il seguente:
TEOREMA 8.1 (sulla funzione di accoppiamento): Le funzioni x , y , l + z , ed r + z , hanno le seguenti proprietà:
1. sono primitive ricorsive ;
2. l + x , y
,#x
ed r + x , y
,# y
;
l + z ,,r +z , # z ;
3.
4. l + z , , r + z , < z .
Ora andiamo a definire una funzione primitiva ricorsiva per la codifica e decodifica di un’arbitraria
sequenza di numeri, ovvero definiamo il numero di Gödel:
DEF.: Chiamiamo numero di Gödel della sequenza + a1 , a2 ,!, an , la seguente funzione primitiva ricorsiva (indicando in parentesi quadre [ ] la sequenza da codificare):
n
( a1 , a2 ,!, an ) # N piai
(chiaramente pi sta per l’i-mo numero primo)
i #1
Tale funzione (assieme ad un’altra funzione che vedremo a breve) ci permette di effettuare una codifica / decodifica biunivoca della sequenza + a1 , a2 ,!, an , , in quanto viene fatto uso dei numeri primi e si
fa leva sul teorema fondamentale dell’aritmetica (ricordiamolo, secondo il quale ogni intero ha una fattorizzazione
unica di numeri primi).
Esempio di numero di Gödel per la sequenza + 3, 1, 5, 4,6 , , viene così espresso: ( 3,1,5, 4,6 ) ed è uguale
3
1
5
a p17p27p 37p
4
4
7p
6
5
3
1
5
4
6
# 2 7 3 7 5 7 7 7 11 # 319 013 847 075 000 . Trattando con numeri primi e po-
tenze è facile ottenere valori spropositati molto facilmente.
Per ogni n fissato la funzione ( a1 , a2 ,! , an ) è primitiva ricorsiva.
TEOREMA 8.2 (rif. D.S.W. pag. 61): La numerazione di Gödel soddisfa la seguente proprietà: se
( a1 , a2 ,!, an ) # (b1 , b2 ,!, bn ) allora ai # bi , 1 < i < n .
Quest’ultima implicazione è proprio conseguenza di quanto detto prima circa l’unicità della fattorizzazione di numeri primi. Però c’è da considerare un caso particolare:
( a1 , a2 ,!, an ) # ( a1 , a2 ,!, an ,0)
e più in generale:
( a1 , a2 ,!, an ) # ( a1 , a2 ,!, an ,0,0,!,0) .
Ciò accade perché pn0%1 # 1 , tale fattore lascia immutata la produttoria, in pratica, aggiungendo zeri
in coda alla sequenza di numeri, il numero di Gödel non cambia. Quindi per convenzione il numero di
Gödel pari a 1 corrisponde alla sequenza vuota, sequenza di lunghezza 0. A eccezione di questo caso la
biunivocità è comunque assicurata per tutti gli altri casi, infatti se si aggiunge uno o più zeri in testa o in
mezzo alla sequenza il numero di Gödel cambia.
EDIT by Qd – Calcolabilità – XVIII Lez.
96
Esempi:
( 2, 0, 3) # 2
( 2, 3) # 2 2 7 33
2
0
# 108 e
( 2, 3, 0) # 2 2 7 33 7 50
# 108 ; ma
( 0, 2, 3) # 2 0 7 32 7 5 3
# 1125 e anche
3
7 3 7 5 # 500 .
Ora definiamo una funzione primitiva ricorsiva che ci è utile per la decodifica dei numeri di Gödel:
+ x ,i
e lo chiameremo i-mo componente del numero di Gödel (o anche funzione di proiezione).
Se x # ( a1 , a2 ,! , an ) allora + x ,i # ai , 1 < i < n e può essere espresso mediante la seguente funzione
primitiva ricorsiva:
+ x ,i # min
+ ) pit %1 | x ,
t <x
da cui si possono verificare i casi particolari in cui + x ,0 # 0 e + 0 ,i # 0, 4i .
La funzione appena vista cerca il più piccolo intero t + < x , tale che pit %1 non divide x (stiamo dunque cercando un esponente t proprio perché i numeri della sequenza codificati compaiono come esponenti). Più intuitiva sarebbe
stata la funzione se avessimo avuto a disposizione una funzione primitiva ricorsiva massimo cosicché avremmo potuto definire l’i-mo componente del numero di Gödel in questo modo: + x ,i # max + pi t | x ,
t <x
più semplicemente.
Vediamo un esempio per comprendere come opera la funzione appena vista che fa uso del minimo: rifacciamoci all’esempio visto prima sul numero di Gödel x # 1125 , vogliamo calcolare + x ,2 , quindi dobbiamo cercare il più piccolo intero t + < x , tale che p2
t %1
t %1
mero t partendo da 0, per t # 0 abbiamo che p2
quindi per
t %1
p2
t #1
abbiamo
t %1
p2
+ # 3t %1 , Z| x + # 1125 , . Iniziamo a cercare il nu-
+ # 3 , | 1125 , quindi andiamo avanti incrementando t,
+ # 3 , | 1125 ;
2
proseguiamo per
t #2
per cui otteniamo
+ # 3 , Z| 1125 . Quindi ci fermiamo nella ricerca e possiamo concludere che + x ,i # t # 2 .
3
Definiamo un’altra funzione primitiva ricorsiva:
+
+
Lt + x , # min + x ,i ' 0 & + 4j ,< x j < i C + x , j # 0
i<x
,,
e la chiameremo lunghezza (length) della sequenza ( a1 , a2 ,! , an ) # x
Definiamo tale sequenza in modo tale che an ' 0 (in quanto se così non fosse la sequenza con uno o
più 0 in coda differirebbe ma non varierebbe il numero x, quindi non si avrebbe univocità nel risultato).
L’uso del quantificatore universale ci assicura che tutto il predicato (min) sia vero se i assume un valore tale che il predicato risulti sempre vero 4j < x (serie di 0 alla coda della sequenza).
Cerchiamo di interpretare la funzione: min + + x ,i ' 0 & !, , se la sequenza fosse fatta di tutti 0 allora il
i<x
predicato + x ,i ' 0 & ! sarebbe sempre falso (da i # 0 a i # x ) quindi il valore che assumerebbe
min + + x ,i ' 0 & !, sarebbe pari a 0.
i<x
Se la sequenza fosse invece priva di zeri, il predicato + x ,i ' 0 (senza considerare il membro a destra di
&) sarebbe vero per tutta la lunghezza della sequenza, ciò comprometterebbe la conta di i. Quindi dob-
EDIT by Qd – Calcolabilità – XVIII Lez.
97
+
,
biamo vedere cosa accade all’altro membro del predicato & e cioè + 4j ,< x j < i C + x , j # 0 che deve risultare falso, in modo da rendere falso tutto l’argomento di min. Quindi ci deve essere almeno un valore
j < x per cui deve essere falso sia j < i che + x , j # 0 e ciò è assicurato dal fatto che ad esempio, poiché
avevamo ipotizzato una sequenza priva di zeri sicuramente si presenterà la condizione in cui j <Z i però
j < n e + x , j #Z 0 , ciò si verificherà fintantoché i 8 n . A quel punto min termina la conta e restituisce il
risultato corretto.
La presenza di uno o più zeri in coda non compromette il risultato che è pari alla lunghezza della sequenza priva di zeri in coda; infatti da un’analisi della funzione, il predicato all’interno del min risulterà
vero se dopo l’analisi di uno 0 termina la sequenza o seguono soltanto altri zeri nel caso in cui j, superato i,
se ci sono numeri diversi da 0, renderà falso il predicato j < i C + x , j # 0
…meglio, anzi meno peggio di così non so spiegarlo, purtroppo.
Da quanto analizzato possiamo affermare che Lt + 0 , # Lt + 1, # 0 (ricordiamo che per convenzione il numero di Gödel pari a 1 rappresenta la sequenza vuota, mentre un numero di Gödel pari a 0 non esiste). Inoltre se ad esempio
2
x # 20 # 2 7 5 # ( 2, 0,1) , allora risulterà, quando verrà effettuata la ricerca + x ,3 # 1 , ma + x ,4 # 0 come ogni + x ,i per
i @ 3 , la ricerca avrà termine quando verrà raggiunto il limite superiore e cioè a + x , x # + x ,20 # 0 . Poiché per i @ 3 tutti i
+ x ,i # 0 , il risultato sarà Lt + 20 , # 3 .
Osserviamo infine che se x @ 1 (come del resto deve essere) e risulta Lt + x , # n , allora pn | x e nessun
primo più grande di pn divide x. Non sarebbe la stessa cosa se ci fossero zeri in coda alla sequenza. Da
ciò affermiamo che:
Lt +( a1 , a2 ,! , an ), # n J an ' 0 (altrimenti Lt +( a1 , a2 , ! , an &1 , 0), # n & 1 ).
Riassumiamo le funzioni di decodifica viste, mediante il seguente:
TEOREMA 8.3 (sulla sequenza numerica – rif. D.S.W. pag. 62):
a.
+( a , a ,!, a ),
1
2
n
i
- ai
#.
/0
se 1 < i < n,
altrimenti
b. SW+ x ,1 , + x ,2 ,!, + x ,n 02 # x
se n * Lt + x ,
+ ( a 1 , a 2 , ! , a n ) ,i # + x ,i
# ai
(+ x ,1 , + x ,2 ,! , + x ,n ) # ( a1 , a2 ,! , an ) # x
n # Lt + x , se non ci sono zeri in coda alla sequenza;
n @ Lt + x , se c’è uno o più zeri in coda alla sequenza.
EDIT by Qd – Calcolabilità – XVIII Lez.
;
Decima Nona Lezione
14/12/2006
Codifica numerica dei programmi
Interruzione di un predicato e problema
dell’insolvibilità dell’arresto
La codifica numerica dei programmi
(rif. D.S.W. pag. 65)
Vediamo ora come associare ad un programma c , di un linguaggio f , un numero (codifica),
che indichiamo così: # +c , , il cui programma (decodifica) potrà essere recuperato mediante questo
numero. Per iniziare fissiamo i nomi delle variabili nell’ordine seguente:
Y X 1 Z1 X 2 Z2 X 3 Z3 !
(anche in questo caso i pedici 1 possono essere omessi);
per le etichette abbiamo:
A1 B1 C 1 D1 E 1 A2 B2 C 2 D2 E 2 A3 !.
L’ordine delle variabili e delle etichette è importante e non deve cambiare, in tal modo possiamo definire notazioni indicanti la posizione di ogni variabile/etichetta in base al nome:
# +V ,
# +L,
posizione variabile;
posizione etichetta (label)
Esempi: # + X 2 , # 4 ; # +Y , # 1 ; # + Z , # 3 ; # + E , # 5 .
Ora poniamo con la lettera I un’istruzione (etichettata o meno) del linguaggio f e scriviamo:
# + I , # a, b, c
(le parentesi angolari indicano chiaramente funzioni di accoppiamento) dove:
1. se I non ha etichetta, allora a # 0 ;
se I ha etichetta L, allora a # # + L , ;
2. se V è la variabile menzionata in I, allora c # # +V , & 1 ;
3. se l’enunciato di I è:
allora si ha rispettivamente:
V $V
o V $V % 1
o V $V &1
b #0
o b #1
o b #2 ;
4. se l’enunciato di I è IF V ' 0 GOTO L6 allora si ha: b # # + L6 , % 2 .
Esempio: il numero dell’istruzione non etichettata X $ X % 1 è a , b , c
, poiché l’istruzione è senza
etichetta a # 0 , mentre c # # + X , & 1 # 2 & 1 # 1 , infine, poiché l’istruzione è V $ V % 1 , si ha b # 1 . Si
ha quindi # + I , # 0, 1,1
# 0, 2 7 + 2 7 1 % 1 , & 1
1
# 0,5
# 2 7 + 2 7 5 % 1 , & 1 # 10 .
0
99
Altro esempio: ( A )
X $ X % 1 che è la stessa istruzione dell’esempio precedente ma questa volta è e-
tichettata, quindi si ha a # # + A , # 1 , mentre b e c restano immutate, si dunque # + I , # 1, 1,1
# 1, 5
# 2 7 + 2 7 5 % 1 , & 1 # 21 .
1
Da notare che per ogni numero q dato vi è un’unica istruzione I tale che # + I , # q , quindi con
qualche stratagemma, da q, possiamo risalire ad a, b e c , quindi all’etichetta (se c’è) dell’istruzione, al
tipo di istruzione e alla variabile rispettivamente.
Calcoliamo inizialmente a che è uguale a l + q , # l + a , b , c
, # a , chiaramente se l + q , # 0 allora
l’istruzione I non ha etichetta, altrimenti I avrà come etichetta la l + q , -ma lettera della nostra lista inizialmente definita.
Per risalire al nome della variabile
+
,,
# r r + a, b, c
# r + b, c
c
menzionata in I dobbiamo calcolare r + r + q , , #
, # c , il cui valore (precisamente c % 1 ) chiaramente indica la posizione del
nome della variabile nella nostra lista.
+
Per risalire infine all’enunciato di I calcoliamo: l + r + q , , # l r + a , b , c
mente se risulta
se
se
se
l +r + q , , # 0
l +r + q , , # 1
l +r + q , , # 2
l +r + q , , & 2 # j @ 0
, , # l + b, c , # b e chiara-
allora I sarà: V $ V ;
allora I sarà: V $ V % 1 ;
allora I sarà: V $ V & 1 ;
allora I sarà: IF V ' 0 GOTO L
ed L corrisponde alla j-ma lettera della lista delle etichette.
Infine definiamo # +c , , con c programma costituito dalle istruzioni I 1 , I 2 ,! , I k (facendo riferimento alla numerazione di Gödel), il numero descritto dalla funzione:
# +c
, # SW # + I 1 , , # + I 2 , ,! , # + I k , 02 & 1
k
# N pi + i , & 1 .
# I
i #1
In particolare il programma vuoto è # + A , # (0) & 1 # 1 & 1 # 0 (viene sottratto un 1 al numero di Gödel per assicurare una corrispondenza tra numero di programma e istruzioni e viceversa, infatti se non ci fosse questa sottrazione il numero di programma 0 non corrisponderebbe ad alcuna sequenza di numeri codificata mediante numerazione di Gödel).
È importante notare che l’istruzione senza etichetta Y $ Y ha come numero 0, 0,0 # 0 e, per
evitare ambiguità, nella numerazione di Gödel in coda alla sequenza, per convenzione si stabilisce che
nessun programma debba avere come ultima istruzione Y $ Y (se così non fosse un qualsiasi # +c , potreb-
be corrispondere a più programmi c aventi un numero differente di istruzioni Y $ Y in coda alla sequenza di istruzioni,
verrebbe così meno l’univocità della decodifica –programmi differenti potrebbero avere lo stesso numero # +c , ).
Chiaramente la decodifica del numero # + I , # 0 , con I non corrispondente all’ultima istruzione del
programma, corrisponderà (regolarmente) all’enunciato Y $ Y .
EDIT by Qd – Calcolabilità – XIX Lez.
100
Interruzione di un predicato
(rif. D.S.W. pag. 68)
Introduciamo un predicato particolare: HALT + x , y , , definiamolo:
DEF.: per un dato y, posto c
HALT + x , y , risulterà vero se ?
(1)
c
un S-programma tale che # +c
, # y . Allora il predicato
+ x , è definita, falso se ? + x , è indefinita. In altre parole possiamo
(1)
c
scrivere che: SW HALT + x , y , J il programma di numero y si ferma sull'ingresso x 02 .
TEOREMA 2.1: HALT + x , y , non è un predicato calcolabile.
DIM.(a): Si dimostra per assurdo, supponendo cioè che HALT + x , y , sia un predicato calcolabile (chia-
ramente mediante un S-programma). Quindi, se HALT + x , y , fosse calcolabile, possiamo utilizzarlo
all’interno di un S-programma sottoforma di macro, in questo modo (X contiene un valore qualsiasi):
c :
( A)
IF
HALT + X , X , GOTO A
-B9
3 ?c(1) + x , # .
B/0
se
se
e chiaramente risluterà:
HALT + x , x , ,
) HALT + x , x ,
Il programma, se HALT + x , x , è vero, ciclerà all’infinito, altrimenti si ferma e il valore di uscita di Y
sarà nullo.
, # y0 , allora, utilizzando la definizione data per il predicato HALT + x , y , , però in
relazione al numero di programma di c , # +c , # y0 otteniamo:
Ora poniamo # +c
HALT + x , y0 , risulta vero se ?c(1) + x , # D
(valore determinato)
nel nostro caso l’unico valore determinato che assume il programma c
HALT + x , x , è falso (cioè quando ) HALT + x , x , ); viceversa abbiamo che:
è 0 e ciò avviene quando
HALT + x , y0 , risulta falso se ?c(1) + x , # 9
e ciò avviene quando il predicato HALT + x , x , è vero (per come è stato concepito il programma, inizia a ciclare
all’infinito), possiamo quindi affermare che (poiché ) HALT + x , x , 5 HALT + x , y 0 , P HALT + x , x , 5
5 ) HALT + x , y 0 , ):
HALT + x , y0 , J ) HALT + x , x , .
Siamo giunti a questa conclusione senza che essa dipendesse da particolari valori di x, cioè tale biiezione
è valida per qualsiasi valore di x, quindi in particolare è valida anche per x # y0 da cui otterremmo:
HALT + y0 , y0 , J ) HALT + y0 , y0 , che è chiaramente una contraddizione.
Il teorema è dunque dimostrato.
EDIT by Qd – Calcolabilità – XIX Lez.
101
DIM.(b): Il teorema può essere dimostrato anche seguendo un ragionamento differente, basandoci
sull’analisi di una particolare matrice (rif. D.S.W. pag. 89) costituita da un insieme di funzioni ? +1, unarie
relative a vari set di istruzioni, più precisamente indichiamo con c n , 4n * 0 il programma di numero
n, possiamo dunque costruire la matrice infinita dei valori che possono assumere le funzioni unarie ? c+1n,
parzialmente calcolabili (che quindi possono assumere valori determinati o indeterminati a seconda di
come sono definite le funzioni ? c+1n, calcolate dai relativi programmi, abbiamo:
E
input
E
D
?c(1)0 + 0 , ?c(1)0 + 1, ?c(1)0 + 2 , ! !
num.
?c(1)1 + 0 , ?c(1)1 + 1, ?c(1)1 + 2 , ! !
prog.
D
?c(1)2 + 0 , ?c(1)2 + 1, ?c(1)2 + 2 , ! !
'
'
'
'
'
'
+
+
Sulla prima riga sono rappresentati tutti i valori che può assumere la funzione ?c(1)0 + x , calcolata dal
programma c 0 di numero 0 al variare di x, ovvero il programma vuoto, quindi la prima riga ha valori
tutti uguali in quanto, al variare dell’input, l’output non cambia. Invece le altre righe rappresentano i
valori che assumono le funzioni calcolate da programmi non vuoti e quindi possono essere diverse tra
loro, chiaramente è anche possibile che alcuni valori possano essere uguali, il caso generale prevede questa possibilità non essendo specificati i programmi che stiamo rappresentando.
In particolare però sulla diagonale principale della matrice sono rappresentate le funzioni calcolate
da programmi il cui valore di input corrisponde al numero di programma.
A questo punto, per dimostrare il teorema basta far vedere che i valori ?c(1) relativi al programma
c visto per la precedente dimostrazione non compaiono nella matrice (la matrice rappresenta tutti i possibili
valori che possono assumere tutti i programmi che calcolano funzioni parzialmente calcolabili, quindi se in questa matrice
non compare una funzione vuol dire che questa funzione non è parzialmente calcolabile, cioè non può essere calcolata). Per
assurdo avevamo assunto che HALT + x , y , fosse un predicato calcolabile e avevamo costruito il programma c essendo giunti alla biiezione:
?c(1) + x , #D J ) HALT + x , x , ,
tale fatto lo possiamo scrivere anche così:
?c(1) + x , #D J ?c(1)x + x , #9 4x
(per come è stato definito il predicato HALT)
Ciò significa (dando un’interpretazione all’ultima biiezione) che una riga (quella corrispondente al programma c ) è costituita da soli tutti zeri se e soltanto se la diagonale della matrice è costituita da tutti
valori indeterminati, ma ciò è una contraddizione perché se si trovassero soltanto valori indeterminati
sulla diagonale della matrice allora, in corrispondenza della riga del programma c avremmo almeno
EDIT by Qd – Calcolabilità – XIX Lez.
102
un elemento della matrice che assume valore indeterminato andando in contraddizione col fatto che sulla riga del programma c dovremmo trovare soltanto zeri. Quindi il teorema è dimostrato.
Tale metodo appena visto fa uso del concetto di diagonalizzazione (sulla diagonale della matrice i due
argomenti del predicato HALT coincidono) ed è un metodo utile a dimostrare che certi insiemi non sono
ricorsivi come vedremo.
Nell’ambito dell’informatica si può operare con numeri o simboli indifferentemente, tale affermazione è
provata ad esempio da quanto visto fino ad ora circa la codifica dei programmi.
L’ultimo teorema visto ci fa capire una cosa importante e cioè che, non essendo calcolabile
HALT + x , y , , non esiste un algoritmo che, dato un programma scritto in un linguaggio f con un da-
to input, sia in grado di determinare se tale programma si fermerà + D , o meno + 9 , sull’input dato (in
altri termini possiamo dire che la codifica dei programmi non permette di risolvere problemi di riconoscimento–arresto).
Quest’ultimo concetto viene chiamato: problema dell’insolvibilità dell’arresto (unsolvability of the halting problem) da cui deriva un altro concetto:
TESI di Church-Turing (rif. D.S.W. pag. 69): ogni funzione parzialmente calcolabile mediante un algoritmo è parzialmente calcolabile (da un S-programma). Ciò vuol dire che si presuppone (essendo soltanto
una tesi –congettura– non dimostrata) che se non esiste un S-programma che calcola una certa funzione, allora tale funzione non sarà calcolabile da nessun metodo algoritmico.
In particolare quindi, se HALT + x , y , non è calcolabile da un S-programma, non sarà calcolabile da
nessun altro metodo algoritmico.
La suddetta è una tesi in quanto è molto complicato formalizzare un’ipotesi che definisca correttamente il concetto di algoritmo, quindi, sebbene abbia valore da 70 anni e più, potrebbe, in futuro, rivelarsi non sempre vera, in tal caso la tesi si rivelerebbe falsa.
Alla luce di questa tesi e del teorema poco fa dimostrato si può affermare che non è affatto possibile stabilire (predire) se un dato programma con un dato input si fermerà o meno dopo un certo numero di passi. In quanto affermarlo vuol dire che il programma prima o poi si fermerà, ma se non si ferma “subito” ciò
non vuol dire che non si fermerà mai, né possiamo affermare con certezza che non si fermerà mai. La certezza la possiamo avere soltanto nell’eventualità che il programma termini.
Ad esempio, consideriamo una congettura (teorema non dimostrato) della teoria dei numeri secondo cui
ogni numero pari * 4 è la somma di due numeri primi. Tale asserzione prende il nome di congettura di
Goldbach ed è chiaramente dimostrata per piccoli numeri come 4 # 2 % 2 , 6 # 3 % 3 , 8 # 3 % 5 , … , ma
non è stato dimostrato che ogni numero pari * 4 è somma di due numeri primi. È chiaro che con facilità
possiamo costruire un S-programma che verifica la veridicità (parziale) di questa congettura, verificando
un numero pari alla volta, il programma non termina (se terminasse vorrebbe dire che è stato trovato un
numero pari per cui non vale la congettura) , ma ciò non basta per asserire che la congettura è vera, ipoteticamente potrebbe darsi che prima o poi il programma termini, ma se ciò non accade non possiamo affermarlo con certezza matematica. In 250 anni dalla formulazione di questa congettura nessuno ha trovato
un programma o comunque un metodo che la dimostri (cosa che al contrario è stata fatta, dopo secoli, circa l’ultimo
teorema di Fermat).
EDIT by Qd – Calcolabilità – XIX Lez.
Ventesima Lezione
19/12/2006
Teorema dell’universalità – programma universale
Insiemi ricorsi, non ricorsivi e primitivi ricorsivi
Per quanto visto finora si è portati a pensare che non vi è una strada semplice per realizzare in modo
generale problemi di calcolo sui numeri, tra poco vedremo che ciò non è vero (rif. D.S.W. pag. 70).
DEF.: 4n @ 0 definiamo la seguente notazione:
[ +n , + x 1 , x 2 ,!, x n , y , # ? c+n , + x 1 , x 2 ,! , x n ,
con y # # +c
,.
La funzione [ (la cui notazione all’apice non deve essere confusa con quella delle funzioni ? , infatti [ +n , ha n % 1
argomenti e non n) rappresenta una sorta di interprete che prende in input i dati x 1 , x 2 ,! , x n e il numero di
programma y # # +c
ta da c , cioè ?
(n )
c
, e restituisce proprio il valore che restituirebbe la funzione (a n variabili) calcola-
(che coincide con il valore della variabile Y allo snapshot terminale).
TEOREMA 3.1 (dell’universalità): 4n @ 0 la funzione [ +n , + x 1 , x 2 ,! , x n , y , è parzialmente calcola-
bile (cioè esiste un S-programma che calcola la funzione corrispondente a [ + , ).
n
DIM.: la dimostrazione viene fatta mostrando un S-programma h n , detto programma universale, che
calcola appunto una funzione ? h( n %n1) + x 1 , x 2 ,!, x n , x n %1 , # [ +n , + x 1 , x 2 ,!, x n , y , .
( n %1)
(n )
y
Da notare che sebbene la funzione ? h n assuma gli stessi valori della funzione da calcolare ?c
con i
parametri x 1 , x 2 , ! , x n è chiaro che le due funzioni sono differenti, nel senso che una svolge il compito di
calcolare, l’altra invece viene calcolata ma ha un significato legato al programma c , oltretutto le due funzioni hanno un numero di parametri differenti.
L’S-programma h n , come anticipato, fungerà da interprete, infatti vengono letti i dati di input corri-
spondenti all’S-programma c , dopodichè viene letto il numero y # # +c , del programma c , poi
interpretate ed eseguite le varie istruzioni del programma c sui dati x 1 , x 2 ,! , x n in modo tale da ottenere:
? h( n %n1) + x 1 , x 2 ,!, x n , x n %1 , # [ +n , + x 1 , x 2 ,! , x n , x n %1 , # ? c( n ) + x 1 , x 2 ,!, x n ,
con x n %1 # y # # +c
,.
Al fine di costruire il programma universale h n faremo abbondante uso di macro. Si ricorda che le variabili ed etichette omesse corrisponderanno al valore 0 nella codifica di Gödel (ad esempio se volessimo coY
X
0
X
0
2
0
1
2
0
dificare lo stato: Y # 0 , X 1 # 2 , X 2 # 1 otterremmo 2 7 3 7 5 7 7 2 # 2 7 3 7 5 7 7 # 3 7 7 # 63 , il fattore 5 corrisponde al valore omesso della variabile Z che nella sequenza stabilita delle etichette delle variabili si trova tra X e X 2 ). Da
notare che le variabili di input x 1 , x 2 ,! , x n hanno tutte posizione pari.
104
In primis il programma universale memorizza due valori: K ed S:
K corrisponde al numero dell’istruzione che deve essere eseguito;
S è il numero di Gödel (0, x 1 ,0, x 2 ,0! 0, x n ) della sequenza di variabili di input (ricordando
quanto detto prima circa la posizione pari delle variabili X 1 , X 2 , ! nella codifica numerica del pro-
gramma).
Vediamo passo passo il funzionamento di h n che darà come risultato finale di output la variabile:
Y # [ +n , + X 1 , X 2 ,! X n , X n %1 ,
con X n %1 chiaramente uguale a # +c
,# y
da non confondere la y (minuscola) con Y (maiuscola)
essendo due valori con significati differenti.
Per rendere più semplice la comprensione del programma universale faremo liberamente uso di nomi ed
etichette, senza cioè rispettare in modo rigoroso le regole dettate dal linguaggio f .
Iniziamo col descrivere le prime tre righe del programma rappresentate da tre macro:
1
Z $ X n %1 % 1
2
S $ N + p2i ,
3
K $1
n
i #1
(memorizzazione numero programma);
Xi
(codifica stato);
(memorizzazione primo passo – prima istruzione);
1. In Z viene memorizzato SW # + I 1 , , # + I 2 , ,! , # + I m , 02 cioè il numero di Gödel relativo alla sequenza di m istruzioni dell’S-programma c , con # +c , # X n %1 + # ( # + I 1 , , # + I 2 , , ! , # + I m ,) & 1, ;
2. In S, come già detto, vengono codificate le variabili di input, ricordando che hanno posto pari
(ecco perché l’uso di p2i -numeri primi di posto pari), si ha dunque:
S # (0, X 1 ,0, X 2 ,! ,0, X n )
3. Come anticipato anche per K, tale variabile rappresenta il contatore d’istruzione e, ovviamente,
quando il programma parte, viene inizializzato a 1.
Proseguiamo con la descrizione delle istruzioni seguenti:
4
(C )
IF K # Lt + Z , % 1 C K # 0 GOTO F
+ or ,
(controllo numero istruzione);
4. Viene effettuato un controllo sul numero di istruzione corrente, infatti Lt + Z , corrisponde alla
lunghezza della sequenza di istruzioni del programma c , come vedremo K verrà incrementato
EDIT by Qd – Calcolabilità – XX Lez.
105
di una unità quando verrà eseguita un’istruzione di c . Quando saranno state eseguite tutte le
m istruzioni di c , K sarà uguale a m % 1 . Vedremo dopo il significato del predicato K # 0 .
Una volta eseguite tutte le istruzioni di c (o se K # 0 ), il programma h n salterà all’ultima istruzione ( F ) + Final , che restituirà l’output Y.
Se non sono state ancora eseguite tutte le istruzioni di c , h n passa all’istruzione:
U $ r + + Z ,k ,
5
(decodifica istruzione corrente);
5. Inizialmente K # 1 , quindi + Z , K # # + I 1 , cioè il numero codificato della prima istruzione di
c . In generale + Z ,i corrisponde all’i-ma istruzione di c .
Ricordiamoci che il numero di un’istruzione I è # + I , # a , b , c , quindi r + # + I , , # b , c . In c
e in b sono contenute rispettivamente le informazioni relative all’eventuale variabile menzionata
nell’istruzione e al tipo di istruzione (che può essere una di queste: istruzione pigra, incremento, decremento,
salto condizionale). Essendo dunque U # b , c K , U contiene informazioni sulla variabile e sulla Kma istruzione di c ;
P $ pr +U ,%1
6
(memorizzazione posizione variabile);
6. Con questa macro stiamo memorizzando in P le informazioni relative all’individuazione della
variabile su cui eseguire la K-ma istruzione, infatti r +U , # c , quindi r +U , % 1 # c % 1 corrisponde alla posizione della variabile della K-ma istruzione. Di conseguenza pc %1 rappresenta il
+ c % 1, –mo numero primo corrispondente alla posizione della variabile codificata in S.
Ricordiamoci che c % 1 # # +V , non è il valore della variabile V, bensì la posizione nella lista
+Y
X Z 1 X 2 !, ; inoltre rammentiamo che la seconda istruzione dell’S-programma h n codifica i
valori delle variabili
+ X , X 2 ,! , X n ,
assieme alla loro posizione, ogni base
+ p2 i ,
della potenza di cia-
scun fattore della produttoria corrisponde alla posizione (pari) nella lista dei nomi delle variabili, mentre
n
all’esponente è menzionato il relativo valore: S # N + pn %1 ,
i #0
Xi
X
X
X
# p2 1 . p4 2 7 ! 7 p2 nn . Di conseguenza, co-
noscendo il + c % 1 , –mo numero primo e il suo esponente, risaliamo rispettivamente alla posizione e al valore della variabile corrispondente.
l +U , # 0 GOTO N
7
IF
8
IF l +U , # 1 GOTO A
(analisi tipo istruzione –pigra);
(analisi tipo istruzione –incremento);
7. Ricordando che U # b , c allora l +U , # b che corrisponde al tipo di istruzione associato. Se
l +U , # 0 dovrà essere eseguita l’istruzione pigra V $ V , quindi, in pratica, il programma universale non deve fare nulla e passare semplicemente all’istruzione successiva, ciò viene gestito
dall’istruzione ( N ) + Null , come vedremo in seguito;
EDIT by Qd – Calcolabilità – XX Lez.
106
8. Analogamente, per l’istruzione 8 si controlla il valore di b, il quale se è pari a 1, vorrà dire che
deve essere fatto un incremento V $ V % 1 e poi passare all’istruzione successiva, ciò viene gestito dall’istruzione ( A ) + Add , come vedremo in seguito;
Se l +U , ' 0,1 ciò vuol dire che l’istruzione da eseguire può essere o un decremento o un salto condizionato (costrutto di selezione), per effettuare il decremento, però è necessario che ci si assicuri che
la variabile da decrementare sia non nulla:
9
IF
) + P | S , GOTO N
(controllo variabile nulla);
9. Se la variabile da decrementare fosse nulla avremmo pc0%1 # 1 , quindi P Z| S e si passerebbe
all’istruzione successiva di c (anche in questo caso l’istruzione ( N ) gestisce il passaggio
all’istruzione successiva da eseguire).
Ricordiamo che P rappresenta la posizione, nella lista delle variabili, della variabile corrente sottoforma
di numero primo, mentre in S è memorizzata la successione di variabili codificate (in qualche modo rappresenta la codifica dello stato corrente del programma c ), quindi se la variabile corrispondente alla poY
sizione rappresentata da P fosse nulla avremmo che se P # pk ed S # p1
lora pk Z|
Y
p1
bili di input
7
Xi
X
p2
7
Z
p3
7
X
p4 2
0
7 ! 7 pk 7 ! .
+ # 1,
7 p2X 7 p3Z 7 p4X 2 7 ! 7 pk0 7 ! , al+ # 1,
È chiaro che lo stato iniziale prevede la codifica delle sole varia-
, ma con l’esecuzione di varie istruzioni lo stato codificato potrebbe arricchirsi di nuovi fat-
tori (corrispondenti alle variabili temporanee Z i e chiaramente Y ).
Anche nel caso in cui l’istruzione da eseguire fosse stata del tipo IF V ' 0 GOTO L6 (anziché
V $ V & 1 ) essendo nulla la variabile in questione si passerebbe comunque all’istruzione successiva anziché all’istruzione L6 essendo falso il predicato V ' 0 .
Nel caso in cui la variabile corrente fosse non nulla allora bisognerebbe verificare se effettuare il suo
decremento o il salto condizionato:
10
IF l +U , # 2 GOTO M
(controllo istruzione di decremento);
10. se l +U , # 2 allora b # 2 , bisogna dunque effettuare il decremento della variabile corrente, tale
operazione viene eseguita dall’istruzione ( M ) + Minus , che vedremo dopo;
11
K $ min SWl + + Z ,i , % 2 # l +U , 02
i <Lt + Z ,
12
GOTO C
EDIT by Qd – Calcolabilità – XX Lez.
(salto condizionato);
(prossima istruzione)
107
11. Nel caso in cui l +U , ' 0,1,2 e la variabile su cui operare è non nulla, bisogna effettuare il salto
condizionato passando all’istruzione etichettata con L6 il cui valore, riferito alla posizione nella
lista delle etichette, è contenuto in b # # + L6 , % 2 .
Poiché un programma potrebbe avere più istruzioni con la stessa etichetta per preservare il determiniamo ed evitare ambiguità,
si considera l’etichetta di ordine minore (cioè quella che viene prima,
leggendo le istruzioni dall’alto verso il basso, come nell’esempio a destra).
!
si E
(D )
( A)
!
!
!
Ecco perché si fa uso della funzione min. Poiché K rappresenta
(B ) !
il valore della prossima istruzione da eseguire, di norma, al ter( A) !
no E
mine di ogni istruzione di c , K viene incrementato di una u(C ) ! GOTO A
nità, ma in questo caso particolare la prossima istruzione da eseguire è L6 , quindi K deve essere aggiornato in modo da contenere il valore relativo all’etichetta L6 di ordine minore
(nell’eventualità ci siano più etichette L6 ). Viene quindi fatta una ricerca per trovare il numero
di istruzione che compare, nell’S-programma c , per primo, corrispondente a L6 .
Il valore di L6 è contenuto in l +U , , più precisamente l +U , # b # # + L6 , % 2 . Quindi vengono
fatti dei confronti tra l +U , ed l + + Z ,i , % 2 fintantoché i confronti danno esito negativo (ricor-
diamo che Z contiene la codifica delle istruzioni del programma c e quindi tutte le informazioni relative ad esse
e quindi anche alle eventuali etichette, + Z ,i corrisponde dunque al numero codificato della i-ma istruzione ed
l + + Z ,i , % 2 corrisponde all’eventuale (posizione) etichetta dell’i-ma istruzione di c ).
K assumerà il più piccolo valore di i per cui è verificata l’uguaglianza.
Chiaramente, se il salto condizionato fa riferimento ad una etichetta inesistente, K assumerà valore 0.
Se L 6 non esiste allora K # 0 in quanto la minimalizzazione è stata definita in modo tale da essere nulla se non viene trovato alcun valore 0 < i < Lt + Z , che soddisfa il predicato, la ricerca in verità dovrebbe
partire da i # 1 corrispondente all’analisi dell’etichetta della prima istruzione, ma, per come è stata definita la minimalizzazione, si parte da 0 e ciò non compromette la ricerca.
12. In ogni caso dopo la ricerca dell’etichetta (che sia stata trovata o meno) si salta di nuovo
all’istruzione (C ) che contiene il controllo K # 0 a cui si era accennato prima. Tale controllo
serve proprio a verificare che l’etichetta del salto condizionato esista o meno, in caso negativo il
programma universale termina e viene restituito il valore di uscita Y (istruzione ( F ) ); se invece
K ' 0 allora si passerà all’esecuzione della K-ma istruzione;
13
( M ) S $ WVS / P 21
(decremento)
13. Questa è la macro relativa all’operazione di decremento richiamata dall’istruzione 10. Se viene
eseguita l’istruzione 13 vuol dire che il decremento può essere effettuato e ciò vuol dire che
P | S . Essendo i valori delle variabili memorizzati in S sottoforma di esponenti dei numeri primi, la sottrazione di una unità da una variabile V, corrisponderà alla divisione di S per il numero
primo corrispondente alla posizione assunta dalla variabile, quindi se, ad esempio, S #
EDIT by Qd – Calcolabilità – XX Lez.
108
# p2X 1 7 p4X 2 7! 7 pVj 7! 7 p2Xnn , # +V , # j e V # L , per ottenere V & 1 , si ha: S / P # S / p j #
# p2X 1 7 p4X 2 7! 7 pLj &1 7! 7 p2Xnn . Anche in questo caso vale l’appunto fatto prima riguardante i pedici pari dei
fattori, cioè non è detto che S sia costituito esclusivamente da fattori i cui pedici sono numeri pari per via
dell’eventuale utilizzo di variabili Z i o della variabile di output Y .
Quindi S verrà aggiornato per contenere la variabile decrementata e si procede con:
14
GOTO
N
(salto incondizionato di fine istruzione)
14. Questa istruzione sarà descritta a breve;
15
( A) S $ S 7 P
(incremento)
15. Se l’istruzione da eseguire è l’incremento della variabile corrente, se per il decremento si è fatto
uso della divisione per P, in modo del tutto equivalente, secondo lo stesso principio delle proprietà delle potenze, viene effettuata la moltiplicazione per P di S e aggiornato il valore di S.
Quindi ad esempio, se S # p2X 1 7 p4X 2 7! 7 pVj 7! 7 p2Xnn , # +V , # j e V # L , per ottenere V % 1 , si
ha: S 7 P # # S 7 p j # p2X 1 7 p4X 2 7! 7 pLj %1 7! 7 p2Xnn , in questo caso V può anche essere nullo avremmo quindi S # p2X 1 7 p4X 2 7! 7 p2Xnn ed S 7 p j # p2X 1 7 p4X 2 7! 7 p j 7! 7 p2Xnn ;
16
(N )
K $ K %1
(aggiornamento variabile prossima istruzione)
16. Terminata l’operazione di decremento o di incremento, prima di passare alla prossima istruzione di c , si aggiorna K incrementandolo di una unità in modo che h n sia in grado di eseguire
le istruzioni successive di c , difatti la variabile K viene utilizzata per fare i controlli (istruzione
(C ) ) sulla K-ma istruzione (se esiste);
17
GOTO
C
(salto alla gestione della prossima istruzione)
17. Conclusa l’istruzione e aggiornato K si ritorna all’istruzione (C ) in modo da eseguire nuovamente tutte le operazioni utili all’esecuzione della prossima istruzione I K di c ;
18
( F ) Y $ + S ,1
(memorizzazione valore di output)
18. Terminate tutte le operazioni (o nel caso in cui il programma termini prematuramente per un
errore), viene memorizzato in Y il valore di output calcolato dal programma che chiaramente si
trova nella prima posizione (per convenzione) della sequenza di variabili memorizzate in S ,
quindi Y $ + S ,1 . Nel caso in cui non venga fatta alcuna assegnazione a Y, tale variabile resterà
nulla (sebbene magari siano state effettuate operazioni di incremento, decremento, ecc… su altre variabili).
EDIT by Qd – Calcolabilità – XX Lez.
109
Abbiamo concluso la descrizione del programma universale che ora vediamo nel complesso, unendo
tutte le macro:
hn :
Z $ X n %1 % 1
n
S $ N + p2n ,
Xi
i #1
(C )
K $1
IF
K # Lt + Z , % 1 C K # 0 GOTO F
U $ r + + Z ,K ,
P $ pr U %1
+ ,
IF l +U , # 0 GOTO N
IF
l +U , # 1 GOTO A
IF
) + P | S , GOTO N
IF
l +U , # 2 GOTO M
K $ min SWl + + Z ,i , % 2 # l +U , 02
i <Lt+ Z ,
GOTO
(M )
( A)
(N )
(F )
C
S $ VWS / P 12
GOTO N
S $ S 7P
K $ K %1
GOTO C
Y $ + S ,1
È chiaro che h n è la chiave per dimostrare il teorema, infatti grazie ad esso possiamo affermare che
se scriviamo [ +n , + x 1 , x 2 ,!, x n ,0 , , [ +n , + x 1 , x 2 ,!, x n ,1, , [ +n , + x 1 , x 2 ,!, x n ,2 , ,! 4n @ 0 (l’ultimo parametro delle funzioni corrisponde al numero di programma), indichiamo la sequenza di tutte le funzioni
parzialmente calcolabili, quindi abbiamo dimostrato il teorema. Possiamo anche scrivere:
[ +yn , + x 1 , x 2 ,!, x n , # [ +n , + x 1 , x 2 ,!, x n , y ,
e se n # 1 possiamo anche omettere l’apice:
[ y + x , # [ + x , y , # [ + 1, + x , y , .
Il programma universale può essere modificato per eseguire un’altra operazione utile e cioè il conteggio dei passi eseguiti dal programma c .
Da quest’ultimo risultato si ha:
EDIT by Qd – Calcolabilità – XX Lez.
110
+n ,
DEF. (rif. D.S.W. pag. 74): con la scrittura STP + x 1 , x 2 ,! , xn , y , t , si definisce un predicato tale che:
STP+n , + x 1 , x 2 ,! , xn , y , t , J [ Il programma di numero y si ferma in un numero
di passi m < t su ingresso x 1 , x 2 ,!, x n ]
e
STP+n , + x 1 , x 2 ,! , xn , y , t , J [ Vi è un calcolo del programma y di lunghezza l < t % 1 ,
se parte dagli input x 1 , x 2 ,!, x n ]
Quindi il predicato appena definito è vero soltanto se il programma c con # +c , # y e con ingresso x 1 , x 2 ,!, x n si ferma dopo un numero finito di passi m < t e allo stesso tempo se esiste un calcolo
(si ricordi la definizione di calcolo, rif. D.S.W. pag. 27 e 29) di lunghezza l < t % 1 (in quanto si parte dallo stato
iniziale 1, quando non è stata eseguita ancora alcuna istruzione di c , e si termina con lo stato finale
t % 1 , dopo che tutte le istruzioni sono state eseguite.
I predicati appena visti (le due biiezioni), essendo conseguenza dell’aggiunta dell’istruzione contatore
W $ W % 1 a h n , sono calcolabili. Ciò non vuol dire che il problema dell’arresto sia stato risolto in quanto qui abbiamo un limite dato dal valore t, che ci permette di affermare con certezza che un programma termina o meno entro un
numero di passi non superiore a t , ma non che un programma termina a fronte di un numero di passi non stabilito. Inoltre
il predicato non calcolabile HALT ha valore soltanto per programmi che ricevono in input un solo valore.
Segue un importante risultato:
TEOREMA 3.2 (del conta passi): 4n @ 0 il predicato STP+n , + x 1 , x 2 ,! , xn , y , t , è primitivo ricorsi-
vo.
[ la dimostrazione segue dopo pag. 111 ]
Insiemi ricorsivi, non ricorsivi e primitivi ricorsivi
(rif. D.S.W. pag. 78)
Si può parlare di problemi risolvibili o non risolvibili in termini insiemistici, strettamente connessi
ai predicati, a tal proposito definiamo una particolare funzione:
DEF. (rif. D.S.W. pag. 6): Con il termine funzione caratteristica intendiamo un predicato P sull’insieme
S (dominio), se R : S e risulta:
-1
P +x, # .
/0
se x > R ,
e abbiamo:
se x \ R
R # !a > S | P + a ," .
Cioè l’insieme R può essere definito mediante l’uso del predicato P che è la funzione caratteristica
dell’insieme R (cioè stabilisce se un elemento appartiene o non appartiene a R a seconda che risulti rispettivamente vero o falso il predicato P).
È indifferente adoperare una notazione insiemistica o mediante la funzione caratteristica.
-1
Un esempio è il seguente: f + x , # .
/0
EDIT by Qd – Calcolabilità – XX Lez.
se
x è primo,
altrimenti
chiaramente f + x , rappresenta la funzione
111
caratteristica dell’insieme dei numeri primi: ! p > & | f + p ," e risulta anche f + x , # Primo + x , .
Altro esempio è HALT + x , y , il quale può essere visto come la funzione caratteristica dell’insieme:
!+ x , y , > &
2
| HALT + x , y ,"
che rappresenta l’insieme di tutte le coppie ordinate + x , y , tali che l’S-programma di numero y si ferma
sull’ingresso x.
Più in generale abbiamo:
DEF.: Dire che un insieme B : N m è:
I
I
I
non calcolabile (non ricorsivo) oppure
calcolabile (ricorsivo) oppure
primitivo ricorsivo
(si sta stabilendo cioè che B appartiene ad una certa classe di funzioni calcolabili o non calcolabili o primitive ricorsive)
vuol dire che la funzione caratteristica P + x 1 , x 2 ,!, x m , di B è rispettivamente:
I
I
I
non calcolabile
calcolabile
primitiva ricorsiva
Quindi il problema di sapere se una funzione è calcolabile o meno (e se è primitiva ricorsiva o meno) si riconduce al problema di sapere se la relativa funzione caratteristica è calcolabile o meno (e se è
primitiva ricorsiva o meno). Analogamente possiamo dire che se esiste l’S-programma che computa la
funzione caratteristica allora esiste l’S-programma che computa la funzione data (generatrice).
EDIT by Qd – Calcolabilità – XX Lez.
Dimostrazione del Teorema Conta-passi
Martin Davis, Ron Sigal, Elaine J. Weyuker
Teorema 1 ∀n > 0, il predicato ST P (n) (x1 , ..., xn , y, t) è primitivo ricorsivo.
Dim. L’idea è dare una versione numerica delle nozioni di successore e istantanea successore
e di mostrare che le funzioni implicate sono primitive ricorsive.
Iniziamo col definire le funzioni che servono ad estrarre le componenti della i-esima istruzione
del programma di numero y:
• LABEL(i, y) = l((y + 1)i )
• V AR(i, y) = r(r((y + 1)i )) + 1
• IN ST R(i, y) = l(r((y + 1)i ))
• LABEL� (i, y) = l(r((y + 1)i ))−̇2
Definiamo inoltre alcuni predicati che indicano, per il programma di numero y e l’istantanea
rappresentata da x, quali sono le possibili istruzioni successive da eseguire.
• SKIP (x, y) ⇔ [IN ST R(l(x), y) = 0 ∧ l(x) ≤ Lt(y + 1)]∨[IN ST R(l(x), y)≥ 2 ∧
∼ (pV AR(l(x),y) | r(x))]
• IN CR(x, y) ⇔ IN ST R(l(x), y) = 1
• DECR(x, y) ⇔ IN ST R(l(x), y) = 2 ∧ pV AR(l(x),y) | r(x)
• BRAN CH(x, y) ⇔
IN ST R(l(x), y) > 2 ∧ pV AR(l(x),y) | r(x) ∧ (∃i)≤Lt(y+1) LABEL(i, y) = LABEL� (l(x), y)
Adesso possiamo costruire la funzione SU CC(x, y) la quale, per il programma di numero y
fornisce la rappresentazione del successore dell’istantanea x.
SU CC(x, y) =

�l(x) + 1, r(x)�





 �l(x) + 1, r(x) · pV AR(l(x),y) �
�l(x) + 1, r(x)/p
�
V AR(l(x),y)



�min
[LABEL(i,
y) = LABEL� (l(x), y)], r(x)�

i≤Lt(y+1)


�Lt(y + 1) + 1, r(x)�
Abbiamo bisogno anche di
IN IT (n) (x1 , ..., xn ) = �1,
1
n
�
i=1
(p2i )xi �,
se SKIP (x, y),
se IN CR(x, y),
se DECR(x, y),
se BRAN CH(x, y),
altrimenti.
che dà la rappresentazione dell’istantanea iniziale con input x1 , ..., xn , e di
T ERM (x, y) ⇔ Z(x) > Lt(y + 1),
che determina se x è un’istantanea terminale per il programma di numero y.
Ora, mediante l’uso delle funzioni appena definite, definiamo ricorsivamente una funzione
che a partire dalle variabili di input x1 , ..., xn , dal numero di programma y e da un indice i,
definisce l’istantanea codificata all’ i-esimo passo del programma:
passo base: SN AP (n) (x1 , ..., xn , y, 0) = IN IT (n) (x1 , ..., xn );
passo ricorsivo: SN AP (n) (x1 , ..., xn , y, i + 1) = SU CC(SN AP (n) (x1 , ..., xn , y, i), y).
Inoltre,
ST P (n) (x1 , ..., xn , y, t) ⇔ T ERM (SN AP (n) (x1 , ..., xn , y, t), y)
e quindi STP(n) (x1 , ..., xn , y, t) è primitiva ricorsiva.
✷
2
Ventesima Prima Lezione
21/12/2006
Teorema della forma normale
Minimalizzazione propria
Insiemi ricorsivamente enumerabili e relativi teoremi
Forniamo ora dei concetti (indispensabili a dimostrare il teorema della forma normale che vedremo
a breve) secondo cui è possibile effettuare la codifica dello stato ! di un programma (rif. D.S.W. pag. 7475), indichiamo quindi con z lo stato codificato ad un certo istante del programma, quindi s "
#Y , X , Z , X 2 ,!$ " p1Y % p2X % p3Z % p4X 2 %! . Quindi possiamo affermare che anche un’istantanea & i,! '
può essere codificata (mediante le funzioni di accoppiamento), se # &! ' " s allora # & & i , ! ' ' " i , s " x
e, poiché quest’ultimo è un numero che codifica un’istantanea, da esso possiamo ricavare il suo successore (solo un accenno) che definiamo come segue:
DEF.: SUCC & x , y ' " i (, s (
con i (, s ( numero dell’istantanea successore di & i ,! ' e
y numero del programma, x è la codifica dello stato ! .
Si può dimostrare che tale funzione è primitiva ricorsiva.
DEF.: INIT&n ' & x 1 , x 2 ,!, x n ' " 1,
n
x
&p '
)
i "1
2i
i
questa rappresenta l’istantanea iniziale
del programma.
Per la quale le variabili Y, Z, Z 2 ,! " 0 , quindi si considerano solo i numeri primi di posto pari corrispondenti alle variabili di input X i .
Anche in questo caso la funzione è primitiva ricorsiva.
Ora, mediante l’uso delle funzioni appena definite, possiamo definire una funzione che a partire
dalle variabili di input x 1 , x 2 ,!, x n , dal numero di programma y e da un indice i, può risalire allo snapshot codificato all’i-mo passo del programma:
DEF.: Ricorsivamente diamo la seguente definizione:
*
passo base:
SNAP&n ' & x 1 , x 2 ,!, x n , y ,0 ' " INIT &n ' & x 1 , x 2 ,!, x n ' ,
*
passo ricorsivo:
SNAP&n ' & x 1 , x 2 ,!, x n , y , i + 1' " SUCC SNAP&n ' & x 1 , x 2 ,!, x n , y , i ' , y .
&
'
Essa rappresenta la funzione che restituisce lo snapshot codificato dopo l’esecuzione di un certo numero
di istruzioni (ultimo argomento i della funzione).
Eruditi delle nozioni appena argomentate passiamo al seguente:
TEOREMA 3.3 (della forma normale – rif. D.S.W. pag. 75-76): Sia f & x 1 , x 2 ,!, x n ' una funzione par-
zialmente calcolabile. Allora vi è un predicato primitivo ricorsivo R & x 1 , x 2 ,!, x n , y ' tale che:
&
'
f & x 1 , x 2 ,!, x n ' " l min R & x 1 , x 2 ,!, x n , z ' .
z
113
DIM.: Possiamo affermare che esiste un numero y0 di un programma che calcola f & x 1 , x 2 ,!, x n ' , infatti per ipotesi f & x 1 , x 2 ,!, x n ' è parzialmente calcolabile. Dobbiamo dimostrare che vale l’uguaglianza
&
'
f & x 1 , x 2 ,!, x n ' " l min R & x 1 , x 2 ,!, x n , z ' e che R & x 1 , x 2 ,!, x n , y ' è un predicato primitivo ricorsivo.
z
Il predicato seguente è utile a dimostrare il teorema:
&
'
, STP&n ' & x 1 , x 2 ,!, x n , y0 , r & z ' ' &
R & x 1 , x 2 ,!, x n , z ' 0 .
. r SNAP&n ' x , x ,!, x , y , r z
& ''
& 1 2
n
0
.1
&& &
/
" l & z ' //
1
2
''
'
che è chiaramente un predicato primitivo ricorsivo. Cerchiamo di interpretarlo.
Il predicato R & x 1 , x 2 ,!, x n , z ' è vero se e soltanto se sono entrambi veri i due predicati:
a. STP&n ' & x 1 , x 2 ,!, x n , y0 , r & z ' '
b.
&r & SNAP
&n '
e
& x1 , x 2 ,!, xn , y0 , r & z ' ' ' '1 " l & z '
a. è vero quando il programma di numero y0 si ferma dopo al più r & z ' passi (il valore di z deve essere
interpretato come il valore 3 , 4 , quindi l & z ' " 3 corrispondente ad un numero che identifica il valore di uscita del programma, mentre r & z ' " 4 rappresenta un valore corrispondente al numero di passi effettuati dal programma);
b. spezzettiamo il predicato e interpretiamo le varie parti:
SNAP&n ' & x 1 , x 2 ,!, x n , y0 , r & z ' ' rappresenta la codifica dello snapshot del programma di nume-
ro y0 al passo r & z ' e per come è stata definita la funzione SNAP, sarà uguale ad un numero del
tipo i , k , con i indice dell’istruzione e k pari al numero codificato dello stato prima
dell’esecuzione della i-ma istruzione ( k " #Y , X , Z , X 2 ,!$ -non è propriamente corretto utilizzare i
nomi delle variabili per indicare la codifica dei valori che essi contengono, ma per comodità e per una maggiore
comprensione utilizziamo questa notazione). Dunque risulta:
&
'
r SNAP&n ' & x 1 , x 2 ,! , x n , y0 , r & z ' ' " k
e anche:
&r & SNAP
&n '
& x1 , x 2 ,!, xn , y0 , r & z ' ' ' '1 " & k '1
e cioè il valore della variabile Y.
Di conseguenza il predicato b è vero quando Y " l & z ' , e quindi quando risulta: l & z ' "
" f & x 1 , x 2 ,!, x n ' .
Dunque il predicato R & x 1 , x 2 ,!, x n , z ' è vero se e soltanto se z assume un valore tale che il programma di numero y0 si ferma dopo al più r & z ' passi e se il valore della variabile Y (relativo allo snapshot finale) è uguale a l & z ' .
EDIT by Qd – Calcolabilità – XXI Lez.
114
Ritornando alla tesi del teorema la scrittura min & R & x 1 , x 2 ,! , x n , z ' ' rappresenta il valore minimo
z
che deve assumere z affinché il predicato R sia vero e ciò avviene nel momento in cui z assume un valore
3 , 4 tale che il programma di numero y0 si ferma dopo al più 4 passi e restituisce il valore
&
'
3 " Y " f & x 1 , x 2 ,!, x n ' . Quindi è chiaro che f & x 1 , x 2 ,! , x n ' " l min & R & x 1 , x 2 ,!, x n , z ' ' .
z
Essendo per ipotesi f parzialmente calcolabile è possibile che per certi valori di input la funzione restituisca un valore indeterminato 5 e che quindi non si fermi, dobbiamo assicurarci che l’uguaglianza
&
'
f & x 1 , x 2 ,! , x n ' " l min & R & x 1 , x 2 ,!, x n , z ' ' valga anche in questo caso particolare, avendo usato una
z
minimalizzazione non limitata, essendo il predicato R mai vero (non si ferma), otterremo un valore in-
&
'
determinato anche per l min & R & x 1 , x 2 ,!, x n , z ' ' .
z
Abbiamo dunque dimostrato che l’uguaglianza vale e che i predicati usati sono primitivi ricorsivi, il
teorema è dunque dimostrato.
Grazie al teorema appena dimostrato abbiamo dato una caratterizzazione per le funzioni parzialmente calcolabili che non è più legata agli S-programmi (non è un caso che questo teorema abbia delle analogie
molto forti con il teorema di Kleene visto per i linguaggi regolari).
Il teorema della forma normale ci è utile per dimostrare il seguente:
TEOREMA 3.4: Una funzione è parzialmente calcolabile se e solo se 0 si può ottenere a partire dalle funzioni iniziali applicando un numero finito di volte la composizione, la ricorsione (primitiva) e la
minimalizzazione (quest’ultima viene applicata solo una volta).
DIM. 6 : Dobbiamo dimostrare che se una funzione si può ottenere dalla funzioni iniziali applicando
un numero finito di volte la composizione, la ricorsione e la minimalizzazione allora tale funzione è parzialmente calcolabile. I teoremi 1.1, 2.1, 2.2, 3.1 e 7.2 (risp. rif. D.S.W. pagg. 39,40,41,42,58) dimostrano che se
una funzione è ottenuta mediante l’applicazione di un numero finito di volte, a partire dalla funzioni
iniziali (teor. 3.1), la composizione (teor. 1.1), la ricorsione (teor. 2.1 e 2.2), la minimalizzazione (teor. 7.2) allora
tale funzione è parzialmente calcolabile. Quindi la prima parte del teorema è dimostrata.
DIM. 7 : Ora dobbiamo dimostrare che se una funzione è parzialmente calcolabile allora essa si può
ottenere a partire dalle funzioni iniziali applicando un numero finito di volte la composizione, la ricorsione e la minimalizzazione e lo facciamo adoperando il teorema della forma normale. Difatti il teorema
della forma normale ci permette di esprimere qualsiasi funzione parzialmente calcolabile f come segue:
f & x 1 , x 2 ,! , x n ' " l 8: min R & x 1 , x 2 ,! , x n , y ' 9;
< y
=
con R predicato primitivo ricorsivo
(per la tesi del teorema della forma normale)
Tale funzione è chiaramente ottenuta da un numero finito di operazioni di composizione, ricorsione e
minimalizzazione. In particolare si è fatto uso di una sola minimalizzazione e della composizione con la
funzione primitiva ricorsiva l (essendo primitiva ricorsiva è ottenibile da funzioni iniziali).
Il teorema è dunque dimostrato.
EDIT by Qd – Calcolabilità – XXI Lez.
115
DEF. (rif. D.S.W. pag. 77): Quando min y R & x 1 , x 2 ,!, x n , y ' è una funzione totale (cioè quando
>x 1 , x 2 ,! , x n vi è almeno un valore di y per cui il predicato R & x 1 , x 2 ,! , x n , y ' è vero) si dice che abbiamo applicato l’operazione di minimalizzazione propria (o regolare) su R.
Quindi se l 8: min R & x 1 , x 2 ,! , x n , y ' 9; è totale 7 lo è anche min R & x 1 , x 2 ,!, x n , y ' da cui abbiamo
y
< y
=
il seguente:
TEOREMA 3.5: Una funzione è calcolabile 0 può essere ottenuta dalle funzioni iniziali mediante
un numero finito di operazioni di composizione, ricorsione e minimalizzazione propria.
DIM.: La dimostrazione deriva direttamente dal teorema precedente e dalla definizione di minimalizzazione propria.
Insiemi Ricorsivamente Enumerabili
(rif. D.S.W. pag. 78)
Ricordiamo che un insieme si dice:
*
primitivo ricorsivo
se la sua funzione caratteristica è primitiva ricorsiva
*
ricorsivo (calcolabile)
se la sua funzione caratteristica è calcolabile.
DEF.: Un insieme B ? " si dice ricorsivamente enumerabile (r.e.) se esiste una funzione parzialmen-
te calcolabile unaria g & x ' tale che: B " @ x B " | g & x ' CA .
Quindi B è l’insieme di tutti quei valori per cui la funzione unaria (se esiste) g & x ' è definita. In altri
termini B è r.e. se coincide con il dominio di definizione di una funzione parzialmente calcolabile
g & x ' . Se c è un programma che calcola la funzione g & x ' allora B è l’insieme di tutti gli input su
c per cui alla fine c si ferma. Da quest’ultima osservazione andiamo ad analizzare i cosiddetti problemi di semidecisione o di semiriconoscimento secondo cui si può realizzare un programma per stabilire
se un dato valore x fa arrestare il programma, da cui x B B (con B r.e.), ma se volessi stabilire se x D B
(con B r.e.) ciò non è possibile in quanto è impossibile prevedere se un programma terminerà o meno.
Ricorrendo alla tesi di Church ci potrebbero essere algoritmi generali per stabilire se x appartiene o meno ad un insieme r.e. B purché tali algoritmi non siano (necessariamente) scritti nel linguaggio f degli
S-programmi (perché per dimostrare la tesi bisogna generalizzare il problema e non specializzarlo al solo
linguaggio f ). Tali algoritmi vengono chiamati: procedure di semidecisione.
TEOREMA 4.3: Se un insieme B è ricorsivo allora 7 B è anche r.e.
Il contrario come vedremo (Teorema 4.7) non vale.
DIM.: Per ipotesi abbiamo che (ad esempio) f B & x ' è la funzione caratteristica di B ed è ricorsiva (cioè
calcolabile), ciò vuol dire che il predicato x B B è calcolabile.
EDIT by Qd – Calcolabilità – XXI Lez.
116
Quindi possiamo costruire un programma c che calcola la funzione (ad esempio) h & x ' :
# A$
IF
f B & X ' " 0 GOTO A
o anche:
# A$
IF
# & X B B ' GOTO A .
Ciò ci assicura che se l’input è un elemento dell’insieme B, per come è stato costruito, il programma
termina ( h & x ' C ) altrimenti entra in un loop infinito ( h & x ' "5 ), abbiamo dunque:
B " @ x B " | h & x ' CA
quindi il teorema è dimostrato.
Il passaggio da notazione insiemistica a proposizionale ci permette di dimostrare i seguenti teoremi:
TEOREMA 4.1 (rif. D.S.W. pag. 79): Se B e C sono insiemi appartenenti ad una classe PRC V (cioè se
possono essere espressi mediante funzioni caratteristiche appartenenti a V ) allora vi appartengono anche:
B EC ,
B FC e
B (complemento di B).
DIM.: La dimostrazione è un’immediata conseguenza del teorema 5.1 (rif. D.S.W. pag. 49 - P G Q , P & Q e
# P ) la cui tesi ci permette di esprimere mediante predicati i tre insiemi B E C , B F C e B .
Nell’ambito delle funzioni # x 1 , x 2 ,!, x m $ e & x 'i della numerazione di Gödel possiamo porre la nostra
attenzione a sottoinsiemi di "m , abbiamo:
TEOREMA 4.2: Posto V classe PRC e B ? "m con m H 1 . Allora B BV se e solo se 0 B ( BV con
B ( " @# x 1 , x 2 ,!, x m $ B " | & x 1 , x 2 ,!, x m ' B BA (chiaramente B ( ? " ).
DIM. 7 : Dobbiamo dimostrare che se B BV allora B ( BV , dunque se PB & x 1 , x 2 ,!, x m ' è la funzione caratteristica di B (per ipotesi B BV quindi PB & x 1 , x 2 ,! , x m ' è primitivo ricorsivo per il Teorema della forma normale) possiamo costruire la funzione caratteristica di B ( così:
PB( & x ' 0 PB & & x '1 , & x '2 ,!, & x 'm ' & Lt & x ' I m & x J 0
Ciò vuol dire che la funzione caratteristica di B( vale 1 se e soltanto se x è un naturale tale che la m-pla
& & x ' , & x ' ,!, & x ' ' B B , se la lunghezza della sequenza codificata in x non è maggiore di m e chiara1
2
m
mente se x " # x 1 , x 2 ,!, x m $ J 0 (per come è stata definita la numerazione di Gödel). Poiché PB( & x ' è primitiva
ricorsiva B ( BV .
DIM. 6 : Vogliamo ora dimostrare che se B ( BV allora B BV . Se indichiamo con PB( & x ' la funzione caratteristica di B( allora possiamo scrivere:
PB & x 1 , x 2 ,!, x m ' 0 PB( &# x 1 , x 2 ,!, x m $'
EDIT by Qd – Calcolabilità – XXI Lez.
117
Cioè la m-pla & x 1 , x 2 ,!, x m ' B B se e soltanto se x " # x 1 , x 2 ,!, x m $ B B ( , poiché abbiamo espresso la
funzione caratteristica di B mediante il predicato PB( &# x 1 , x 2 ,!, x m $' che è primitivo ricorsivo, B BV .
Conseguenza importante del teorema appena dimostrato è che l’insieme:
@# x , y $ B " | HALT & x , y 'A
non è calcolabile poiché non lo è la relativa funzione
caratteristica e cioè HALT & x , y ' .
TEOREMA 4.4: L’insieme B è ricorsivo se e solo se 0 B e B( sono entrambi r.e.
DIM. 7 : Se B è ricorsivo, allora dal teorema 4.1, lo è anche B e dal teorema 4.3 ricaviamo che, poiché
B e B sono ricorsivi allora B e B sono anche r.e.
DIM. 6 : Se B e B sono entrambi r.e. dobbiamo provare che B è ricorsivo, a tal fine possiamo scrivere:
B " @ x B " | g & x ' CA
e
B " @ x B " | h & x ' CA
(con g & x ' e h & x ' parzialmente
calcolabili per la definizione di insiemi r.e.)
Supponendo che g & x ' venga calcolata dal programma c ed h & x ' dal programma d , posto
p " # &c ' e q " # &d ' . Allora possiamo scrivere un programma che calcola l’insieme B, cioè che calcola la funzione caratteristica di B (tale metodo prende il nome di incastro (dovetailing) di due algoritmi
adoperando il teorema 3.2 del contapassi secondo cui la funzione STP è primitiva ricorsiva):
# A$
IF
STP&1' & X , p,T ' GOTO C
IF
STP&1' & X , q ,T ' GOTO E
Se il programma c di numero p si ferma su ingresso X dopo al più T
passi, il programma a sinistra rappresentato restituisce 1 (istruzione
#C $ ), ciò vuol dire che X B B , essendo B l’insieme costituito dai natu-
rali tali che la funzione g & x ' calcolata da c sia determinata ( C ).
Se invece il programma p non si ferma dopo al più T passi, ciò potrebGOTO A
be corrispondere al fatto che X D B , per verificare ciò si esegue il predicato STP sul programma d , in caso negativo si incrementa T e si ripe#C $ Y K 1
tono i controlli sul programma c sempre su ingresso X ma in base ad
un numero di passi maggiore ( T + 1 ), in caso positivo si traduce questa cosa in X D B e si esce dal programma descritto a
sinistra, il quale ritorna 0 (ricordiamo che STP è un predicato calcolabile).
T KT + 1
Il programma descritto è di fatto una funzione caratteristica per B che è ricorsiva, quindi B è ricorsivo.
TEOREMA 4.5: Se B e C sono insiemi r.e. allora lo sono anche B E C e B F C .
DIM. F : Posto B " @ x B " | g & x ' CA e C " @ x B " | h & x ' CA
(chiaramente g e h sono parzialmente calcolabili)
Sia f & x ' la funzione calcolata dal programma:
EDIT by Qd – Calcolabilità – XXI Lez.
118
Y K g &X '
Y K h&X '
in pratica il programma termina soltanto quando sia g & x ' che h & x '
terminano, possiamo affermare quindi che:
B F C " @ x B " | f & x ' CA che rappresenta la definizione di insieme r.e. essendo f & x ' parzialmente calcolabile.
DIM. E : Per ottenere la dimostrazione ci serviamo nuovamente dell’algoritmo d’incastro. Posto di
nuovo B " @ x B " | g & x ' CA e C " @ x B " | h & x ' CA , posto p " # &c
' e q " # &d ' i numeri dei programmi che calcolano rispettivamente g & x ' e h & x ' , consideriamo ora la funzione k & x ' calcolata dal
seguente programma:
# A$
& X , p,T ' GOTO E
STP&1' & X , q ,T ' GOTO E
IF STP
IF
& 1'
T KT + 1
GOTO A
Il programma è simile a quello visto prima però in questo caso possiamo affermare che k & x ' C soltanto quando almeno
uno dei due programmi p o q termina su ingresso X dopo al
più T passi, di conseguenza possiamo concludere che:
B E C " @ x B " | k & x ' CA . Il teorema è dunque dimostrato.
DEF.: Con il simbolo Wn indichiamo l’insieme:
Wn " @ x B " | L & x , n ' CA
( " @ x B " | g & x ' CA con g & x ' parzialmente calcolabile
dal programma c
e # &c
' "n)
Ne segue:
TEOREMA 4.6 (dell’enumerazione): Un insieme B è r.e. se e solo se 0 esiste un n tale che
B " Wn .
DIM.: È un’immediata conseguenza della definizione data per L & x , n ' .
Si ha infatti B " Wn 0 B " @ x B " | g & x ' CA " @ x B " | L & x , n ' CA con g & x ' parzialmente calcolabile dal programma c
e # &c
' "n.
Il teorema deve il suo nome al fatto che la sequenza W0 ,W1 ,W2 ,! rappresenta una enumerazione di
tutti gli insiemi r.e., scandisce cioè tali insiemi in base al numero di programma ( # &c ' " 0,1,2,! ).
DEF.: Con K indichiamo il seguente insieme:
K " @n B " | n BWn A
EDIT by Qd – Calcolabilità – XXI Lez.
( " @n B " | L & n, n ' CA con n " # &c
')
119
Esso rappresenta l’insieme di tutti i naturali per cui i programmi di numero n si fermano su ingresso n,
tale insieme può essere identificato tra gli elementi della diagonale della matrice delle funzioni unarie
M &1' vista prima:
N
input
Mc(1)0 & 0 ' Mc(1)0 & 1'
C
num.
prog.
C
N
Mc(1)0 & 2 '
!!
Mc(1)1 & 0 '
Mc(1)1 & 1' Mc(1)1 & 2 '
!!
Mc(1)2 & 0 '
Mc(1)2 & 1'
Mc(1)2 & 2 ' ! !
$
$
$
$
$
$
Non è detto però che tutti i numeri corrispondenti ai
programmi che calcolano le funzioni sulla diagonale siano tutti appartenenti all’insieme K, in quanto alcuni elementi sulla diagonale potrebbero assumere valori indeterminati 5 .
%
%
Da quanto visto possiamo affermare che:
n BWn 0 L & n, n ' C0 HALT & n, n ' .
Allora K rappresenta l’insieme di tutti gli interi n tali che il programma di numero n si ferma su ingresso n, da cui abbiamo:
TEOREMA 4.7: K è un insieme r.e. ma non è ricorsivo.
DIM.: Per assurdo supponiamo che K sia ricorsivo, quindi, per il Teorema 4.4, abbiamo che sia K che
K sono r.e. Sappiamo per certo che K è r.e. infatti, essendo K " @n B " | L & n, n ' CA , L & n, n ' per il
Teorema
3.1
dell’universalità
è
certamente
parzialmente
K " @n B " | L & n, n ' CA rispecchia la definizione di insieme r.e.
calcolabile,
quindi
la
scrittura
Ora, se anche K fosse r.e., per il Teorema 4.6 dell’enumerazione, si avrebbe K " Wi per qualche i. Da
ciò conseguirebbe che i BWi 0 i B K (se i B Wi allora i B K e viceversa, essendo uguali), ma si ha anche che
(per definzione K " @n B " | n B Wn A ) i B K 0 i BWi (nel caso in cui i " n , cioè effettuando la diagonalizzazione),
da cui si avrebbe i B K 0 i B K , ma ciò è assurdo ( K è il complemento di K quindi i B K 0 i D K ). Quindi
l’insieme K è r.e. ma non è ricorsivo e inoltre si apprende che K non è r.e.
A tale conclusione si può giungere anche mostrando che, poiché K " @n B " | HALT & n, n 'A , HALT
rappresenta la funzione caratteristica che definisce K, essendo
HALT & x , y '
(in particolare
HALT & x , x ' ) un predicato non calcolabile, allora K non è calcolabile (cioè non è ricorsivo, per definizione un insieme si dice non calcolabile o non ricorsivo se la sua funzione caratteristica non è calcolabile).
EDIT by Qd – Calcolabilità – XXI Lez.
Esercitazione di fine Corso
9/01/2007
Esercizio 1 (rif. D.S.W. pag. 28, ex.1): Sia c il programma (b) (rif.
D.S.W. pag. 19), scrivere un calcolo di c
iniziando dallo snapshot 1 # A $ IF X O 0 GOTO B
2
Z K Z +1
& 1,! ' con ! " @ X " 2,Y " 0, Z " 0A .
3
IF Z O 0 GOTO E
Abbiamo la sequenza:
4 #B $ X K X P 1
s1 " & 1,! ' ; s2 " & 4, @ X " 2,Y " 0, Z " 0A ' ;
5
Y KY +1
s3 " & 5, @ X " 1,Y " 0, Z " 0A ' ; s 4 " & 6, @ X " 1,Y " 1, Z " 0A ' ;
6
Z K Z +1
s5 " & 7, @ X " 1,Y " 1, Z " 1A ' ; s6 " & 1, @ X " 1,Y " 1, Z " 1A ' ;
7
IF Z O 0 GOTO A
s7 " & 4, @ X " 1,Y " 1, Z " 1A ' ; s8 " & 5, @ X " 0,Y " 1, Z " 1A ' ;
8
s9 " & 6, @ X " 0,Y " 2, Z " 1A ' ; s10 " & 7, @ X " 0,Y " 2, Z " 2A ' ;
s11 " & 1, @ X " 0,Y " 2, Z " 2A ' ; s12 " & 2, @ X " 0,Y " 2, Z " 2A ' ;
s13 " & 3,@ X " 0,Y " 2, Z " 3A ' ; s14 " & 8, @ X " 0,Y " 2, Z " 3A '
s14 è l’istantanea terminale.
Esercizio 2 (rif. D.S.W. pag. 28, ex.2): Creare un programma c tale che per ogni calcolo s1 , s2 ,! , sk di
c con s1 " & 1,! ' risulta k " 5 .
Possiamo scrivere il seguente programma che soddisfa la traccia dell’esercizio:
1 X K X +1
2 X K X P1
3 X K X +1
Qualsiasi sia l’input vi sarà sempre un calcolo per cui sk " s5 .
4 X K X P1
5
Esercizio 3 (rif. D.S.W. pag. 31, ex.1): Sia c il seguente programma:
IF X O 0 GOTO A
# A$
X K X +1
IF X O 0 GOTO A
# A$
Y KY +1
calcolare M c&1' & x ' .
Sia X " r O 0 : poiché X O 0 si salta all’istruzione etichettata con A (la prima), quindi X " r + 1 ;
all’istruzione successiva risulta ancora X O 0 , quindi si salta all’istruzione A (sempre la prima) e
X " r + 2 , si capisce bene che questo meccanismo non avrà mai termine, quindi in questo caso la funzione calcolata dal programma assume valore indeterminato.
121
Mentre, se X " 0 , dalla prima istruzione si passa alla seconda, quindi X " 1 , alla terza istruzione risulta X non nulla quindi si salta all’istruzione etichettata con A (sempre la prima); si deduce che anche in
questo caso la funzione calcolata dal programma non assumerà mai valori determinati, si ha dunque:
M c&1' & x ' "5 >x B " .
Esercizio 4 (rif. D.S.W. pag. 36, ex.5): Sia P & x ' un predicato calcolabile. Dimostrare che la seguente
funzione è parzialmente calcolabile:
QR x 1 + x 2 se P & x 1 + x 2 '
f & x1 , x2 ' " S
altrimenti
RT5
(il comportamento di P non ci interessa, cioè non ci interessa sapere per quali valori sarà vero o falso).
Essendo P & x ' calcolabile per ipotesi possiamo adoperarlo all’interno di un S-programma che calcoli f & x 1 , x 2 ' :
# A$
Z K X1 + X2
IF # P & Z ' GOTO A
Y KZ
Chiaramente tale programma calcola la funzione f & x 1 , x 2 ' , quindi
possiamo affermare che essa è parzialmente calcolabile, avendo esibito un S-programma che la calcola.
Esercizio 5 (rif. D.S.W. pag. 36, ex.6): Sia P & x ' un predicato calcolabile. Dimostrare che la funzione seguente è parzialmente calcolabile:
QR1
EX P & r ' " S
RT5
se vi sono almeno r numeri n tali che P & n ' " 1
altrimenti
.
In pratica EX P & r ' " 1 se r è il numero minimo di predicati P & n '
veri (se ad esempio P & 0 ' " 1 , P & 1' " 1 , P & 2 ' " 0 , P & 3 ' " 1 , P & k ' " 0 >k H 4
allora risulterà: EX P & 0 ' " 1 , EX P & 1 ' " 1 , EX P & 2 ' " 1 , EX P & 3 ' " 1 , EX P & 4 ' "5 ,
EX P & 5 ' "5 , in quanto il predicato P è vero soltanto per 3 valori di x). Si deve
dunque realizzare un programma che verifichi che P & x ' sia vero almeno r volte e quindi che restituisca come output il valore 1, in caso contrario deve entrare in un loop infinito, il programma a destra calcola
EX P & r ' .
Se avessimo voluto dimostrare invece che EX P & r ' era primitiva ricorsiva
non era sufficiente esibire un S-programma che la calcolasse, ma avremmo
dovuto esprimere la funzione utilizzando le funzioni iniziali adoperando un
numero finito di volte composizione di funzioni e ricorsione primitiva.
IF X " 0 GOTO C
# A$
IF P & Z ' GOTO B
Z K Z +1
GOTO A
#B $
X K X P1
Z K Z +1
IF X O 0 GOTO A
#C $
Y K1
Esercizio 6 (rif. D.S.W. pag. 43, ex.2): Dimostrare che la classe di tutte le funzioni totali è una classe
PRC.
Sappiamo che una qualsiasi classe PRC è costituita da funzioni totali. Le funzioni ottenibili dallo schema
di ricorsione e composizione di funzioni appartenenti ad una classe PRC sono ancora totali, infatti la
classe PRC è chiusa rispetto alla ricorsione e composizione. Quindi possiamo affermare che la classe delle
funzioni totali è PRC.
EDIT by Qd – Esercitazione
122
Esercizio 7: Dimostrare che la classe di tutte le funzioni totali unarie non è enumerabile.
Si può dimostrare esibendo una funzione che non appartiene alla enumerazione, possiamo adoperare il
metodo della diagonale. Supponiamo per assurdo che tale classe sia enumerabile, avremo: f 0 & x ' ,
f 1 & x ' , f 2 & x ' , …, f n & x ' , … >x B " . Ora definiamo la funzione g & x ' " f x & x ' + 1 la quale è chiaramente una funzione totale, quindi deve trovarsi nella enumerazione, cioè deve esiste un indice k tale
che g & x ' " f k & x ' . Ma se scegliamo un valore di x uguale proprio a k (diagonalizzazione) avremo:
f k &k ' " g &k ' " f k &k ' + 1
Che è chiaramente impossibile, quindi la classe non è enumerabile.
Esercizio 8 (rif. D.S.W. pag. 47, ex.2): Dimostrare che >k B " la funzione f & x ' " k è primitiva ricorsiva.
Bisogna esprimere la funzione adoperando composizione e ricorsione applicate alle funzioni iniziali un
numero finito di volte, si ha quindi:
&
f & x ' " s s & s ! s & n & x ' ' !'
'
La funzione successore s deve essere applicata k volte e la funzione nulla n una sola volta, abbiamo quindi una funzione primitiva ricorsiva.
Esercizio 9 (rif. D.S.W. pag. 54, ex.1): Dimostrare che la seguente funzione è primitiva ricorsiva:
se x è un quadrato perfetto
Q2 x
g &x ' " S
T2 x + 1 altrimenti
Per dimostrare che la funzione è primitiva ricorsiva dobbiamo sostituire all’ipotesi “se x è un quadrato perfetto” un predicato primitivo ricorsivo come il seguente:
P & x , y ' 0 & Uy 'I x & x " y 2 '
Non è difficile dimostrare che le due funzioni f & x ' " 2 x e h & x ' " 2 x + 1 sono primitive ricorsive,
quindi possiamo riscrivere g & x ' così:
QR f & x ' se P & x , y '
g &x ' " S
RTh & x ' altrimenti
La quale risulta primitiva ricorsiva (rif. teorema 5.4, definizione per casi D.S.W. pag. 50).
Esercizio 10 (rif. D.S.W. pag. 58, ex.5): Sia R & x , t ' un predicato primitivo ricorsivo e
g & x , y ' " max R & x , t '
tIy
cioè g & x , y ' è il più grande valore t I y per cui R & x , t ' è vero, in caso contrario (cioè se non c’è alcun valore per cui il predicato è vero) allora g & x , y ' " 0 , vogliamo dimostrare che tale funzione è primitiva ricorsi-
va.
EDIT by Qd – Esercitazione
123
Possiamo esprimere la funzione g & x , y ' come segue:
@
A
g & x , y ' " mint I y R & x , t ' V # Uu I y ,1R & x , u ' V & u J t '-2
Non avendo a disposizione una funzione primitiva ricorsiva max, si simula il suo comportamento assicurando che il massimo valore per cui è vero il predicato R & x , t ' equivale al minimo, ma aggiungendo
anche la clausola che non deve esistere alcun valore maggiore di t che rende vero il predicato
Esercizio 11 (rif. D.S.W. 77, ex.1): Sia Lu & x ' la funzione universale che calcola il programma di numero u. Si deve dimostrare che per ogni u esistono infiniti numeri v per cui Lu & x ' " Lv & x ' >x B " .
Possiamo costruire, a partire dal programma c di numero u con n istruzioni, il nuovo programma
c i di numero v, di n + 1 istruzioni, aggiungendo al programma c dopo la sua ultima istruzione
l’istruzione pigra: Z i K Z i (se avessimo aggiunto come ultima istruzione Y K Y allora u " v - rif. D.S.W. pag. 67).
È chiaro che # &c i ' O # &c
' #, ma i due programmi calcolano la stessa funzione. Tale metodo può es-
sere applicato un numero infinito di volte fornendo infiniti valori di v che soddisfano sempre
l’uguaglianza: Lu & x ' " Lv & x ' . Ciò ci fa capire che se esiste un programma per una funzione parzialmente calcolabile
allora ne esistono infiniti che calcolano la stessa funzione (analogamente a quanto accade per gli automi).
Esercizio 12 (rif. D.S.W. 85, ex.7-a): Siano A e B due insiemi. Provare o confutare che:
se A E B è r.e. 7 A e B sono entrambi r.e.
L’implicazione è falsa, il controesempio è dato dall’insieme " che è r.e. e può essere visto come
l’unione di K e K , sappiamo che K è r.e. ma non K .
Esercizio 13 (sulle grammatiche C.F. - rif. D.S.W. 287, ex.1-a): Esibire una grammatica C.F. che genera il seguente linguaggio:
@
A
L & W ' " a # j $b #i $ | j H i J 0 .
La grammatica C.F. W ha le seguenti produzioni: S N ab | aSb | aS e chiaramente genera il linguaggio
suindicato.
N.B.: Questi erano solo alcuni dei tanti (e differenti) esercizi che esistono circa gli argomenti visti, è vivamente consigliato,
al fine di superare l’esame, di svolgere un numero consistente di esercizi, prendendo spunto dal libro di testo e dalle indicazioni dei Professori, nonché ovviamente partire da una buona conoscenza dei concetti teorici, senza i quali sarebbe molto
difficile risolvere gli esercizi, soprattutto quelli sulla calcolabilità.
In bocca al lupo a Tutti
EDIT by Qd – Esercitazione
Qd
124
Modifiche apportate rispetto alla versione del 29 Settembre 2008 (le pagine indicate in questo elenco
si riferiscono alla versione del 29 Settembre 2008):
*
*
*
Pag. 23: Nel passo induttivo della formula di Kleene, l'esponente del primo elemento del secondo membro dell'equazione è "k", non "k+1";
Pag. 24: Nella dimostrazione del Lemma a fine pagina, nel passo induttivo, l'esponente del
primo elemento del secondo membro dell'equazione è "r", non "r+1";
Pag. 28: Nel teorema 5.4, al punto 1.c, la forma corretta del secondo membro
dell’equivalenza è:
& &
*
*
*
' '
L " 8: si1 & si2 & si3 ! sim ! 9;
<
=
Pag. 29: Nella dimostrazione del teorema 6.1, al secondo rigo, la frase corretta è "... è ovvio
che almeno una cassetta dovrà contenere almeno due lettere";
Pag. 84: Aggiunti i corollari 5.2 e 5.3, (rif.: D.S.W. pag. 50);
Pag. 87: Al punto "Mentre il predicato Q E viene così espresso", nella formula dopo dev'essere Q E invece di QU ;
*
Pag. 109: Al passo # F $ nel programma universale è Y K & S '1 , non Y K & S 'i ;
*
Pag. 110: Definizioni errate di STP. Tra gli argomenti della funzione, manca y, la versione
corretta è: STP&n ' & x 1 , x 2 ,!, xn , y , t ' ;
*
Pag. 110: Per il nuovo A.A., non basta il solo enunciato del teorema 3.2, recuperare la dimostrazione relativa dal D.S.W. pag. 74;
Pag. 110: Nella definizione di funzione caratteristica, la forma corretta è "...e abbiamo:
R " @a B S | P & a 'A ";
*
*
Pag. 115: Dopo la DEF. l’implicazione corretta è: “…se l 8: min R & x 1 , x 2 ,! , xn , y ' 9; è totale
< y
=
7 lo è anche min R & x 1 , x 2 ,! , xn , y ' …”;
y
*
*
Pag. 118: Nella dimostrazione di U, all'ultimo rigo è B E C , non B F C ;
Infine, spero che Alan mi perdoni dall’aldilà … pag. 102: si scrive Turing , non Touring.