You are on page 1of 14

Leberrigot-Bourgouin

ESSI-Transmissions Numriques

Bourgouin Jrmy Leberrigot Samuel

Codage convolutionnel et algorithme de Viterbi


Ecole suprieure en sciences informatiques Sophia Antipolis

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.

Codes convolutionnels, codage des donnes :

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/00 00 1/11 1/00 0/10 01

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

1/11 1/00 0/10


4

01

0/11

1/01

10

0/01
3

11 1/10

exemple de fonctionnement de lautomate

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

II. Algorithme de Viterbi :


Le rcepteur va recevoir le message cod qui t envoy par lmetteur. Cependant, il se peut que ce message comporte des erreurs. Le but de lalgorithme de Viterbi est de tenter de reconstituer le message original. Pour cela, le rcepteur dispose du mme automate que celui utilis pour coder les donnes dans lmetteur. Au dbut du dcodage, lautomate est dans ltat 00. Ensuite, il essaye deux possibilits : soit lentre tait 0, soit elle tait 1. Ces deux possibilits vont produire deux messages. On compare ces deux messages au message rceptionn et on regarde le nombre de bits qui diffrent : ce nombre est ce quon appelle la distance de Hamming. Les deux possibilits vont nous amener deux tats diffrents. Pour chacun de ces tats, on essaye les deux possibilits : entre 0 et entre 1. A chaque fois, la distance de Hamming est le nombre de diffrence entre les bits auquel on ajoute la distance de Hamming du chemin do lon vient. Le principe de Viterbi est de retenir le chemin correspondant la distance de Hamming la plus petite parmi les deux chemins. On ritre le procd jusqu la fin du message. On considre que le message original est celui associ la distance de Hamming la plus petite. Si le message est arriv sans erreur, la distance de Hamming est nulle. On peut visualiser le droulement de cet algorithme en utilisant un treillis.

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

1/01 0/01 1/10

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

Annexe : code source


#include <unistd.h> #include <stdio.h> // les etats de l'automate #define _00 3 #define _10 2 #define _01 1 #define _11 0 // l'etat suivant de l'automat, a partir // de l'etat courant et de la valeur generee int etatSuivant[4][2] = {{_10, _11}, {_10, _11}, {_00, _01}, {_00, _01}}; // le code genere a partir d'un etat // et de la valeur generee int code[4][2] = {{_01, _10}, {_10, _01}, {_11, _00}, {_00, _11}}; // pour le random int calls = 0; // une sequnce de bits typedef struct seq { int nb_bits; int *bits; } seq; // une structure pour les etats de l'algo typedef struct etat { int dist; int prec; int val; } etat; // une sequence aleatoire de nb_bits seq random_seq(int n_bits); // la sequence emettre seq emission(seq s); // la squence emmettre 's' entachee de p% d'erreurs seq erreurs(seq s, int p); // calcul du pourcentage effectif d'erreurs double pourcent_err(seq *s1, seq *s2); // decodage a partir de la sequence s seq decode(seq* s); // rempli le tableau pour le decodage void remplir(etat **tab, seq *s);

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

You might also like