Professional Documents
Culture Documents
1. Introduction
Nous avons présenté, dans les cours précédents, l’amélioration des performances d’une communication
numérique sur des canaux sans mémoire (canal binaire symétrique ou additif blanc gaussien) grâce à l’enploi du
codage par bloc.
Les codes convolutifs, introduits en 1955 par Elias, peuvent être considérés comme un cas particulier des codes
en bloc linéaires, mais un point de vue plus large nous fera découvrir que la structure convolutive additionnelle
munit le code linéaire de propriétés favorables qui facilitent à la fois son codage et amélioent ses performances.
Les codes convolutifs forment une classe extrêmement souple et efficace de codes correcteurs d’erreurs. Ce sont
les codes les plus utilisés dans les systèmes de télécommunications fixes et mobiles. Théoriquement, ils ont les
mêmes caractéristiques que les codes en blocs sauf pour la valeur de leur dimension et leur longueur. Les codes
convolutifs s’appliquent sur des séquences infinies de symboles d’information et génèrent des séquences infinies
de symboles codés.
Dans un premier temps, nous présenterons les codes convolutifs comme un cas particulier des codes en bloc
linéaires, avant d’exploiter dans un deuxième temps leur structure spécifique pour aboutir à un procédé de
décodage à maximum de vraisemblance de faible complexité.
Chaque élément g l 0≤l≤L-1, de la matrice est un vecteur ligne binaire à n composantes de la forme :
[
g l = g l1 , g l 2 ," g ln ]
Les zones laissées vides en bas à gauche et en haut à droite correspondent à des éléments tous nuls. Chaque ligne
s’obtient en décalant la précédente de n colonnes vers la droite. Cette matrice, de taille B×(nB+L-1) décrit donc
un code linéaire en bloc dont les mots de code pourraient être engendrés par le dispositif de la Figure 1.
Généralement, les mots de codes sont très longs, c’est à dire B>>L et nous pouvons même considérer cette
matrice comme infinie. Ce code linéaire ne possède donc plus à proprement parler de dimension ni de longueur.
Le rendement ne peut alors être défini comme pour les codes en blocs. Cependant en négligeant la fermeture du
code (le vidage des registres), nous remarquons qu’il existe un rapport 1/n entre le nombre de bits d’information
et le nombre de bits du mot de code. Le rendement de ce code est donc :
r=1/n
Le terme « convolutif » s’applique à cette classe de codes parce que la suite de bits codés s peut s’exprimer
comme le résultat de la convolution de la suite de bits d’information e par les coefficients g. En effet, puisque le
code est linéaire, nous avons : s = e . G. En observant la forme particulière de G, les n bits en sortie du codeur à
l’instant t, correspondant à une entrée, s’écrivent :
t
st = ∑ ek g u − k
u = max (1,t − L +1)
Exercice 1 : Donner le rendement, la longueur de contrainte, construire la matrice et le schéma de codage d’un
code convolutif de coefficients : g0=(1,1), g1=(1,0), g2=(1,1).
n
k 7 g 0 g1 " g L −1
g0 g1 " g L−1
G=
% %
g0 g1 " g L−1
Exemple 1 : Soit le code convolutif de rendement 2/3 et de longueur de contrainte L=2 défini par les coefficients
suivants :
1 1 1 1 0 1
g0 = g1 =
0 1 0 1 1 0
La sortie d’un codeur convolutif à l’instant t dépend de ses entrées à l’instant t et de l’état des registres du codeur
à cet instant. En posant ν=L-1, tout code convolutif de rendement k/n et de longueur de contrainte L possède kν
registres, qui peuvent donc prendre 2 kν états différents. Comme l’entrée est constituée de k bits différents, il
existe 2 k transitions possible à partir d’un état du codeur à un instant donné.
où l’inconue x symbolise un retard d’une période. Le coefficient eiA est le bit présent à la i-ème entrée du codeur
à l’instant A . De la même manière, les n sorties du codeur peuvent être indexées par j et s’écrivent :
+∞
s j (x ) = ∑ s jA x A , j = 1,", n
A=0
La relation introduite par le code convolutif entre les entrées et les sorties peut s’écrire de façon élégante avec
ses notations, en introduisant les polynômes générateurs. Le polynôme générateur qui lie la i-ème entrée à la j-
ième sortie est noté g ij (x ) , et est de degré inférieur ou égal à L-1. Le coefficient de degré r de ce polynôme vaut
1 si une connexion existe entre la sortie j et le bit présent dans le r-ième registre correspondant à l’entrée i.
La notation octale est couramment utilisée pour représenter ces polynômes. Ainsi, g (x ) = 1 + x + x 3 sera
représenté par le nombre 15.
Les sorties se calculent en fonction des entrées à l’aide des polynômes générateurs :
k
s j (x ) = ∑ g ij (x )ei (x ), j = 1,", n
i =1
Exercice 2 : Expliciter et donner la représentation octale des polynômes générateurs des codes introduits à
l’exercice 1 et l’exemple 1.
Une représentation matricielle compacte de la formule précédente se déduit de l’écriture sous forme vectorielle
des entrées et sorties :
E = [e1 (x ) e2 (x ) " ek (x )] S = [s1 (x ) s 2 (x ) " s n (x )]
S = GE
# # #
g k 1 (x ) g k 2 (x ) " g kn (x )
Un code convolutif est dit systématique lorsque une partie de ses sorties est exactement égale à ses entrées. Cela
revient à dire que (g11(x)=1, g21(x)=0, … , gk1(x)=0), (g12(x)=0, g22(x)=1, … , gk2(x)=0), …, et (g1k(x)=0,
g2k(x)=0,… , gkk(x)=1).
Un cas particulièrement intéressant est celui de la transformation d’un code convolutif non récursif non
systématique (NRNSC) de rendement k/(k+1) en un code récursif systématique (RSC). Prenons l’exemple d’un
code NRNSC de rendement ½. Il est défini par la donnée de ses deux polynômes générateurs g11(x)= g1(x) et
g12(x)= g2(x), qui forment la matrice :
G = [ g 1 ( x ) g 2 (x ) ]
La transformation en code RSC correspond à considérer le code défini par la matrice génératrice suivante :
g 2 (x )
G = 1
g1 (x )
Exemple 2 : Soit le code convolutif NRNSC de rendement ½, de longueur de contrainte L=3 et de polunômes
générateurs (7,5). Ses polynômes s’écrivent : g1(x)=1+x+x2 et g2(x)=1+x2. Son codeur possède la structure
suivante :
Ses deux sorties s1(x) et s2(x) s’expriment en fonction de l’entrée e(x) de la manière suivante :
s1(x)=(1+x+x2)e(x) et s1(x)=(1+x2)e(x)
Exercice 3 : Prouver, en dérivant les équations des sorties en fonction de l’entrée à partir du schéma ci-dessus,
qu’il s’agit bien du code (1,5/7). Donner une autre représentation correspondant à un filtrage ARMA.
Exercice 4 : Donner les conditions sur les polynômes générateurs pour qu’un code NRNSC de rendement k/n
puisse être transformé en un code RSC.
• L’arbre est un graphe de hauteur et de largeur infinies. Un sommet dans l’arbre représente un état possible
du codeur. Une arrête symbolise une transition d’un état à l’autre. Classiquement l’arbre commence à son
sommet par l’état 0 (le registre à décalage est initialisé à 0). Tout chemin dans l’arbre du code est une
séquence possible (un mot de code) à la sortie du codeur convolutif.
• Le treillis est obtenu en repliant l’arbre sur sa largeur, par fusion des sommets représentant le même état au
même instant.
• Le diagramme d’états est à son tour construit en repliant le treillis sur sa longueur, par fusion des sommets
représentant aussi le même état, à des instant différents.
Incontestablement, le treillis est l’outil graphique le plus performant pour caractériser un code et concevoir des
algorithmes de décodage. Nous illustrons ci-dessous l’arbre, le treillis et le diagramme des deux codes, l’un
NRNSC (7,5) et l’autre RSC (1,5/7) à 4 états.
• Supposons que le codeur est dans l’état a à l’instant t=0. Deux transitions, correspondant aux valeurs
possibles du bit à l’entrée du codeur partent de l’état a :
• la première a → a correspond à une entrée e=0 et une sortie s=00.
• la seconde a → c correspond à une entrée e=1 et une sortie s=11.
Ces deux transitions restent valables à n’importe quel instant t dans le treillis.
• Supposons maintenant le codeur dans l’état b. Les deux transitions partant de l’état b sont les suivantes :
• b → c correspond à une entrée e=1 et une sortie s=00.
• b → a correspond à une entrée e=0 et une sortie s=11.
• Les deux transitions qui partent de l’état c sont les suivantes :
• c → b correspond à une entrée e=0 et une sortie s=10.
• c → d correspond à une entrée e=1 et une sortie s=01.
• Les deux transitions partant de l’état d sont :
• d → d correspond à une entrée e=1 et une sortie s=10.
• d → b correspond à une entrée e=0 et une sortie s=01.
00
a
11
00
c
11 b
10
00
c
01
0
d
a
1
11
11 b
00
10
c
b
01
01
d
10
Le treillis est obtenu en repliant l’arbre sur sa hauteur. Il est représenté à la Figure 6. Les deux premiers bits sur
chaque transition représentent la sortie, et le dernier l’entrée correspondante. Notons que le treillis devient
périodique à partir de la 3ème étape où l’on retrouve les 8 transitions entre les 4 états. En général, le treillis d’un
code convolutif devient stationnaire après L=ν+1 étapes.
Etats
00/0 00/0 00/0 00/0 00/0
a=00
11/1 11/1 11/1 11/1 11/1
Les mots du code (7,5) sont tous les chemins possibles dans le treillis. Il est facile de vérifier que le code est
linéaire, i.e. le chemin 00...0 appartient au treillis et la somme binaire modulo 2 des bits codés présents sur les
branches de deux chemins correspond aux bits présents sur les branches d’un troisième chemin dans le treillis.
D’autre part, le treillis permet de trouver facilement la distance minimale du code. Il s’agit du poids de Hamming
minimal entre deux mots de codes, donc deux chemins. En comparant tous les chemins au chemin tout à zéro,
dans notre cas, un chemin divergeant à n’importe quel instant du chemin tout à zéro, en suivant a→c→b→a pour
converger à nouveau vers le chemin tout à zéro possède le poids de sortie minimal WHmin=5. Nous en déduisons
que la distance minimale dHmin (aussi appelée distance libre dfree) du code convolutif (7,5) est égale à 5. Ce
chemin correspond à un poids en entrée de 1.
Exercice 5 : Construire le diagramme d’état du code convolutif NRNSC (7,5). Il s’agit d’un graphe dont les
sommets représentent les états, mais où la notion temporelle n’apparaît pas. On l’obtient par fusion dans le
treillis de tous les états identiques à des instants différents.
Cas du code RSC R=1/2, g1=1 g2=5/7 : les 4 états a, b, c, d sont notés de manière similaire à ceux du code
NRNSC. La structure du treillis est parfaitement identique : deux branches arrivent et partent de chaque état. Le
treillis devient périodique à la L=3ème étape, lorsque toutes les transitions sont présentes. La différence entre le
code récursif et non récursif réside dans l’étiquetage binaire des branches. En effet, sachant que le code RSC est
systématique, le 1er bit de sortie est égal à l’entrée. Ainsi les deux bits associés à une branche du treillis
représentent toujours les deux bits de sortie et la valeur de l’entrée est contenue dans le 1er bit
Exercice 6 : Construire le treillis du code RSC (1,7/5) dont le codeur est représenté à la Figure 4.
Remarquons que la distance minimale de ce code RSC est elle aussi égale à 5 et se déduit du même chemin
a→c→b→a. Une entrée non nulle permet de quitter l’état 0 dans les deux cas récursifs et non récursifs. En
revanche, une entrée nulle n’est pas suffisante pour revenir à l’état 0 dans le cas du code RSC. En effet, le retour
b→a est généré par e=0 pour le code NRNSC, et par e=1 pour le code RSC. Ainsi, le poids d’entrée du chemin à
distance minimale du code RSC est égal à 2.
4.1. Perforation
Considérons un code convolutif binaire récursif ou non de rendement R=k/n et de mémoire quelconque. Durant u
étapes dans le treillis, le codeur reçoit k×u bits d’information et délivre n×u bits codés. Parmi ces bits codés, v
sont supprimés et n×u-v sont émis sur le canal. Cette opération, appelée perforation du code convolutif,
transforme le rendement R=k/n en un rendement R’=(k×u)/(n×u-v). Par exemple, un code convolutif de
rendement ½ est facilement converti par perforation en un code de rendement 2/3 (u=2 v=1) ou un rendement ¾
(u=3,v=2).
Le choix des bits codés non transmis (on dit perforés) se fait généralement suivant un motif périodique décrit par
une matrice binaire, dite de perforation, de taille n×u qui comporte v zéro.
5. Algorithmes de décodage
Nous décrivons dans ce paragraphe deux algorithmes de décodage applicables aux codes convolutifs. Ils
effectuent leurs opérations sur un treillis, qui représente, dans le cas du décodage des codes convolutifs, la
structure du code. Ils sont cependant applicables plus généralement à le recherche du chemin dans un treillis qui
minimise un critère de distance additive. Ils sont donc aussi applicables au décodage des codes en bloc (par
l’intermédiaire de leur représentation en treillis), à celui des modulations codées en treillis, où à la detection au
maximum de vraisemblance sur un canal introduisant de l’interférence entre symboles, problème qui correspond
à l’estimation des symboles d’un modèle de chaîne de Markov cachée, représentable lui aussi par un treillis.
Le premier algorithme décrit ci-dessous est celui de Viterbi (VA). Il s’agit d’un algorithme de décodage à entrée
ferme ou souple mais à sortie ferme (des décisions sont prises sur chaque transition du chemin choisi dans le
treillis) qui calcule le chemin dont la vraisemblance est maximale (ML : Maximum Likelihood). Il s’agit donc
d’un algorithme de décodage ML par séquence (chemin).
Le deuxième algorithme est un Viterbi modifié afin de fournir une sortie souple (SOVA : Soft-Output Viterbi
Algorithm) : à chacun des symboles associés aux transitions du chemin choisi, il fait correspondre une
information de fiabilité sous optimale.
Un troisième algorithme, le Forward-Backward, fait l’objet d’un document séparé. Il calcule de manière exacte
la probabilité a posteriori des symboles présents sur les branches. Il s’agit donc aussi d’un algorithme à entrée et
sortie souples (SISO : Soft-Input Soft-Output) à décision MAP (Maximum A Posteriori) qui peut tenir compte
d’une information probabiliste a priori disponible sur les symboles émis. Contrairement aux algorithme de
Viterbi, il s’agit d’une maximisation symbole par symbole.
Les algorithmes de Viterbi, le SOVA et le Forward-Backward sont couramment utilisés dans les systèmes de
transmission mobile et fixe à codage simple ou concaténé.
Soit C un code convolutif binaire de rendement R=k/n et de longueur de contrainte L. Le nombre de bits à
l’entrée du codeur (respectivement en sortie) est égal à k (respectivement à n). L’algorithme de Viterbi est le
moyen le plus répandu pour le décodage ML lorsque C possède un treillis de taille raisonnable, i.e. un nombre
d’états inférieur ou égal à 256. L’algorithme de Viterbi est de faible complexité et est simple à implanter.
Le décodage à maximum de vraisemblance correspond à chercher dans le treillis du code C le chemin le plus
proche (le plus vraisemblable) de la séquence reçue (i.e. l’observation). La distance employée dans l’algorithme
est soit la distance euclidienne dans le cas d’entrées souples, soit la distance de Hamming dans le cas d’entrées
fermes.
k(L-1)
Rappelons que le nombre d’états dans le treillis du code C est égal à 2 et que le nombre de transitions par
k k
état est 2 . Chaque sommet dans le treillis est connecté de part et d’autre par 2 branches vers les sommets
k(L-1) k kL
antérieurs et postérieurs. Le nombre total de branches entre deux étapes dans le treillis est 2 ×2 = 2 . La
séquence à décoder étant théoriquement de longueur infinie, on se limite en pratique à la recherche du chemin le
plus proche sur une fenêtre de largeur W. Les chemins manipulés dans le treillis du code sont donc de longueur
W branches. Si l’on essaie d’appliquer une méthode de décodage par recherche exhaustive et même si nous
supposons connus les états initiaux et finaux (cas d’un code convolutif dont on a fermé le treillis), nous nous
kL W-L)
trouvons confrontés à la recherche du meilleur chemin parmi (2 )( possibilités. La complexité d’un tel
procédé est prohibitive puisqu’elle est exponentielle en fonction de W. L’algorithme de Viterbi décrit ci-dessous
apporte une grande réduction de la complexité de la recherche, qui devient linéaire en W.
• Initialisation : λ(0,0)=0.0 et λ(0,s)=+∞ pour s≠0. En effet, nous savons que le codeur par de l’état 0.
• A l’étape t, pour chaque état st :
On choisit la branche T(st-1,st) telle que la distance cumulée λ(t, st) entre le chemin sélectionné et
l’observation jusqu’au temps t soit minimale
[ ]
λ (t , s t ) = min st −1 λ (t − 1, s t −1 ) + d 2 {T (s t −1 , s t ), observation}
L’état st-1 qui correspond à ce minimum est appelé smin. On stocke ensuite le chemin survivant :
survivant (t , s t ) = survivant (t − 1, s min ) + T (s min , s t )
• Résultat du décodage ML (avec un délai W) : on fournit la branche T(t-W,s,s’) appartenant au survivant(t,st)
ayant la plus petite métrique cumulée λ(t, st) entre tous les survivants.
kL
L’algorithme de Viterbi nécessite donc le calcul de 2 métriques à chaque étape t, d’où une complexité de
kL
W×2 , linéaire en W. Cependant, la complexité reste exponentielle en k et L, ce qui limite l’utilisation aux
codes de petite taille (kL de 7 à 10 maximum). La largeur W de la fenêtre de décodage est prise dans la pratique
à 5L environ. Cette valeur garantie (de manière empirique) que les survivants convergent vers un chemin unique
k(L-1)
à l’intérieur de la fenêtre de décodage. L’algorithme de Viterbi nécessite donc le stockage de 2 métriques
k(L-1)
cumulées et 2 survivants de longueur 5kL bits.
Les figures suivantes illustrent l’état de la fenêtre de décodage pour t=1..10. Les métriques cumulées sont
affichées sur le côté droit de la fenêtre. Les chemins survivants sont dessinés en lignes continues.
0 1
+∞ +∞
+∞ 1
+∞ +∞
Pour simplifier la description du SOVA, plaçons nous dans le cas d’un code convolutif binaire de rendement 1/n.
Nous avons ainsi deux transitions partant de et arrivant à chaque état dans le treillis. Le nombre d’états du treillis
ν
est noté S=2 où ν=L-1 est la mémoire du code.
ν
Supposons que le VA classique prenne des décisions avec un délai W suffisamment grand pour que les 2
survivants convergent vers le même chemin avec une très grande probabilité. A l’instant t, l’algorithme de
Viterbi doit choisir un survivant pour l’état 0 ≤ s l < S . Ceci est illustré par la Figure 12. Le VA sélectionne le
chemin ayant la plus petite métrique cumulée. Dans le cas où le canal est un canal gaussien (AWGN) à sortie
souple, les métriques cumulées s’expriment sous la forme :
2
r − x (m)
∑ ∑ (rij − xij( m ) )
Es t n
2
Mm = = m = 1,2
2N 0 N0 j = t −W i =1
(m)
où xij est le i-ème bit codé à l’instant j parmi les n bits associés à une branche du chemin d’indice m arrivant à
l’état st. L’échantillon rij est l’observation en sortie du canal correspondant au bit numéro i à l’instant j. Nous
supposons que les symboles (confondus avec les bits) appartiennent à une modulation BPSK, i.e.
x ij = ± 2 E s où Es est l’énergie moyenne par symbole codé sur fréquence porteuse. En mettant en facteur
2 E s , nous écrivons les symboles sous la forme x ij = ±1 d’où le rapport Es/N0.
Avec les notations définies ci-dessus, la probabilité que le chemin m soit émis sachant que l’observation est
proportionnelle à la probabilité conditionnelle de l’observation sachant le chemin m émis :
P (chemin m observation ) α e − M m
Nous indexons arbitrairement le chemin ayant la métrique cumulée minimale par m=1. Ainsi nous avons
M 1 ≤ M 2 et le VA choisit le chemin survivant d’indice 1. Après normalisation par la somme des probabilités
des deux cas possibles, la probabilité de choisir le mauvais chemin survivant, à l’instant t et pour l’état st, est
égale à :
e−M2 1 1
p st = − M −M 2
= M 2 − M1
=
e 1
+e 1+ e 1 + e∆
avec ∆ = M 2 − M 1 ≥ 0 . Cette probabilité approche 0.5 si M2≈M1 et tend vers 0 si M2>>M1. L’algorithme de
Viterbi commettra des erreurs avec une probabilité p st sur les e positions où les chemins 1 et 2 ont des bits
(1) (2)
d’information différents uj ≠uj pour les positions j=j1,j2,…,je. . Notons que e=2 dans la Figure 12. Les
(1) (2)
positions où uj =uj ne sont pas affectées par la sélection du survivant. Notons Wm la largeur de la fenêtre
dans le treillis où les chemins 1 et 2 arrivant à l’état st ne sont pas confondus (voir Figure 12). Ainsi, nous avons
e bits d’information différents et Wm -e bits d’information identiques.
(1)
Notons p̂ j la probabilité que le bit uj associé au chemin 1 de l’état st soit erroné. Supposons que les valeurs de
p̂ j sont stockées en mémoire pour les instants j=l-Wm,…,t-1. Prenons comme valeur initiale pˆ l = 0 (le bit
décodé reste parfaitement fiable tant que les deux chemins indiquent la même valeur). Sachant que l’algorithme
de Viterbi a sélectionné le chemin 1, nous pouvons mettre à jours les probabilités d’erreurs des bits différents
selon la formule :
pˆ j ← pˆ j (1 − psl ) + (1 − pˆ j ) p sl pour j = j1,j2,…,je
Cette équation nous fournit une approximation de la probabilité d’erreur pour le bit d’information uj. Même si le
SOVA est incapable de fournir l’APP exacte du bit uj, une valeur de confiance µj est facilement obtenue à partir
de p̂ j :
1 − pˆ j
µ j = log 0 ≤ µ j < +∞
pˆ j
En combinant les équations ci-dessus, nous obtenons une formule de mise à jour des valeurs de confiance :
αµ j + ∆
1 1+ e
µ j ← f (µ j , ∆) = log αµ
e +e j α ∆
Rappelons que la mise à jour est effectuée sur les positions j=j1, j2,…, je. Le facteur α introduit dans la fonction
f() permet d’éviter les débordements de la valeur de confiance à fort rapport signal-à-bruit. Asymptotiquement,
E
nous pouvons normaliser la moyenne de à 1.0 en choississant α = 4d H min s où dHmin est la distance minimale
N0
du code convolutif. Une approximation simple et pratique de la fonction f() est
f ( µ j , ∆ ) ≈ min( µ j , ∆ / α )
Cette dernière formule permet une mise à jour très rapide de la valeur de confiance sans même connaître la
valeur du rapport Es/N0.
Nous pouvons maintenant décrire de manière générale les étapes de l’algorithme SOVA :
Stockage :
• L’indice t du temps, modulo W+1
• Les suites des bits décodés par décisions dures u(st)={ ul-W(st),…, ul(st)}, uj(st)∈±1 pour 0 ≤ s t < S .
• Les suites de valeurs de confiance µ(st)={µl-W(st),…,µl(st)} avec 0 ≤ µ j ( s t ) < +∞ pour 0 ≤ s t < S .
• Les valeurs des métriques cumulées λ(t, st) pour 0 ≤ s t < S .
Mise à jour :
• Etape VA classique:
Pour chaque état st, calculer λ(t, st). Stocker la métrique cumulée, le survivant et le bit décidé ut(st).
• Etape de décision à sortie souple:
Pour chaque état st, stocker la différence des deux métriques
[ ] [ ]
∆ = max λ (t − 1, s t −1 ) + d 2 (T ( s t −1 , s t ), observation ) − max 2 λ (t − 1, s t −1 ) + d 2 (T ( s t −1 , s t ), observation )
Initialiser µt(st)=+∞.
(1) (2)
Pour j=t-ν en arrière jusqu’à t-Wm, comparer les deux chemins convergents en st et si uj (st)≠uj (st)
mettre à jour les fiabilités par la formule µj(st)=f(µj(st),∆).
+1
+1
-1 +1 -1 +1
S états
m=1
sl
m=2
-1 +1
l-W l-Wm -1 l