Professional Documents
Culture Documents
ESSI-Transmissions Numriques
Page 1 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Sommaire :
Introduction I. Codes convolutionnels, codage des donnes : II. Algorithme de Viterbi : Conclusion Annexe : code source
Introduction :
Nous avons vu quun signal peut tre altr par un canal de transmission numrique. Cependant, nous aimerions tre capable de reconstituer ce signal la rception, malgr les altrations possibles. Le principe pour pouvoir dtecter, voir mme corriger de telles erreurs, est de rajouter une information supplmentaire dans le message transmettre. Il existe diverses mthodes pour parvenir cet objectif, des plus simples (rajout dun bit de parit) aux plus labores (turbocodes). Ici, nous allons tudier une de ces mthodes : lalgorithme de Viterbi.
Page 2 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
I.
Il faut coder les donnes envoyer dune manire bien prcise pour pouvoir leurs appliquer lalgorithme de Viterbi. Le principe des codes convolutionnels est le suivant : chacune des donnes binaires mettre est remplace par de nouvelles donnes. Le codage des donnes est ralis par un automate.
0/11
1/01
10
0/01
automate de codage des donnes
11 1/10
Lorsquon dmarre le codage des donnes, on se trouve dans ltat 00. Ensuite, on lit le premier bit du message : si on lit un 0, on crit 00 et on va dans ltat 00; si on lit un 1, on crit 11 et on va dans ltat 01. On procde de mme pour le bit suivant en partant de ltat obtenu par le codage du bit prcdant, et ainsi de suite. A la fin, on obtient le message cod : celui-ci fait deux fois la longueur du message original. Cest ce message cod que lon va mettre.
Page 3 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Voici un exemple de fonctionnement de lautomate sur le message s = 110100 : -on part de 00, on lit s(0) = 1, on crit 11 et on va en 01 -on lit s(1) = 1, on crit 01 et on va en 11 -on lit s(2) = 0, on crit 01 et on va en 10 -on lit s(3) = 1, on crit 00 et on va en 01 -on lit s(4) = 0, on crit 10 et on va en 10 -on lit s(5) = 0, on crit 11 et on va en 00 Le message final aprs codage est donc 110101001011.
0/00
1
00
6 5
01
0/11
1/01
10
0/01
3
11 1/10
On peut voir le droulement de lopration de codage sur le schma ci-dessus : les flches rouges montrent les diffrentes tapes de ce codage.
Page 4 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Page 5 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Exemple de treillis
11
10
01
1/1 1
00
0/00
tat
E=1 E=0
0/1 0
1/11 1/00
t
Le schma ci-dessus est un exemple de treillis. On est parti du message 101101. Le code obtenu aprs passage dans lautomate est 111000010100. A la rception, on suppose que le message est 001000010100 (erreur sur les deux premiers bits). On peut visualiser grce ce treillis le cheminement effectu par lalgorithme de Viterbi pour tenter de retrouver la squence qui a t mise. Au final, on prend le chemin qui a la plus petite distance de Hamming.
Page 6 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Nous avons fait des tests pour voir quelle tait lefficacit de lalgorithme de Viterbi. Pour cela, nous gnrons un message de manire alatoire et nous le codons grce lautomate. Ensuite, on lui rajoute des erreurs, avec une probabilit p davoir une erreur sur chaque bit du message cod. On applique lalgorithme de Viterbi ce message erron et on compare le rsultat avec le message initial : on regarde le pourcentage derreur restant. On procde ainsi un nombre lev de fois pour une mme probabilit p. Ensuite, on change p et on recommence.
Pourcentage d'erreurs
7 6
% d'erreurs aprs correction
5 4 3 2 1 0 0 2 4 6 8 10
% d'erreurs avant correction
Ce graphique montre le rsultat de nos tests. Nous avons commenc avec un p = 0 et effectu 100 gnration de messages, puis nous avons augment p de 1 chaque fois. On peut remarquer que les points sont lgrement dcals par rapport aux valeurs demandes de p : cela est du au fait que la probabilit relle nest pas forcment exactement gale p car nous faisons appel au gnrateur de nombres alatoires de C. De plus, nous ne voyons pas tous les points car il y a souvent des superpositions (notamment pour p = 0, ce qui est normal car il ny a pas derreur). Il aurait t possible de faire une courbe de la moyenne du taux derreurs restant aprs correction, cependant, il aurait fallut faire un nombre de gnrations de message bien plus importants pour chaque valeur de p, et ce afin de compenser la dispersion entre la valeur demande de p et la valeur retourne par le gnrateur de nombre alatoire : il faut en effet sassurer que le nombre de tests fait pour un mme p est assez important pour obtenir
Page 7 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
une moyenne correcte. Cependant, on voit clairement sur notre courbe que lallure gnrale est en accord avec la thorie : nous pouvons donc supposer que notre algorithme de Viterbi fonctionne correctement.
Conclusion :
Nous avons vu grce ce projet comment il tait possible, laide dun algorithme, de corriger un message erron. Cependant, nous avons aussi pu voir quels taient les deux principaux inconvnients des mthodes de corrections derreurs. Premirement, la quantit dinformations transmettre augmente beaucoup (elle double dans le cas de Viterbi) ce qui rduit considrablement le dbit de transmission. De plus, les mthodes de codage et de dcodage de linformation ncessite une certaine puissance de calcul, ce qui peut poser certains problmes (par exemple dans des systmes embarqus o on dispose dun puissance de calcul limit, pourtant, il faut que le calcul se fasse en temps rel). Enfin, seuls des messages faibles pourcentages derreurs peuvent tre corrigs. Cest pourquoi beaucoup despoirs sont placs dans la techniques des turbocodes car on approche la limite donne par le deuxime thorme de Shannon. .
Page 8 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
Page 9 sur 14
Leberrigot-Bourgouin
ESSI-Transmissions Numriques
// calcule de la distance de hamming entre un etat // et le deux bits d'indice 2i et 2i+1 int distance(seq *s, int etat, int i); // decodela sequence a partir du tableau seq decode_seq(etat **tab, seq *s); // une fonction pour afficher une sequence void dispS(seq s); // une fonction pour afficher un tableau void dispT(etat **tab, seq *s); // une fonction pour afficher un etat void dispE(etat e); //--------------------------------------------------------------------------------------// une sequence aleatoire de nb_bits seq random_seq(int n_bits) { int i; seq s; s.nb_bits = n_bits; s.bits = (int *) malloc(sizeof(int) * n_bits); srandom(getpid() + ++calls); for(i = 0; i < n_bits; i++) s.bits[i] = random() % 2; return s; } // la sequence emettre seq emission(seq s) { int i, etatCourant = _00, c; seq es; es.nb_bits = 2 * s.nb_bits; es.bits = (int *) malloc(sizeof(int) * es.nb_bits); for (i = 0; i < s.nb_bits; i++) { c = code[etatCourant][s.bits[i]]; etatCourant = etatSuivant[etatCourant][s.bits[i]]; switch(c) { case _00: es.bits[2*i] = 0; es.bits[2*i+1] = 0; break; case _01: es.bits[2*i] = 0; es.bits[2*i+1] = 1; break; case _10: es.bits[2*i] = 1; es.bits[2*i+1] = 0; break; case _11: es.bits[2*i] = 1; es.bits[2*i+1] = 1; break; } } return es; }
Page 10 sur 14
Leberrigot-Bourgouin // la squence emmettre 's' entachee de p% d'erreurs seq erreurs(seq s, int p) { int i = 0, m = 1000, pm; seq err_seq; err_seq.nb_bits = s.nb_bits; err_seq.bits = (int *)malloc(sizeof(int) * err_seq.nb_bits); if (p > 100) { printf("Donnez une probabilit < 100\%\nvaleur prise par dfaut 50\%\n"); p = 50; } pm = p * m; srandom(getpid() + calls++); for (i = 0; i < s.nb_bits; i++) { if(random() % (100 * m) > pm) err_seq.bits[i] = s.bits[i]; else err_seq.bits[i] = !s.bits[i]; } return err_seq; } // calcul du pourcentage effectif d'erreurs double pourcent_err( seq *s1, seq *s2) { if (s1->nb_bits != s2->nb_bits) { return 0; } else { int i = 0; double p = 0; for (i = 0; i < s1->nb_bits; i++) { if(s1->bits[i] != s2->bits[i]) p++; } return (p / s1->nb_bits) * 100; } } // decodage a partir de la sequence s seq decode(seq *s) { etat *tab[4]; int i, j, t; t = s->nb_bits/2+1; for(i = 0; i < 4; i++) { tab[i] = (etat *) malloc(t * sizeof(etat)); for(j = 0; j < t; j++) { tab[i][j].dist = -1; tab[i][j].prec = -1; tab[i][j].val = -1; } } tab[_00][0].dist = 0; remplir(tab, s); return decode_seq(tab, s); } // rempli le tableau pour le decodage void remplir(etat **tab, seq *s) { int i, j, k, es, d, t; etat *e; t = s->nb_bits/2; for(i = 0; i < t; i++) { for(j = 0; j < 4; j++) {
ESSI-Transmissions Numriques
Page 11 sur 14
Leberrigot-Bourgouin if(tab[j][i].dist != -1) { for(k = 0; k < 2; k++) { es = etatSuivant[j][k]; e = &tab[etatSuivant[j][k]][i+1]; d = tab[j][i].dist + distance(s, code[j][k], i); // important if(e->dist == -1 || e->dist > d) { e->dist = d; e->prec = j; e->val = k; } } } } } } // calcule de la distance de hamming entre un etat // et le deux bits d'indice 2i et 2i+1 int distance(seq *s, int etat, int i) { int bit1, bit2, d = 0; bit1 = s->bits[2*i]; bit2 = s->bits[2*i+1]; switch(etat) { case _00: if (bit1 == 1) d++; if (bit2 == 1) d++; break; case _01: if (bit1 == 1) d++; if (bit2 == 0) d++; break; case _10: if (bit1 == 0) d++; if (bit2 == 1) d++; break; case _11: if (bit1 == 0) d++; if (bit2 == 0) d++; break; } return d; } // decodela sequence a partir du tableau seq decode_seq(etat **tab, seq *s) { seq dec_s; etat e; int i; dec_s.nb_bits = s->nb_bits/2; dec_s.bits = (int *) malloc(dec_s.nb_bits * sizeof(int)); e.dist = 120000; //TODO for(i = 0; i < 4; i++) { if(tab[i][dec_s.nb_bits].dist < e.dist) e = tab[i][dec_s.nb_bits]; } for(i = dec_s.nb_bits; i > 0; i--) { dec_s.bits[i-1] = e.val; e = tab[e.prec][i-1]; } return dec_s; } // une fonction pour afficher une sequence void dispS( seq s) { int i; for(i = 0; i < s.nb_bits; i++) printf("%d", s.bits[i]);
ESSI-Transmissions Numriques
Page 12 sur 14
Leberrigot-Bourgouin } // une fonction pour afficher un tableau void dispT(etat **tab, seq *s) { int i, j; for(i = 0; i < s->nb_bits/2+1; i++) { printf("{"); for (j = 0; j < 4; j++) dispE(tab[j][i]); printf("}\n"); } printf("\n"); } // une fonction pour afficher un etat void dispE(etat e) { printf("[%d, %d, %d]", e.dist, e.prec, e.val); } int main(int argv, char* argc[]) { seq s, err_s, cod_s, dec_s; int nbbits, pc; double ppc; if (argv < 2) { printf("Donner le nombre de bits pour la squence coder...\n"); exit(0); } else if (argv == 2) { nbbits = atoi(argc[1]); pc = 10; } else { nbbits = atoi(argc[1]); pc = atoi(argc[2]); } /* s = random_seq(nbbits); cod_s = emission(s); err_s = erreurs(cod_s, pc); dec_s = decode(&err_s); */ s = random_seq(nbbits); cod_s = emission(s); for(ppc = 0; ppc < 15; ppc += 0.01) { err_s = erreurs(cod_s, ppc); dec_s = decode(&err_s); printf("%f %f\n", pourcent_err(&cod_s, &err_s), pourcent_err(&s, &dec_s)); } // les print... /* printf("\nLa squence: \n"); dispS(s); printf("\nLa squence codee:\n"); dispS(cod_s); printf("\nLa squence codee avec erreurs:\n"); dispS(err_s); printf("\nPourcentage effectif d'erreur:\n"); printf("%f\n", pourcent_err(&cod_s, &err_s)); //getchar();
ESSI-Transmissions Numriques
Page 13 sur 14
Leberrigot-Bourgouin printf("\nLa sequence decodee:\n"); dispS(dec_s); printf("\nPourcentage d'erreur un fois decode:\n"); printf("%f\n", pourcent_err(&s, &dec_s)); printf("\n"); */ return 0; }
ESSI-Transmissions Numriques
Page 14 sur 14