Implémentation et étude d`un turbo-code

publicité
Implémentation et étude d’un turbo-code
Sujet proposé par Jean-Pierre Tillich
Distribué le 12 novembre 2010
1
Quelques mots sur le sujet
Le but de ce projet est de réaliser et de comprendre comment fonctionne un code correcteur d’erreurs
très proche des codes correcteurs qui sont standardisés actuellement, c’est à dire un turbo-code. Comme
cela sera vu dans le cours 8, les codes convolutifs agissent comme d’excellents codes réducteurs de bruit
sur le canal, mais souffrent du fait que si l’on veut réaliser le décodage au maximum de vraisemblance
avec l’algorithme de Viterbi, la mémoire du code doit rester petite : typiquement des mémoires de l’ordre
de 3 − 7 sont usuelles, et de l’ordre de 10 − 15 très exceptionnellement utilisées. Le fait que la probabilité
d’erreur par bit après décodage reste élevée, typiquement de l’ordre de 10−3 − 10−4 font que l’on est
obligé d’utiliser d’autres moyens de codage. Jusqu’au début des années 1990, la solution la plus répandue
consistait à concaténer un code convolutif avec un code de Reed-Solomon (voir cours 7). Berrou et
Glavieux ont proposé en 1993 une solution à la fois de faible complexité et beaucoup plus performante
en termes de probabilité d’erreur après décodage : les turbo-codes. Cette solution consiste à combiner de
manière astucieuse deux codes convolutifs de manière à obtenir des codes :
(i) dont la distance minimale n’est plus bornée par une constante quand la longueur augmente,
(ii) qui peuvent être décodés en décodant les deux codes convolutifs de base, et en combinant de manière
adéquate le résultat des deux décodages au moyen d’une procédure itérative.
Avec un choix convenable des codes convolutifs, les performances peuvent être excellentes.
Dans ce projet, il s’agira essentiellement d’effectuer la programmation d’un turbo-code et de répondre
à un certain nombre de questions d’approfondissement (ou de compréhension) données ici.
2
Une description d’un certain type de code convolutif
Par souci de simplification, nous allons nous intéresser qu’à des turbo-codes construits en utilisant
des codeurs convolutifs de type (2, 1) (il est à signaler que cela concerne bon nombre de turbo-codes
utilisés en pratique, comme par exemple les turbo-codes mis en oeuvre dans la 3G).
Définition 1 (Codeur convolutif de type (2, 1) de mémoire m)
1. Un codeur convolutif de type
(2, 1) de mémoire m est caractérisé par la donnée de trois mots binaires de longueur m + 1,
a1 = (a10 , . . . , a1m ), a2 = (a20 , . . . , a2m ) et b = (b0 , . . . , bm ).
2. Il associe à une séquence d’information d’une taille arbitraire K : u = (u1 , . . . , uK ) ∈ {0, 1}K deux
séquences x1 = (x11 , . . . , x1K ) ∈ {0, 1}K et x2 = (x21 , . . . , x2K ) ∈ {0, 1}K .
3. Celles-ci sont obtenues en calculant K vecteurs d’“état” auxiliaires s1 = (s1,1 , . . . , s1,m ), . . . , sK =
(sK,1 , . . . , sK,m ) appartenant à {0, 1}m via les formules (on effectue les sommes et les produits dans
1
le corps à deux éléments)
s0
= |0 .{z
. . 0}
m
si
=
(bm ui +
m−1
X
bj si−1,m−j , si−1,1 , . . . , si−1,m−1 ) pour i ≥ 1.
j=0
En d’autres termes si est obtenu au moyen de si−1 et de ui en décalant les coordonnées de si−1
vers la droite, et en prenant pour première coordonnée une certaine combinaison linéaire fixe des
coordonnées de si−1 et de ui .
4. Les séquences x1 et x2 sont alors obtenues par les formules
x1i
= a1m ui +
m−1
X
a1j si−1,m−j
j=0
x2i
= a2m ui +
m−1
X
a2j si−1,m−j
j=0
Il sera commode d’introduire la fonction
e : {0, 1} × {0, 1}m
→
{0, 1}m
(u, s1 , . . . , sm ) 7→ (bm u +
m−1
X
bj sm−j , s1 , . . . , sm−1 )
j=0
En d’autres termes
si = e(ui , si−1 ).
Un tel codeur peut être réalisé très simplement en prenant un registre à décalage de taille m stockant les
coordonnées de si au temps i. Dans le cas des turbo-codes nous serons plus particulièrement intéressé
par des codeurs systématiques et récursifs. Ils sont définis par :
Définition 2 (Codeur convolutif de type (2, 1) systématique) Un tel codeur correspond au choix
a1 = (0, . . . , 0, 1), c’est à dire a1i = 0 pour i ∈ {0, . . . , m − 1} et a1m = 1. En d’autres termes, la séquence
d’entrée u se retrouve copiée intégralement dans la séquence de sortie x1 : x1i = ui pour tout i strictement
positif. On appelle dans ce cas la suite x2 la redondance du codeur.
Par la suite on fera toujours l’hypothèse que bm = 1. Pour expliciter l’algorithme de décodage des
turbo-codes, il sera intéressant de considérer les fonctions suivantes définies pour un codeur convolutif
systématique de type (2, 1) de mémoire m :
u : {0, 1}m × {0, 1}m
m
m
r : {0, 1} × {0, 1}
→
{0, 1, ∞}
→
{0, 1, ∞}
u(s, s0 ) est défini comme égal à l’infini si et seulement il n’existe pas de valeur de x ∈ {0, 1} telle que
e(x, s) = s0 et est égale à l’unique valeur de x telle que e(x, s) = s0 sinon. r(s, s0 ) est infini si et seulement
si u(s, s0 ) est infini. Dans le cas contraire on a
r(s, s0 ) = a2m u(s, s0 ) +
m−1
X
a2j sm−j
j=0
(avec s = (s1 , . . . , sm )).
Définition 3 (Codeur convolutif de type (2, 1) récursif ) Un codeur de type (2, 1) est dit récursif
si au moins un des bi pour i dans {0, . . . , m − 1} est non nul.
2
Question 1 Considérer une séquence d’information u de taille arbitraire ne comportant qu’un seul 1.
Que peut-on dire des poids des sorties x1 et x2 dans le cas d’un codeur non récursif et dans le cas d’un
code récursif ?
3
Un turbo-code
Voyons maintenant plus précisément ce qu’est un turbo-code. Dans la littérature existent de nombreuses variantes du schéma de base de Berrou et Glavieux. Ce que nous appelons turbo-code dans cette
section porte généralement dans la littérature le nom de turbo-code parallèle. Cela correspond au
schéma de codage suivant.
Définition 4 Le turbo-code de longueur d’information k associé à deux codages convolutifs systématiques
u → (u, r1 (u)) et u → (u, r2 (u)) 1 et à une permutation π de {1, 2, . . . , k} est l’ensemble des mots de la
forme
(u, r1 (u), r2 (uπ ),
où u = (ui )1≤i≤l désigne un mot binaire de longueur k et uπ désigne le vecteur (uπ(i) )1≤i≤k .
En d’autres termes le codage consiste à prendre la sortie d’un premier code convolutif (que l’on
suppose systématique), puis à faire rentrer la même séquence d’entrée permutée par π dans un deuxième
codeur convolutif systématique, mais à ne rajouter que la sortie du deuxième code correspondant à la
redondance.
Question 2 Pouvez-vous donner une borne sur la distance minimale d’un turbo-code utilisant deux
codeurs de type (2, 1) non récursifs de mémoire m ?
4
Décodage du turbo-code
Si l’on sait décoder un code convolutif au maximum de vraisemblance avec une complexité réduite,
pour peu que la mémoire du codeur convolutif soit petite, il n’en va pas de même d’un turbo-code : en effet,
on ne sait pas décoder de tels codes au maximum de vraisemblance avec une complexité raisonnable, et
ce même si la mémoire des deux codes convolutifs constituants est petite. Cependant, on peut les décoder
de manière sous-optimale avec un algorithme de décodage itératif. Une itération consiste principalement
à décoder avec l’algorithme de Viterbi chaque code convolutif séparément, puis à donner le résultat
de ce décodage à l’autre code convolutif pour l’itération suivante. Nous allons maintenant donner cet
algorithme de décodage pour le canal binaire symétrique. En substance, chaque décodage de type Viterbi
consiste à appliquer un algorithme dont les entrées et sorties correspondent à la description donnée dans
l’algorithme 3.
L’algorithme itératif consiste ici alors à effectuer l’algorithme 2
Avec la description d’un code convolutif vue précédemment, la description précise de l’algorithme
SOVA devient
Question 3 A la première itération, voyez-vous un lien entre les quantités f [i][b] et certaines quantités
calculées par l’algorithme de Viterbi ?
Question 4 Implémenter cet algorithme pour plusieurs choix de codes convolutifs de type (2, 1), plusieurs valeurs de permutation et des valeurs de k comprises entre 500 et 10000. Evaluer les performances
pour des valeurs de probabilité d’erreur sur le canal binaire symétrique variant entre p = 0.05 et p = 0.15.
Voyez-vous une différence entre utiliser des codeurs récursifs et non récursifs ? Pouvez-vous donner une
explication de ce phénomène ?
1. Ici ri (u) désigne la redondance correspondant à l’entrée u pour le i-ème codeur convolutif.
3
Algorithme 1 Squelette du décodage de type Viterbi (ou SOVA dans la littérature pour Soft Output
Viterbi Algorithm) SOVA(u, e, r)
INPUT :
1. u la séquence d’information reçue par le canal,
2. e = (e[i][b])1≤i≤k une information de fiabilité pour chaque bit d’information, pour chaque bit
0≤b≤1
i on dispose de deux quantités, e[i][0] et e[i][1], si la deuxième quantité est plus grande que la
première c’est une indication qu’il est plus vraisemblable que ui soit égal à 0, sinon c’est la valeur
de 1 qui est plus vraisemblable.
3. r la redondance telle qu’elle a été reçue par le canal
OUTPUT :
e0 une nouvelle information de fiabilité pour chaque bit d’information.
Algorithme 2 Algorithme de décodage itératif du turbo-code
INPUT: - u = (u1 , . . . , uk ) la séquence d’information reçue,
- r1 la redondance reçue pour le premier code convolutif,
- r2 le redondance reçue pour le second code convolutif.
- π une permutation de {1, . . . , k}.
OUTPUT: û = (û1 , . . . , ûk ) la séquence d’information décodée
{Initialisation (on met à zéro toutes les entrées de e1 et e2 )}
e1 ← 0
e2 ← 0
{Itérations. Le nombre d’itérations N est compris entre 5 et 20 environ en pratique.}
for t = 1 to N do
e2 ← SOVA(u, e1π−1 , r1 )
e1 ← SOVA(uπ , e2π , r2 )
{Etape finale (on note δa=b la fonction de Kronecker)}
for i = 1 to k do
if δui =1 + e1 [π −1 (i)][0] + e2 [i][0] ≤ δui =0 + e1 [π −1 (i)][1] + e2 [i][1] then
ûi ← 0
else
ûi ← 1
4
Algorithme 3 Squelette du décodage de type Viterbi (ou SOVA dans la littérature pour Soft Output
Viterbi Algorithm) SOVA(u, e, r)
INPUT :
1. u = (u1 , . . . , uk ) la séquence d’information reçue par le canal,
2. e = (e[i][b])1≤i≤k une information de fiabilité pour chaque bit d’information, pour chaque bit
0≤b≤1
i on dispose de deux quantités, e[i][0] et e[i][1], si la deuxième quantité est plus grande que la
première c’est une indication qu’il est plus vraisemblable que ui soit égal à 0, sinon c’est la valeur
de 1 qui est plus vraisemblable.
3. r = (r1 , . . . , rk ) la redondance reçue par le canal
OUTPUT :
e0 une nouvelle information de fiabilité pour chaque bit d’information.
{Initialisation de deux tableaux bidimensionnels, m est la mémoire du codeur convolutif.}
for i = 0 to k − 1 do
for a = 0 to 2m − 1 do
f [i][a] ← ∞
b[i][a] ← ∞
f [0][0] ← 0
for a = 0 to 2m − 1 do
b[k][a] ← 0
{Calcul des valeurs finales des tableaux b et f (noter que l’on voit ici un mot binaire de longueur m
comme un nombre entier dans {0, 1, . . . , 2m − 1})}
for i = 1 to k − 1 do
for b = 0 to 2m − 1 do
f [i][b] ← min0≤a≤2m −1:u(a,b)6=∞ f [i − 1][a] + e[i][u(a, b)] + δui =1−u(a,b) + δri =1−r(a,b)
b[k − i][b] ← min0≤a≤2m −1:u(b,a)6=∞ b[k − i + 1][a] + e[k − i + 1][u(b, a)] + δuk−i+1 =1−u(b,a) +
δrk−i+1 =1−r(b,a)
{Calcul du tableau de fiabilité e0 }
for i = 1 to k do
e0 [i][0] = min0≤a,b≤2m −1:u(a,b)=0 f [i − 1][a] + b[i][b] + δri =1−r(a,b)
e0 [i][1] = min0≤a,b≤2m −1:u(a,b)=1 f [i − 1][a] + b[i][b] + δri =1−r(a,b)
return e0
5
Question 5 Proposer une (très) légère modification de l’algorithme de manière à pouvoir corriger les
effacements sur un canal à effacement. Recommencer les simulations précédentes pour des probabilités
d’effacement de l’ordre de p = 0.5.
5
Extensions possibles
Suivant l’état d’avancement du projet, plusieurs extensions (facultatives) du projet seront proposées
ici.
6
Téléchargement