Quaderni di Informatica Macchine e Linguaggi Luigino Calvi I.I.S. Negrelli-Forcellini - Feltre 2014
ii
Capitolo 1 Macchine di Turing Potrebbe essere deludente apprendere che, fondamentalmente, computer e matematici non sono altro che macchine di Turing camuffate. D altra parte potrebbe anche essere un fatto incoraggiante, dato che la macchina di Turing, in apparenza alquanto semplicistica, è in grado di risolvere qualsiasi tipo di problema di calcolo. La somiglianza teorica fra matematico e macchina vale non solo per problemi che essi sono in grado di risolvere ma anche per quelli che non sanno risolvere. P. Hoffman, La vendetta di Archimede Già agli inizi del ventesimo secolo si notò che la definizione informale di algoritmo risultava inadeguata quando si dovevano affrontare delle questioni delicate relative alla calcolabilità delle funzioni, alla logica matematica, alla potenziale risolubilità di alcuni problemi. Si avvertì allora l esigenza di disporre di rigorosi modelli di calcolo che eliminassero qualsiasi forma di ambiguità. Uno dei più noti e fortunati modelli di calcolo fu introdotto dal matematico e logico inglese Alan Turing nel 1936, ancora prima che i calcolatori elettronici fossero pensati e realizzati. In onore del suo ideatore, questo modello di calcolo è denominato macchina di Turing. Dal punto di vista delle sue potenzialità la macchina di Turing risulta essere la macchina più semplice possibile in grado di fare qualcosa che può fare qualsiasi altra macchina. 1
2 CAPITOLO 1. MACCHINE DI TURING 1.1 LE MACCHINE DI TURING Il termine macchina attribuito alle macchine di Turing (in seguito MdT) è derivato dal fatto che questo modello di calcolo si presta in modo naturale ad essere pensato e realizzato come un meccanismo fisico di calcolo. Una MdT, descritta nella figura 1.1, è costituita da un unità di controllo dotata di una memoria interna che può assumere uno stato fra un insieme finito e prefissato di stati, da un nastro suddiviso in celle ciascuna delle quali può contenere un carattere appartenente ad un alfabeto finito di simboli, da una testina di lettura/scrittura che permette di leggere e scrivere sul nastro un carattere alla volta. Il nastro deve essere ritenuto illimitato in entrambe le direzioni, nel senso che, all occorrenza, viene automaticamente allungato con delle celle vuote. Poiché in ogni istante solo una porzione del nastro è utilizzata, si assume la convenzione che la restante parte sia riempita con il carattere spazio, indicato con il simbolo. Si assume inoltre l ipotesi che tale carattere faccia sempre parte dell alfabeto della MdT, anche se non viene esplicitamente indicato. nastro * * * testina di lettura/scrittura stato unità di controllo Figura 1.1: Schema di una macchina di Turing. Ogni azione che viene intrapresa da una MdT risulta deterministicamente definita dalle seguenti informazioni: stato corrente dell unità di controllo simbolo corrente sul nastro Un azione di una MdT risulta composta dalle seguenti azioni parziali: cambiare lo stato dell unità di controllo scrivere un simbolo alla posizione attuale sul nastro
1.2. PROGRAMMI PER LE DELLE MDT 3 spostarsi a destra o a sinistra (o rimanere ferma) Si assume la convenzione che quando in una situazione non esista alcuna indicazione che precisi come proseguire, la MdT si fermi. Viene imposta inoltre la condizione che le MdT siano deterministiche, ossia che in una stessa condizione di stato interno e di simbolo osservato procedano in modo univoco. Nel seguito saranno tacitamente adottate queste convenzioni. 1.2 PROGRAMMI PER LE DELLE MdT Esistono diversi formalismi per descrivere il funzionamento di una MdT. Uno dei più semplici consiste nel precisare un azione elementare di una MdT mediante una quintupla di simboli; precisamente: una quintupla (p, x, q, y, m) va interpretata come descritto nell algoritmo 1. Algoritmo 1 - Interpretazione di una quintupla (p, x, q, y, m) di una MdT 1: if la MdT è nello stato p e legge il carattere x then 2: passa nello stato q 3: scrive sul nastro il carattere y 4: esegue il movimento m 5: end if Il movimento m può essere descritto mediante uno dei seguenti tre simboli: < : spostamento di un passo a sinistra > : spostamento di un passo a destra - : nessuno spostamento In base a queste premesse, un programma per una MdT risulta costituito da un insieme di quintuple. Per garantire la condizione di determinismo si impone la condizione che quintuple distinte non coincidano sulle prime due componenti. Con un altro formalismo, una quintupla (p, x, q, y, m) può essere descritta mediante una tabella a doppia entrata, detta matrice funzionale, scrivendo lo stato iniziale p ed il simbolo attuale x come entrate della tabella e la porzione
4 CAPITOLO 1. MACCHINE DI TURING di quintupla (q, y, m) all interno della tabella, in corrispondenza delle due entrate p e x. Per alcune argomentazioni risulta comodo rappresentare un programma per una MdT sotto forma di automa descritto mediante un grafo di transizione di stato; usando questa notazione, una quintupla (p, x, q, y, m) viene equivalentemente rappresentata come illustrato nella figura 1.2. Lo stato iniziale viene denotato mediante una freccia entrante e gli stati finali mediante un cerchio a doppia linea. p x, y, m q Figura 1.2: Grafo di transizione di stato che descrive la quintupla (p, x, q, y, m). Esempio 1. In questo esempio è descritta, mediante un insieme di quintuple (fig. 1.3), mediante un grafo di transizione degli stati (fig. 1.5), e mediante una matrice funzionale (fig. 1.4), una MdT che, partendo dallo stato iniziale 0 e posizionata sul primo carattere a sinistra di una sequenza di a e b, trasforma le a in b e viceversa e, alla fine, si riposiziona sul primo carattere a sinistra. Con _ si denota il carattere spazio. Figura 1.3: quintuple. 0,a,0,b,> 0,b,0,a,> 0,_,1,_,< 1,a,1,a,< 1,b,1,b,< 1,_,f,_,> Programma di una MdT espresso mediante un insieme di a b _ 0 0 b > 0 a > 1 _ < 1 1 a < 1 b < f _ > Figura 1.4: Programma di una MdT espresso mediante una matrice funzionale.
1.3. RISOLUZIONE DI PROBLEMI CON MDT 5 a b > a a < < 0 b a > > 1 b b < f Figura 1.5: Programma di una MdT espresso mediante un grafo di transizione di stato. Osservazione. L insieme di quintuple che descrive una MdT deve essere visto in modo dichiarativo e non in modo imperativo, nel senso che si tratta di un insieme di indicazioni di comportamento e non come una sequenza di istruzioni da eseguire. 1.3 RISOLUZIONE DI PROBLEMI CON MdT Nonostante una MdT non comprenda il significato di quanto c è scritto sul nastro iniziale e di quanto viene scritto sul nastro durante i passi della computazione, codificando opportunamente i dati sul nastro e decodificando opportunamente i risultati lasciati sul nastro alla fine della computazione, le MdT si prestano a risolvere tutte le forme di problemi finora visti (computazionali, decisionali, trasformazionali). La possibilità di scrivere sul nastro rende le MdT estremamente potenti dal punto di vista computazionale in quanto il nastro può essere utilizzato come una memoria sulla quale registrare dati e risultati intermedi prodotti nel corso dell elaborazione. Un altra informazione ricavabile dalla computazione di una MdT è rappresentata dallo stato di arresto finale; in questo modo una MdT, anche senza modificare il nastro, è in grado di risolvere dei problemi di tipo decisionale, ad esempio decidere se la stringa presente inizialmente sul nastro è un teorema di un dato sistema formale. Lo snodo logico e pratico cruciale riguardante l utilizzo delle MdT risiede nel seguente quesito: Come fa una MdT a risolvere un dato problema? Il meccanismo dell applicabilità di una MdT alla risoluzione di un dato problema è quello generale che sottostà all utilizzo di un generico esecutore: c è l esigenza di passare dallo spazio delle soluzioni, nel quale viene ricercata e sviluppata la
6 CAPITOLO 1. MACCHINE DI TURING soluzione del problema da parte del solutore, allo spazio delle computazioni, cioè all ambiente nel quale opera l esecutore; per il caso particolare in cui l esecutore sia costituito da una MdT il passaggio dallo spazio delle soluzioni allo spazio delle computazioni può essere descritto mediante lo schema riportato nella figura 1.6. spazio delle soluzioni dati algoritmo risultati codifica dei dati traduzione dell algoritmo in un insieme di quintuple decodifica dei risultati spazio delle computazioni nastro con i dati MdT nastro con i risultati Figura 1.6: Schema del processo di risoluzione di un problema mediante una macchina di Turing. Resta il dubbio se ogni algoritmo descritto in una qualsiasi notazione algoritmica sia traducibile in quintuple per una MdT: la risposta, affermativa, è fornita dalla Tesi di Church-Turing. 1.4 ESEMPI DI MACCHINE DI TURING Negli esempi che seguono viene utilizzato il formalismo delle quintuple; ogni riga contiene una quintupla; le righe che iniziano con un carattere # vengono intese come commenti e non hanno alcuna influenza sulla modalità di funzionamento della MdT. Con _ viene indicato il carattere spazio. Come si supporrà sempre nel seguito, la MdT inizia la computazione nello stato 0 e si trova posizionata sul primo carattere non-spazio a sinistra.
1.4. ESEMPI DI MACCHINE DI TURING 7 Esempio 2. In questo esempio viene calcolato il successivo di un numero espresso in notazione unaria, usando il carattere *: il numero zero viene rappresentato con *, il numero uno con **, il numero due con *** e cosí via. Il numero di cui si vuole calcolare il successivo si trova inizialmente codificato sul nastro; alla fine della computazione sul nastro si troverà il risultato (sempre espresso in notazione unaria). 0,*,0,*,> 0,_,1,*,> 1,*,1,*,< 1,_,f,_,< Osservazione. Bisogna notare la differenza fra il livello sintattico e livello semantico in quanto la MdT che incrementa un numero espresso in notazione binaria non conosce i concetti di numero, base di rappresentazione di un numero, operazione di incremento,...); la MdT opera al livello dei segni, indipendentemente dal significato che si voglia attribuire loro. Esempio 3. In questo altro esempio viene calcolato il successivo di un numero espresso in notazione binaria. # posizionamento sul carattere piu a destra 0,0,0,0,> 0,1,0,1,> 0,_,1,_,< # computazione del successivo 1,0,2,1,- 1,1,1,0,< 1,_,2,1,< # posizionamento sul carattere piu a sinistra 2,0,2,0,< 2,1,2,1,< 2,_,f,_,> Osservazione. Dal confronto fra questo esempio ed il precedente si nota che utilizzando un maggior numero di simboli per codificare i dati (per risolvere uno stesso problema) si ha un aumento del numero di quintuple necessario per descrivere la soluzione. Seguendo l obiettivo di massima semplicità si tende ad usare un numero molto ridotto di simboli del nastro. In tale modo la descrizione di una MdT risulta semplificata. Questa semplicità va ad appesantire l esecuzione, ma questo fatto risulta un problema marginale nelle questioni che coinvolgono le MdT.
8 CAPITOLO 1. MACCHINE DI TURING Esempio 4. Viene presentato a seguire un programma per una MdT in grado di calcolare, mediante l algoritmo di Euclide, il massimo comune divisore dei due numeri naturali presenti sul nastro, espressi in notazione unaria. Si lascia per esercizio la comprensione di come queste quintuple costituiscano la codifica dell algoritmo di Euclide. 0,_,0,_,> 3,_,4,_,> 6,_,6,_,< 9,_,2,_,> 0,1,1,1,< 3,1,3,1,> 6,1,1,1,< 9,1,1,1,< 1,_,2,1,> 4,_,4,_,> 7,_,7,_,< A,1,A,1,< 1,1,1,1,< 4,1,5,_,> 7,1,8,1,< A,_,f,_,> 2,_,A,_,> 5,_,7,_,< 8,_,9,_,< 2,1,3,_,> 5,1,6,1,< 8,1,8,1,< Osservazione. Come si vede in questi esempi, anche per la soluzione di semplici problemi (calcolo del successore di un numero naturale, calcolo del massimo comune divisore fra due numeri naturali), le MdT richiedono che venga precisato un consistente numero di quintuple; questa situazione era prevedibile in base al principio di complessità della soluzione. Ciò può risultare scoraggiante, specialmente quando si tratta di risolvere un problema di una certa complessità. Ma le MdT non vengono utilizzate per risolvere in pratica problemi significativi e complessi, quanto piuttosto come strumento teorico per indagare e decidere sulla potenziale risolvibilità di alcuni problemi. Osservazione. Dal punto di vista delle azioni svolte, le macchine di Turing sono degli esecutori estremamente semplici e rudimentali. La loro importanza non è dovuta al fatto che rappresentino dei modelli di calcolatori reali, ma alla loro estrema semplicità di descrizione e minimalità architetturale che ben si presta a molteplici utilizzi nell analisi di diverse questioni relative alla computabilità e per indagare sulla risolvibilità teorica dei problemi. D altra parte, si ritiene che tale semplicità non costituisca una limitazione alla risolvibilità dei problemi, in quanto, da varie argomentazioni, è plausibile ritenere che ciò che può essere calcolato da qualsiasi calcolatore esistente o immaginabile, possa essere calcolato anche da una macchina di Turing; viceversa, per ogni problema risolvibile, esiste una macchina di Turing che lo risolve. 1.5 TRASFORMAZIONI DI STRINGHE Nella sua forma più generale, com è stata descritta nei paragrafi precedenti, una MdT T può essere pensata come un trasformatore di stringhe: la stringa s presente come dato scritto sul nastro all inizio della computazione viene trasformata in un altra stringa s = T (s) presente sul nastro alla fine della
1.5. TRASFORMAZIONI DI STRINGHE 9 computazione (nel caso la MdT si fermi), secondo lo schema di trasformazione illustrato nella figura 1.7. s T s Figura 1.7: Processo di trasformazione di una stringa s in una stringa s mediante una MdT T. Esistono moltissimi ed interessanti problemi che possono essere inquadrati e risolti mediante un processo di trasformazione di stringhe. Ad esempio, rovesciare una stringa. Questa accezione di MdT come trasformatore di stringhe non è comunque limitante in quanto qualsiasi dato di altra natura (numero, sequenza di numeri, espressione simbolica,...) può essere trasformato in stringa e successivamente la stringa finale lasciata sul nastro alla fine della computazione può essere interpretata e riconvertita. Nel seguito saremo spesso interessati a funzioni della forma N k N che potranno essere calcolate mediante una MdT che parte con il nastro iniziale sul quale è impressa la codifica di k numeri naturali spaziati, ad esempio, mediante un carattere spazio. Il processo di trasformazione di stringhe mediante le MdT può essere descritto in modo funzionale, assimilando la MdT T ad una funzione parziale: s s Questa modalità di interpretazione suggerisce che più MdT T 1, T 2,..., T n (possibilmente diverse) possano essere fatte agire in sequenza, ognuna agente sul nastro lasciato scritto dalla MdT precedente; il risultato finale, presente sul nastro alla fine dell elaborazione della MdT T n, sarà uguale a T n (T n 1 (... T 2 (T 1 (s)))) ottenuto dalla catena di trasformazioni s 0 s 1 s n, indicando con s 0 la stringa presente sul nastro all inizio della computazione e con s i la stringa lasciata scritta sul nastro dalla MdT T i. Per rendere univoca l attivazione in sequenza di più MdT, si assume l ipotesi che ogni MdT termini la propria fase di elaborazione fermandosi sul primo carattere non-spazio a sinistra. L idea della concatenazione di MdT viene utilizzata anche nei moderni linguaggi di programmazione e trova concretizzazione nello strumento dei sottoprogrammi.
10 CAPITOLO 1. MACCHINE DI TURING 1.6 LA MdT UNIVERSALE Da quanto è stato esposto nei precedenti paragrafi si possono definire molte MdT, ciascuna caratterizzata da uno specifico insieme di quintuple e quindi in grado di risolvere una specifica classe di problemi. Una generalizzazione di queste macchine si fonda sull idea di considerare un unica MdT programmabile, in grado di simulare e svolgere il compito di una generica MdT, leggendo dal nastro, come input, le quintuple, consultando il nastro durante il processo di computazione per scegliere la quintupla da eseguire man mano che procede il processo di computazione). Tale MdT viene detta macchina di Turing universale. Al di là della difficoltà di realizzazione pratica, una tale MdT è facilmente immaginabile; tale idea di generalizzazione ha avuto importanti ricadute pratiche ed ha dato il via allo sviluppo dei calcolatori attuali secondo l architettura di von Newman. Tale architettura, caratterizzata dall avere in memoria sia il programma che i dati che vengono elaborati, caratterizza la stragrande maggioranza degli attuali calcolatori. 1.7 ESERCIZI 1. Molto spesso si usano con lo stesso significato le seguenti due locuzioni: (a) La MdT descritta dall insieme di quintuple X (b) Il programma per una MdT costituito dall insieme di quintuple X Dire quale delle due forme sopra è preferibile. possono essere accettate entrambe le forme. Dire perché, comunque, 2. Spiegare perché le MdT costituiscono una conferma del principio di complessità della soluzione. 3. Il nastro di una MdT contiene un solo asterisco. Individuare una strategia per portarsi sull asterisco trovandosi su uno spazio e non sapendo da quale parte rispetto all asterisco. Scrivere un programma per una MdT corrispondente alla strategia individuata. 4. Decidere se un nastro è completamente vuoto. Si noti che, in questo caso, la MdT potrebbe non fermarsi. Nota. Nei seguenti esercizi si richiede di scrivere dei programmi per una MdT, assumendo l ipotesi che la macchina parta dallo stato iniziale 0 e che sia posta sul primo carattere non-spazio a sinistra. Descrivere il
1.7. ESERCIZI 11 procedimento dapprima a parole e successivamente codificarlo mediante un formalismo per le MdT. 5. Spostare a destra di una posizione una sequenza di asterischi presenti inizialmente sul nastro. 6. Spostare a destra di una posizione una sequenza compatta di 0 e 1 presenti inizialmente sul nastro. 7. Spostare alla fine il carattere iniziale di una posizione una sequenza compatta di 0 e 1 presenti inizialmente sul nastro. 8. Calcolare in successione tutti i successivi del numero presente inizialmente sul nastro, senza fermarsi. Si risolva l esercizio adottando le seguenti notazioni di codifica dei numeri: unaria, binaria e decimale. 9. Realizzare le seguenti funzioni sui numeri naturali, codificati in notazione unaria, in notazione binaria ed in notazione decimale: successivo: n n + 1 precedente: n 0 se n = 0; n 1 altrimenti doppio: n n 2 metà: n n/2 logaritmo: n log 2 n 10. Eseguire l addizione fra due numeri espressi in notazione binaria; ad esempio: nastro prima della computazione: 101+1100 nastro alla fine della computazione: 10001 11. Convertire un numero dalla notazione binaria a quella decimale. 12. Assumendo come alfabeto del nastro l insieme A = {0, 1}, risolvere i seguenti problemi: (a) Eliminare tutti i simboli del nastro. (b) Eliminare tutti gli 0 e compattare gli 1 verso sinistra. (c) Decidere se una stringa è formata da un numero pari di 0. (d) Decidere se una stringa rappresenta un numero pari (in notazione binaria).
12 CAPITOLO 1. MACCHINE DI TURING (e) Decidere se una stringa è formata da simboli alternati; ad esempio: 0, 10, 01010. (f) Decidere se una stringa è composta da un uguale numero di 0 ed 1. 13. Decidere se un numero naturale in rappresentazione unaria ed in rappresentazione binaria è pari o dispari. La MdT deve lasciare sul nastro la stringa com era all inizio della computazione fermandosi sullo stato Y se la stringa è composta da un numero pari di asterischi, nello stato N altrimenti. Spiegare perché in questo caso risulta più semplice operare con una rappresentazione binaria che con una unaria. 14. Decidere se una stringa di + e - è palindroma, ossia se si legge indifferentemente da sinistra a destra e da destra a sinistra. La MdT deve lasciare sul nastro la stringa com era all inizio della computazione; deve fermarsi sullo stato Y se la stringa è palindroma, nello stato N altrimenti. 15. Il nastro di una MdT contiene una sequenza contigua composta da + e -. Decidere se la sequenza è composta da almeno due caratteri consecutivi uguali. 16. Decidere se il nastro contiene un numero pari di simboli +; la MdT deve cancellare dal nastro di input tutti i simboli + se essi sono in numero pari, deve lasciare sul nastro un solo simbolo + se il nastro di input contiene un numero dispari di simboli +. 17. Decidere se una data stringa è formata da caratteri a e b alternati. Ad esempio, devono essere riconosciute le seguenti stringhe: a, ba, ababa, babababa. 18. Decidere se una data stringa è formata da una successione di a seguite da una successione di b, in uguale numero. Ad esempio, devono essere riconosciute le seguenti stringhe: ab, aabb, aaabbb. 19. Usando 3 stati (oltre allo stato finale) ed il solo simbolo *, descrivere una MdT che, partendo da un nastro vuoto, scriva il maggior numero possibile di asterischi e poi si fermi. Una MdT come quella appena descritta viene detta castoro a 3 stati. Un castoro massimale che genera il maggior numero di asterischi viene detto alacre castoro. 20. Approfondire e discutere la seguente architettura (di von Neuman) di macchina di Turing (macchina di Turing Universale):
1.7. ESERCIZI 13 La MdT opera secondo un prefissato programma (non modificabile); la particolarizzazione del procedimento (per adattarsi alla soluzione di diverse classi di problemi) avviene precisando (come dato di input) sul nastro sia l insieme delle quintuple (che permettono di risolvere i problemi di una classe di problemi) che (come succede per le MdT viste finora) i dati di input per risolvere una particolare istanza di problema (della classe considerata). 21. Date le seguenti tre MdT: M 1 che trasforma un numero da notazione unaria a notazione decimale M 2 che trasforma un numero da notazione decimale a notazione unaria M 3 che calcola il massimo comune divisore fra due numeri naturali espressi in notazione unaria comporle opportunamente in modo da ottenere una MdT M che calcola il massimo comune divisore fra due numeri naturali espressi in notazione decimale. 22. Oltre alle macchine di Turing sono stati ideati altri meccanismi di calcolo. La macchina UMR (ideata nel 1963 da Shepherdson e Sturgis e successivamente modificata da Cutland nel 1980) è composta da un numero illimitato di registri, indicati con R 1, R 2,.... Ogni registro, in un dato istante, contiene un numero naturale. Il contenuto dei vari registri può essere modificato mediante le seguenti istruzioni: Istruzione di azzeramento Z(n) : viene posto uguale a zero il contenuto del registro R n Istruzione di successivo S(n) : viene aumentato di uno il contenuto del registro R n Istruzione di trasferimento T(m,n) : viene sostituito il valore del registro R m con il valore del registro R n Istruzione di salto J(m,n,p) : se il contenuto del registro R m è uguale a quello del registro R n la macchina va alla p-esima istruzione del programma Discutere comparativamente i livelli di proceduralità delle MdT e delle macchine URM. Scrivere programma per una macchina URM che esegua il prodotto fra due numeri naturali memorizzati nei registri R 1 ed R 2 ; il risultato deve essere memorizzato nel registro R 3.
14 CAPITOLO 1. MACCHINE DI TURING
Capitolo 2 Computabilità La tesi di Church-Turing [...] è certamente uno dei concetti più importanti della filosofia della matematica, del cervello e della mente. D. R. Hofstadter, Gödel, Escher, Bach Il fatto che la ricerca scientifica sia riuscita a riconoscere in modo preciso i limiti delle sue possibilità, ci sembra una prestazione dello spirito umano, più grande della tecnicizzazione del nostro mondo, tanto spesso ammirata. H. Meschkowsky, Mutamenti nel pensiero matematico [...] è molto importante il fatto che si possa dimostrare in modo puramente matematico che i sostituti proposti per il concetto di algoritmo mediante vari concetti matematici rigorosi (che hanno origine da punti di partenza differenti) risultano equivalenti. H. Hermes, Enumerabilità, decidibilità, computabilità Il concetto di computabilità, che sarà appena sfiorato nelle poche pagine che seguiranno, è un argomento che coinvolge varie discipline: informatica, tecnologia, matematica, filosofia, epistemologia, ed altre ancora. L argomento si presta, quindi, ad essere indagato e trattato, dall interno di ciascuna disciplina, in modi diversi e con diversi accenti. La teoria della computabilità permette di tracciare una linea di demarcazione fra ciò che è computabile e ciò che non lo è, ossia fra i problemi che (almeno in linea teorica) sono risolvibili e problemi che non lo sono. Tutto il capitolo è impostato sulla presentazione di risultati in negativo che segnano una sorta di ideale confine invalicabile dai metodi e dagli strumenti della scienza. 15
16 CAPITOLO 2. COMPUTABILITÀ 2.1 LA TESI DI CHURCH-TURING Esistono moltissimi problemi per i quali è stata fornita una rigorosa dimostrazione del fatto che essi non sono risolvibili. Tale limitazione non è comunque dovuta all incapacità del solutore nel formulare un adeguato algoritmo, ma alla natura intrinseca della logica, della matematica e del linguaggio. Nella dimostrazione di non risolvibilità di questi problemi gioca un ruolo fondamentale la seguente ipotesi, formulata da Church e Turing nel 1937, che, da varie argomentazioni, è plausibile ritenere che sia vera, cosicché si è meritata l appellativo di tesi. TEOREMA 1 (Tesi di Church-Turing). Tutti i meccanismi di calcolo (MdT, personal computer, mainframe, calcolatori paralleli,...) 1. finora realizzati (dato di fatto dimostrato) e 2. realizzabili in futuro (ipotesi plausibile) sono equivalenti, cioè possono risolvere gli stessi problemi. Dalla tesi di Church-Turing discende il seguente corollario. TEOREMA 2 (Corollario della tesi di Church-Turing). Ogni problema è risolvibile se e solo se esiste una MdT che lo risolve. In base a questo risultato si può parlare di problemi risolvibili e problemi non risolvibili senza fare alcun riferimento all esecutore. Operativamente, si dimostra che un problema è non risolvibile dimostrando che non esiste alcuna MdT (e quindi nessun altra macchina, per la tesi di Church-Turing) che lo risolve. 2.2 IL TEOREMA DI INCOMPLETEZZA Uno dei primi problemi che è stato dimostrato essere non risolvibile è noto con il nome di teorema di incompletezza di Gödel, dimostrato nel 1931 dal logico e matematico austriaco Kurt Gödel. Questo teorema tratta degli enunciati sui numeri naturali; sono esempi di enunciati i seguenti: E 1 per ogni x N si ha x x > 0 (falso) E 2 esiste x N tale che x + 2 = 0 (falso) E 3 esistono x, y N, x > 1, y > 1, tali che x y = 978829207 (vero) E 4 non esistono x, y, z, n N, n > 2, tali che x n + y n = z n (vero)
2.3. IL PROBLEMA DELLA FERMATA 17 Da questo breve elenco di enunciati sembrerebbe che per ogni enunciato si possa stabilire, con più o meno difficoltà, se esso sia vero o falso; nei casi più complicati può rimanere il dubbio. Ma la situazione è ancora più paradossale: esistono degli enunciati che risultano intrinsecamente indecidibili; questo fatto è stabilito dal TEOREMA 3 (Teorema di incompletezza di Gödel). Non è possibile stabilire se un generico enunciato sui numeri naturali sia vero o falso. Naturalmente, esistono moltissimi ed interessanti enunciati che sono decidibili, ossia enunciati per i quali è possibile stabilire se sono veri o falsi; ma ce ne sono molti altri che si sottraggono a questa classificazione. I risultati di Godel del 1931, sintetizzati nel suo teorema di icompletezza, mandarono in frantumi le speranze di Hilbert di dare un fondamento assoluto alla matematica. 2.3 IL PROBLEMA DELLA FERMATA Un altro famoso problema, considerato inizialmente da Turing e per il quale lo stesso Turing ha fornita una dimostrazione di non decidibilità, è il seguente, noto come Problema della fermata : Dato un generico programma P (insieme di quintuple di una MdT, programma scritto in un qualche linguaggio di programmazione o altro differente formalismo) ed un insieme di dati di input I, stabilire se il programma P, avendo come input I, si fermerà o no. La soluzione di questo problema è l oggetto del seguente teorema. TEOREMA 4. Il problema della fermata è indecidibile, ossia non esiste alcun procedimento in base al quale, dato un programma P ed un insieme di dati di input I sui quali opera il programma P, si possa decidere se il programma P si fermerà se viene fatto partire sul nastro sul quale vi siano codificati i dati di input I. Il problema della fermata acquista particolare rilevanza nell ambito della teoria della programmazione in quanto viene ad affermare che è impossibile stabilire se un generico programma giungerà o no alla fine dell esecuzione o continuerà all infinito, senza mai fermarsi; esistono comunque dei programmi abbastanza semplici per i quali si riesce a dimostrare la terminazione o la non terminazione. La non risolvibilità del problema della fermata acquista anche
18 CAPITOLO 2. COMPUTABILITÀ una valenza strumentale per la soluzione di altre classi di problemi; infatti, esistono varie classi di problemi che si dimostrano essere non risolvibili seguendo una linea di ragionamento come la seguente: si dimostra che tali classi di problemi sono riconducibili al problema della fermata e pertanto se ammettessero soluzione, di conseguenza risulterebbe risolvibile anche il problema della fermata. Da questa contraddizione si deduce che queste classi di problemi sono non risolvibili. Ad esempio, si dimostra in questo modo che la decisione se due programmi risultino equivalenti è non risolvibile. Osservazione. Il quadro avvilente, presentato nei precedenti paragrafi, riguardante la risolvibilità di importanti classi di problemi, viene in parte riscattato dal fatto che spesso si considerano particolari sottoinsiemi di queste classi di problemi e, per questi sottoinsiemi, si riesce a trovare un adeguata soluzione e si è in grado di dimostrare che l esecuzione giungerà al termine per ogni possibile istanziazione dei dati di input. 2.4 FUNZIONI COMPUTABILI Una funzione dicesi computabile o calcolabile se esiste un procedimento meccanico (algoritmo) che permette di determinare il valore della funzione per ogni possibile valore degli argomenti. Nel caso in cui il processo di calcolo, per qualche valore dei dati di input, non termini si parla di funzioni parzialmente computabili. Per le considerazioni che seguiranno ci limiteremo a considerare funzioni sui numeri naturali. Esempio 5. Sono esempi di funzioni computabili le seguenti: n 2 n (m, n) massimo comune divisore fra m ed n n n-esima cifra decimale di 2 La distinzione fra funzioni computabili e non computabili non avrebbe ragione d esistere fintantochè non si sia dimostrato che esistono funzioni non computabili oppure non si sia prodotto un esempio di funzione non computabile. Dimostriamo subito che esistono funzioni non computabili. Ogni MdT è descritta mediante il suo programma (insieme di quintuple); tale programma può essere convertito in una stringa (ad esempio concatenando le stringhe che codificano ciascuna quintupla). Le stringhe che codificano le MdT possono essere enumerate in sequenza, ad esempio in ordine alfabetico. Le funzioni fra
2.5. COMPUTABILITÀ DEI NUMERI REALI 19 numeri naturali (della forma N N) non sono numerabili. Quindi esistono funzioni non computabili. Da questa dimostrazione abbiamo ottenuto un risultato più forte di quanto ci eravamo prefissi: le funzioni non computabili sono la stragrande maggioranza fra tutte le funzioni ossia, in altri termini, quasi tutte le funzioni fra numeri naturali sono non computabili. Il fatto che questa conclusione contrasti con l opinione comune che le funzioni siano tutte computabili dipende dal fatto che le funzioni che si incontrano spontaneamente e che si costruiscono sono definite apposta per essere computabili. Esibire degli esempi di funzioni non computabili non è facile e serve un po di inventiva. Un classico esempio di funzione non computabile 1 è rappresentato dalla funzione f N N definita come segue: f(n) = 1 se nella rappresentazione decimale di π c è una successione di n cifre 7 consecutive 0 altrimenti Esssendo che un algoritmo è concettualmente assimilabile ad una funzione, si può parlare indifferentemente di problemi risolvibili e funzioni computabili. 2.5 COMPUTABILITÀ DEI NUMERI REALI Un apparente limite di cui sembrano soffrire gli elaboratori consiste nella difficoltà di gestire in modo numerico (e non solamente simbolico) i numeri reali irrazionali. Ciò dipende dal fatto che la rappresentazione dei numeri avviene in modo finito mentre i numeri irrazionali richiedono un espansione numerica decimale non finita. In questi casi, come avviene in molti algoritmi numerici, si approssima l infinito attuale con un infinito potenziale, secondo l idea descritta nella seguente definizione. DEFINIZIONE 1. Un numero reale x si dice computabile se esiste un algoritmo A N {0, 1,..., 9} tale che A(n) sia l n-esima cifra decimale di x, assumendo che A(0) = x ; in altri termini deve essere calcolabile (mediante un procedimento effettivo) la seguente funzione: f(n) = { x se n = 0 n-esima cifra decimale di x se n > 0 1 Riportato in N. Cutland, Computability, Cambridge Univ. Press, 1980.
20 CAPITOLO 2. COMPUTABILITÀ Equivalentemente, la computabilità di un numero reale x può essere basata sulla calcolabilità della seguente funzione: g(n) = { x se n = 0 numero formato dalle prime n cifre decimali di x se n > 0 Risulta abbastanza evidente e facile da dimostrare che tutti i numeri razionali sono computabili. La computabilità effettiva dei numeri reali con espansione decimale illimitata e non periodica richiede invece che venga fornito un procedimento algoritmico che genera una successione convergente. Esempio 6. I seguenti due risultati stabiliscono che i due numeri reali 2 e π sono computabili: la successione a 0 = 1, a n = 1 2 (1 + 1 a n 1 ) converge a 2 la serie 4 ( 1) k+1 1 k=1 k = 4 (1 1 3 + 1 5 1 + ) converge a π 7 Esistono però numeri irrazionali con computabili. 2.6 ESERCIZI 1. Dimostrare che tutti i numeri razionali sono computabili. 2. Dimostrare che esistono numeri reali non computabili. Suggerimento: utilizzare un procedimento diagonale analogo a quello utilizzato per dimostrare che l insieme dei numeri reali non è numerabile. 3. Dimostrare che, per ogni x R +, x è computabile. 4. Si analizzi e si commenti la seguente frase del filosofo Ernst Cassirer (1937) nel contesto della computabilità. Non è lecito pensare al limite come semplice ostacolo a cui noi ci si debba sottrarre non appena e per quanto possibile: esso piuttosto delimita il solo campo in cui il nostro pensiero e il nostro conoscere si compiono - quello in cui essi ottengono il loro significato.
Capitolo 3 Blocchi Ci fu un tempo, prima che i nostri traguardi diventassero più ambiziosi, in cui trovavamo strano e meraviglioso riuscire a fare una torre o una casa coi blocchetti delle costruzioni. Eppure, benché tutti gli adulti sappiano fare queste cose, nessuno ancora ha capito come s impari a farle! M. Minsky, La società della mente Per dominare la complessità, sia dal punto di vista concettuale che dal punto di vista operativo, l uomo fa spesso ricorso al principio di astrazione. Si tratta di un meccanismo fondamentale per l informatica ma è trasversale ed è di supporto a tutte le altre scienze. Una applicazione del principio dell astrazione è rappresentata dal concetto di blocco. La nozione di blocco permette di definire un utile dicotomia fra il fuori ed il dentro, fra il progetto e la realizzazione, fra il cosa fa un oggetto verso l esterno e come è fatto un oggetto al suo interno. Questo concetto si evidenzia sia a livello progettuale, quando si definisce l interfaccia di un blocco e si demanda a tempi successivi la sua implementazione, sia a livello implementativo, quando si delimita un sistema di componenti considerandoli come un tutt uno. I blocchi facilitano la comprensione e gestione della realtà in quanto consentono di trascurare i dettagli di come il blocco è fatto al suo interno. Inoltre offrono il vantaggio operativo fondato sulla possibilità di clonare un blocco al fine di utilizzarli nella costruzione di altri blocchi. 21
22 CAPITOLO 3. BLOCCHI 3.1 BLOCCHI Un blocco, considerandolo solamente dal punto di vista di come interagisce con l esterno, può essere pensato come una scatola nera, e può essere utilizzato senza riferirsi ad alcun dettaglio relativo alla sua costituzione interna. Indipendentemente dalla sua funzionalità, un blocco viene generalmente descritto mediante una forma rettangolare come descritto nella figura 3.1. blocco Figura 3.1: Schema grafico per denotare un blocco. Il concetto di blocco può assumere diversi significati a seconda del contesto in cui si colloca, assumendo di volta in volta delle diverse denominazioni, come descritto dalla lista che segue: problema: blocco vuoto in cui sono esplicitati solamente gli ingressi (dati del problema), le uscite (risultati del problema) ed i vincoli fra gli ingressi e le uscite algoritmo: è un blocco in cui si vuole evidenziare la descrizione del procedimento di elaborazione interna; in pratica il blocco algoritmo costituisce l implementazione del blocco problema macchina: blocco caratterizzato da un meccanismo di elaborazione automatico interno che produce delle uscite in conseguenza di certi ingressi; altri termini sinonimi: automa, robot. funzione: blocco in cui si vuole evidenziare il legame funzionale fra gli ingressi e le uscite operazione: blocco che genera un risultato mediante un operazione sugli ingressi oggetto: blocco dotato di uno stato interno componente: blocco costituente un elemento di un sistema sistema: blocco composto da più oggetti fra loro interagenti rete: blocco in cui si evidenziano le mutue interrelazioni fra le componenti costitutive struttura: blocco composto da una struttura di dati
3.2. FUNZIONE DI UN BLOCCO 23 3.2 FUNZIONE DI UN BLOCCO Un blocco, per essere efficace, deve interagire con l ambiente circostante. L interazione di un blocco con l ambiente esterno ad esso può essere scissa in due componenti: ingressi e uscite. In questo modo un blocco risulta caratterizzato da una funzione di trasformazione F che lega gli ingressi x e le uscite y, secondo lo schema generale descritto nella figura 3.2. Si evidenzia così una perfetta analogia fra blocco e funzione: un blocco rappresenta la percezione fisica e la versione ingegneristica del concetto matematico di funzione. x F y Figura 3.2: Schema funzionale di un blocco avente funzione di trasformazione F, ingressi x ed uscite y. Per un dato blocco F, coerentemente con lo schema generale presentato nella figura 3.2, vale l uguaglianza y = F[x] Questa relazione funzionale evidenzia che le uscite y si ottengono mediante la trasformazione F che agisce sugli ingressi x. Due blocchi aventi funzioni di trasformazione F 1 e F 2 si dicono equivalenti se, con ingressi uguali, forniscono uguali uscite. Matematicamente significa che F 1 [x] = F 2 [x] per ogni ingresso x Quando si vuole esplicitare i singoli ingressi, x 2,..., x m e le singole uscite y 1, y 2,..., y n viene solitamente usata la seguente notazione lineare: [y 1, y 2,..., y n ] = F[, x 2,..., x m ] L equivalente notazione grafica è descritta nella figura 3.3. In questo caso F è una funzione vettoriale costituita da una sequenza di funzioni [f 1, f 2,..., f n ]; in dettaglio, per ciascuna componente per ciascuna componente dell uscita si ha: y 1 = f 1 [, x 2,..., x m ] y 2 = f 2 [, x 2,..., x m ] y n = f n [, x 2,..., x m ]
24 CAPITOLO 3. BLOCCHI x 2 x m F y 1 y 2 y n Figura 3.3: Blocco avente funzione di trasformazione F, avente ingressi, x 2,..., x m ed uscite y 1, y 2,..., y n. Il legame funzionale fra gli ingressi e le uscite può essere descritto in diversi modi: mediante una descrizione di tipo dichiarativo Esempio 7. Un blocco che determina il massimo comune divisore fra due numeri naturali può essere descritto come segue: ingressi: numeri naturali m, n uscite: massimo numero naturale che è divisore di m e di n mediante un espressione Esempio 8. Un blocco che determina la potenza di un numero reale elevato ad un esponente intero può essere descritto come segue: ingressi: numero naturale reale x, numero intero k uscite: numero reale x k mediante un insieme di vincoli Esempio 9. Un blocco che ordina due numeri può essere descritto come segue: ingressi: numeri reali, x 2 uscite: numeri reali y 1, y 2 tali che (y 1 y 2 ) ({, x 2 } = {y 1, y 2 })
3.3. CLASSIFICAZIONE DEI BLOCCHI 25 3.3 CLASSIFICAZIONE DEI BLOCCHI I blocchi possono essere classificati in base alla loro funzione di trasformazione. Alcuni linguaggi di programmazione (Scratch, Snap!) adottano la seguente classificazione: blocchi comando: blocco che non fornisce alcun risultato in uscita; il risultato viene automaticamente indirizzato su un oggetto (ad esempio, assegnazione di un valore ad una variabile) oppure producendo un effetto su un dispositivo di output (visualizzazione di una scritta, disegno di una figura, produzione di un suono) blocchi reporter: blocco che, in funzione degli ingressi, produce un uscita blocchi predicato: è un caso particolare di blocco reporter che fornisce in uscita un valore di tipo booleano comando reporter predicato Figura 3.4: Le varie tipologie dei blocchi. 3.4 COSTRUZIONE DEI BLOCCHI Un blocco viene costruito connettendo fra loro i blocchi elementari che realizzano le operazioni di base (+,,, /,... ); Nella costruzione dei blocchi, in molte situazioni insorge l esigenza di duplicare un ingresso; in questi casi viene utilizzato un particolare operatore duplicatore che duplica l ingresso: come descritto nella figura 3.5. x dup x x Figura 3.5: Specifica del blocco che duplica l ingresso x.
26 CAPITOLO 3. BLOCCHI Solitamente, l operatore dup viene sottinteso e viene sostituito da una semplice biforcazione, evidenziata con un pallino, del ramo di ingresso, come descritto nella figura 3.6. x x x Figura 3.6: Schema del blocco che duplica l ingresso x. Il seguente esempio illustra le tre fasi della realizzazione di un blocco. Esempio 10. Supponiamo di avere a disposizione gli operatori aritmetici di base e l operatore condizionale if; supponiamo inoltre che sugli ingressi di un blocco sia definita una relazione d ordine. Vogliamo costruire l operatore min che determina il minimo fra due ingressi e x 2 secondo la specifica funzionale descritta nella figura 3.7. x 2 min minimo fra ed x 2 Figura 3.7: Specifica del blocco che determina il minimo fra e x 2. L operatore min può essere realizzato come descritto nella figura 3.8. min x 2 < if minimo fra ed x 2 Figura 3.8: Struttura del blocco che determina il minimo fra i due ingressi e x 2.
3.4. COSTRUZIONE DEI BLOCCHI 27 In modalità testuale il blocco min può essere definito dalla scrittura min[, x 2 ] if[ < x 2,, x 2 ] L operatore min può essere usato in vari contesti: per risolvere una specifica istanza di problema, ad esempio per determinare il minimo fra due elementi a e b e depositare il risultato nella variabile r, scrivendo, in modalità testuale: r min[a, b] oppure per costruire altri blocchi, ad esempio per determinare il minimo fra tre elementi, come illustrato dal diagramma riportato nella figura 3.9. In modalità testuale questo blocco viene definito dalla scrittura min[, x 2, x 3 ] min[min[, x 2 ], x 3 ] x 2 x 3 min min minimo fra, x 2, x 3 Figura 3.9: Struttura del blocco min per determinare il minimo fra tre elementi, x 2 ed x 3. La costituzione interna di un blocco può essere descritta mediante un algoritmo sequenziale, dove possono essere usate delle variabili locali interne al blocco per memorizzare dei risultati parziali oppure per realizzare i blocchi duplicatori. Esempio 11. La struttura interna del blocco descritto nella figura 3.8 può essere descritta mediante la seguente porzione di algoritmo: [, x 2 ] t < x 2 y if[t,, x 2 ] y
28 CAPITOLO 3. BLOCCHI 3.5 BLOCCHI E PROBLEM SOLVING I blocchi costituiscono un importante strumento per concretizzare le metodologie top-down e bottom-up nella soluzione dei problemi. Per costruire un blocco (ma, in generale, per risolvere un problema) si possono adottare due strategie: comporre gli operatori che già si hanno a disposizione (operatori di base o operatori precedentemente costruiti) oppure usare, pensandoli già disponibili, dei blocchi che verranno costruiti in un secondo momento. La prima strategia corrisponde alla metodologia bottom-up mentre la seconda alla metodologia top-down. Spesso queste due strategie dimostrano la loro massima efficacia se vengono utilizzate in modo combinato. Esempio 12. La rete combinatoria riportata nella figura 3.10 valuta il valore di un binomio della forma ax + b. a x b bin + ax + b Figura 3.10: Blocco per il calcolo del binomio ax + b. Il blocco bin può essere usato per costruire un blocco tri per valutare il valore del trinomio ax 2 + bx + c, componendo due istanze del blocco bin, basandosi sull identità ax 2 + bx + c = (ax + b)x + c = bin[bin[a, x, b], x, c] 3.6 COMPLESSITÀ DEI BLOCCHI Nel caso di blocchi equivalenti risulta importante analizzare e decidere quale sia il migliore, dove con tale termine si intende che usa la minor quantità di risorse. Nel caso dei blocchi combinatori, come quelli precedentemente esaminati, la complessità di un blocco viene definita come il numero dei suoi componenti elementari.
3.6. COMPLESSITÀ DEI BLOCCHI 29 tri a x b c bin bin ax 2 + bx + c Figura 3.11: Rete combinatoria per il calcolo del trinomio ax 2 + bx + c. Per tempo di esecuzione di un blocco si intende il numero di unità di tempo impiegate per l elaborazione del blocco. Un approssimazione plausibile, benché semplificativa, consiste nel ritenere che il tempo dell operatore di duplicazione sia trascurabile mentre tutti gli altri operatori impieghino una stessa quantità di tempo unitaria. Bisogna comunque distinguere i seguenti due casi: esecuzione sequenziale: in ogni istante è operativo un solo componente esecuzione parallela: i componenti, i cui ingressi ed uscite non sono interdipendenti, operano contemporaneamente Questa distinzione è descritta nell esempio che segue. Esempio 13. I seguenti due blocchi sono equivalenti (entrambi determinano la somma dei quattro numeri in ingresso). La dimostrazione di equivalenza si può fondare sulla proprietà associativa dell operazione di addizione. add 4 x 2 x 3 x 4 + + + + x 2 + x 3 + x 4
30 CAPITOLO 3. BLOCCHI add 4 x + + + x 2 + x 3 + x 4 2 x 3 x + 4 Questi due blocchi hanno la stessa complessità strutturale ma il secondo è più efficiente del primo in caso di esecuzione parallela, in quanto impiega due unità di tempo (al posto delle tre unità di tempo impiegate dal primo). Essi corrispondono a due diverse parentizzazioni descritte dalle seguenti due espressioni: (( + x 2 ) + x 3 ) + x 4 ( + x 2 ) + (x 3 + x 4 ) 3.7 BLOCCHI CON CONTROLLI Un sistema di blocchi ha delle potenzialità molto limitate; ad esempio, dati in ingresso due numeri x ed n non si riesce a costruire un sistema di blocchi in grado di calcolare il valore della potenza x n, usando i quattro operatori aritmetici di base +,,, /. Questa limitazione è dovuta al fatto che un sistema di blocchi è equivalente alla valutazione di un espressione che, in sostanza, corrisponde all applicazione di una formula. D altra parte moltissimi problemi, anche limitandosi ai problemi numerici (ad esempio il calcolo del massimo comune divisore fra due generici numeri naturali), non sono risolvibili mediante una formula, ma richiedono procedimenti più articolati. Nei casi in cui la soluzione di un problema richieda delle elaborazioni condizionali e cicliche, nella costruzione di un blocco si fa ricorso ai controlli della programmazione strutturata. Esempio 14. Il calcolo del massimo comune divisore fra due numeri naturali m ed n è realizzabile mediante un blocco avente la seguente interfaccia: m n mcd massimo comune divisore fra m ed n L implementazione di questo blocco può essere basata sull algoritmo di Euclide.
3.8. ESERCIZI 31 3.8 ESERCIZI 1. Dimostrare che il seguente blocco produce sempre il valore di verità vero. x 2 < if y 2. Stabilire cosa produce il seguente blocco, essendo ed x 2 ingressi numerici: x 2 + y 1 y 2 Dare una dimostrazione di quanto stabilito. 3. Usando gli operatori binari +, e max, costruire un blocco per determinare il minimo fra due numeri. 4. Usando gli operatori aritmetici, l operatore if e gli operatori min e max, costruire un blocco per determinare la somma dei due valori più piccoli fra tre valori. 5. Costruire un blocco per decidere se tre dati valori possono costituire le misure dei lati di un triangolo. 6. Usando i soli operatori di confronto binari = e, costruire un blocco equivalente alla porta logica not. 7. Usando gli operatori di confronto =,, <, >,, e l operatore if, costruire un blocco per determinare il massimo fra 2 valori. Utilizzando tale blocco come componente elementare, costruire un blocco per determinare il massimo fra 3 elementi ed il massimo fra 4 elementi. 8. Realizzare dei blocchi che svolgono le seguenti funzioni:
32 CAPITOLO 3. BLOCCHI (a) valutazione di un binomio della forma a x + b (b) valutazione di un trinomio della forma a x 2 + b x + c (c) decidere se x è soluzione dell equazione a x 2 + b x + c = 0 9. Componendo il blocco bin, costruire un blocco quad per valutare il quadrinomio ax 3 + bx 2 + cx + d. Generalizzare al caso di un polinomio di grado n prefissato. 10. Usando l operatore tri che valuta un trinomio della forma ax 2 + bx + c costruire un blocco per decidere se un punto del piano cartesiano di coordinate (x, y) appartiene alla parabola di equazione y = ax 2 + bx + c. 11. Costruire un blocco con ingresso x ed uscita x 5. 12. Costruire un blocco ad un unico ingresso x e con le uscite x, x 2, x 3, x 4, x 5,. 13. Il calcolo di x 8 può essere svolto usando solo 3 operatori moltiplicativi, sfruttando la relazione x 8 = ((x 2 ) 2 ) 2 ; il calcolo di x 9 richiede l uso di 4 operatori moltiplicativi sfruttando la relazione x 9 = x x 8. A partire da questi casi particolari, generalizzare e stabilire in funzione del numero naturale n quanti operatori moltiplicativi sono necessari per calcolare x n. 14. Costruire due blocchi aventi funzioni di trasformazione corrispondenti alle seguenti definizioni di funzione: x = minimo numero intero x x = massimo numero intero x essendo x un numero decimale. Spiegare perchè, per ogni numero naturale n, vale la relazione n/2 + n/2 = n. 15. Usando gli operatori aritmetici binari +,,, / che operano sui numeri naturali, costruire un blocco che calcoli il quoziente ed il resto della divisione intera fra due dati numeri naturali m ed n. Descrivere un algoritmo sequenziale equivalente alla rete combinatoria che si è descritta.
Capitolo 4 Sistemi In fisica, come in qualsiasi altra disciplina, un sistema è un gruppo di parti interagenti. Nella maggior parte dei sistemi che conosciamo, durante l interazione le parti mantengono la loro identità, sicchè continuano ad essere visibili all interno del sistema. D. R. Hofstadter, Gödel, Escher, Bach Come una macchina meccanica è composta da dadi, bulloni, staffe, ingranaggi ed altri componenti elementari, così le macchine informatiche sono composte da elementi di base che eseguono delle operazioni elementari sui dati. I blocchi possono essere composti fra loro per realizzare un sistema avente una specifica funzionalità. Un sistema, a sua volta, è caratterizzato da degli ingressi e delle uscite legate agli ingressi secondo una ben specifica relazione funzionale. In pratica un sistema si comporta a sua volta come un blocco costituito da blocchi che costituiscono l implementazione del sistema complessivo. 33
34 CAPITOLO 4. SISTEMI 4.1 NOTAZIONI La composizione dei blocchi che costituiscono un sistema può essere descritta con diverse notazioni. Queste diverse modalità sono utilizzate nei vari ambienti di sviluppo visuale. notazione a fili: ingressi ed uscite sono rappresentati mediante dei fili unidirezionali che trasportano i dati che entrano dei blocchi (ingressi) e che escono dai blocchi (uscite). Questa notazione è utilizzata in alcuni ambienti di progettazione visuale, quali LabVIEW. F 1 F 4 F 5 x 2 x 3 x 4 x 5 F 2 F 3 Figura 4.1: Composizione di blocchi con notazione a fili. notazione ad annidamento: negli ambienti di programmazione visuale (quali Scratch, Snap! ed altri) gli ingressi di un blocco vengono rappresentati mediante dei riquadri interni al blocco; la forma dei riquadri indica il tipo degli ingressi ingressi e la forma del blocco denota il tipo dell uscita del blocco. x 2 x 3 x 4 x 5 Figura 4.2: Composizione di blocchi con notazione ad annidamento. notazione funzionale: la connessione dei vari blocchi viene denotata mediante un espressione funzionale i cui argomenti costituiscono gli ingressi. La composizione sequenziale dei blocchi viene denotata mediante
4.2. COMPOSIZIONE DI BLOCCHI 35 una sequenza di istruzioni contenenti notazioni funzionali che denotano la composizione di funzioni. F 5 [F 4 [F 1 [ ], F 3 [F 2 [x 2, x 3 ], x 4, x 5 ] ] Vengono inoltre utilizzate delle assegnazioni ( ) al fine di memorizzare in delle variabili dei risultati intermedi o per spezzare la descrizione del processo di elaborazione, al fine di renderlo più leggibile. 4.2 COMPOSIZIONE DI BLOCCHI I blocchi possono essere composti fra loro per costituire blocchi più complessi, più potenti e versatili. Uno dei metodi più semplici per costruire dei blocchi consiste nel comporre due o più blocchi in modo tale che le uscite di uno vengano usate come ingressi per un altro. Gli esempi che seguono illustrano alcuni possibili schemi di composizione di blocchi. Esempio 15. Lo schema riportato nella figura 4.3 descrive la modalità di composizione sequenziale. x F 1 F 2 y Figura 4.3: Composizione sequenziale di due blocchi aventi funzioni di trasformazione F 1 e F 2. In questo caso, coerentemente con la notazione matematica relativa alla composizione di funzioni, l uscita è definita dalla scrittura y F 2 [F 1 [x] ] Equivalentemente, memorizzando in una variabile t il risultato del primo blocco, si può scrivere x t F 1 [x] y F 2 [t] y
36 CAPITOLO 4. SISTEMI Esempio 16. Oltre alla composizione sequenziale descritta nell esempio precedente, i blocchi possono essere combinati in modi più articolati come descritto nella figura 4.4. In questo caso l uscita del primo blocco viene sdoppiata per alimentare i due blocchi che seguono. F 2 y 1 x F 1 t F 3 y 2 Figura 4.4: Composizione di blocchi con sdoppiamento di un uscita. Il sistema di blocchi riportato nella figura 4.4 può essere descritto in modo testuale come segue, usando la variabile t per realizzare lo sdoppiamento dell uscita del primo blocco. x t F 1 [x] y 1 F 2 [t] y 2 F 3 [t] [y 1, y 2 ] Esempio 17. Un altro fondamentale schema di composizione di blocchi è descritto nella figura 4.5. F 1 F 3 y x 2 F 2 Figura 4.5: Composizione di blocchi con connessione di uscite.
4.2. COMPOSIZIONE DI BLOCCHI 37 Il sistema di blocchi riportato nella figura 4.5 può essere descritto in modo testuale come segue: x y F 3 [F 1 [ ], F 2 [x 2 ] ] y Esempio 18. Il seguente sistema di blocchi utilizza tutte le precedenti forme di composizione. x 2 F 1 F 3 F 5 y 1 x 3 F 2 F 4 F 6 y 2 Figura 4.6: Composizione di blocchi con varie modalità. Questo sistema di blocchi può essere espresso come segue: [, x 2, x 3 ] t 1 F 2 [x 3 ] t 2 F 3 [F 1 [, x 2 ], t 1 ] y 1 F 5 [t 2 ] y 2 F 6 [t 2, F 4 [t 1 ] ] [y 1, y 2 ] Osservazione. Dalle scritture sequenziali riportate negli esempi precedenti si evidenzia una perfetta corrispondenza fra sistema di blocchi e sequenza di espressioni.
38 CAPITOLO 4. SISTEMI 4.3 COMPOSITORI E SELETTORI In quasi tutti i linguaggi di programmazione sono predisposti dei meccanismi per comporre elementi e per accedere alle componenti di un elemento composto. Questi meccanismi possono essere espressi in termini di blocchi come segue. L operatore di composizione di elementi è descritto nella figura 4.7. x 2... x n [ ] a Figura 4.7: Schema dell operatore di composizione. In modalità testuale l operatore di composizione descritto nella figura 4.7 si scrive a = [, x 2,..., x n ] L operatore di composizione completa la sua efficacia ed utilità in combinazione con l operatore di selezione, che consente di accedere ad una data componente di una composizione, come descritto nella figura 4.8. a k sel k-esima componente di a Figura 4.8: Schema dell operatore di selezione. In modalità testuale l operatore di selezione descritto nella figura 4.8 si scrive y = a[k]
4.4. ESERCIZI 39 4.4 ESERCIZI 1. Esprimere in notazione funzionale il legame fra gli ingressi e le uscite del seguente blocco. x2 F 1 F 2 y 2. Descrivere una sequenza di passi elementari corrispondenti all esecuzione a ciascuno dei seguenti sistemi: F 1 F 3 F 4 y x 2 F 2 F 1 F 3 F 5 y x 2 F 2 F 4 Indicando con t i il tempo di esecuzione del blocco avente funzione di trasformazione F i, determinare il tempo di esecuzione sequenziale e dell esecuzione parallela (nell espressione del tempo è possibile usare gli operatori min e max). 3. Utilizzando la grafica della tartaruga costruire un blocco poligono[n, l] che disegna un poligono regolare di n lati di lunghezza l. Usando il blocco poligono disegnare una casa costituita da una facciata quadrata e da un tetto a forma di triangolo equilatero. 4. Utilizzando la grafica della tartaruga costruire un blocco casa[b, h, a] che disegni una casa di data base b ed altezza h, avente il tetto con due
40 CAPITOLO 4. SISTEMI falde che formano fra loro un angolo a. Usando il blocco casa, costruire un blocco schiera che disegni una serie di case a schiera. Costruire un blocco campanile ed un blocco chiesaconcampanile. Discutere come sono intervenute le metodologie top-down e bottom-up nello sviluppo della soluzione di questo esercizio. Usando il blocco casa[b, h, a] che disegna una casa come descritto sopra, scrivere un blocco casa[b, h, a, f] che disegna una casa con fattore di scala f. Costruire un blocco viale che disegni un viale di case a schiera con effetto prospettico. 5. Costruire un blocco lunghezza[n] che valuti il numero di cifre di cui è composto un numero naturale n, considerato in base 10. Costruire un blocco cifra[n, k] che valuti il valore della k-esima cifra di un numero naturale n (nell ipotesi che sia k lunghezza[n]). Usando i blocchi sopra definiti, scrivere un blocco-predicato palindromo[n] per decidere se il numero naturale n è palindromo. 6. Risolvere ciascuno dei problemi sotto riportati mediante un adeguato blocco. I numeri devono essere intesi in notazione decimale. Determinare il rovescio di un numero (ad esempio, il rovescio di 4527 è 7254). Decidere se un numero è palindromo, ossia se si legge indifferentemente da sinistra a destra e da destra a sinistra (esempi di numeri palindromi: 7, 44, 121, 3663, 25352). Decidere se un numero naturale è un quadrato (esempi di quadrati: 0, 1, 4, 9, 16, 25). Decidere se un numero è un quadrato palindromo (esempi di quadrati palindromi: 0, 1, 4, 9, 121). Descrivere il grafo delle chiamate reciproche dei vari blocchi utilizzati. Discutere il caso dei numeri che terminano con degli zeri (in questi casi non è chiaro cosa deve valutare la funzione che rovescia un numero...).
Capitolo 5 Reti Illustrazione di Victor Juhasz In molti contesti gli elementi acquistano significato ed utilità in quanto appartenenti ad un sistema di elementi. In questi casi acquista importanza il sistema complessivo degli elementi fra loro interconnessi, ossia la rete. Un moderno computer è costituito da semplicissimi circuiti, denominati porte logiche, che vengono collegate fra loro per costituire le cosidette reti logiche. La potenza di calcolo di questi computer si fonda su due fattori: l altissimo numero di circuiti elementari che combinati insieme consentono di realizzare enormi reti logiche di calcolo aventi funzionalità via via più complesse; la straordinaria velocità con cui vengono aperti e chiusi gli interruttori di tali circuiti. 41
42 CAPITOLO 5. RETI 5.1 RETI Nella terminologia dei blocchi una rete è costituita da blocchi elementari uguali o appartenenti ad una stessa categoria. Le reti vengono solitamente classificate in due categorie: reti combinatorie: le uscite dipendono univocamente dagli ingressi reti sequenziali: le uscite dipendono sia dagli ingressi sia dalla storia della rete stessa, ossia dalla sequenza dei valori assunti nel tempo dagli ingressi 5.2 RETI COMBINATORIE Gli operatori di base possono essere composti per costituire dei blocchi in grado di svolgere diverse e più complesse operazioni. Un blocco costruito combinando degli operatori più elementari viene detto rete combinatoria. A seconda della categoria degli operatori utilizzati, una rete combinatoria assume diverse denominazioni; le più utilizzate sono le seguenti: rete logica: composta da operatori logici (,, ) rete aritmetica: composta da operatori aritmetici (operatori +,,, /) rete di permutazione: composta da operatori binari a due uscite che invertono gli ingressi (operatore inv) rete di ordinamento: composta da operatori binari a due uscite che ordinano gli ingressi (operatore sort) 5.3 PORTE LOGICHE Nella storia dell evoluzione tecnologica una decisiva idea è stata quella di rappresentare i numeri e, più in generale, tutte le informazioni in forma binaria. La chiave del successo delle porte e delle reti logiche è legata alla loro capacità di implementare ed unificare il calcolo aritmetico ed il calcolo logico introdotto dal matematico inglese G. Boole (1815-1864) intorno alla metà del secolo scorso. Il punto in cui si passa dall analogico al digitale, ossia il punto di contatto fra elettronica ed informatica, è rappresentato dal punto in cui i segnali elettrici diventano zeri e uni e i circuiti elettronici vengono schematizzati mediante
5.3. PORTE LOGICHE 43 porte logiche. Questo passo di astrazione dall analogico al digitale permette di prescindere dalla tecnologia elettronica impiegata. Una porta logica è un componente elettronico che, dal punto di vista funzionale, può essere schematizzato come un blocco avente degli ingressi e delle uscite digitali indicate convenzionalmente con 0 e 1. Le porte logiche costituiscono le componenti elementari di un generico elaboratore. Esempio 19. Le porte logiche più frequentemente utilizzate sono descritte nella figura 5.1. x 2 and y or y x x not y 2 Figura 5.1: Schemi delle porte logiche fondamentali. La relazione funzionale che lega gli ingressi e le uscite delle tre porte and, or e not può essere descritta mediante una tavola di verità come riportato nella tabella 5.1. x 2 and x 2 or x 2 not 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 1 1 1 0 Tabella 5.1: Tavola di verità della porte logiche fondamentali. La tabella 5.2 riporta la lista delle porte logiche abitualmente utilizzate, corrispondentemente ai simboli alternativi usati per rappresentarle. porta notazione notazione notazione logica circuitale algebrica logica and = or = + not Tabella 5.2: Simboli usati per denotare le porte logiche.
44 CAPITOLO 5. RETI Oltre alle porte logiche fondamentali sopra descritte, vengono usate anche altre porte logiche; il loro funzionamento è descritto dalla tavola di verità riportata nella tabella 5.3. x 2 nand x 2 nor x 2 xor x 2 0 0 1 1 0 0 1 1 0 1 1 0 1 0 1 1 1 0 0 0 Tabella 5.3: Tavola di verità delle porte logiche nand, nor e xor. 5.4 RETI LOGICHE Componendo le porte logiche si costruiscono le reti logiche aventi una sequenza di ingressi binari [, x 2,..., x m ] e un sequenza di uscite binarie [y 1, y 2,..., y n ]. Esempio 20. Una fondamentale operazione è l addizione binaria di due bit (half-adder); le due uscite rappresentano il bit s di somma ed il bit c di riporto (figura 5.2). x 2 ha s c Figura 5.2: Schema di un half-adder. Il funzionamento dell operatore half-adder può essere descritto mediante la tavola di verità riportata nella tabella 5.4. x 2 s c 0 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1 Tabella 5.4: Tavola di verità dell operatore half-adder.
5.4. RETI LOGICHE 45 Le due uscite s e c di un half-adder possono essere descritte, in termini di porte logiche, individualmente come segue: s = xor x 2 c = and x 2 In termini di porte logiche elementari, un half-adder può essere descritto mediante lo schema riportato nella figura 5.3. half-adder x 2 xor s and c Figura 5.3: Schema di un half-adder. Esempio 21. Un full-adder è una rete combinatoria costituita da 3 ingressi e 2 uscite. I primi due ingressi e x 2 rappresentano i bit da addizionare mentre il terzo ingresso x 3 rappresenta il bit di riporto (del passo precedente); le uscite s e c forniscono la somma dei due ingressi e x 2 ed il riporto (per il passo successivo). Il funzionamento dell operatore full-adder può essere descritto mediante la tavola di verità riportata nella tabella 5.5. x 2 x 3 s c 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 Tabella 5.5: Tavola di verità dell operatore full-adder.
46 CAPITOLO 5. RETI Usando i teoremi dell algebra booleana è facile ricavare le seguenti due identità: s = xor x 2 xor x 3 c = (x 2 and x 3 ) or and (x 2 xor x 3 ) Da queste scritture si può dedurre che un full-adder può essere realizzato mediante due half-adder ed una porta logica or come descritto nella figura 5.4. full-adder x 2 x 3 ha ha or s c Figura 5.4: Schema di un full-adder. 5.5 RETI ARITMETICHE Le reti aritmetiche sono costituite dagli operatori aritmetici di base corrispondenti alle operazioni aritmetiche fondamentali. Esempio 22. Usando gli operatori aritmetici di base sui numeri naturali è possibile costruire un blocco che valuta il resto della divisione intera fra due numeri naturali. Tale operatore viene solitamente denotato in notazione infissa con il simbolo % e viene detto modulo; ad esempio, 7 % 3 = 1. Questo blocco è descritto nella figura 5.5. m n / r Figura 5.5: Blocco per il calcolo del resto r della divisione intera fra m ed n.
5.6. RETI DI OPERAZIONI BINARIE 47 Questo blocco può essere descritto in una forma più familiare mediante la semplice identità r = m ((m/n) n) L analogia fra il blocco descritto in modo grafico e l equivalente espressione fa capire che il problema di costruire un blocco componendo degli operatori di base è equivalente al problema di scrivere un espressione che, valutata, fornisca il risultato. 5.6 RETI DI OPERAZIONI BINARIE In molti casi le reti sono composte da più occorrenze di un solo binario associativo e producono una sola uscita. La proprietà di associatività permette di costruire reti equivalenti ma di diversa topologia; queste diverse topologie di reti presentano efficienze significativamente diverse nel caso di esecuzione parallela. Consideriamo un operatore binario associativo (, x 2 ) y che denoteremo in modo grafico come descritto nella figura 5.6. y x 2 Figura 5.6: Schema di un generico operatore binario che agli ingressi, x 2 associa l uscita y. In queste ipotesi l operatore su più operandi, x 2,..., x n può essere denotato mediante una rete ad albero come descritto nella figura 5.7, corrispondente alla seguente scrittura associativa a sinistra: (((((( x 2 ) x 3 ) x 4 ) x 5 ) x 6 ) x 7 ) x 8 Una rete equivalente può essere ottenuta organizzando gli operandi con una parentizzazione bilanciata, come descritto nella nella figura 5.8, corrispondente alle scrittura bilanciata: (( x 2 ) (x 3 x 4 )) ((x 5 x 6 ) (x 7 x 8 ))
48 CAPITOLO 5. RETI y x 2 x 3 x 4 x 5 x 6 x 7 x 8 Figura 5.7: Rete di operazioni binarie che agli ingressi, x 2, x 3, x 4, x 5, x 6.x 7, x 8 associa l uscita y, mediante una valutazione basata sull associatività a sinistra. y x 2 x 3 x 4 x 5 x 6 x 7 x 8 Figura 5.8: Rete di operazioni binarie che agli ingressi, x 2, x 3, x 4, x 5, x 6, x 7, x 8 associa l uscita y, mediante una valutazione basata su una parentizzazione bilanciata. Le reti descritte nella figura 5.7 e nella figura 5.8 sono topologicamente diverse ma equivalenti dal punto di vista computazionale. Queste due reti hanno la stessa efficienza nel caso di esecuzione sequenziale ma manifestano, invece, un efficienza sostanzialmente diversa nel caso di esecuzione parallela: nell ipotesi che ciascun operatore impieghi un tempo di esecuzione unitario, la prima rete impiega un tempo pari a n mentre la seconda impiega un tempo pari a log 2 n.
5.7. RETI DI PERMUTAZIONE 49 5.7 RETI DI PERMUTAZIONE Un componente elementare spesso usato nella costruzione delle reti combinatorie è costituito dall operatore inv che inverte i due ingressi, secondo lo schema descritto nella figura 5.9. Operatori di questo tipo vengono solitamente usati per realizzare delle macchine composte da più operatori evitando che i fili si intersechino. inv x 2 x 2 Figura 5.9: Schema dell operatore di inversione. Una rete composta di elementi inv viene detta rete di permutazione. In notazione grafica la rete di permutazione che inverte due ingressi viene indicata sinteticamente con lo schema descritto in figura 5.10. Figura 5.10: Schema di una rete di permutazione a due ingressi. Esempio 23. La rete di permutazione riportata nella figura 5.11 inverte la sequenza di ingresso [, x 2, x 3, x 4 ] producendo in uscita la sequenza [x 4, x 3, x 2, ]. x 2 x 3 x 4 x 4 x 3 x 2 Figura 5.11: Rete di permutazione che inverte i quattro ingressi.
50 CAPITOLO 5. RETI 5.8 RETI DI ORDINAMENTO L ordinamento costituisce una delle più importanti problematiche dell informatica. Le reti di ordinamento sono dei sistemi combinatori in grado di fornire in uscita, ordinati, gli ingressi. Esempio 24. Vogliamo costruire una rete combinatoria sort per ordinare due elementi, x 2, sui quali sia definita una relazione d ordine. In pratica vogliamo realizzare un blocco soddisfacente alla specifica funzionale descritta nella figura 5.12. x sort min[, x 2 ] 2 max[, x 2 ] Figura 5.12: Specifica del blocco sort che ordina due ingressi. Supponendo di poter disporre dei due operatori min e max (che determinano rispettivamente il minimo ed il massimo fra due elementi) il blocco sort che ordina due ingressi può essere descritto nella figura 5.13. sort min min[, x 2 ] x 2 max max[, x 2 ] Figura 5.13: Struttura di una rete combinatoria che ordina due ingressi. In notazione grafica la rete combinatoria che ordina due ingressi viene indicata sinteticamente con lo schema descritto in figura 5.14. Una rete composta da operatori sort che produca in uscita una sequenza ordinata viene detta rete di ordinamento.
5.9. RETI SEQUENZIALI 51 Figura 5.14: Schema di una rete di ordinamento a due ingressi. Esempio 25. Componendo degli operatori sort che ordinano due elementi, si può costituire una rete di ordinamento che ordina tre elementi (figura 5.15). sort 3 x 2 x 3 sort sort sort y 1 y 2 y 3 Figura 5.15: Struttura di una rete di ordinamento che ordina tre ingressi. Una rete di ordinamento come quella descritta figura 5.15 viene solitamente disegnata, in una forma più sintetica, come descritto nella figura 5.16. x 2 x 3 y 1 y 2 y 3 Figura 5.16: Schema di una rete di ordinamanto che ordina tre ingressi. 5.9 RETI SEQUENZIALI Una rete sequenziale è un blocco caratterizzato dal fatto che l uscita dipende, oltre che dagli ingressi, dallo stato interno il quale a sua volta dipende dagli ingressi precedenti. La storia pregressa della rete viene sintetizzata mediante lo stato attuale, costituito da una memoria che, unitamente ai valori degli ingressi, determina i valori delle uscite; inoltre, ad ogni transizione, lo stato viene
52 CAPITOLO 5. RETI a sua volta aggiornato, assumendo un nuovo valore che dipende, in generale, dagli ingressi e dal precedente valore dello stato. Ad un livello di dettaglio più raffinato, una rete sequenziale può essere schematizzata come illustrato nella figura 5.17. y 1 x m rete y n combinatoria memoria m 1 m k t 1 t k Figura 5.17: Schema di una rete sequenziale. Le uscite t 1, t 2,..., t k (eventualmente coincidenti con alcune delle uscite y 1, y 2,..., y n ) vengono registrate in delle variabili di memoria m 1,..., m k che vanno ad alimentare gli ingressi al passo successivo. Il comportamento di una rete sequenziale è descritto dalla tabella delle transizioni che contiene un certo numero di stati interni realizzabili con elementi di memoria. Per una rete sequenziale si usa spesso il termine macchina o sistema.
5.10. ESERCIZI 53 5.10 ESERCIZI 1. Costruire una rete combinatoria in grado di decidere se tre elementi a, b, c sono tutti uguali fra loro. 2. Costruire una rete combinatoria in grado di decidere se tre dati numeri possono costituire le misure dei lati di un triangolo; la condizione di costruibilità di un triangolo si può esprimere come segue: Il lato più lungo deve essere minore della somma degli altri due. 3. Costruire una rete combinatoria in grado di decidere se tre numeri numeri possono può costituire le misure dei lati di un triangolo isoscele. Si assuma l ipotesi che i tre numeri soddisfino alla condizione di costruibilità di un triangolo. 4. Costruire una rete combinatoria in grado di decidere se tre assegnati numeri costituiscono le misure dei lati di un triangolo rettangolo (se vale questa proprietà una terna viene detta pitagorica). 5. Costruire una rete aritmetica costituita da soli operatori di addizione e sottrazione, per ruotare a sinistra tre ingressi numerici secondo lo schema di trasformazione [, x 2, x 3 ] [x 2, x 3, ]. 6. Descrivere una rete aritmetica composta dai soli operatori aritmetici +,,, /, che operano sui numeri naturali, per rovesciare un numero naturale di 2 cifre (in notazione decimale); ad esempio con l ingresso 63 si deve ottenere l uscita 36; con l ingresso 40 si deve ottenere l uscita 4. Spiegare perchè non è possibile costruire una rete aritmetica per rovesciare un generico numero naturale. 7. Si dice peso binario di un numero naturale il numero di cifre 1 della sua rappresentazione binaria. Spiegare perchè non è possibile costruire una rete aritmetica per il calcolo del peso binario di un numero naturale. 8. Costruire una rete di permutazione per permutare tre ingressi secondo la trasformazione [, x 2, x 3 ] [x 3, x 2, ], ed una per invertire quattro ingressi secondo la trasformazione: [, x 2, x 3, x 4 ] [x 4, x 3, x 2, ]. 9. Stabilire l effetto della seguente rete di permutazione:
54 CAPITOLO 5. RETI x 2 x 3 x 4 y 1 y 2 y 3 y 4 10. Descrivere una rete di permutazione che rovescia gli n ingressi, x 2,..., x n generando la sequenza di uscita x n, x n 1,...,. 11. La composizione sequenziale di due reti di permutazione costituisce una rete di permutazione. Stabilire se questa operazione di composizione sequenziale di due reti è commutativa e associativa. 12. Sia rand[m, n] un blocco che fornisce in uscita un numero naturale casuale compreso fra i due numeri m ed n. Usando questo operatore realizzare un blocco perm che fornisce in uscita i due ingressi oppure la loro inversione, scegliendo casualmente fra queste due alternative. Componendo l operatore perm costruire una rete di permutazione di tre ingressi che fornisca in uscita una permutazione degli ingressi, in modo che siano permesse tutte le possibili permutazioni degli ingressi. 13. Descrivere una rete di ordinamento per ordinare tre elementi. Descrivere il processo di ordinamento nel caso di un istanza di problema aventi gli ingressi ordinati in modo inverso all uscita. 14. Dati quattro ingressi, x 2, x 3, x 4, con la condizione x 2, x 3 x 4, descrivere una rete di ordinamento che, usando l operatore sort binario, ordina i quattro ingressi dati. Valutare il tempo di esecuzione nel caso di elaborazione sequenziale ed elaborazione concorrente, assumendo come unitario il tempo di esecuzione di un operatore sort binario. 15. Componendo l operatore sort si può comporre una rete di ordinamento per ordinare 4 elementi come descritto sotto. Dimostrare che questa rete funziona correttamente. Evidenziare il processo di ordinamento dei numeri 7, 4, 9 e 3, scrivendo i numeri in corrispondenza di ciascun ramo di uscita. Determinare il tempo di esecuzione, nel caso sequenziale e nel caso parallelo, assumendo come unitario il tempo di elaborazione di un blocco sort che ordina 2 elementi.
5.10. ESERCIZI 55 x 2 x 3 x 4 y 1 y 2 y 3 y 4 16. Dimostrare che le seguenti due reti di ordinamento sono equivalenti (entrambe ordinano i 4 elementi di ingresso). x 2 x 3 x 4 y 1 y 2 y 3 y 4 x 2 x 3 x 4 y 1 y 2 y 3 y 4 Stabilire quale delle due è più efficiente nel caso di elaborazione parallela. 17. Descrivere una rete di ordinamento per ordinare 5 elementi. 18. Dimostrare che la seguente rete di ordinamento ordina correttamente 6 elementi. x 2 x 3 x 4 x 5 x 6 y 1 y 2 y 3 y 4 y 5 y 6 Generalizzare al caso di n elementi. Determinare, in funzione di n, quanti sono gli operatori sort necessari. Calcolare il tempo di ordinamento in funzione di n (nel caso di esecuzione sequenziale e nel caso di esecuzione parallela).
56 CAPITOLO 5. RETI 19. Dimostrare che, anche se alquanto inaspettatamente, l aggiunta di un operatore sort ad una rete di ordinamento funzionante, può compromettere la funzionalità della rete. 20. Dimostrare il seguente Principio Zero-Uno: Se una rete di ordinamento funziona correttamente con ingressi presi dall insieme {0, 1}, allora funziona correttamente anche per elementi di qualsiasi tipo sul quale sia stabilito un criterio di ordine lineare.