Documente Academic
Documente Profesional
Documente Cultură
Bucureşti
2017
Cuprins
Introducere 3
Capitolul 1. Preliminarii 5
1. Inelul claselor de resturi modulo n 5
2. Rezolvarea sistemelor de ecuaţii liniare. Eliminare Gauss 9
3. Spaţii Vectoriale 13
Capitolul 2. Coduri numerice 17
1. Exemple de Coduri Numerice 17
2. Detecţia erorilor 19
Capitolul 3. Coduri liniare 21
1. Noţiuni de bază 21
2. Coduri liniare 24
3. Decodare Coset. Codul Golay 27
Capitolul 4. Coduri Hamming 31
Capitolul 5. Aplicaţii 35
1. USPS Postal Code 36
2. The Universal Product Code 37
3. ISBN-10 38
4. Codul Golay 39
5. Codul Hamming 45
Concluzie 49
Bibliografie 51
1
Introducere
4
CAPITOLUL 1
Preliminarii
ā = {b ∈ Z : b ≡ a mod n}
Lema 1.5. Fie n ∈ Z+ şi a, b ∈ Z. Atunci a ≡ b mod n dacă şi numai dacă a şi
b au acelaşi rest la ı̂mpărţirea la n. Cu alte cuvinte, a ≡ b mod n dacă şi numai
dacă există q, q 0 ∈ Z astfel ı̂ncât a = qn + r şi b = q 0 n + r, cu 0 ≤ r < n.
Corolar 1.6. Fie n ∈ Z+ . Atunci orice număr ı̂ntreg este congruent modulo n cu
exact un ı̂ntreg din mulţimea {0, . . . , n − 1}.
Definiţia 1.7. Fie n ∈ Z+ şi a ∈ Z, arbitrar. Unicul număr ı̂ntreg din {0, . . . , n−1}
cu care a este congruent modulo n se numeşte cel mai mic rest a lui a modulo n
Corolar 1.8. Clasele de echivalenţă a ı̂ntregilor modulo n sunt ı̂n corespondenţă
bijectivă cu resturile după ı̂mpărţirea la n.
Aceste resturi sunt mai precis ı̂ntregii din mulţimea Zn , unde Zn = {0, 1, . . . , n−
1}, de unde şi corolarul.
Acum vom discuta despre o generalizare a ceasului aritmetic. Ne amintim că,
să determinăm, spre exemplu, timpul peste 8 ore când ceasul indică ora 10, vom
aduna 8 + 10 obţinând 18 şi scădem 12 ca să obţinem că ora va fi 6. Cu alte
cuvinte, adunăm numerele şi scădem 12 ori de câte ori este nevoie până se obţine o
oră validă. Aceasta este şi ideea din spatele adunării in Zn . Similar, putem defini
şi ı̂nmultirea.
Definiţia 1.9. Fie n ∈ Z+ , iar a şi b elemente ale lui Zn . Atunci a + b = a + b, iar
a · b = ab.
Ceea ce spune definiţia este că pentru a aduna două elemente din Zn , le
reprezentăm ca fiind clasa de echivalenţă a unor ı̂ntregi, după care adunăm ı̂ntregii
şi luăm clasa de echivalenţă a sumei. Similar şi dacă ı̂nmulţim două elemente din
Zn . Vom lua două exemple din Z12 :
8 + 10 = 18 = 6
şi
8 · 10 = 80 = 8.
Aplicând aceste definiţii, obţinem tabelele de adunare şi de ı̂nmulţire pentru
Z2 :
+ mod 2 0 1 · mod 2 0 1
0 0 1 0 0 1
1 1 0 1 0 1
Tabelele de adunare şi ı̂nmulţire pentru Z4 , sunt:
7
+ mod 4 0 1 2 3 · mod 4 0 1 2 3
0 0 1 2 3 0 0 0 0 0
1 1 2 3 0 1 0 1 2 3
2 2 3 0 1 2 0 2 0 2
3 3 0 1 2 3 0 3 2 1
Lema 1.10. Fie n ∈ Z+ . Dacă a, b, c, d ∈ Z cu a ≡ c mod n şi b ≡ d mod n,
atunci a + b ≡ c + d mod n şi ab ≡ cd mod n.
Demonstratie. Fie n ∈ Z+ şi presupunem că a ≡ c mod n şi b ≡ d mod n.
Atunci c − a şi d − b sunt divizibile cu n, deci exista s, t ∈ Z astfel ı̂ncât a − c = sn
şi b − d = tn. Aşadar a = c + sn şi b = d + tn. Dacă adunăm ecuaţiile, obţinem
a + b = (c + sn) + (d + tn) = (c + d) + (s + t)n,
ceea ce arată că (a + b) − (c + d) este un multiplu de n, adică, a + b ≡ c + d mod n.
Analog, dacă ı̂nmulţim ecuaţiile, obţinem
ab = (c + sn) · (d + tn) = cd + ctn + dsn + sntn
= cd + (ct + sd + snt)n
deci ab − cd este un multiplu de n, deci ab ≡ cd mod n. Asta demonstrează
lema.
În cele mai multe aplicaţii, metoda aleasă pentru a calcula cel mai mare divizor
comun dintre două numere ı̂ntregi este algoritmul lui Euclid. În principiu, prin
factori comuni se poate calcula cel mai mare divizor comun, dar dacă numerele
sunt prea mari, nu mai este eficient din punct de vedere de timp. Algoritmul lui
Euclid are avantajul de calcul uşor; Maple şi alte programe folosesc acest algoritm
pentru calcularea celui mai mare divizor comun.
Algoritmul lui Euclid pentru calcularea celui mai mare divizor comun a două
numere a, b ∈ Z+ constă ı̂n următorii paşi:
(1) a0 = max(a, b);a1 = min(a, b), iar i = 1.
(2) Dacă ai = 0, atunci ai−1 = cmmdc(a, b).
ai−1
(3) Dacă ai 6= 0, se ı̂mparte ai−1 la ai , şi se obţine ai−1 = qai + r.
ai
(4) Se ı̂nlocuieşte i cu i + 1.
(5) ai primeşte valoarea ai = r.
(6) Se ı̂ntoarce la pasul 2.
Exemplul 1.11. Algoritmul funcţionează ı̂n felul următor. Vom afla cmmdc(75432, 19787634)
19787634 = 262 · 75432 + 24450
75432 = 3 · 24450 + 2082
24450 = 11 · 2082 + 1548
2082 = 1 · 1548 + 534
1548 = 2 · 534 + 480
534 = 1 · 480 + 54
480 = 8 · 54 + 54
54 = 1 · 48 + 6
48 = 8·6+0
8
Deci, ultimul rest diferit de 0 este 6, aşadar cel mai mare divizor comun dintre
19787634 şi 75432 este 6.
Lema 1.12. Fie a, b ∈ Z, nu amândouă 0, şi există q, r ∈ Z astfel ı̂ncât b = qa + r.
Atunci cmmdc(a, b) = cmmdc(a, r).
Demonstratie. Fie d = cmmdc(a, b) şi c = cmmdc(a, r). Din b = qa+r observăm
că c divide b deci c ≤ d. Dar r = b − qa deci d divide r şi d ≤ c totodată, deci
d = c.
unde x3 şi x5 sunt arbitrari. Putem scrie cele patru soluţii ale acestui sistem de
ecuaţii, deoarece x3 şi x5 pot avea valorile 0 sau 1:
(x1 , x2 , x3 , x4 , x5 ) = (1 + x3 , 1 + x3 + x5 , x3 , 1, x5 ),
unde x3 ∈ {0, 1} şi x5 ∈ {0, 1}.
Soluţia generală este
(1 + x3 , 1 + x3 + x5 , x3 , 1, x5 ) = (1, 1, 0, 1, 0) + x3 (1, 1, 1, 0, 0) + x5 (0, 1, 0, 0, 1),
astfel ı̂ncât (1, 1, 0, 1, 0), care corespunde valorilor x3 = x5 = 0, să fie o soluţie
particulară a sistemului liniar. Pe de altă parte, vectorii (1, 1, 1, 0, 0), (0, 1, 0, 0, 1)
rezolvă sistemul omogen
x1 + x2 + x5 = 0
x1 + x3 = 0
x 2 + x 3 + x4 + x5 = 0
x2 + x3 + x5 = 0.
11
Pe final, ne amintim o teoremă care ne va ajuta să determinăm date numerice
despre codurile de corectare a erorilor. Înainte de a ı̂ncepe teorema, explorăm
contextul in care va fi aplicată şi ne amintim câţiva termeni. Nucleul, sau spaţiul-
nul, al unei matrici A este mulţimea tuturor soluţiilor ecuaţiei omogene AX = 0.
Exemplul 1.19. Daca avem matricea
1 0 1 0 1 0 1 0
H = 0 1 1 0 0 1 1 0 ,
0 0 0 1 1 1 1 0
soluţia ecuaţiei omogene, HX = 0, poate fi descrisă sistematic prin determinarea
unei baze pentru nucleul lui H. Deoarece din fiecare alegere distinctă a variabilelor,
x3 , x5 , x6 şi x7 ı̂n Z2 rezultă o soluţie unică pentru HX = 0, obţinem patru soluţii
prin a-i da, succesiv, unei variabile aleatoare, valoarea 1 si celorlalte 0, apoi folosind
x1 = x3 + x5 + x7
x2 = x3 + x6 + x7
x4 = x5 + x6 + x7
pentru a determina valorile variabilelor rămase. Obţinem următorii vectori
1 1 0 1
1 0 1 1
1 0 0 0
0 , 1 , 1 , 1 ,
0 1 0 0
0 0 1 0
0 0 0 1
care formează baza pentru nucleul lui H. Într-adevăr, soluţia generală a ecuaţiei
HX = 0 este dată de
x1 x3 + x5 + x7 1 1 0 1
x2 x3 + x6 + x7 1 0 1 1
x3 x 3
1 0 0 0
x4 = x5 + x6 + x7 = x3 0 + x5 1 + x6 1 + x7 1 .
x5 x5 0 1 0 0
x6 x6 0 0 1 0
x7 x7 0 0 0 1
Acest exemplu indică faptul general că pentru un sistem omogen AX = 0,
numărul de variabile care nu corespund cu 1 conducători este egal cu dimensiunea
nucleului lui A. Numim aceste variabile, variabile libere, iar celelalte variabile ( care
sunt exact atâtea cât rangul lui A ) ca variabile de bază. Din matricea eşalonată
superior a lui A, variabilele de bază pot fi exprimate ı̂n termeni de variabile libere.
Prin imitarea exemplului de mai sus, se obţine o mulţime distinctă de soluţii pentru
AX = 0, prin a ı̂i da succesiv unei variabile libere valoarea 1 şi celorlalte 0. Apoi
orice soluţie poate fi scrisă, unic, ca o combinaţie liniară a acestor soluţii. În
particular, această mulţime distinctă de soluţii este o bază pentru nucleul lui A,
aşadar numărul variabilelor libere este egal cu dimensiunea nucleului. Deoarece
fiecare variabilă este numărul de coloane al matricii, obţinem importanta teoremă
de rang-defect. Defectul matricii A este dimensiunea nucleului lui A.
12
Teorema 1.20. Fie A o matrice cu m linii şi n coloane. Atunci n este egal cu
suma dintre rangul lui A şi defectul lui A.
Ideea acestei teoreme, este că, ı̂n momentul ı̂n care cunoşti rangul lui A, atunci
poţi calcula imediat şi defectul lui A. Deoarece lucrăm ı̂n Z2 , numărul soluţiilor
pentru AX = 0 este 2defect(A) . În teoria codării acesta ne permite să determinăm
numărul de cuvinte cod dintr-un cod.
3. Spaţii Vectoriale
Într-un spaţiu vectorial V peste corpul comutativ F avem două operaţii, adunarea
cu vectori şi ı̂nmulţirea cu scalari. Operaţia de adunare este o operaţie binară pe V .
Înmulţirea cu scalari este mai diferită, deoarece ı̂n stânga egalului avem un element
scalar din corpul comutativ F şi un vector din V , iar ı̂n dreapta egalului, un vector,
deci ı̂nmulţirea cu scalari este de fapt o funcţie definită pe F × V cu valori ı̂n V .
Pentru a păstra convenţia, scriem această funcţie ca α · v sau mai simplu αv.
Definiţia 1.21. Fie F un corp comutativ. Un F -spaţiu vectorial este o mulţime
nevidă V ı̂mpreună cu operaţia + : V × V → V şi o operaţie · : F × V → V , cu
următoarele proprietăţi:
1. (V, +) grup comutativ,
2. α(u + v) = αu + αv, pentru oricare α ∈ F şi oricare u, v ∈ V ,
3. (α + β)u = αu + βu, pentru oricare α, β ∈ F şi oricare u ∈ V ,
4. (αβ)u = α(βu), pentru oricare αβ ∈ F şi oricare u ∈ V ,
5. 1 · u = u, pentru oricare u ∈ V .
Exemplul 1.22. Pentru un exemplu fundamental, folosim un F -spaţiu vectorial
ı̂n spaţiul F n al n-uplelor de elemente din F . Aşadar,
F n = {(a1 , . . . , an ) : ai ∈ F }.
Operaţiile care-l transformă pe F n ı̂ntr-un spaţiu vectorial sunt operaţiile pe com-
ponente provenite din adunarea şi ı̂nmulţirea ı̂n corpul comutativ F :
(a1 , . . . , an ) + (b1 , . . . , bn ) = (a1 + b1 , . . . , an + bn )
α(a1 , . . . , an ) = (αa1 , . . . , αan ).
Lema 1.23. Fie F un corp comutativ şi V un spaţiu vectorial peste F . Dacă
v ∈ V , atunci 0 · v = 0.
Demonstratie. Fie v ∈ V . Pentru a arăta că 0 · v = 0, trebuie să arătăm că 0 · v
satisface definiţia adunării. Prin utilizarea unei legi de distribuţie, observăm
0·v+v = 0 · v + 1 · v = (0 + 1) · v
= 1 · v = v = 0 + v.
Prin urmare obţinem 0 · v = 0.
Lema 1.24. Fie F un corp comutativ şi fie V un spaţiu vectorial peste F . Dacă
v ∈ V , atunci (−1) · v = −v.
Demonstratie. Fie v ∈ V . Pentru a demonstra că (−1) · v = −v, trebuie să
arătăm că este inversul adunării cu v. Avem
v + (−1) · v = 1 · v + (−1) · v = (1 + (−1)) · v
= 0·v =0
13
din lema precedentă. Aceste ecuaţii arată ı̂ntr-adevăr că (−1) · v este inversul lui v
ı̂n raport cu adunarea.
α · (v + w) = α · v + α · w ∈ W,
unde α ∈ F şi v, w ∈ V .
La ı̂nceputul secţiunii actuale am definit spaţiile vectoriale peste un corp co-
mutativ şi am demonstrat câteva proprietăţi simple. În continuare discutăm cele
mai importante noţiuni asociate cu spaţiile vectoriale, cele care conduc la termenul
de bază.
Definiţia 1.27. Fie F un corp comutativ şi fie V un spaţiu vectorial peste F . Dacă
avem o mulţime finită de vectori {v1 , . . . , vn } din V şi o mulţime finită de scalari
n
P
{a1 , . . . , an } din F , atunci vectorul ai vi se numeşte o combinaţie liniară de vi
i=1
Definiţia 1.28. Fie F un corp comutativ şi fie V un spaţiu vectorial peste F . O
mulţime {v1 , . . . , vn } de elemente din V este liniar independentă dacă şi numai dacă
n
P
pentru orice mulţime de scalari {a1 , . . . , an } astfel ı̂ncât ai vi = 0 atunci fiecare
i=1
ai = 0.
Definiţia 1.29. Fie F un corp comutativ şi fie V un spaţiu vectorial peste F .
O mulţime {v1 , . . . , vn } de elemente din V este o mulţime de generatori pentru V
dacă fiecare element din V poate fi exprimat ca o combinaţie liniară de vectorii
{v1 , . . . , vn }.
Definiţia 1.30. Fie F un corp comutativ şi fie V un spaţiu vectorial peste F . O
submulţime {v1 , . . . , vn } de elemente din V este o bază pentru V dacă este liniar
independentă şi dacă este o mulţime de generatori pentru V .
Exemplul 1.31. Fie H o matrice, iar nucleul lui
0 0 0 1 1 1 1
H= 0 1 1 0 0 1 1 ,
1 0 1 0 1 0 1
Aşadar, C este ı̂nchis faţă de adunarea şi ı̂nmulţirea cu scalari, deci este ı̂ntr-adevăr
un subspaţiu din Z72 . Am observat că o soluţie arbitrară (x1 , x2 , x3 , x4 , x5 , x6 , x7 )
14
pentru Hx = 0 satisface
x1 = x3 + x5 + x7 ,
x2 = x3 + x6 + x7 ,
x4 = x5 + x6 + x7 ,
iar x3 , x5 , x6 şi x7 sunt arbitrare. Obţinem patru soluţii dacă alegem o variabilă să
fie 1 şi restul 0. Făcând asta obţinem
c1 = (1, 1, 1, 0, 0, 0, 0)
c2 = (1, 0, 0, 1, 1, 0, 0)
c3 = (0, 1, 0, 1, 0, 1, 0)
c4 = (1, 1, 0, 1, 0, 0, 1).
Susţinem că {c1 , c2 , c3 , c4 } constituie o bază pentru C. Aceasta se observă prin
ecuaţia
x1 x3 + x5 + x7 1 1 0 1
x2 x3 + x6 + x7 1 0 1 1
x3 x3 1 0 0 0
x4 = x5 + x6 + x7 = x3 · 0 +x5 · 1 +x6 · 1 +x7 · 1 ,
x5 x5 0 1 0 0
x6 x6 0 0 1 0
x7 x7 0 0 0 1
ce denotă faptul că fiecare soluţie este o combinaţie liniară de {c1 , c2 , c3 , c4 }.
Şi descompunerea elementelor lui C demonstrează, de asemenea, liniar
independenţa mulţimii {c1 , c2 , c3 , c4 } deoarece, dacă o combinaţie liniară a acestor
vectori este egală cu vectorul zero, atunci coordonatele 3,5,6 şi 7 a rezultatului că
cei patru coeficienţi sunt toţi 0.
Asta demonstrează că {c1 , c2 , c3 , c4 } formează o bază pentru C.
Teorema 1.32. Fie F un corp comutativ şi V un spaţiu vectorial peste F . Atunci
V are o bază. În plus, numărul de elemente din orice două baze ale lui V sunt
egale.
Definiţia 1.33. Fie F un corp comutativ şi V un spaţiu vectorial peste F cu o
baza B. Atunci, dimensiunea lui V este cardinalul lui B.
În continuare, arătăm că dacă un spaţiu vectorial din Z2 are dimensiunea n,
atunci cardinalul său, adică numărul de elemente din spaţiul vectorial, este egal cu
2n .
Propoziţia 1.34. Presupunem că V este un spaţiu vectorial peste Z2 . Dacă
dim(V ) = n, atunci |V | = 2n .
16
CAPITOLUL 2
Coduri numerice
a) Codul USPS
b) Codul UPC
0 13241 54321 2
The Universal Product Code, sau UPC, este codul de bare care apare efectiv
pe toate produsele pe care le cumpărăm zi de zi. Este un cod de 12 cifre, ce constă
ı̂n două blocuri de câte 5 urmate şi precedate de o singura cifră, cum putem observa
ı̂n imaginea de mai sus. Primele şase cifre, identifică ţara şi producătorul, ı̂n timp
ce următoarele cinci identifică produsul ı̂n sine, ultima cifra reprezentând cifra de
verificare.
Un UPC de 12 cifre (a1 , . . . , a12 ) este valid doar dacă suma
3a1 + a2 + 3a3 + a4 + · · · + 3a11 + a12
este divizibilă cu 10. Codul de bare de mai sus este 0 13241 54321 2. Aşadar, suma
codului este
3 · 0 + 1 + 3 · 3 + 2 + 3 · 4 + 1 + 3 · 5 + 4 + 3 · 3 + 2 + 3 · 1 + 2 = 60.
Suma este ı̂ntr-adevăr divizibilă cu 10, deci codul este recunoscut ca fiind un cod
de bare valid.
Ca şi la codul USPS, avem destule informaţii doar din primele 11 cifre, pentru
a determina, unic, cifra de verificare. Spre exemplu, fie codul UPC de mai sus, cu
cifra de verificare x, atunci
3 · 0 + 1 + 3 · 3 + 2 + 3 · 4 + 1 + 3 · 5 + 4 + 3 · 3 + 2 + 3 · 1 + x = 58 + x,
ceea ce face ca x = 2.
c) Codul ISBN
Înainte de anul 2009, cărţile erau identificate printr-un cod de zece cifre, pres-
curtat ISBN-10. Spre exemplu, cartea 1984, publicată de George Orwell, are ca
18
ISBN-10 numărul 0-451-52493-5. Prima cifră reprezintă limba ı̂n care este scrisă
cartea, următorul bloc de cifre identifică scriitorul, al doilea bloc de cifre reprezintă
cartea ı̂n sine, iar ultima cifră este cifra de verificare. În această schema, o cifră
poate fi 0, . . . , 9 sau X, care reprezintă numărul 10. Un cod (a1 , . . . , a10 ) este un
ISBN-10 valid, dacă suma
10a1 + 9a2 + · · · + 2a9 + a10
este divizibilă cu 11. Pentru codul de mai sus, avem
10 · 0 + 9 · 4 + 8 · 5 + 7 · 1 + 6 · 5 + 5 · 2 + 4 · 4 + 3 · 9 + 2 · 3 + 5 = 11 · 17 = 187
deci codul este ı̂ntr-adevăr valid.
Ca şi cu celelalte două exemple, cifra de verificare poate fi descoperită unic,
ţinând cont că este ı̂ntre 0 şi 10. Urmând exemplul de mai sus am avea suma
10 · 0 + 9 · 4 + 8 · 5 + 7 · 1 + 6 · 5 + 5 · 2 + 4 · 4 + 3 · 9 + 2 · 3 + x = 182 + x,
unde 182 + x trebuie să fie strict divizibil cu 11. Deoarece ştim că 11 · 16 = 176,
următorul număr divizibil cu 11 este 187, de unde aflăm că x = 5.
2. Detecţia erorilor
Cifra de verificare nu furnizează informaţii despre identificare; ea este redun-
dantă. Scopul acestei redundanţe ı̂ntr-un număr de identificare este de a detecta
erori ı̂n citirea numărului. Iniţial avem nevoie de o noţiune familiară a produsului
scalar de vectori din Rn ; dacă a = (a1 , . . . , an ) şi b = (b1 , . . . , bn ) sunt n-upluri de
numere reale, fie
Xn
a·b= ai bi = a1 b1 + · · · + an bn .
i=1
Testul pentru validitate ı̂n cele trei scheme este aşadar reprezentat ı̂n termeni de
produs. Un număr de zece cifre, sau mai precis, un 10-uplu a (a ∈ Z10 ) de cifre, este
un cod poştal valid, dacă a · (1, 1, 1, 1, 1, 1, 1, 1, 1, 1) este divizibil cu 10. Deaseme-
nea un UPC este un 12-uplu a de cifre cum ar fi a · (3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1)
dacă este divizibil cu 10. În final, un 10-uplu a este un ISBN-10 valid dacă
a · (10, 9, 8, 7, 6, 5, 4, 3, 2, 1) este divizibil cu 11. Să presupunem că avem un n-uplu
w(denumit şi pondere) ce conţine numere ı̂ntregi pozitive şi fie m ∈ Z+ . Putem
face o schemă cu număr de identificare după cum urmează. Considerăm n-upluri
a = (a1 , . . . , an ) unde 0 ≤ ai ≤ m − 1. Deci a este un număr de identificare valid
dacă a · w = 0 mod n. Ne vom referi la această schemă ca schema cu număr de
identificare cu ponderea w şi ı̂ntregul m. Motivul pentru restricţia pe ai este că ai
şi ai+m sunt egale modulo m. Aşadar, schema nu poate detecta diferenţa dintre
aceste două numere. Pentru a elimina această problemă, trebuie să limităm posi-
bilităţile lui ai astfel ı̂ncât două posibilităţi ale lui ai să poată fi distinse de schemă;
aşadar, oricare două posibilităţi trebuie să fie distincte modulo m.
Propoziţia 2.1. Fie w si m ca mai sus. Atunci, orice eroare din citirea poziţiei i
din a poate fi detectată dacă fiecare wi este relativ prim cu m.
Coduri liniare
1. Noţiuni de bază
Pentru a discuta despre codurile de corectare a erorilor, trebuie mai ı̂ntâi să
fixăm contextul şi să definim nişte termeni. Vom lucra peste tot ı̂n sistemul binar,
adică ı̂n Z2 . Pentru simplificarea notaţiilor, notăm elementele lui Z2 ca 0 si 1 ı̂n loc
de 0 şi 1. Dacă n ∈ Z+ , atunci mulţimea Zn2 este mulţimea n-uplurilor cu elemente
din Z2 . Elementele din Zn2 se numesc cuvinte (de lungime n). Pentru convenienţă
vom scrie elementele din Zn2 cu notaţia uzuală sau ca o concatenare de cifre. Spre
exemplu, scriem (0, 1, 0, 1) şi 0101 pentru acelaşi 4-uplu. Îi putem adăuga lui Zn2
operaţia de adunare, element cu element şi aşa definim
(a1 , . . . , an ) + (b1 , . . . , bn ) = (a1 + b1 , . . . , an + bn )
O consecinţă a faptului că ı̂n Z2 avem 0 + 0 = 0 = 1 + 1, este că a + a = 0 pentru
oricare a ∈ Zn2 , unde 0 este vectorul (0, . . . , 0) ce conţine toate zerourile.
Definiţia 3.1. Un cod liniar de lungime n este o submulţime nevidă din Zn2 care
este ı̂nchisă faţă de adunarea ı̂n Zn2 .
Chiar dacă există coduri neliniare şi sunt studiate, codurile liniare sunt folosite
mai frecvent ı̂n aplicaţii. Pentru importanţa lor, vom considera numai codurile
liniare de acum ı̂ncolo. Ne vom referi la elementele unui cod ca fiind cuvinte cod.
Exemplul 3.2. Mulţimea {000, 001, 010, 100, 110, 101, 011, 111} = Z32 este un cod
de lungime 3 şi mulţimea {00000, 10101, 01010, 11111} este o submulţime a lui Z52
21
şi de asemenea un cod de lungime 5. Dacă mulţimea de mai sus ar fi schimbată ı̂n
{00000, 10101, 01110, 11111}, aceasta nu ar mai reprezenta şi un cod.
Fie w = a1 . . . an un cuvânt de lungime n. Atunci ponderea lui w este numărul
de cifre din w egale cu 1. Notăm ponderea lui w cu ρ(w). O cale echivalentă şi folos-
itoare pentru a ne gândi la ponderea cuvântului w = a1 . . . an este să considerăm
elementele ai ca ı̂ntregi 0 şi 1 şi să ţinem cont că
n
X
ρ(w) = ai
i=1
Există câteva consecinţe evidente ı̂n urma acestei definiţii. În primul rând, ρ(w) = 0
dacă şi numai dacă w = 0. În al doilea rând, ρ(w) ∈ Z+ . Un lucru important de
ştiut, despre pondere, este relaţia sa cu adunarea. Dacă v, w ∈ Zn2 , atunci
ρ(v + w) ≤ ρ(v) + ρ(w).
Asta este adevărat pentru că pe poziţia i, elementele din v şi w pot fi ambele egale
cu 1 sau 0. Mai precis, scriem xi pentru elementul cu poziţia i a unui cuvânt x.
Aşadar, ponderea lui x este dată de ecuaţia
ρ(x) = |{i : 1 ≤ i ≤ n, xi = 1}|.
Ţinem cont că (v + w)i = vi + wi , astfel ı̂ncât (v + w)i = 1 implică ori vi = 1 ori
wi = 1(dar nu amândouă). Deci,
|{i : 1 ≤ i ≤ n, (v + w)i = 1}| ⊆ |{i : vi = 1}| + |{i : wi = 1}|.
Deoarece |A ∪ B| ≤ |A| + |B| pentru oricare două mulţimi finite A şi B, din incluz-
iunea de mai sus şi descrierea ponderei rezultă că ρ(v + w) ≤ ρ(v) + ρ(w), cum ne
doream. Ideea de pondere ne oferă noţiunea de distanţă ı̂n Zn2 . Dacă v şi w sunt
cuvinte, atunci definim distanţa D(v, w) dintre v şi w ca
D(v, w) = ρ(v + w).
Exemplul 3.3. Fie v = 01101100 şi w = 10010110 două cuvinte din Z82 , atunci
distanţa dintre ele este dată de relaţia
D(v, w) = ρ(v + w)
= ρ(01101100 + 10010110)
= ρ(11111010)
= 1+1+1+1+1+0+1+0=6
Alternativ, D(v, w) este egal cu numărul de poziţii ı̂n care v şi w diferă. Funcţia
D are aceleaşi proprietăţi de bază a distanţei ı̂n spaţiul euclidian. Mai precis,
satisface proprietăţile următoarei leme.
Lema 3.4. Funcţia distanţă D, definită pe Zn2 × Zn2 cu valori ı̂n R satisface
următoarele proprietăţi:
(1) D(v, w) = 0 pentru oricare v ∈ Zn2 ;
(2) Fie v, w ∈ Zn2 ; dacă D(v, w) = 0, atunci v = w;
(3) D(v, w) = D(w, v) pentru oricare v, w ∈ Zn2 ;
(4) D(v, w) ≤ D(v, u) + D(u, w), pentru oricare u, v, w ∈ Zn2 .
Demonstratie. (1) Deoarece v + v = 0, avem
D(v, v) = ρ(v + v) = ρ(0) = 0.
22
(2) Ţinem cont că 0 este singurul cuvânt de pondere 0. Aşadar, dacă D(v, w) =
0, atunci ρ(v + w) = 0, ce ı̂nseamnă că v + w = 0. Dar, adunând w ı̂n
ambele părţi, obţinem că v = w.
(3) Egalitatea D(v, w) = D(w, v) este evidentă pentru că v + w = w + v.
(4) Fie u, v, w ∈ Zn2 , avem, din definiţie şi ponderea unei sume de mai sus,
D(v, w) = ρ(v, w) = ρ((v + u) + (u + w))
≤ ρ(v + u) + ρ(u + v)
= D(v, u) + D(u, w)
Pentru a discuta corectarea erorilor, trebuie mai ı̂ntâi să formalizăm noţiunea.
Fie C un cod: dacă w este un cuvânt, pentru a-l corecta sau decoda, ı̂nseamnă să
selectăm un cuvânt cod v ∈ C astfel ı̂ncât
D(v, w) = min{D(u, w) : u ∈ C}.
Cu alte cuvinte ı̂l decodăm pe w alegând cel mai apropiat cuvânt cod de w, sub
noţiunea noastră de distanţă. Totuşi, cel mai apropiat cuvânt cod nu trebuie sa
fie unic. Când se ı̂ntâmplă asta, fie putem alege aleator cel mai apropiat cuvânt
cod fie nu facem nimic. Ne referim la această noţiune de decodare ca fiind cea mai
probabilă detecţie sau MLD(Maximum Likelihood Detection), presupunerea fiind
că metoda de transmisie a informaţiei este sigură deci dacă o eroare este introdusă,
informaţia corectă este cel mai probabil să fie cuvântul cod care diferă de cuvântul
primit, ı̂n cele mai puţine poziţii.
Definiţia 3.5. Fie C un cod şi fie t ∈ Z+ . Atunci, C este un cod de corectare a t
erori, oricând un cuvânt w diferă de cel mai apropiat cuvânt cod v de o distanţă
cel mult t, atunci v este cel mai apropiat cuvânt cod unic pentru w.
Dacă un cuvânt cod v este transmis şi primit ca w, putem exprima w ca fiind
v + u şi spunem că u = v + w este eroarea ı̂n transmisie. Ca şi cuvânt, eroarea u
are o anumită pondere. Deci C este cod de corectare a t erori dacă pentru fiecare
cuvânt cod v şi fiecare cuvânt u al cărui pondere este cel mult t, atunci v este cel
mai apropiat cuvânt cod unic de v + u.
Aşadar o cale să interpretăm definiţia este că dacă v ar fi un cuvânt cod, şi
dacă w ar fi obţinut prin schimbarea a cel mult t valori din v, atunci v este cel mai
apropiat cuvânt cod de w. Aşadar, prin decodarea MLD, w va fi decodat ca fiind
v.
Definiţia 3.6. Distanţa d a unui cod C este definită astfel
d = min{D(u, v) : u, v ∈ C, u 6= v}.
Din motive intuitive, ar fi mai folositor să ne gândim la cea mai mică distanţă
ca fiind diametrul celui mai mic cerc care să conţină cel puţin două cuvinte cod.
Notăm cu bac cel mai mare număr ı̂ntreg mai mic sau egal cu a.
d−1
Propoziţia 3.7. Fie C un cod de distanţă d şi fixăm t = b c. Atunci C este
2
un cod de corectare a t, erori dar nu un cod de corectare a t + 1 erori.
Demonstratie. Pentru a demonstra prima parte, fie w un cuvânt şi presupunem
că v este un cuvânt cod cu D(v, w) ≤ t. Trebuie să arătăm că v este cel mai
apropiat cuvânt cod unic de w. Astfel demonstrăm că D(u, w) > t pentru oricare
23
cuvânt cod u 6= v. Dacă nu, presupunem că u este un cuvânt cod cu u 6= v şi
D(u, w) ≤ t. Apoi, din inegalitatea triunghiului,
D(u, v) ≤ D(u, w) + D(w, v) ≤ t + t = 2t < d.
Asta fiind o contradicţie a definiţiei lui d. Aşadar, v este ı̂ntr-adevăr cel mai
apropiat cuvânt cod unic de w.
u1
•
t •
w
•u
2
În continuare, trebuie să arătăm că C nu corectează t + 1 erori. Deoarece codul
are distanţa d, există cuvinte cod u1 , u2 cu d = D(u1 , u2 ); cu alte cuvinte, u1 şi u2
diferă ı̂n exact d poziţii. Fie w un cuvânt cod obţinut, prin schimbarea a t + 1 din
acele d poziţii, din u1 . Avem D(u1 , w) = t + 1 şi D(u2 , w) = d − (t + 1). Deoarece
d−1
t=b c prin presupunerea noastră,
2
d−2 d−1
≤t≤ .
2 2
În particular, d − 2 ≤ 2t astfel ı̂ncât
D(u2 , w) = d − (t + 1) < t + 1.
Aşadar u1 nu este cel mai apropiat cuvânt cod unic de w, deoarece u2 este ı̂n egală
măsură sau mai aproape de w. Deci C nu este un cod de corectare a (t + 1) erori.
t−1
• • •
u1 w u2
2. Coduri liniare
Un cod liniar este un cod C, ca o submulţime din Zn2 , este un subspaţiu din
Zn2 .Vom spune că un cod C(n, k, d) este un cod de lungime n, de dimensiune k,
iar distanţa sa este d.
24
Exemplul 3.8. Dacă A este o matrice m × n peste Z2 , atunci nucleul lui A este
un cod liniar de lungime n, ı̂ntrucât ştim că nucleul unei matrici este ı̂ntotdeauna
un spaţiu vectorial.
Lema 3.9. Dacă C este un cod liniar cu distanţa d, atunci
d = min{ρ(v) : v ∈ C, v 6= 0}.
Demonstratie. Fie e = min{ρ(v) : v ∈ C, v 6= 0}. Fie un vector nenul u ∈ C
putem scrie e = ρ(u). Apoi e = D(v, 0), deoarece 0 ∈ C, observăm că d ≤ e prin
definiţia lui d.
Invers, dacă avem doi vectori distincţi v, w ∈ C, putem scrie d = D(v, w). Apoi
d = ρ(v +w), deoarece C este un cod liniar, v +w ∈ C şi v +w 6= 0 pentru că v 6= w.
Aşadar, prin definiţia lui e, observăm că e ≤ d, deci, d = e, cum ne doream.
Propoziţia 3.10. Fie G ∈ Mk,n (Z2 ) de rang k şi C = {vG : v ∈ Zk2 }. Fie d
distanţa lui C. Atunci C este un cod liniar (n, k, d) şi G este matricea generatoare
pentru C.
Demonstratie. Ştim din ı̂nmulţirea matricilor că dacă v = (a1 , . . . , ak ) ∈ Zk2 şi
r1 , . . . , rk sunt cele k linii ale lui G, atunci
X
vG = ai ri .
i
În plus, această ecuaţie arată că orice combinaţie liniară de linii din G poate fi
scrisă sub forma vG. Deci, C este generat de liniile lui G astfel ı̂ncât C este un
subspaţiu din Zn2 . Mai mult, deoarece liniile lui G sunt liniar independente, ele
formează o bază pentru C. Aşadar, C are dimensiunea k şi, dacă d este distanţa
lui C, atunci C este un cod (n, k, d). Prin construcţie, G este matricea generatoare
pentru C.
Teorema 3.11. Fie C un cod liniar (n, k, d) cu matricea generatoare G. Atunci
C = {vG : v ∈ Zk2 }.
În continuare discutăm despre un cod de lungime 24, folosit de NASA ı̂n anii
’70 şi ’80 pentru a transmite imagini cu Jupiter si Saturn, fotografiate de naveta
Voyager. Acest cod, numit codul Golay extins, este mulţimea de soluţii a ecuaţiei
cu matrici Hxt = 0, unde H este matricea 12×24, H = [I|B], iar partea din stânga
este matricea identitate 12 × 12, iar partea din dreapta este matricea 12 × 12
1 1 0 1 1 1 0 0 0 1 0 1
1 0 1 1 1 0 0 0 1 0 1 1
0 1 1 1 0 0 0 1 0 1 1 1
1 1 1 0 0 0 1 0 1 1 0 1
1 1 0 0 0 1 0 1 1 0 1 1
1 0 0 0 1 0 1 1 0 1 1 1
B= .
0 0 0 1 0 1 1 0 1 1 1 1
0 0 1 0 1 1 0 1 1 1 0 1
0 1 0 1 1 0 1 1 1 0 0 1
1 0 1 1 0 1 1 1 0 0 0 1
0 1 1 0 1 1 1 0 0 0 1 1
1 1 1 1 1 1 1 1 1 1 1 0
Fotografiile erau făcute folosind 4096 de culori. Fiecare culoare era codată
cu un cuvânt cod din codul Golay. Prin rezolvarea ecuaţiei cu matrici Hxt = 0,
putem observa clar că sunt 4096 de cuvinte cod. În plus, o verificare anostă a
fiecărui cuvânt cod arată că distanţa codului Golay este d = 8. Aşadar, codul
poate corecta până la b(8 − 1)/3c = 3 erori, prin urmare până la 3 din 24 de cifre
ale unui cuvânt cod pot fi corupte, iar informaţia originală tot poate fi regăsită.
Pentru că acest cod poate corecta mai mult de o eroare, orice procedură de
decodare este, fără o ı̂ndoială, mai complicată decât pentru codul Hamming.
Pentru a lucra mai convenabil cu acest cod, scriem un cuvânt u = (u1 , u2 ),
unde u1 constă ı̂n primele 12 cifre, iar u2 ı̂n ultimele 12 cifre.
28
Deoarece H = [I|B], observăm că u ∈ C dacă şi numai dacă Hut = 0 şi este
adevărat dacă şi numai dacă ut1 + But2 = 0. Pentru un cuvânt w, următorii paşi
sunt folosiţi pentru a-l decoda. Notăm cu v cuvântul cod obţinut din w. Ca de
obicei, ei reprezintă 12-uplul cu cifra 1 pe poziţia i şi 0 pe restul, ı̂n timp ce bi
reprezintă linia i a matricii B.
(1) Calculăm st = Hwt . Dacă st = 0, atunci w este un cuvânt cod.
(2) Dacă 1 ≤ ρ(s) ≤ 3, atunci v = w + (s, 0).
(3) Dacă există i astfel ı̂ncât ρ(s) > 3 şi ρ(s+bi ) ≤ 2, atunci v = w+(s+bi , ei ).
(4) Dacă nu am determinat v ı̂ncă, calculăm sB, care este egal cu (Bst )t prin
simetria lui B.
(5) Dacă 1 ≤ ρ(sB) ≤ 3, atunci v = w + (0, sB).
(6) Dacă există i astfel ı̂ncât ρ(sB) > 3 şi ρ(sB + bi ) ≤ 2, atunci v = w +
(ei , sB + bi ).
(7) Dacă nu am găsit v până acum, atunci w nu poate fi decodat.
29
CAPITOLUL 4
Coduri Hamming
Fie x ∈ Znq , |S0 (x) = 1|, acel 1 fiind doar x. Există (q −1) căi de a schimba orice
coordonată x şi a obţine un nou cuvânt codşi n posibile coordonate de schimbat,
n
prin urmare |S1 (x)| = 1 + n(q − 1). Există căi de a alege două coordonate
2
să se schimbe şi (q − 1)2 căi pentru a le schimba pe ele, deci
n
|S2 (x)| = 1 + n(q − 1) + (q − 1)2 .
2
Din
T discuţia precedentă, un cod este un corector de t erori, dacă şi numai dacă
St (x) St (y) = ∅, oricând x 6= y. Aşadar, dacă C este un cod corector de t erori,
|C| · |St (x)| ≤ |Zq |n , pentru orice x, deoarece cardinalul unei sfere nu depinde de
alegerea lui x.
Definiţia 4.3. Un cod corector de t erori se numeşte perfect dacă
sau dacă
t
n
X n
|C| = |Zq | / (q − 1)i
i
i=0
33
Termenul din dreapta egalului este egal cu q n , unde n = (q r − 1)/(q − 1). Partea
din stânga este
(q r − 1)
n−r n−r
q (1 + n(q − 1)) = q 1+ (q − 1)
(q − 1)
= q n−r (1 + (q r − 1))
= q n−r (q r )
= qn .
Deci, codurile Hamming sunt coduri perfecte de corectare a unei erori.
n n
Definiţia 4.5. Un cod de acoperire t este un cod C ⊂ A pentru care A =
S
{St (x)|x ∈ C}.
Propoziţia 4.6. Dacă C este un cod de acoperire t, atunci |C| · |St (x)| ≥ |Zq |n .
Definiţia 4.7. Dacă există egalitate ı̂n ultima propoziţie, atunci C se numeşte cod
de acoperire t, perfect.
Desigur, codurile de corectare a t erori, coincid cu cele de acoperire t. De
asemenea, este cunoscut că singurele coduri perfecte de corectare a unei erori, sunt
codurile Hamming. Astfel de coduri sunt foarte utile deoarece procesul de decodare
va obţine ı̂ntotdeauna un cuvânt cod.
34
CAPITOLUL 5
Aplicaţii
În capitolul următor vom construi un program pe baza C/C++, ce poate de-
coda cele cinci tipuri de coduri despre care am vorbit ı̂n capitolele anterioare: USPS
Postal Code, The Universal Product Code, ISBN-10, Codul Golay şi Codul Ham-
ming. Programul este scris având la bază funcţia switch, ce permite alegerea tipului
de decodare la rularea programului.
#include <iostream>
int main()
{
int sa=0,sb=0,sc=0;
int a[10],b[12],c[10];
int i,x,j;
int B[12][12];
int H[12][24];
int w[24],s[12],s0=0,sbi[12],sbi0=0,w0=0;
int ei[12],sB[12],sB0=0,sBbi[12],sBbi0=0;
int Hamm[3][7]={{0,0,0,1,1,1,1},{0,1,1,0,0,1,1},{1,0,1,0,1,0,1}};
int y[7],Hw[3],e[7],Hw0=0;
cout<<"Alegeti un tip de cod de decodat:"<<endl;
cout<<"1.USPS Postal Code"<<endl;
cout<<"2.The Universal Product Code"<<endl;
cout<<"3.ISBN-10"<<endl;
cout<<"4.Codul Golay"<<endl;
cout<<"5.Codul Hamming"<<endl;
cout<<"Optiunea aleasa este: ";
cin>>x;
35
switch(x)
{
case 1: Programul de decodare pentru USPS Postal Code
case 2: Programul de decodare pentru The Universal Product Code
case 3: Programul de decodare pentru ISBN-10
case 4: Programul de decodare pentru Codul Golay
case 5: Programul de decodare pentru Codul Hamming
}
}
În prima parte a programului, se declara variabilele ce vor urma să fie folosite
imediat şi ţinem cont că matricile H şi B, ce reprezintă matricile de la Codul Golay,
sunt iniţializate complet ı̂n cadrul programului dar au fost scrise restrâns din punct
de vedere estetic.
Fiecare opţiune de case din switch se ocupă ı̂n parte de fiecare cod, iar ı̂n cele
ce urmează le vom discuta pe rând.
case 2:
cout<<"Introduceti codul de 12 cifre:"<<endl;
for(i=0;i<12;i++)
cin>>b[i];
for(i=0;i<12;i++)
{
if(i%2==0)
sb=sb+3*b[i];
else
sb=sb+b[i];
}
if(sb%10==0)
cout<<"Codul introdus este valid";
else
cout<<"Codul introdus nu este valid";
break;
37
Introducerea unui cod valid, 0-13241-54321-2, ı̂n urma algoritmului, afişează
mesajul dorit.
3. ISBN-10
Codul ISBN-10, ce se află pe spatele fiecărei cărţi şi cu care putem identifica,
unic, fiecare carte ı̂n parte, este un cod de 10 cifre (a1 , . . . , a10 ) şi este valid dacă
suma
este divizibilă cu 11, unde a1 , . . . , a10 pot avea următoarele valori 1, . . . , 9, X, iar
X reprezintă numărul 10.
Algoritmul decodării unui ISBN-10 este următorul:
case 3:
cout<<"Introduceti codul de 10 cifre:"<<endl;
for(i=0;i<10;i++)
cin>>c[i];
for(i=0;i<10;i++)
{
for(j=10;j>0;j--)
{
sc=sc+j*c[i];
}
}
if(sc%11==0)
cout<<"Codul introdus este valid";
else
cout<<"Codul introdus nu este valid";
break;
38
Am furnizat ISBN-ul cărţii din exemplul de mai sus pentru a fi sigur că algo-
ritmul programului funcţionează.
4. Codul Golay
Pentru o mai uşoară ı̂ntelegere a programului, ne vom aduce aminte despre
algoritmul folosit la decodarea codului Golay, acesta fiind:
(1) Calculăm st = Hwt . Dacă st = 0, atunci w este un cuvânt cod.
(2) Dacă 1 ≤ ρ(s) ≤ 3, atunci v = w + (s, 0).
(3) Dacă există i astfel ı̂ncât ρ(s) > 3 şi ρ(s+bi ) ≤ 2, atunci v = w+(s+bi , ei ).
(4) Dacă nu am determinat v ı̂ncă, calculăm sB, care este egal cu (Bst )t prin
simetria lui B.
(5) Dacă 1 ≤ ρ(sB) ≤ 3, atunci v = w + (0, sB).
(6) Dacă există i astfel ı̂ncât ρ(sB) > 3 şi ρ(sB + bi ) ≤ 2, atunci v = w +
(ei , sB + bi ).
(7) Dacă nu am găsit v până acum, atunci w nu poate fi decodat.
În prima secţiune de program, iniţializăm codul nostru, calculăm st = Hwt şi ı̂n
acelaşi timp când facem schimbarea ı̂n baza 2 a lui s, ı̂i calculăm şi ponderea de
fiecare dată când ı̂ntâmpinăm un element egal cu 1, pentru a rezolva pasul 1.
case 4:
cout<<"Se va lucra numai in baza 2, introduceti codul de 24 cifre: "<<endl;
for(i=0;i<24;i++)
cin>>w[i];
cout<<endl<<"Codul dumneavoastra este: ";
for(i=0;i<24;i++)
{
if(w[i]%2==0)
w[i]=0;
else
w[i]=1;
cout<<w[i];
}
39
for(i=0;i<12;i++)
for(j=0;j<24;j++)
{
s[i]=s[i]+H[i][j]*w[j];
}
/*Pasul 1*/
for(i=0;i<12;i++)
{
if(s[i]%2==0)
s[i]=0;
else
{
s[i]=1;
s0++;
}
}
if(s0==0)
{
cout<<"Codul introdus este un cuvant cod valid."<<endl<<endl;
break;
}
În cea de-a doua secţiune de program, verificăm dacă ponderea lui s, adică ρ(s),
are valoarea cuprinsă ı̂ntre 1 şi 3, iar dacă este adevărat, urmează decodarea lui w
ca fiind v = w + (s, 0).
/*Pasul 2*/
if(1<=s0 && s0<=3)
{
for(i=0;i<24;i++)
{
if(i<12)
w[i]=w[i]+s[i];
if(w[i]%2==0)
w[i]=0;
else
w[i]=1;
}
cout<<endl<<"Cuvantul cod decodat la pasul 2 este: ";
for(i=0;i<24;i++)
cout<<w[i];
cout<<endl<<endl;
break;
}
Pentru următorul pas, căutăm o linie din B astfel ı̂ncât ρ(s + bi ) ≤ 2, iar dacă
am găsit o linie care să ı̂ndeplinească inegalitatea, atunci decodăm w ca fiind v =
w + (s + bi , ei ).
/*Pasul 3*/
for(i=0;i<12;i++)
{
40
for(j=0;j<12;j++)
{
sbi[j]=s[j]+B[i][j];
if(sbi[j]%2==0)
sbi[j]=0;
else
{
sbi[j]=1;
sbi0++;
}
}
if(sbi0<=2)
{
for(j=0;j<12;j++)
{
if(j==i)
ei[j]=1;
else
ei[j]=0;
}
for(j=0;j<24;j++)
{
if(j<12)
w[j]=w[j]+sbi[j];
else
w[j]=w[j]+ei[j-12];
if(w[j]%2==0)
w[j]=0;
else
w[j]=1;
}
cout<<"Cuvantul cod decodat la pasul 3 este: ";
for(j=0;j<24;j++)
cout<<w[j];
cout<<endl<<endl;
break;
}
}
În continuare, pentru paşii 4 şi 5, calculăm vectorul sB şi de asemenea, când ı̂l
trecem ı̂n baza 2, ı̂i calculăm şi ponderea, care, evident, dacă este cuprinsă ı̂ntre 1
şi 3, obţinem codul decodat v = w + (0, sB).
/*Pasul 4-5*/
for(i=0;i<12;i++)
{
for(j=0;j<12;j++)
{
sB[i]=sB[i]+s[j]*B[j][i];
41
}
if(sB[i]%2==0)
sB[i]=0;
else
{
sB[i]=1;
sB0++;
}
}
if(1<=sB0 && sB0<=3)
{
for(i=0;i<24;i++)
{
if(i>11)
w[i]=w[i]+sB[i-12];
if(w[i]%2==0)
w[i]=0;
else
w[i]=1;
}
cout<<"Cuvantul cod decodat la pasul 5 este: ";
for(i=0;i<24;i++)
cout<<w[i];
cout<<endl<<endl;
break;
}
În secţiunea următoare, din nou căutăm o linie din matricea B care să ı̂ndeplinească
condiţia ρ(sB + bi ) ≤ 2, pentru a putea decoda v = w + (ei , sB + bi ).
În cazul ı̂n care, ı̂n niciunul dintre paşii anteriori, codul nu a putut fi decodat,
programul va returna un mesaj ce indică eşuarea decodării lui w.
/*Pasul 6*/
if(sB0>3)
{
for(i=0;i<12;i++)
{
for(j=0;j<12;j++)
{
sBbi[j]=sB[j]+B[i][j];
if(sBbi[j]%2==0)
sBbi[j]=0;
else
{
sBbi[j]=1;
sBbi0++;
}
}
42
if(sBbi0<=2)
{
for(j=0;j<12;j++)
{
if(j==i)
ei[j]=1;
else
ei[j]=0;
}
for(j=0;j<24;j++)
{
if(j<12)
w[j]=w[j]+ei[j];
else
w[j]=w[j]+sBbi[j-12];
if(w[j]%2==0)
w[j]=0;
else
w[j]=1;
}
cout<<"Cuvantul cod decodat la pasul 6 este: ";
for(j=0;j<24;j++)
cout<<w[j];
cout<<endl<<endl;
break;
}
}
}
cout<<endl<<"Codul introdus nu poate fi decodat."<<endl<<endl;
break;
43
În primul exemplu am optat ca verificarea programului să constea ı̂n folosirea unui
cod valid din start, iar acesta a returnat mesajul de validitate.
Pentru cel de-al doilea exemplu am ales un cod invalid şi observăm cum decodarea
sa durează mai mult, deci ı̂i oferă mici dificultăţi programului, dar acesta este de-
codat de la pasul 2 ı̂mpreună cu afişarea codului corectat.
44
5. Codul Hamming
Un cod Hamming are următorul algoritm de decodare:
• Fie un cuvânt w dat, se calculeaza Hwt
• Dacă produsul este 0, atunci w este un cuvânt cod.
• Dacă produsul nu este 0, atunci este egal cu coloana i a lui H pentru
un ı̂ntreg unic i. Atunci w + ei este un cuvânt cod valid, şi este cel mai
apropiat cuvânt cod de w.
Se poate observa că ı̂n prima secţiune de program, după introducerea codului pe
care dorim să-l decodăm, calculăm vectorul Hwt , iar dacă ponderea sa este egală
cu 0, atunci ştim că am primit de la tastatură un cod valid.
case 5:
/*Pasul 1-2*/
cout<<"Introduceti codul de 7 cifre: "<<endl;
for(i=0;i<7;i++)
cin>>y[i];
cout<<"Codul dumneavoastra este: ";
for(i=0;i<7;i++)
{
if(y[i]%2==0)
y[i]=0;
else
y[i]=1;
cout<<y[i];
}
cout<<endl<<endl;
for(i=0;i<3;i++)
{
for(j=0;j<7;j++)
Hw[i]=Hw[i]+Hamm[i][j]*y[j];
if(Hw[i]%2==0)
Hw[i]=0;
else
{
Hw[i]=1;
Hw0++;
}
}
if(Hw0==0)
{
cout<<"Cuvantul cod introdus este valid.";
break;
}
45
Dacă ponderea vectorului Hwt , nu este egală cu 0, atunci ştim că vectorul calculat,
este egal cu una dintre coloanele lui H şi verificăm pe rând coloanele până când
condiţia este ı̂ndeplinită.
/*Pasul 3*/
for(i=0;i<7;i++)
{
if(Hw[0]==Hamm[0][i] && Hw[1]==Hamm[1][i] && Hw[2]==Hamm[2][i])
{
for(j=0;j<7;j++)
{
if(j==i)
e[j]=1;
else
e[j]=0;
}
for(j=0;j<7;j++)
{
y[j]=y[j]+e[j];
if(y[j]%2==0)
y[j]=0;
else
y[j]=1;
}
cout<<"Eroarea se afla pe pozitia "<<i+1<<" din codul introdus, ";
cout<<"iar cuvantul cod decodat este: ";
for(j=0;j<7;j++)
cout<<y[j];
cout<<endl<<endl;
}
}
46
De asemenea, ca la exemplul codului Golay, şi aici pentru o verificare uşoară
a funcţionării programului, am ales un cod deja valid, adică 0111100, pentru a
observa ce va returna programul.
Cum ştim că exemplul anterior a returnat un cod valid, am ales să schimb
a patra cifră din cod, deci din 0111100 l-am schimbat ı̂n 0110100, iar programul
anunţă poziţia corectă pe care s-a efectuat eroare şi imediat după, codul decodat.
47
Concluzie
49
Bibliografie
51