Funzioni ricorsive - Dipartimento di Matematica

FUNZIONI RICORSIVE
Caratterizzazione matematica delle funzioni computabili.
Introdotta da Godel e Kleene negli annni ’30, ha ispirato, ancora negli anni ’50,
modelli e linguaggi di programmazione funzionale (formalismo di McCarthy e LISP).
Consideriamo l’insieme di tutte le funzioni intere:
F ={f | f: Nn → N, n ≥ 0}
Se n = 0 la funzione è una costante.
Def. Sono funzioni base le funzioni:
- zero, cioè le funzioni O(n) (x1, ... , xn) = 0
(se n = 0 la funzione O(0)( ) corrisponde a 0)
- successore, cioè la funzione S (x) = x + 1
- selettive (o identita), cioè le funzioni Ui(n) (x1, ... , xn) = xi
Def. La classe delle funzioni ricorsive primitive è la piu piccola classe di funzioni che contiene le
funzioni base ed è chiusa rispetto alle operazioni di:
- composizione: a partire da m funzioni g1, ..., gm di n argomenti e da una funzione h di m argomenti:
f(x1,..., xn) = h(g1(x1,..., xn),..., gm (x1,..., xn))
- ricorsione primitiva: a partire da una funzioni g di n argomenti e da una h di n+2 argomenti:
f(x1,..., xn, 0) = g(x1,..., xn)
{
f(x1,..., xn, y+1) = h(x1,..., xn, y, f(x1,..., xn, y))
Es. Dimostrare che sono primitive ricorsive le funzioni seguenti:
0.
qualunque funzione costante
1.
incr2 (x) = x+2
2.
somma (x, y) = x+y
3.
prod (x, y) = x*y
4.
s(x, y) = ∑ f(x,t)
t<y
f pri. ric. e convenzione standard che
∑ f(x, t) =0
t<0
5.
p(x, y) = ∏ f(x,t)
t<y
f pri. ric. e convenzione standard che
∏ f(x, t) =1
6.
esp(x,y) = xy
pse (x, y) = yx
7.
f(x, y, z)=g(y, 3, x, x)
8.
Ogni funzione ottenuta da una prim. ric. per “trasformazione esplicita”, come scambio
di colonne, variabili ripetute, variabili omesse, sostituzione di costanti, ecc.
9.
f(0)
e
=c
t<0
a partire da g pri. ric.
c∈N
{
f(y+1) = h (y, f(y))
10.
f(n) = n!
con h prim. ric.
11.
pred (0)
= 0
{
pred (x+1) = x
12.
- (x, y) = x-y
0
se x > y
altrimenti
13.
f(x)
= g(x)
h(x)
se p(x)=1
se p(x)=0
g, h prim. ric. e p(x) ∈ {0,1} pred. prim. ric.
f(x)
= g(x)
h(x)
t(x)
se p(x)=1
se q(x)=1
se r(x)=1
g, h, t prim. ric.
p, q, r pred. prim. ric con p(x)+q(x)+r(x) = 1
Qualche predicato primitivo ricorsivo:
14.
zero(x) = 1
0
se x = 0
se x > 0
15.
pos(x)
16.
mineq (x, y) = 1
0
se x ≤ y
altr.
17.
min (x, y) = 1
18.
eq (x, y) = 1
0
se x = y
altr.
19.
20.
f(0)
f(1)
f(2)
f(x+1)
= c0
= c1
= c2
= h (x, f(x))
=1
0
se x > 0
se x = 0
0
neq (x, y) = 1
0
se x < y
altr.
se x≠ y
altr.
x ≥ 2, h prim. ric.
21. Teorema Siano h e g funzioni ricorsive primitive. È ricorsiva primitiva la funzione cosi defnita
μ t ≤ h(x1,..., xn) [g(x1,..., xn, t) = 0]
se esiste un tale t
0
altrimenti
f(x1,..., xn) = {
Alternativamente a partire da h, g ed r ricorsive primitive:
μ
r(x1,..., xn) ≤ t ≤ h(x1,..., xn)
[g(x1,..., xn, t) = 0]
se esiste un tale t
f(x1,..., xn) = {
0
22.
f(n) = ⎣√n⎦
23.
dip(m, n)= 1
0
24.
mindip(n) = minimo divisore proprio di n, se esiste, 0 altrimenti
23 bis div(m, n) = 1
0
altrimenti
se m divide propriamente n
altr.
se m divide n
altr.
25.
prime (n) = 1
0
se n è primo
altr.
26.
p(n) = n-esimo numero primo, n ≥ 0 { p(0) = 2, p(1)=3, …....}
27.
E(i, x) = esponente dell'i-esimo primo p(i) nella decomposizione di x in fattori primi
28.
M(x) = massimo intero m tale che il primo p(m) divide x > 1, 0 altrimenti.
La funzione di Ackermann A(m, n, p) è una funzione di tre variabili totale e calcolabile.
Alla fine del 1920 Hilbert ipotizzò che la funzione non fosse primitiva ricorsiva ma fu Ackermann,
segretario personale di Hilbert e suo studente, che lo dimostrò.
Una funzione simile, definita più tardi da Rozsa Peter e Raphael Robinson, totale ma non pr. rec. è:
A(0, n) = n+1
A (m+1, 0) = A (m,1)
A(m+1, n+1) = A (m, A(m+1, n)
m\n
0
1
2
3
0
1
2
3
5
1
2
3
5
13
4
13
65533
Valori di A(m, n)
2
3
3
4
4
5
7
9
29
61
265536 − 3
5 65533 A(4, 65533) A(4, A(5, 1)) A(4, A(5, 2))
6 A(5, 1) A(5, A(5, 1)) A(5, A(6, 1)) A(5, A(6, 2))
4
5
6
11
125
n
n+1
n+2
2n + 3
(n + 3)
2
−3
A(3, A(4, 3))
A(4, A(5, 3)) A(4, A(5, n-1))
A(5, A(6, 3)) A(5, A(6, n-1)
La ricorsione primitiva non è quindi suffcientemente potente per descrivere tutte le funzioni
calcolabili. Infatti:
1. esistono funzioni totali che sono calcolabili mediante algoritmi ma non sono ricorsive primitive.
2. esistono funzioni parziali calcolabili, ad esempio la funzione:
f(dM, x) = 1 se la macchina di Turing M si arresta su input x, indefnita altrimenti
Def. La classe delle funzioni ricorsive (dette anche parziali o generali) è la piu piccola classe di
funzioni che contiene le funzioni base ed è chiusa rispetto alle operazioni di composizione, ricorsione
primitiva e:
- minimizzazione: a partire da una funzione g di n+1 argomenti :
μ t [g(x1,..., xn, t) = 0]
se esiste un tale t
U
altrimenti indefinita
f(x1,..., xn) = {
Alternativamente: a partire da funzioni h e g di n+1 argomenti :
μ t [h(x1,..., xn, t) > g (x1,..., xn, t)]
se esiste un tale t
U
altrimenti indefinita
f(x1,..., xn) = {
Funzioni ricorsive e linguaggi imperativi
Si puo facilmente verifcare che le funzioni ricorsive sono calcolabili mediante macchine di Turing o
mediante macchine a registri. Piu diffcile è mostrare il risultato opposto e cioè:
Teorema. Ogni funzione calcolabile con una macchina a registri è ricorsiva.
Dim. Per semplifcare la dimostrazione mostriamo che la funzione calcolata da una macchina a
registri elementare è ricorsiva.
Ricordiamo che una MREL viene inizializzata con i valori x1 ,..., xn nei registri R1,..., Rn e quando
termina (se esegue un salto all’istruzione 0) il valore del risultato è contenuto nel registro R1.
Osserviamo innanzitutto che la confgurazione di una MREL, è completamente determinata se
forniamo il contenuto dei suoi registri e il contenuto del ‘program counter’, cioè il numero d’ordine
della prossima istruzione da eseguire. Per trasformare tali valori in numeri interi adottiamo le
seguenti codifche.
Data una sequenza di interi z0, ..., zn denotiamo con < z0, ..., zn > l’intero 2x03x15x2 ... pnxn
Se t è un intero positivo indichiamo con (t)k l’esponente del primo pk nella decomposizione di t in
fattori primi. Cosi se pm è il massimo numero primo che divide t, abbiamo che t = <(t)0,..., (t)m> .
Possiamo codifcare il contenuto dei registri e la confgurazione di una MREL nel seguente modo:
cod(registri) = < R[1], ..., R[n] >
cod(confgurazione) = < PC, cod(registri) >
e codifcare una computazione eseguita dalla MREL, cioè una sequenza di confgurazioni c 0, ..., ck,
( c0 confgurazione iniziale) come:
cod(computazione) = < cod(c0),..., cod(ck) >
A questo punto, dato un programma π per MREL si puo defnire un predicato T π che, data una
sequenza di interi x1, ..., xn ed un intero t, verifca se t codifca la computazione compiuta dal
programma π con input x1, ..., xn.
Il predicato Tπ (x1, ..., xn, t), con t = <(t)0,..., (t)m>, assume quindi valore vero se e solo se:
• (t)0 è codifca della confgurazione iniziale
• per ogni i ≥ 0, (t)i+1 è la codifca della confgurazione seguente alla confgurazione codifcata
con (t)i in base a quanto previsto dalle istruzioni del programma π.
• (t)m è codifca di confgurazione fnale (cioè m è il massimo numero primo che divide t ed il
PC contiene 0).
Supponendo che un intero t soddisf il predicato T π, per il dato input x1, ..., xn, il valore della
funzione calcolata dal programma π è recuperabile facilmente dalla codifca (t)m poiche non è
altro che il contenuto del registro R1 nella confgurazione fnale della computazione, cioè è il valore
Uπ(t) = (((t)m)1)0
In defnitiva avremo che la funzione f calcolata dalla MREL soddisfa la seguente forma (Forma
Normale di Kleene):
f(x1, ..., xn) = Uπ (μt (Tπ (x1, ..., xn, t) = 1)) .
Funzioni ricorsive e linguaggi funzionali
Sul libro viene introdotto un semplice linguaggio di programmazione funzionale
chiamato SLF e viene dimostrato che:
Th. Il linguaggio SFL consente la definizione di tutte le funzioni ricorsive.
I linguaggi di programmazione funzionale permettono di descrivere funzioni senza
fare riferimento esplicito ai modelli di macchina che eseguono il calcolo. In questo
contesto il concetto di esecuzione di una computazione viene sostituito da quello di
valutazione di una espressione.
Insiemi ricorsivi e
insiemi ricorsivamente enumerabili
Le seguenti formulazioni sono date per insiemi di interi, ma valgono per altre tipologie
di insiemi, come i linguaggi defniti su alfabeti opportuni.
Def. Un insieme è detto ricorsivo se la sua funzione caratteristica è ricorsiva.
Th. Un insieme S ⊆ N è ricorsivo ⇔ è decidibile.
Dim. Basta osservare che la funzione carattteristica è ricorsiva ⇔ esiste una MT che
la calcola, e che quindi accetta ogni input x in S e rifuta ogni x non in S.
Def. Un insieme S ⊆ N è ricorsivamente enumerabile (r.e.), se è vuoto oppure è
l'immagine di una funzione f totale computabile; in tal caso diciamo che la funzione f
lo enumera.
Teorema. Le seguenti affermazioni sono equivalenti:
i)
S è ricorsivamente enumerabile.
ii)
S è semidecidibile (accettato da una macchina di Turing M)
iii) S è il dominio di una funzione calcolabile parziale g
iv) S è l'immagine di una funzione calcolabile parziale h
Dim.
i) ⇒ ii) Se S è vuoto è ovviamente semidecidibile. Se S non è vuoto per decidere se un
intero n appartiene ad S basta calcolare f(0), f(1), ecc., cioè enumera gli elementi di S
ed accettare n se compare nell'enumerazione.
ii) ⇒ iii) La funzione g è defnita nel seguente modo:
g(n) = 1 se M accetta n, indefnita altrimenti
iii) ⇒ iv) La funzione h puo essere defnita cosi:
h(n) = n se g(n) è defnita, indefnita altrimenti.
iv) ⇒ i) Se l'immagine di h è vuota è r.e. per defnizione. Altrimenti essa contiene
almeno un elemento z; una macchina puo essere defnita che opera cosi, per fasi:
fase 1: 1 passo di h(0); se termina ritorna h(0);
fase 2: 2 passi di h(0), 2 passi di h(1); per ogni computazione che termina (in al
piu 2 passi) ritorna il valore trovato;
fase 3: 3 passi di h(0), 3 passi di h(1), 3 passi di h(2); per ogni computazione
che termina ( (in al piu 3 passi) ritorna il valore trovato; ecc.
Allora la funzione seguente è totale, computabile ed enumera S:
f(n) = y se y è l’(n+1)-esimo valore restituito