Fondamenti dell’Informatica a.a. 2004-2005 Esercizi svolti in aula. La maggior parte degli esercizi sono tratti dal testo: Kfoury, Moll, Arbib:”A Programming Approach to Computability” (gli esercizi del testo riportano la numerazione del testo, gli altri sono numerati A,B,…) Notazioni: sia N l’insieme dei numeri naturali. Sia l’operazione di prodotto tra naturali e ^ l’operazione di elevazione a potenza. denota la composizione di funzioni, cioè fg(x)=f(g(x)). denota la sottrazione tra naturali (nm=se nm allora n-m altrimenti 0). Sezione 1.1 1)Un’esempio di una sequenza infinita di funzioni parziali 1, 2,…., i, … tale che i<j per i<j, è il seguente: i= - x se xi - altrimenti. A)Dimostrare che ogni numero ha una unica scomposizione come prodotto di potenze di numeri primi. Soluzione: per induzione sul numero n di fattori del prodotto. Caso base: n=1. Allora il numero dato e’ primo, e coincide con la sua scomposizione. Caso induttivo. Per assurdo supponiamo l’assunto non vero. Allora esiste un numero a, che ha almeno due scomposizioni, di cui almeno una ha un numero di fattori n+1. Sia a=p1p2…pn+1=q1q2…qm, dove pi e qj sono primi (1in+1,1jm. Notare che i fattori possono presentarsi con ripetizione (esempio: 6=222). Allora a è divisibile per pn+1; quindi esiste j tale che qj=pn+1. Per ipotesi induttiva a/pn+1=p1p2…pn ha una scomposizione unica, quindi ogni pi è identico a un qr, per un dato r. Ma poiché a= (a/pn+1)pn+1,la nostra supposizione è falsa, e a ha una unica scomposizione. 1 Sezione 1.3 1) Dimostrare che ciascuno dei seguenti insiemi ha la cardinalità di N. 1.a)Il prodotto cartesiano NN. Ricordiamo che (m,n)(p,q) se e solo se np oppure nq. Sia f: NNN tale che:f((n,m))= 2^n 3^m . f è iniettiva,per la proprietà della unica scomposizione dei numeri naturali in fattori primi. Quindi NNN. Sia g: NNN tale che: g(n)=(0,n). g e’ ovviamente iniettiva, quindi N NN. 1.b)L’insieme delle stringhe finite sull’alfabeto {A,B,…,Z}. |{A,B,…,Z}|= 21. Quindi possiamo mettere in ordine i simboli dell’alfabeto (ad esempio in ordine alfabetico) e interpretarli come cifre in un sistema numerico in base 22. Definiamo una funzione c che interpreta le lettere dell’alfabeto nel modo seguente: c(A)=1,c(B)=2,…, c(Z)=21. Sia b0,…,bn una generica stringa su e sia f la funzione tale che f(b0,…,bn)=c(b0)22^0+ c(b1)22^1+…+ c(bn)22^(n). La funzione f è una funzione iniettiva da in N, infatti ogni stringa è trasformata da f in un numero in base 22, scritto senza la cifra 0, e ogni numero ha una unica rappresentazione in base 22. L’eliminazione della cifra 0 è necessaria per differenziare stringhe come, ad esempio, 0 e 00. D’altra parte, sia g: N la funzione che, dato un numero n, lo trasforma in base 21, sia a0…an,e trasforma a sua volta questo nella stringa d(a0)…d(an), dove d(0)=A,…,d(20)=Z. d trasforma numeri diversi in stringhe diverse, e quindi è iniettiva. Si noti che g non è l’inversa di f! d)L’insieme Q0 dei numeri razionali compresi tra 0 e 1. Ogni numero razionale è il rapporto tra due naturali, quindi un razionale q=num/denum può essere rappresentato con la coppia di naturali (num,denum). Inoltre 0q1 implica numdenum. Inoltre deve essere denum0. Si può quindi adattare a questo esercizio la soluzione dell’esercizio 1.a), definendo: -f:Q0N tale che: 2 f(n,m)=2^n 3^m f è iniettiva. - g: NQ0 tale che: g(n)=(n,n+1) g è iniettiva. Notare che la funzione g: NQ0, definita nell’esercizio 1.a) non può essere usata, perché applicata a 0 restituisce (0,0) che non codifica un elemento di Q0. e)L’insieme delle funzioni parziali da N in N con dominio di definizione finito (sia P(N)). Dimostriamo prima che l’insieme fin(N) dei sottoinsiemi finiti di N ha la stessa cardinalità di N. Sia {n1,…,nmN, e sia h: fin(N)N la funzione tale che h({n1,…,nm)=2^n1+2^n2+…+2^nm. Poiché, per definizione di insieme, ninj quando ij,h è iniettiva e suriettiva, in quanto ogni naturale ha una unica scomposizione in base 2. Questo implica che l’insieme dei sottoinsiemi finiti di N ha la stessa cardinalità di N. Tornando al problema originale, ogni funzione parziale unaria con dominio di definizione finito può essere rappresentata come un insieme finito di coppie di naturali {(i1,o1),…,(in,on) (dove oj rappresenta il valore della funzione sull’argomento ij). Allora una funzione iniettiva da fin(N)in N è hf, e una funzione iniettiva da N in fin(N)è gh-1 (f e g sono definite nell’esercizio 1.3.1.a)). 2) Dimostrare che i seguenti insiemi sono non numerabili, cioè hanno cardinalità maggiore di quella di N. 2.b)L’insieme (N)di tutti i sottoinsiemi di N. La dimostrazione usa il metodo della diagonalizzazione. Per assurdo, ipotizziamo che (N) e N abbiano la stessa cardinalità. Quindi deve esistere una iniezione da (N)in N e una iniezione da N in (N), il che implica (come ha dimostrato Cantor) l’esistenza di una biiezione tra (N)e N (sia h). Allora possiamo numerare tutti i sottoinsiemi di N, e quindi la lista h(0),h(1),…,h(n),… contiene tutti gli elementi di (N).Possiamo rappresentare (N) mediante la seguente tabella (infinita): 0 h(0) * 1 * 2 * 3 * 3 h(1) * h(2) * h(3) * * * * * * * dove all’incrocio della colonna i e della riga h(j) l’elemento * assume valore 1 se ih(j), 0 altrimenti. Consideriamo ora l’insieme I tale che: per ogni i in N,iI se e solo se ih(i). I non può appartenere alla tabella: infatti I differisce da ogni riga della tabella in almeno un punto (cioè differisce da ogni h(k) nel punto k, per definizione). Quindi la tabella non può contenere tutti i sottoinsiemi di N, e quindi l’ipotesi iniziale è falsa. Notiamo che la dimostrazione rimane vera anche se ci limitiamo a considerare i sottoinsiemi di cardinalità infinita. 2.a)L’insieme delle funzioni totali da N in {0,1}. Una funzione f totale da N in {0,1} può essere sempre scritta come insieme di coppie argomento-valore nel modo seguente: {(i,*) | i N e *{0,1}} e questo è un insieme infinito. Possiamo codificare l’insieme delle coppie (i,*) con una funzione h nel modo seguente: - 2i se *=0 h(i,*)= - 2i+1 se *=1. Quindi, tramite la funzione di codifica h, ogni funzione totale f da N in {0,1} può essere rappresentata con un insieme infinito di naturali, e conseguentemente numerare l’insieme di queste funzioni corrisponde a numerare i sottoinsiemi dei naturali di cardinalità infinita. Ma questo non è possibile, in quanto è stato dimostrato nell’esercizio precedente. 2.c)L’insieme delle funzioni parziali da N in N con range finito. Una funzione parziale da N in N può essere rappresentata da un insieme di coppie di interi, che può essere finito o infinito, indipendentemente dal fatto che il suo range sia finito. Ad esempio: 4 - 0 se n è pari (n)= - se n è dispari è una funzione parziale, tale che RAN()={0}, e l’insieme di coppie che la rappresenta è: {(n,0)|nN e n pari}. Poiché ciascuna coppia può essere rappresentata con un intero, numerare l’insieme delle funzioni parziali con range finito corrisponde a numerare tutti i sottoinsiemi di N, ma questo non è’ possibile (esercizio 1.3.2.b)). Sezione 2.2 3)Scrivere un programma while che computi pred(X), usando solo statement di assegnazione della forma X:=0 e X:=succ(X).Il seguente programma restituisce il risultato come valore della variabile Y. Begin T:=0; Y:=0; while XT then begin Z:=succ(Y); while XY do while XZ do begin Z:=succ(Z); Y:=succ(Y) end end end Sezione 2.3 3.a) Per induzione su numero n di istruzioni del programma lineare (per definizione di programma lineare, le istruzioni sono solo assegnazioni). Caso base:n=0. Ovvio, l’unico programma con 0 istruzioni e’: begin end e termina, per definizione di computazione. Caso induttivo. Assumiamo, per ipotasi induttiva, che tutti i programmi con numero di istruzioni minore o uguale a n terminino. Un programma generico con n+1 assegnaazioni è della forma: begin ;Xi:=g(Xj)end dove è una sequenza di n istruzioni. Per ogni vettore di stato (a1,…,ak)la sequenza termina producendo il vettore 5 (b1,…,bk). Per definizione, l’istruzione Xi:=g(Xj), su questo vettore di stato, termina restituendo il vettore (b1,…,bi-1,bj,bi+1,…,bk). B)Definiamo la seguente macro: loop X do begin end come: begin Y:=0; while XY do begin ;X:=succ(X)end end dove Y è una variabile nuova che non occorre in . I programmi loop, per definizione, sono programmi che non contengono istruzioni while, ma solo assegnazioni e loop. Dimostrare che tutti i programmi loop terminano sempre. Prima definiamo il livello di annidamento dei loop di un programma P, dove P ha livello di annidamento 0 se non contiene loop, e livello di annidamento n+1 se contiene almeno un loop il cui corpo è un programma di livello n. La dimostrazione del Lemma è per induzione sul livello n di annidamento del programma. Caso base:n=0. allora il programma è lineare e termina, per l’esercizio 2.3.a). Caso induttivo: assumiamo per ipotesi che un programma di livello n termini sempre. Allora il nostro programma P contiene almeno un loop del tipo: loop X do begin end dove è programma di livello di annidamento n, quindi terminante per ipotesi induttiva. Il loop in questione è equivalente al programma: begin ,…, end dove il numero di è uguale al valore della variabile X. Allora il loop è equivalente a una sequenza finita di pezzi terminanti, e quindi termina, per definizione di computazione. P a sua volta è una sequenza finita di programmi ciascuno di livello n, e quindi termina anc’esso. Sezione 3.3 1)Scrivere i programmi while che head, tail e | (concatenazione). calcolano le funzioni head: begin 6 while X12^6 do X1:=div(X1,2^6) end tail: begin X2:=0; X3:=0;X4:=0; while X12^6 do begin X2:=X2+6; X4:=div(X1,2^6); X3:=X3+mod(X1,2^6)2^(X2-1); X1:=X4; end X1:=X3; end | (le stringhe da concatenare sono in X1 e X2): begin X3:=X1;X4:=X2;X5:=6; while X12^6 do begin X5:=X5+6; X3:=div(X3,2^6); end X1:=X2+X12^X5; end C)Dimostrare che esiste un programma P che effettua un ”interleaving” di due programmi dati Pi e Pj (che calcolano funzioni unarie) nel modo seguente: P esegue in parallelo Pi e Pj e restituisce come risultato il risultato ottenuto dal primo dei due che si ferma. Questo equivale a dimostrare che la seguente funzione è calcolabile: (i,j,k)= - i(k) se z.step(i,k,z)>step(j,k,z) oppure z. step(i,k,z)=step(j,k,z) - j(k) se z.step(j,k,z)> step (i,k,z) - se sia i(k) che j(k)è indefinita. 7 dove step è la funzione definita nell’esempio 4 paragrafo 4.2 (una prima versione nell’esempio 5 paragrafo 4.1) che ha il seguente comportamento: step(x,y,z)= - 1 se Px sull’input y termina in z passi - 0 altrimenti. step è calcolabile. Il programma cercato e’ il seguente: del del begin X4:=1; while step(X1,X3,X4)=0 and step(X2,X3,X4)=0 do X4:=succ(X4); if step(X1,X3,X4)= 1 then (X1,X3) else (X2,X3) end 8