Codice Gray. (versione Marzo 2007)

Documenti analoghi
Un esempio di calcolo di complessità: insertion sort

APPUNTI SULLA DIAGONALIZZAZIONE Corso Prof. F.Podestà, a.a

1 Combinazioni lineari.

Inversa di una matrice

LeLing12: Ancora sui determinanti.

Appunti sui Codici di Reed Muller. Giovanni Barbarino

1 Riduzione per righe e matrici equivalenti per righe.

Metodo di Gauss-Jordan 1

NOTE DI ALGEBRA LINEARE v = a 1 v a n v n, w = b 1 v b n v n

Laboratorio di Python

1 Indipendenza lineare e scrittura unica

Esercitazione di Reti degli elaboratori

1 Definizione di sistema lineare omogeneo.

DAI NUMERI NATURALI AI NUMERI RAZIONALI

LOGICA MATEMATICA PER INFORMATICA (A.A. 12/13)

1 Giochi di Ehrenfeucht-Fraissé e Logica del Prim ordine

Corso di Informatica di Base

Derivazione numerica. Introduzione al calcolo numerico. Derivazione numerica (II) Derivazione numerica (III)

RISOLUZIONE IN LOGICA PROPOSIZIONALE. Giovanna D Agostino Dipartimento di Matemaica e Informatica, Università di Udine

Sui determinanti e l indipendenza lineare di vettori

La codifica digitale

Gli Array. Dichiarazione di un array

04 - Logica delle dimostrazioni

Note per il corso di Geometria Corso di laurea in Ing. Edile/Architettura. 4 Sistemi lineari. Metodo di eliminazione di Gauss Jordan

Note sull algoritmo di Gauss

Forme bilineari simmetriche

Lo sviluppo di un semplice programma e la dimostrazione della sua correttezza

Lezione 6 Introduzione al C++ Mauro Piccolo

02 - Logica delle dimostrazioni

Lista di esercizi 11 maggio 2016

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Dati e Algoritmi I (Pietracaprina) Esercizi sulle Nozioni di Base

Riassumiamo le proprietà dei numeri reali da noi utilizzate nel corso di Geometria.

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

METODI MATEMATICI PER L INFORMATICA

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Sistemi lineari - Parte Seconda - Esercizi

Introduzione alla logica proposizionale

Transcript:

