Teoria dell Informazione II Anno Accademico 2015 2016 Lezione 17 Ugo Vaccaro Nella Lezione scorsa abbiamo introdotto una classe di codici a correzione di errore (codici di Hamming) in grado di correggere tutte le possibili occorrenze di un errore che potevano capitare durante la trasmissione di parole del codice. In questa lezione introdurremo una generalizzazione dei codici di Hamming e proveremo che essi sono in grado di correggere un numero maggiore di errori. In via preliminare, abbiamo bisogno di ricordare alcune propietà di base dei campi finiti. Innanzitutto, ricordiamo che una struttura algebrica (F,, +) dotata di operazione di addizione e moltiplicazione, è un campo finito se, denotando con 0 l elemento neutro rispetto all addizione, vale che: 1. a, b F vale che a b F; 2. (F \ {0}, ) è un gruppo commutativo; 3. (F, +) è un gruppo commutativo; 4. a, b, c F, (a + b) c = a c + b c. Un classico esempio di campo finito è il campo F p = {0, 1,..., p 1}, dove p è un numero primo, e le operazioni di addizione e moltiplicazione sono le solite operazioni di addizione e moltiplicazioni modulo p. É possibile costruire campi finiti con p m elementi, per ogni primo p e numero naturale m 1. Diamo un idea su come ciò sia possibile. Denotiamo con F 2 il campo con elementi {0, 1}, munito dell operazione di addizione e moltiplicazione modulo 2. Con F 2 m denoteremo il campo composto da tutti i 2 m vettori binari di lunghezza m. L operazione di addizione in F 2 m è la solita operazione di addizione vettoriale, ovverosia se a, b F 2 m, allora a + b = c F 2 m, ed il vettore c ha come i-esima componente la somma (modulo 2) della i-esima componente di a e b. Per definire un opportuna operazione di moltiplicazione in F 2 m, è utile vedere gli elementi (vettori) di F 2 m come polinomi di grado al più m 1. Ovvero, dato il vettore a = (a 0, a 1..., a m 1 ), esso lo vedremo come il polinomio a(x) = a 0 + a 1 x +... + a m 1 x m 1. Un polinomio p(x) di grado > 1 a coefficienti in F 2 è detto polinomio irriducibile su F 2 se esso non è divisibile per nessun altro polinomio di grado > 1 a coefficienti in F 2. Si può vedere che un polinomio irriducibile su F 2 necessariamente divide il polinomio x 2m 1 + 1. Un polinomio p(x) a coefficienti in F 2 è detto polinomio primitivo se esso è un polinomio irriducibile (quindi divide x 2m 1 + 1), e non divide x n + 1 per ogni n < 2 m 1. Polinomi primitivi esistono e sono noti per ogni m. Ad esempio, i seguenti polinomi sono primitivi su F 2 : m = 3, x 3 + x + 1 m = 4, x 4 + x + 1 m = 5, x 5 + x 2 + 1. A questo punto, definiamo la seguente regola di moltiplicazione tra vettori in F 2 m. Fissato un polinomio primitivo p(x) = p m x m +... + p 0, per ogni coppia di dati a, b F 2 m, porremo a b = c se e solo se c(x) = a(x)b(x) mod p(x). (1) Si può vedere facilmente che in questo modo l insieme F 2 m {0} è un gruppo commutativo. Ne segue che F 2 m munito dell operazione di addizione prima definita e della operazione di moltiplicazione (1) è un campo finito. Sia ora p(x) = p 0 + p 1 x +... + p m x m un polinomio primitivo di grado m su F 2, e sia α una radice di p(x). Ogni radice di p(x) viene detta radice primitiva. Poichè per definizione p(x) divide x 2m 1 + 1, otteniamo che x 2m 1 + 1 = q(x)p(x), per qualche polinomio q(x), da cui α 2m 1 + 1 = q(α)p(α) = 0, e quindi α 2m 1 = 1. Ciò che è interessante, è che è possibile provare che le successive potenze 1 = α 0,..., α 2m 2 sono tutti gli elementi di V m (F 2 ), tranne 0, in altri termini α è un generatore del gruppo (moltiplicativo) F 2 m {0}. 1
Vediamo un esempio. Sia m = 3, sia dato il polinomio primitivo x 3 + x + 1 e sia α radice primitiva, per cui α 3 + α + 1 = 0, il che è equivalente a dire che α 3 = α + 1. Il campo F 2 3 ha ovviamente 8 elementi, che possono essere rappresentati come 8 potenze di α, oppure come 8 polinomi su F 2 di grado al più 2, oppure come vettori binari a tre componenti, come mostrato nella tabella di seguito: α i polinomio (grado 2) vettore (a 2, a 1, a 0 ) α 0 = 1 α 0 1 001 α 1 α x 010 α 2 α 2 x 2 100 α 3 α + 1 x + 1 011 α 4 α(α + 1) = α 2 + α x 2 + x 110 α 5 α(α 2 + α) = α 2 + α + 1 x 2 + x + 1 111 α 6 α(α 2 + α + 1) = α 2 + 1 x 2 + 1 101 α 7 α(α 2 + 1) = 1 É inoltre semplice calcolare l inverso di un elemento attraverso la identità α i = α n i, dove n = 2 m 1. Utilizzando una rappresentazione siffatta, possiamo effettuare in maniera semplice le operazioni di addizione e moltiplicazione nel campo F 2 3. Ad esempio, se volessimo effettuare la moltiplicazione dell elemento 111 per l elemento 101, possiamo notare che 111 corrisponde a α 5 mentre 101 corrisponde ad α 6, per cui 111 101 = α 5 α 6 = α 11 = α 7 α 4 = α 4 = 011. Analogamente, se volessimo dividere il vettore 111 per il vettore 101 avremmo 111 101 = α6 α 5 = α6 α 5 = α 6 α 7 5 = α 6 α 2 = α 8 = α = 010. Viceversa, se dovessimo addizionare α 5 con α 6, possiamo passare alla loro rappresentazione vettoriale nell ultima colonna a destra, e agevolmente dedurre che α 5 + α 6 = α. Allo stesso identico modo, se fossimo partiti da un campo F p arbitrario, avremmo potuto costruire un campo con p m elementi. Il fatto interessante è che ogni campo finito F q con q elementi è di questo tipo, ovvero è isomorfo ad un campo di polinomi con p m elementi, per opportuni p primo e m numero naturale. Ritorniamo al problema della costruzione di codici correttori di errore. I codici che studieremo, detti Codici di Reed-Solomon, sono definiti come la valutazione di polinomi di grado limitato su di un campo finito. Sia F un campo finito dato (può essere utile immaginare che esso sia il campo F 2 m, ma non è strettamente necessario). I messaggi sorgente che vogliamo codificare, ad esempio sequenze binarie a {0, 1} l, li possiamo interpretare come coefficienti di un polinomio di un dato grado fissato k 1. Ad esempio, possiamo scrivere a = a 0 a 1..., a k 1, dove ogni sottosequenza a i {0, 1} m, i = 0,..., k 1, ed interpretare ciascuna a i come un elemento del campo F 2 m prima visto. In questo modo, ad ogni sequenza a = a 0 a 1..., a k 1 {0, 1} l possiamo unicamente associare un polinomio f(x) = f 0 + f 1 x + f 2 x 2 +... + f k 1 x k 1 di grado al più k 1, dove f 0 = a 0, f 1 = a 1,..., f k 1 = a k 1. In questo modo, i codici di Reed-Solomon sono ottenuti specificando il campo F, l intero k, ed n < F punti α 1,..., α n F, e le sue parole sono k 1 C = {(f(α 1 ), f(α 2 ),..., f(α n )) : f(x) = f i x i, f 0,..., f k 1 F}. Denotiamo questa famiglia di codici, in generale, come RS F (n, k). Un caso particolare molto importante si ottiene quando n = F e valutiamo quindi i polinomi f(x) su tutti gli elementi del campo F. Possiamo notare 2
una similarità con lo schema di condivisione di chiavi segrete di Shamir. In tal caso, la chiave segreta veniva assegnata al coefficiente di grado zero del polinomio f(x). Qui, invece, la sequenza sorgente (f 0 f 1... f k 1 ) viene innanzitutto codificata nel polinomio f(x) = f 0 + f 1 x +... + f k 1 x k 1, indi codificata nella sequenza c = (f(α 1 ), f(α 2 ),..., f(α n )) di tutte le valutazioni f(x). Di conseguenza, ogni componente/simbolo della parola codice c è un elemento del campo F 2 m e quindi, dal punto di vista pratico, è da considerarsi come una sequenza binaria lunga m. Nel caso non binario, ovvero nel caso in cui il campo in questione è F = F p m, per dati interi p (primo) e m 1, ogni componente/simbolo di una parola codice di RS F (n, k) è un elemento del campo F p m e quindi deve essere considerato esso stesso come una sequenza lunga m sull alfabeto {0, 1,..., p 1}. Osserviamo innanzitutto che il codice RS F (n, k) è un codice lineare. Dalla definizione, ciò equivale a provare che ogni combinazione lineare di parole codice in RS F (n, k) appartiene ancora a RS F (n, k). Siano a tale scopo c = (c 1,..., c n ), d = (d 1,..., d n ) arbitrarie parole in RS F (n, k). Proviamo che per ogni α, β F vale che αc + βd = ((αc 1 + βd 1 ),..., (αc n + βd n )) = (a 1,..., a n ) RS F (n, k). Dalla definizione, esistono polinomi f(x) = k 1 f ix i e g(x) = k 1 g ix i tali che c 1 = f(α 1 ),..., c n = f(α n ) e d 1 = g(α 1 ),..., d n = g(α n ), per cui a 1 = h(α 1 ),..., a n = h(α n ), dove h(x) è il polinomio h(x) = αf(x) + βg(x) di grado k 1. Di conseguenza, per definizione si ha che (a 1,..., a n ) RS F (n, k). Vale il seguente Lemma 1 La distanza minima di RS F (n, k) è pari a d = n k + 1. Dimostrazione. Proviamo innanzitutto che d n k + 1. Essendo RS F (n, k) un codice lineare, basterà provare che il peso minimo di RS F (n, k) è n k + 1. Ovvero, basterà provare che per ogni polinomio f(x) di grado k 1 vale che {x F : f(x) = 0} k 1, da cui {i : f(α i ) 0} n k + 1. Ciò di fatto discende dal Teorema Fondamentale dell algebra, che implica che ogni polinomio f di grado al più r, non identicamente nullo, ha al più r radici. Ne diamo qui una prova per induzione su r. Se r = 0 allora il polinomio f è una costante diversa da zero, per cui ha zero radici. Assumiamo pertanto r 1. Sia α F tale che f(α) = 0. Definiamo g(x) = f(x + α), per cui g(0) = 0 e g(x) è ancora un polinomio di grado al più r. Scriviamo r r g(x) = f i (x + α) i = g i x i. Poichè vale che g 0 = g(0) = 0, otteniamo che g(x) = xh(x), dove h(x) = r 1 g i+1x i è un polinomio di grado r 1. Pertanto f(x) = g(x α) = (x α)h(x α). Per ipotesi induttiva, il polinomio h(x α) ha al più r 1 radici, e quindi f ha al più r radici. Per provare che il peso minimo di RS F (n, k) è pari esattamente a n k+1 basterà ora esibire una parola codice che ha esattamente tale numero di componenti diverse da zero. Si vede immediatamente che ogni parola codice del tipo (f(α 1 ), f(α 2 ),..., f(α n )), ottenuta in corrispondenza del polinomio f(x) = (x α i1 )(x α i2 ) (x α ik 1 ), dove α i1,..., α ik 1 sono k 1 arbitrari elementi di F, ha appunto esattamente n k + 1 componenti diverse da zero. In virtù dei risultati visti nella lezione scorsa sappiamo che il codice RS F (n, k) permette, in linea di principio, la correzione di e errori, dove e (n k)/2. Nel resto della lezione vedremo un algoritmo efficiente per la correzione di un tale numero di errori. Innanzitutto, però, notiamo un interessante caratteristica dei codici RS F (n, k). Ovviamente, RS F (n, k) = F k = F n d+1. D altra parte, nella lezione scorsa abbiamo dimostrato che ogni codice C {0, 1,... q 1} n, con distanza minima d, non può avere più di q n d+1 parole codice. Ne 3
consegue che i codici RS F (n, k), per i parametri per cui essi esistono, hanno il massimo mumero di parole codice. Equivalentemente, fissato i parametri n e k, i codici RS F (n, k) sono quelli che correggono il maggior numero di errori per tali parametri. Vediamo ora come progettare un algoritmo efficiente per la correzione di eventuali e (n k)/2 errori occorsi. Sia f(x) = r f ix i un polinomio incognito di grado al più k 1. Conosciamo la sua valutazione sui punti α 1,..., α n ma e di queste valutazioni sono errate. In altri termini, conosciamo valori y 1,..., y n F, tali che y i f(α i ) per al più e errori. Se sapessimo quali sono i valori y i errati, potremmo ignorarli ed attraverso l interpolazione solo sui valori corretti ricostruire il polinomio f(x) (e quindi la relativa parola codice). Purtroppo, noi non conosciamo i valori errati. Definiamo il polinomio E(x) nel seguente modo: E(x) = i:y i f(α i) (x α i ). Ovviamente, non essendo noti i valori y i errati, cioè quelli diversi dai f(α i ), non è noto nenanche il polinomio E(x). Ciononostante, possiamo utilizzarlo nell analisi. Chiaramente, esso soddisfa le seguenti proprietà (ovvero, equazioni che i coefficienti di E e f devono soddisfare): E(α i )(f(α i ) y i ) = 0 1 i n. Sia N(x) = E(x)f(x). Notiamo che grado(e) = e e grado N(x) = grado(e) + grado(f) e + k 1. Sulla base delle precedenti osservazioni, abbiamo di fatto il seguente risultato, che formalizziamo esplicitamente per future referenze. Lemma 2 Esistono polinomi E(x) e N(x), di grado e e di grado e k + 1, rispettivamente, tali che per ogni 1 i n. N(α i ) y i E(α i ) = 0 L idea che sfrutteremo è che possiamo trovare polinomi siffatti risolvendo un sistema di equazioni. Lemma 3 Possiamo trovare polinomi E (x), N (x), di grado pari al più ad e e di grado pari al più a e + k 1, non entrambi zero, tali che N (α i ) y i E (α i ) = 0 per ogni 1 i n. Dimostrazione. Siano E (x) = e a j x j, N (x) = dove a j e b j sono coefficienti incogniti. Tali coefficienti ovviamente soddisfano il seguente sistema di equazioni lineari: e+k 1 e b j (α i ) j y i a j (α i ) j = 0 1 i n. Sappiamo che un tale sistema ammette almeno una soluzione (ciò dal Lemma 2), che ovviamente possiamo trovare mediante i metodi dell algebra lineare. Ovviamente, non abbiamo alcuna garanzia che i polinomi E (x) e N (x) che troveremo saranno uguali ai polinomi E(x) e N(x) cui siamo interessati. Tuttavia, il seguente risultato ci dice che possiamo recuperare il polinomio f da ogni coppia E (x) ed N (x) che possiamo aver trovato. e+k 1 b j x j, 4
Lemma 4 Sotto l ipotesi che il numero di errori occorso e sia tale che e (n k)/2, si ha che f(x) = N (x) E (x). Dimostrazione. Consideriamo il polinomio R(x) = N (x) E (x)f(x). Notiamo che per ogni i tale che f(α i ) = y i (ovvero per tutti le componenti i-esime della parola codice su cui non è occorso alcun errore, ed esse sono in numero di n e), abbiamo che R(α i ) = N (α i ) E (α i )f(α i ) = N (α i ) E (α i )y i = 0. Ciò dal Lemma 3. Ne segue che il polinomio R(x) ha almeno n e zeri. D altra parte, il grado di R(x) è al più pari a max(grado(n ), grado(e ) + grado(f)) e + k 1. Sotto la nostra ipotesi che e (n k)/2 abbiamo che n e > e + k 1. Ovvero, il polinomio R(x) ha più zeri del suo grado, quindi R(x) deve essere necessariamente il polinomio zero, e quindi N (x) = E (x)f(x). In conclusione, potendo dedurre il polinomio f(x) dai polinomi N (x) e E (x), possiamo calcolarci la parola codice originale (f(α 1 ), f(α 2 ),..., f(α n )). 5