Codice Gray (versione Marzo 27) Data una formula booleana con n variabili, per costruire una tavola di verità per questa formula è necessario generare tutte le combinazioni di valori per le n variabili. Usando per vero e per falso, di solito si parte con n zeri e poi si continua ad incrementare di in binario; ad es. con n2: Per un certo tipo di tavole di verità (le "mappe di Karnaugh") serve elencare le combinazioni in modo tale che tra due consecutive ci sia esattamente un bit di differenza; questo modo di elencare le combinazioni si chiama Codice Gray. Nella tabella di sopra, la a e la 2a riga differiscono di bit, ma la 2a e la 3a hanno 2 bit di differenza. E` facile rimediare, basta invertire le ultime due righe: Notare che il codice Gray non e` unico; anche quello che segue ha la proprietà voluta Nel seguito cerchiamo di ottenere il codice "del primo tipo"; quindi diciamo "il codice Gray" ed usiamo G n per indicare il codice Gray per n variabili. Problema: trovare un modo per generare il codice Gray per n variabili (n > ). più precisamente: scrivere una procedura che, dato n, stampa il codice Gray per n. Approccio induttivo alla soluzione: proviamo a risolvere per n piccolo (questa è la base dell'induzione); vediamo se, avendo costruito il codice Gray per, 2,..., n- variabili, riusciamo a generare quello per n variabili usando i precedenti (questo è il passo induttivo). La base è facile, perchè per n il codice è banale: G (Inoltre abbiamo anche la soluzione per n2.) Per capire il passo induttivo, vediamo il caso n3. Pensandoci un po', si capisce che: scrivendo seguito da G 2 abbiamo scritto metà di G 3

il resto si ha scrivendo seguito da G 2 in ordine rovesciato (cioè scrivendolo a partire dall'ultima riga): G 3 [ questo è G 2 ] [ questo è G 2 rovesciato ] E` immediato verificare che si può ragionare cosí anche per andare da G a G 2 G 2 [ questo è G ] [ questo è G rovesciato ] A questo punto dovrebbe essere chiaro che la cosa vale in generale. Scrivendo GR n per il codice Gray per n variabili scritto in ordine inverso, abbiamo: G n+ G n GR n A questo punto, se si deve risolvere il problema "su un pezzo di carta", abbiamo finito: partendo da G riusciamo a generare tutti i G n Volendo scrivere una procedura per risolvere il problema, dopo un po' si capisce che bisogna anche trovare una "formula" per GR n Studiando i casi n, 2, 3, vediamo che: GR GR 2 [ questo è G ] [ questo è GR ] GR 3 [ questo è G 2 ] [ questo è GR 2 ] 2

Quindi si capisce che la formula generale è: GR n+ G n GR n A questo punto, avendo un modo induttivo per generare sia G n che GR n possiamo procedere per capire come scrivere la procedura per stampare il codice. Algoritmo - Prima idea: per generare G n definiamo una matrice n x 2 n e poi la riempiamo seguendo lo schema di sopra; alla fine basterà stampare la matrice. Definiamo una procedura gray (n: int) che stampa G n Questa dichiara una matrice tab di dimensione n x 2 n e poi usa due ulteriori procedure, gd per generare il codice Gray e gr per generare il codice rovesciato. Guardando i disegni di sopra, si capisce che per generare, ad esempio, G 7 servirà, ad esempio, generare G 3 e GR 3 piu' volte ed in posizioni diverse della matrice; quindi gd e gr avranno come parametri: la matrice tab e poi 4 indici che individuano la poosizione della matrice su cui lavorare: left_col (colonna sinistra), right_col (colonna destra), upper_row (riga superiore), lower_row (riga inferiore); ovviamente, se, come sopra, il codice da generare è G 3 (oppure GR 3 ), avremo che: right_col left_col + 3 quindi non c'è bisogno del parametro corrispondente al numero di variabili. Per adeguarci al C, facciamo partire gli indici degli array da. procedura gray( n : integer IN ) { qui n > var k, j, num_righe : integer; num_righe <--- 2 n { blocco con dichiarazioni: var tab : array [.. n- ;.. num_righe-] of char ora generiamo la tabella completa da colonna a colonna n- e da riga a riga num_righe- : gd(tab,, n-,, num_righe-); e poi stampiamo il risultato : per k,, 2,... num_righe- { per j,, 2,..., n- scrivi ( tab[k][j] ) vai a capo chiude il per su k chiude blocco chiude procedura 3

procedura gd( tab [ ] [ ] of char IN - OUT left_col, right_col, upper_row, lower_row : integer IN) { if (left_col < right_col) { int k, med; med <---- (upper_row + lower_row) div 2; per k upper_row, upper_row+,..., med: tab[k][left_col] <--- ''; gd(tab, left_col+, right_col, upper_row, med); per k med+, med+2,... lower_row : tab[k][left_col] <---- ''; gr(tab, left_col+, right_col, med+, lower_row); procedura gr( tab [ ] [ ] of char IN - OUT left_col, right_col, upper_row, lower_row : integer IN) { e` uguale a gd, tranne che si scambiano '' e '' if (left_col < right_col) { int k, med; med <---- (upper_row + lower_row) div 2; per k upper_row, upper_row+,..., med: tab[k][left_col] <--- ''; gd(tab, left_col+, right_col, upper_row, med); per k med+, med+2,... lower_row : tab[k][left_col] <---- ''; gr(tab, left_col+, right_col, med+, lower_row); La versione C segue questo schema, però c'è un problema: nelle procedure non è possibile usare un parametro array con due dimensioni non specificate. Per risolvere il problema, in una prima versione, gray_.c, si fissa un limite al numero di variabili; nella seconda versione, gray bis.c, si usano i puntatori. Algoritmo - seconda idea: per generare G n utilizziamo solo un vettore di lunghezza n; generiamo una riga della tabella alla volta e poi la stampiamo. Vediamo prima l'algoritmo e poi lo commentiamo. 4

procedura gray( n : integer ) { qui n > var : k : integer w : array [.. n] of char come una stringa in C, usiamo terminatore : '\' per k,,..., n- : w[k] <--- ' ' w[n] <--- '\' ; gd(, w); per togliere eventuali caratteri nulli presenti procedura gd( k : integer IN, w : array [ ] of char IN-OUT ) { if (w[k] '\') then scrivi ( w ) else { w[k] <--- '' gd(k+, w); w[k] <--- ''; gr(k+, w); procedura gr( k : integer IN, w : array [ ] of char IN-OUT ) { come gd, ma scambiando ed if (w[k] '\') then scrivi ( w ) else { w[k] <--- '' gd(k+, w); w[k] <--- ''; gr(k+, w); Non è per nulla evidente che funzioni; in effetti è anche difficile spiegare come si arriva a questo algoritmo. L'idea che c'è sotto è: ricordiamo che w è un array con indici da a n; indichiamo con w k la stringa w[] w[]... w[k-] allora inoltre w[n] terminatore; (nota: w stringa nulla); gd(k, w) stampa, nell'ordine previsto dal nostro codice Gray, tutte le stringhe della forma w k u con u che appartiene a G i con i n-k. (qui: il indica concatenazione tra stringhe e G { e, dove e stringa vuota) Quindi, gd(, w) stampa G n In effetti, per capire veramente come funzionano le cose, bisogna anche precisare cosa produce gr(k, w), ma questo è facile: come per gd(k, w), ma usando GR i. 5

Proviamo a dimostrare il tutto per induzione. Ipotesi: w è un array con indici da a n (n > ); inoltre w[n] terminatore; Notazione: w k indica a stringa w[] w[]... w[k-] Tesi: (w e stringa nulla); [a] gd(k, w) stampa, nell'ordine previsto dal nostro codice Gray, tutte le stringhe della forma w k u con u che appartiene a G i con i n-k (dove G { e ). [b] gr(k, w) stampa, nell'ordine previsto dal nostro codice Gray, tutte le stringhe della forma w k u con u che appartiene a GR i con i n-k (dove GR { e ). Dimostrazione per induzione (a passi) su i n-k ( < i < n) Base, i. La tesi è verificata, perchè per kn sia gd(k,w) che gr(k,w) stampano la stringa contenuta in w, cioè w n. Passo: supponiamo vera la tesi per i- ( < i- < n) e dimostriamo che vale anche per i. Vediamo prima la tesi [a]. Poichè i >, abbiamo k < n; quindi nell'eseguire gd(k,w) si sceglie il ramo else. Poichè n-(k+) i-, per ipotesi induttiva la tesi vale per le due chiamate gd(k+,w) e gr(k+,w); quindi: gd(k+, w) stampa, nell'ordine previsto..., tutte le stringhe della forma w k+ u con u che appartiene a G i- e, successivamente, gr(k+, w) stampa, nell'ordine previsto..., tutte le stringhe della forma w k+ u con u che appartiene a GR i- A causa delle due assegnazioni w[k] <--- '' e w[k] <--- '' quanto sopra si può riscrivere come segue: gd(k+, w) stampa, nell'ordine previsto..., tutte le stringhe della forma w k "" u con u che appartiene a G i- e, successivamente, gr(k+, w) stampa, nell'ordine previsto..., tutte le stringhe della forma w k "" u con u che appartiene a GR i- Ma allora gd(k,w) stampa proprio tutte le stringhe della forma w k u con u che appartiene a G i come si voleva. La tesi [b] si dimostra in modo del tutto analogo. Quindi la dimostrazione è fatta ed abbiamo finito!!! 6