1727 lines
46 KiB
Typst
1727 lines
46 KiB
Typst
#import "composants.typ": *
|
|
|
|
#set page(
|
|
paper: "presentation-4-3",
|
|
margin: 0cm,
|
|
)
|
|
|
|
// Font
|
|
#set text(
|
|
font: "New Computer Modern",
|
|
size: 20pt,
|
|
fill: black,
|
|
)
|
|
#set math.mat(delim: "[")
|
|
|
|
// Page de garde
|
|
#slide[
|
|
#place(center + horizon)[
|
|
#graphe_tanner_fond(1cm, 1.5)
|
|
]
|
|
#v(1fr)
|
|
#align(center + horizon)[
|
|
#pad(x: 2cm)[
|
|
#text(size: 3em, weight: "bold", fill: black)[#titre]
|
|
|
|
#text(size: 1.2em, weight: "bold", fill: black)[#auteur]
|
|
|
|
#h(0.5em)
|
|
|
|
#text(size: 1.2em, fill: black)[n°#numero]
|
|
|
|
#text(size: 0.95em, fill: black)[#annee]
|
|
]
|
|
]
|
|
#v(1fr)
|
|
]
|
|
|
|
#myslide("Introduction : Utilisation")[
|
|
#align(center + horizon)[
|
|
#grid(
|
|
columns: (1.5fr, 1.5fr),
|
|
gutter: 1.5cm,
|
|
align: center + horizon,
|
|
[
|
|
#box(width: 80%)[
|
|
#stack(
|
|
dir: ttb,
|
|
spacing: -0.5em,
|
|
image("src/athena_fidus_no_text.jpg", width: 100%),
|
|
align(left)[
|
|
#box(
|
|
inset: (x: 5pt, y: 0pt),
|
|
text(size: 0.45em, fill: white)[* https://gallery.ariane.group *],
|
|
)
|
|
],
|
|
)
|
|
]
|
|
#v(0.5em)
|
|
Athena-Fidus
|
|
],
|
|
[
|
|
#box(width: 80%)[
|
|
#stack(
|
|
dir: ttb,
|
|
spacing: -0.5em,
|
|
image("src/runcamfpv2.png", width: 100%),
|
|
align(left)[
|
|
#box(
|
|
inset: (x: 5pt, y: 0pt),
|
|
text(size: 0.45em, fill: white)[* https://www.runcam.com/ *],
|
|
)
|
|
],
|
|
)
|
|
]
|
|
#v(0.5em)
|
|
Module OpenIPC
|
|
],
|
|
)
|
|
]
|
|
]
|
|
|
|
#myslide("Introduction : Communication Numérique")[
|
|
#place(center + horizon, dy: 8cm)[
|
|
#canal_shannon_intro()
|
|
]
|
|
]
|
|
|
|
#myslide("Problématique")[
|
|
#place(center + horizon, dy: 8.1cm)[#graphe_tanner_fond(0.9cm, 1.75)]
|
|
#place(center + horizon, dy: 7.7cm)[
|
|
#block(width: 100%)[
|
|
#text(size: 1.2em, weight: "bold", fill: black)[
|
|
Comment utiliser les codes LDPC pour garantir la fiabilité d'une transmission en présence de bruit ?
|
|
]
|
|
]
|
|
]
|
|
]
|
|
|
|
#myslide("Plan")[
|
|
#grid(
|
|
columns: (auto, 1fr),
|
|
align: horizon,
|
|
place(center + horizon, dx: 11.8cm, dy: 0.7cm)[#decor_matrice_etoilee()],
|
|
design_plan((
|
|
[Introduction],
|
|
[Codes linéaires],
|
|
[LDPC],
|
|
[Codage],
|
|
[Décodage],
|
|
[Analyse],
|
|
)),
|
|
)
|
|
]
|
|
|
|
#myslide("Définition : Codes Linéaires en Bloc")[
|
|
#definition(titre: [Code $display((n,k) in NN^2)$])[
|
|
$cal(C)$ sous-espace vectoriel de dimension $k$ de $FF_2^n$
|
|
]
|
|
|
|
#[
|
|
#set text(size: 1.1em)
|
|
- $k$ : longueur du message original
|
|
- $n$ : longueur du mot de code
|
|
- $m = n - k$ : nombre de bits de parités
|
|
]
|
|
|
|
#definition(titre: "Encodage")[
|
|
$Phi : FF_2^k & -> FF_2^n in cal(L)(FF_2^k, FF_2^n)$
|
|
]
|
|
|
|
#v(-1.3em)
|
|
|
|
#align(center + horizon)[
|
|
#plongement_schema()
|
|
]
|
|
]
|
|
|
|
#myslide("Définition : Matrice Génératrice")[
|
|
#v(0.80cm)
|
|
#definition(titre: "Matrice Génératrice")[
|
|
$G in cal(M)_(k,n)(FF_2)$ dont les lignes sont une base de $cal(C)$
|
|
]
|
|
|
|
#definition(titre: "Encodage")[
|
|
Pour un message $u in FF_2^k$ le mot de code $c in cal(C)$ est :
|
|
$
|
|
c = Phi(u) = u G
|
|
$
|
|
]
|
|
|
|
#definition(titre: "Forme systématique")[
|
|
// TODO : changer [I_k | P] en un graphique jolie avec I et P dans un carré coloré
|
|
$
|
|
#dessiner_matrice($G =$, ((texte: $I_k$, largeur: 2.2, fond: gray.lighten(75%)), (texte: $P$, largeur: 2.2, fond: gray.lighten(75%))))
|
|
// G = mat(
|
|
// I_k, P;
|
|
// augment: #1,
|
|
// delim: "[",
|
|
// )
|
|
$
|
|
]
|
|
|
|
#[
|
|
#set text(size: 1.2em)
|
|
// - Pour $u in FF_2^k, space display(u dot.o G = mat(u, u dot.o P; augment: #1, delim: "[",))$
|
|
|
|
// - Pour $u in FF_2^k, space #dessiner_matrice($u dot.o G =$, (
|
|
// (texte: $u$, largeur: 1.1, fond: gray.lighten(75%)),
|
|
// (texte: $u dot.o P$, largeur: 3.0, fond: gray.lighten(75%)),
|
|
// ))$
|
|
|
|
- $P in cal(M)_(k ,n-k)(FF_2)$ matrice de parité\
|
|
]
|
|
]
|
|
|
|
#myslide("Définition : Matrice de Contrôle")[
|
|
#v(1.1cm)
|
|
#definition(titre: "Matrice de Contrôle")[
|
|
// $H = mat(
|
|
// P^top, I_(n-k);
|
|
// augment: #1,
|
|
// delim: "[",
|
|
// )
|
|
$
|
|
#dessiner_matrice($H =$, (
|
|
(texte: $P^top$, largeur: 2.2, fond: gray.lighten(75%)),
|
|
(texte: $I_(n-k)$, largeur: 2.2, fond: gray.lighten(75%)),
|
|
))
|
|
$
|
|
|
|
]
|
|
#[
|
|
#set text(size: 1.2em)
|
|
// - $cal(C) = ker(H) = {v in FF_2^n | H dot.o v^top = 0}$
|
|
|
|
- $cal(C) = ker(H)$ -- $H c^top = 0$ $=>$ $c in cal(C)$
|
|
|
|
|
|
// - $display(G dot.o H^top = 0)$
|
|
]
|
|
|
|
#definition(titre: "Syndrome")[
|
|
Pour un vecteur reçu $r = c + e, space s in FF_2^(n - k)$
|
|
$
|
|
s = H r^top = H c^top + H e^top = 0 + H e^top
|
|
$
|
|
]
|
|
#[
|
|
#set text(size: 1.2em)
|
|
- $s = 0 => r in cal(C)$
|
|
- $s != 0$ donne la signature de l'erreur $e$
|
|
]
|
|
// Possible décodage par syndrome
|
|
]
|
|
|
|
#myslide("Exemple d'un code linéaire")[
|
|
#[
|
|
#set text(size: 1.1em)
|
|
#let col-u = blue
|
|
#let col-p = orange
|
|
|
|
#underline(offset: 3pt)[Exemple d'un code $(5,2)$]
|
|
|
|
|
|
- On choisit la matrice de parité $P$ :
|
|
$
|
|
P = #math.mat(
|
|
(text(fill: col-p)[1], text(fill: col-p)[1], text(fill: col-p)[0]),
|
|
(text(fill: col-p)[0], text(fill: col-p)[1], text(fill: col-p)[1]),
|
|
)
|
|
$
|
|
|
|
- Alors la matrice génératrice $G$ est :
|
|
$
|
|
G = #math.mat(
|
|
(text(fill: col-u)[1], text(fill: col-u)[0], text(fill: col-p)[1], text(fill: col-p)[1], text(fill: col-p)[0]),
|
|
(text(fill: col-u)[0], text(fill: col-u)[1], text(fill: col-p)[0], text(fill: col-p)[1], text(fill: col-p)[1]),
|
|
augment: 2,
|
|
)
|
|
$
|
|
|
|
- Message $display(u = #math.mat((text(fill: col-u)[1], text(fill: col-u)[1])))$
|
|
|
|
- Mot de code $c = u G$ :
|
|
#set text(size: 1.2em)
|
|
$
|
|
c = #math.mat((text(fill: col-u)[1], text(fill: col-u)[1]))
|
|
#math.mat(
|
|
(text(fill: col-u)[1], text(fill: col-u)[0], text(fill: col-p)[1], text(fill: col-p)[1], text(fill: col-p)[0]),
|
|
(text(fill: col-u)[0], text(fill: col-u)[1], text(fill: col-p)[0], text(fill: col-p)[1], text(fill: col-p)[1]),
|
|
augment: 2,
|
|
)
|
|
=
|
|
#math.mat((
|
|
text(fill: col-u)[1],
|
|
text(fill: col-u)[1],
|
|
text(fill: col-p)[1],
|
|
text(fill: col-p)[0],
|
|
text(fill: col-p)[1],
|
|
))
|
|
$
|
|
]
|
|
]
|
|
|
|
#myslide("Exemple d'un code linéaire")[
|
|
#let colp = orange
|
|
#let colu = blue
|
|
#let cole = red
|
|
#set math.mat(delim: "[")
|
|
#v(0.2cm)
|
|
#set text(size: 1.1em)
|
|
Structure systématique de $H$ :
|
|
#v(0.3em)
|
|
#align(center)[
|
|
#scale(108%)[
|
|
#dessiner_matrice($H =$, (
|
|
(texte: $P^top$, largeur: 2.0, fond: colp.lighten(90%)),
|
|
(texte: $I_3$, largeur: 3.0, fond: colu.lighten(90%)),
|
|
))
|
|
]
|
|
]
|
|
#v(0.4em)
|
|
Ainsi :
|
|
#v(-1.2em)
|
|
#align(center)[
|
|
#scale(110%)[
|
|
$
|
|
H = mat(
|
|
text(fill: colp, "1"), text(fill: colp, "0"), text(fill: colu, "1"), text(fill: colu, "0"), text(fill: colu, "0");
|
|
text(fill: colp, "1"), text(fill: colp, "1"), text(fill: colu, "0"), text(fill: colu, "1"), text(fill: colu, "0");
|
|
text(fill: colp, "0"), text(fill: colp, "1"), text(fill: colu, "0"), text(fill: colu, "0"), text(fill: colu, "1")
|
|
)
|
|
$
|
|
]
|
|
]
|
|
#v(0.55em)
|
|
Mot de code valide $c = (#text(fill: colp)[1], #text(fill: colp)[1], #text(fill: colu)[1], #text(fill: colu)[0], #text(fill: colu)[1])$ : #h(0.4em) $H c^top = mat(0; 0; 0)$ #h(0.5em) #text(fill: green.darken(20%))[✓]
|
|
#v(-0.5em)
|
|
Mot reçu avec #text(fill: cole)[une erreur] : $r = (#text(fill: colp)[1], #text(fill: colp)[1], text(fill: cole, "0"), #text(fill: colu)[0], #text(fill: colu)[1])$
|
|
#v(0.4em)
|
|
#align(center)[
|
|
#scale(110%)[
|
|
$
|
|
H r^top = mat(
|
|
text(fill: colp, "1"), text(fill: colp, "0"), text(fill: colu, "1"), text(fill: colu, "0"), text(fill: colu, "0");
|
|
text(fill: colp, "1"), text(fill: colp, "1"), text(fill: colu, "0"), text(fill: colu, "1"), text(fill: colu, "0");
|
|
text(fill: colp, "0"), text(fill: colp, "1"), text(fill: colu, "0"), text(fill: colu, "0"), text(fill: colu, "1")
|
|
) mat(
|
|
text(fill: colp, "1"), text(fill: colp, "1"), text(fill: cole, "0"), text(fill: colu, "0"), text(fill: colu, "1")
|
|
)^top = mat(1; 0; 0) != mat(0; 0; 0)
|
|
$
|
|
]
|
|
]
|
|
]
|
|
|
|
// A REMPLACER AVEC DE VRAI DONNE SUR DE VRAI CODE LDPC ET HAMMING PAR EXEMPLE
|
|
#myslide("Approcher la Limite de Shannon")[
|
|
// Faire un graphique waterfall comme sur les papiers de recherche...
|
|
#limite_shannon_graphique()
|
|
]
|
|
|
|
// #myslide("Redondance et limite théorique")[
|
|
// Graphique waterfall avec n = 100 et n = 64800 avec limite de Shannon, $display(R = k /n) < 1$, $m = n - k$
|
|
//
|
|
// Bande passante...
|
|
//
|
|
// Il existe $C$ pour un canal tel que pour $R < C$ on peut atteindre une probabilité d'erreur nulle.
|
|
// $=>$ gros bloc (moyenne du bruit aléatoire)
|
|
// ]
|
|
|
|
#myslide("Le Mur de la Complexité")[
|
|
#place(dy: 2.5cm)[
|
|
#set text(size: 19pt)
|
|
#definition(titre: [Décodage par Maximum de Vraisemblance], accent: black)[
|
|
Chercher le mot de code $bold(c) in cal(C)$ le plus probable sachant $bold(r)$ reçu :
|
|
$ hat(bold(c)) = arg min_(bold(c) in cal(C)) d_H (bold(r), bold(c)) $
|
|
]
|
|
|
|
#text(size: 21pt)[
|
|
- Équivalent à chercher l'erreur $bold(e)$ de poids minimal tel que $bold(H) bold(e)^top = bold(s)$.
|
|
]
|
|
|
|
#v(0.5em)
|
|
|
|
#definition(titre: "Le Problème du décodage par Syndrome")[
|
|
NP-Difficile et pour $H$ quelconque : $cal(O)(2^k)$
|
|
]
|
|
|
|
// - Pour $k=100$ bits, $2^100 approx 10^30$ opérations nécessaires.
|
|
]
|
|
]
|
|
|
|
#myslide("Définition des Codes LDPC")[
|
|
#definition(titre: [Codes LDPC Réguliers])[
|
|
#text(size: 22.97pt)[
|
|
Code linéaire en bloc avec une matrice de contrôle $bold(H)$ *clairsemée*.
|
|
#align(center)[
|
|
#grid(
|
|
columns: (auto, 3em, auto),
|
|
align: left,
|
|
[- Poids de Colonne *$w_c$*], [], [- Poids de Ligne *$w_r$*],
|
|
)
|
|
]
|
|
]
|
|
]
|
|
|
|
#place(center, dx: -290pt, dy: 60pt)[
|
|
#text(size: 13pt, style: "italic", fill: luma(160))[
|
|
$H in cal(M)_(15, 30)(FF_2)$, $display(R = 1/2)$
|
|
]
|
|
]
|
|
#v(-0.3cm)
|
|
#align(center)[
|
|
#scale(100%)[#hldpc()]
|
|
]
|
|
|
|
#v(0.0cm)
|
|
#grid(
|
|
columns: (1fr, 1fr),
|
|
column-gutter: 1.75em,
|
|
[#definition(titre: "Faible Densité", accent: black)[
|
|
#set align(center)
|
|
$w_c << m$ #h(1cm) $w_r << n$
|
|
]],
|
|
[#definition(titre: "Rendement")[
|
|
#set align(center)
|
|
$R = 1 - m / n$
|
|
]],
|
|
)
|
|
]
|
|
|
|
// #myslide("Définition des Codes LDPC")[
|
|
// #v(1.3cm)
|
|
// #definition(titre: [Codes LDPC Réguliers])[
|
|
// #text(size: 22.97pt)[
|
|
// Code linéaire en bloc avec une matrice de contrôle $bold(H)$ *clairsemée*.
|
|
// ]
|
|
// ]
|
|
// #v(0.3em)
|
|
// #align(center + horizon)[
|
|
// #grid(
|
|
// columns: (auto, 3em, auto),
|
|
// align: left,
|
|
// [• Poids de Colonne *$w_c$*], [], [• Poids de Ligne *$w_r$*],
|
|
// )
|
|
// ]
|
|
// #v(0.5em)
|
|
//
|
|
// // - Poids de Colonne *$w_c$*
|
|
// //
|
|
// // - Poids de Ligne *$w_r$*
|
|
// //
|
|
// // #v(0.5em)
|
|
//
|
|
// #definition(titre: "Conditions de Faible Densité", accent: black)[
|
|
// #set align(center)
|
|
// // $w_c << n - k$ #h(2cm) $w_r << n$
|
|
// $w_c << m$ #h(2cm) $w_r << n$
|
|
// ]
|
|
//
|
|
// #definition(titre: "Rendement")[
|
|
// // $ display(R = (n - op("rg")(H)) / n >= 1 - m / n) $
|
|
// $ display(R = 1 - m / n) $
|
|
// ]
|
|
// ]
|
|
//
|
|
// #myslide([Matrice de contrôle])[
|
|
// // #definition(titre: [Code LDPC $(6, 3)$])[
|
|
// // $m w_r = n w_c$ donc $H in cal(M)_(15, 30)(FF_2)$ et $display(R = 1 - m / n = 1/2)$
|
|
// // ]
|
|
// #definition(titre: [Code LDPC $(6, 3)$])[
|
|
// #v(8pt)
|
|
// $H in cal(M)_(15, 30)(FF_2)$ et $display(R = 1/2)$
|
|
// #v(5pt)
|
|
// ]
|
|
//
|
|
// #v(2cm)
|
|
//
|
|
// #place(center + horizon, dx: 0cm, dy: 7.3cm)[
|
|
// #scale(140%)[#hldpc()]
|
|
// ]
|
|
// ]
|
|
|
|
#myslide("De la Matrice aux Équations de Parité")[
|
|
#set text(size: 17pt)
|
|
|
|
#let v_space = 2.83cm
|
|
|
|
#align(center)[
|
|
#scale(115%)[
|
|
#grid(
|
|
columns: (auto, auto),
|
|
gutter: -15pt,
|
|
align: horizon,
|
|
[#hldpc_dual(row1: 0, row2: none)],
|
|
[
|
|
// #set math.mat(gap: 24.5pt)
|
|
#move(dy: 13.8pt)[
|
|
$
|
|
underbrace(
|
|
mat(r_0; r_1; #v(v_space);dots.v; r_29; delim: "["),
|
|
#text()[Mot reçu] r space in space FF_2^30
|
|
)
|
|
$
|
|
]
|
|
],
|
|
)
|
|
]
|
|
]
|
|
|
|
#v(0.5cm)
|
|
|
|
#set text(size: 1.2em)
|
|
|
|
// - Chaque ligne $j$ de $H$ définit une équation de parité $f_j$.
|
|
- $L_j$ définit une équation de parité $f_j$
|
|
- Pour $r$, on vérifie le syndrome : $H r^top = 0$
|
|
#v(0.2cm)
|
|
|
|
#definition(titre: [Équations de Parité], accent: orange)[
|
|
#set text(size: 1em)
|
|
#text(fill: orange)[$ f_0 : r_7 plus.o r_10 plus.o r_15 plus.o r_22 plus.o r_24 plus.o r_29 = 0 $]
|
|
]
|
|
|
|
#v(0.3cm)
|
|
#text(size: 1.1em)[- Si $f_j = 1$, un nombre impair de bits a été inversé par le canal.]
|
|
]
|
|
|
|
// #myslide("L'Entrelacement des Contraintes")[
|
|
// #set text(size: 17pt)
|
|
//
|
|
// #align(center)[
|
|
// #move(dx: -1.2cm)[
|
|
// #scale(115%)[#hldpc_dual(row1: 0, row2: 14)]
|
|
// ]
|
|
// ]
|
|
//
|
|
// #v(1cm)
|
|
//
|
|
// #set text(size: 1.1em)
|
|
// - Chaque bit $r_i$ participe à $w_c = 3$ équations distinctes
|
|
//
|
|
// #v(1cm)
|
|
//
|
|
// // --- Étage 2 : Système et Décision ---
|
|
// #set align(center + horizon)
|
|
// #scale(115%)[
|
|
// #block(fill: gray.lighten(95%), inset: 10pt, stroke: 0.5pt + gray, radius: 4pt)[
|
|
// $
|
|
// cases(
|
|
// #text(fill: orange)[$r_7 plus.o r_10 plus.o r_15 plus.o r_22 plus.o bold(r_24) plus.o r_29 &= 0$],
|
|
// #h(4.5cm) #text(size: 20pt)[$bold(dots.v)$],
|
|
// #text(fill: blue)[$r_1 plus.o r_3 plus.o r_12 plus.o bold(r_24) plus.o r_25 plus.o r_28 &= 0$]
|
|
// )
|
|
// $
|
|
// ]
|
|
// ]
|
|
//
|
|
// #v(1cm)
|
|
//
|
|
// #set align(left)
|
|
// #set text(size: 1.1em)
|
|
// - *$r_24$* : Surveillé par #text(fill: orange)[$f_0$] et #text(fill: blue)[$f_14$].
|
|
// - Si #text(fill: orange)[$f_0 = 1$] et #text(fill: blue)[$f_14 = 1$], $r_24$ est suspect
|
|
// ]
|
|
|
|
#myslide("L'Entrelacement des Contraintes")[
|
|
#v(0.7cm)
|
|
#set text(size: 20pt)
|
|
#align(center)[
|
|
#move(dx: -1.2cm)[
|
|
// #scale(110%)[#hldpc_triple(row1: 0, row2: 9, row3: 14)]
|
|
#scale(110%)[#hldpc_col24(row1: 0, row2: 9, row3: 14, col: 24)]
|
|
]
|
|
]
|
|
#v(0.5cm)
|
|
- Chaque bit $r_i$ participe à $w_c = 3$ équations distinctes :
|
|
#v(0.3cm)
|
|
#align(center)[
|
|
#block(fill: gray.lighten(95%), inset: 10pt, stroke: 0.5pt + gray, radius: 4pt)[
|
|
$
|
|
cases(
|
|
#text(fill: orange)[$r_7 plus.o r_10 plus.o r_15 plus.o r_22 plus.o$ #text(fill: red)[$bold(r_24)$] #text(fill: orange)[$plus.o r_29 &= 0 quad (f_0)$]],
|
|
#text(fill: green.darken(20%))[$r_7 plus.o r_13 plus.o r_23 plus.o$ #text(fill: red)[$bold(r_24)$] #text(fill: green.darken(20%))[$plus.o r_25 plus.o r_27 &= 0 quad (f_9)$]],
|
|
#text(fill: blue)[$r_1 plus.o r_3 space thick$] #h(0.3pt) #text(fill: blue)[$plus.o r_12 plus.o$ #text(fill: red)[$bold(r_24)$] #text(fill: blue)[$plus.o r_25 plus.o r_28 &= 0 quad (f_14)$]]
|
|
)
|
|
$
|
|
]
|
|
]
|
|
#v(0.5cm)
|
|
- *$r_24$* : Surveillé simultanément par #text(fill: orange)[$f_0$], #text(fill: green.darken(20%))[$f_9$] et #text(fill: blue)[$f_14$].
|
|
- Si $forall #tricolor-j in {#text(fill: orange)[$0$], #text(fill: green.darken(20%))[$9$], #text(fill: blue)[$14$]}, space f_(#scale(80%)[#tricolor-j]) = 1$, alors le bit est considéré suspect.
|
|
]
|
|
|
|
#myslide("Graphe de Tanner : Définition")[
|
|
#set text(size: 1em)
|
|
#definition(titre: [Graphe de Tanner $cal(G)(bold(H))$])[
|
|
#set text(size: 0.9em)
|
|
Graphe bipartite $cal(G) = (#text(fill: blue)[$V$] union.sq #text(fill: orange)[$C$], A)$
|
|
:
|
|
#v(4pt)
|
|
$ (#text(fill: blue)[$v_j$], #text(fill: orange)[$c_i$]) in A space <==> space H_(i,j) = 1 $
|
|
]
|
|
|
|
#v(0.4em)
|
|
|
|
#set text(size: 1.1em)
|
|
#grid(
|
|
columns: (1.4fr, 1fr),
|
|
gutter: 1em,
|
|
[- $#text(fill: blue)[$V$] = {#text(fill: blue)[$v_0$], dots, #text(fill: blue)[$v_(n-1)$]}$ nœuds de *variable*],
|
|
[- $|A| = n dot #text(fill: blue)[$w_c$] = m dot #text(fill: orange)[$w_r$]$],
|
|
|
|
[
|
|
- $#text(fill: orange)[$C$] = {#text(fill: orange)[$c_0$], dots, #text(fill: orange)[$c_(m-1)$]}$ nœuds de *contrôle*
|
|
],
|
|
[- $H tilde.equiv cal(G)$],
|
|
|
|
[- $deg(#text(fill: blue)[$v_j$]) = #text(fill: blue)[$w_c$]$],
|
|
[- $deg(#text(fill: orange)[$c_i$]) = #text(fill: orange)[$w_r$]$],
|
|
)
|
|
|
|
#align(center)[
|
|
#scale(115%)[
|
|
#tanner_illustration()
|
|
]
|
|
#text(size: 0.8em, style: "italic", fill: gray.darken(20%))[
|
|
Exemple $n=4, space m=2$
|
|
]
|
|
]
|
|
]
|
|
|
|
#myslide("Construction du Graphe : Les Nœuds")[
|
|
|
|
#v(1.2em)
|
|
|
|
#align(center)[
|
|
#scale(100%)[
|
|
// #h_mini_tanner()
|
|
#grid(
|
|
columns: (1fr, 1fr),
|
|
gutter: 1em,
|
|
|
|
[#hldpc_dynamic(hl_cols: range(30), show_labels: false, h_show: true)],
|
|
[#hldpc_dynamic(hl_rows: range(15), show_labels: false, h_show: false)],
|
|
)
|
|
]
|
|
]
|
|
|
|
#v(3.5em)
|
|
|
|
#align(center)[
|
|
#scale(180%)[
|
|
#tanner_canvas(colored: true)
|
|
]
|
|
]
|
|
|
|
// #v(2.5em)
|
|
|
|
// #[
|
|
// #set text(size: 1.05em)
|
|
// - Chaque *colonne* $j$ de $bold(H)$ $arrow$ nœud de variable #text(fill: blue, weight: "bold")[$v_j in V$] \ #text(fill: blue)[$n = 30$] nœuds, représentés par des *cercles* ○
|
|
// - Chaque *ligne* $i$ de $bold(H)$ $arrow$ nœud de contrôle #text(fill: orange, weight: "bold")[$c_i in C$] \ #text(fill: orange)[$m = 15$] nœuds, représentés par des *carrés* □
|
|
// - Les arêtes seront déterminées par les $1$ de $bold(H)$ — étapes suivantes
|
|
// ]
|
|
]
|
|
|
|
#myslide("Construction du Graphe : Nœud de Contrôle")[
|
|
|
|
#v(1.2em)
|
|
|
|
#align(center)[
|
|
#move(dx: 12.6pt, dy: -1.3pt)[
|
|
#scale(100%)[
|
|
#hldpc_dynamic(hl_rows: (0,), show_labels: true, h_show: true)
|
|
]
|
|
]
|
|
]
|
|
|
|
#v(3.5em)
|
|
|
|
#align(center)[
|
|
#move(dx: 2.7pt, dy: -13.8pt)[
|
|
#scale(180%)[
|
|
#tanner_canvas(hl_row: 0)
|
|
]
|
|
]
|
|
]
|
|
|
|
// #v(0.4em)
|
|
// #[
|
|
// #set text(size: 1.05em)
|
|
// - Ligne #text(fill: orange, weight: "bold")[0] de $bold(H)$ : $bold(H)_(0,j) = 1$ pour $j in {7, 10, 15, 22, 24, 29}$
|
|
// - #text(fill: orange)[$c_0$] est relié à #text(fill: orange)[$v_7, v_10, v_15, v_22, v_24, v_29$] — chaque 1 crée une arête
|
|
// - $deg(c_0) = 6 = w_r$ — $c_0$ porte l'équation : #text(fill: orange)[$f_0 : r_7 plus.o r_10 plus.o r_15 plus.o r_22 plus.o r_24 plus.o r_29 = 0$]
|
|
// ]
|
|
]
|
|
|
|
#myslide("Construction du Graphe : Nœud de Variable")[
|
|
|
|
#v(1.2em)
|
|
|
|
#align(center)[
|
|
#scale(100%)[
|
|
#hldpc_dynamic(hl_cols: (10,), show_labels: true, h_show: true)
|
|
]
|
|
]
|
|
|
|
#v(3.5em)
|
|
|
|
#align(center)[
|
|
#move(dx: -0pt, dy: -39pt)[
|
|
#scale(180%)[
|
|
#tanner_canvas(hl_col: 10)
|
|
]
|
|
]
|
|
]
|
|
// #v(0.15em)
|
|
// #align(center)[
|
|
// #grid(
|
|
// columns: (auto, auto),
|
|
// column-gutter: 0.7cm,
|
|
// align: horizon,
|
|
// [#h_mini_tanner(hl_col: 10)], [#tanner_canvas(hl_col: 10)],
|
|
// )
|
|
// ]
|
|
|
|
// #[
|
|
// #set text(size: 1.05em)
|
|
// - Colonne #text(fill: blue, weight: "bold")[10] de $bold(H)$ : $bold(H)_(i,10) = 1$ pour $i in {0, 5, 11}$
|
|
// - #text(fill: blue)[$v_10$] est relié aux nœuds de contrôle #text(fill: blue)[$c_0, c_5, c_11$] — participe à *3 équations* de parité
|
|
// - $deg(v_10) = 3 = w_c$ — chaque bit est surveillé par $w_c$ contraintes indépendantes
|
|
// ]
|
|
]
|
|
|
|
#myslide("Graphe de Tanner Final")[
|
|
|
|
#move(dy: 4.5cm)[
|
|
#align(center + horizon)[
|
|
#tanner_canvas(scale: 0.91cm, show_all: true, colored: true, v_c_show: false)
|
|
]
|
|
|
|
#align(center)[
|
|
#grid(
|
|
columns: (1fr, 1fr),
|
|
gutter: 0.45cm,
|
|
block(
|
|
fill: blue.lighten(88%),
|
|
stroke: 0.5pt + blue.lighten(40%),
|
|
radius: 6pt,
|
|
inset: (x: 10pt, y: 8pt),
|
|
width: 100%,
|
|
)[
|
|
#place(dx: 47pt, dy: -0pt)[#scale(110%)[#icon_var]] #text(fill: blue, weight: "bold")[ Nœuds de variable] \
|
|
// $n = 30 quad deg = w_c = 3$
|
|
],
|
|
block(
|
|
fill: orange.lighten(88%),
|
|
stroke: 0.5pt + orange.lighten(40%),
|
|
radius: 6pt,
|
|
inset: (x: 10pt, y: 8pt),
|
|
width: 100%,
|
|
)[
|
|
#place(dx: 47pt, dy: -0pt)[#scale(110%)[#icon_chk]] #text(
|
|
fill: orange,
|
|
weight: "bold",
|
|
)[ Nœuds de contrôle] \
|
|
// $m = 15 quad deg = w_r = 6$
|
|
],
|
|
)
|
|
]
|
|
]
|
|
]
|
|
|
|
#let mot_valide = (
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
0,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
0,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
1,
|
|
0,
|
|
1,
|
|
0,
|
|
0,
|
|
)
|
|
|
|
#myslide("La Contrainte de Somme Nulle")[
|
|
#set text(size: 18pt)
|
|
|
|
#definition(titre: "Vision Graphe", accent: green)[
|
|
Si $s = 0$ alors que chaque nœud de contrôle est localement satisfait
|
|
]
|
|
|
|
#v(1cm)
|
|
|
|
#align(center)[
|
|
#scale(150%)[
|
|
#tanner_status(
|
|
scale: 0.55cm,
|
|
v_values: mot_valide,
|
|
hl_v: (),
|
|
)
|
|
]
|
|
]
|
|
|
|
#v(1.2cm)
|
|
|
|
#set text(size: 20pt)
|
|
#align(center + horizon)[
|
|
Chaque #icon_chk calcule le xor de ses voisins #icon_var : $space display(f_i = xor.big_(j in cal(N)(c_i)) v_j)$
|
|
]
|
|
|
|
#v(1em)
|
|
#align(center)[
|
|
#move(dy: -10pt)[
|
|
#scale(150%)[
|
|
#zoom_contrainte(is_ok: true)
|
|
]
|
|
]
|
|
]
|
|
|
|
// #v(1em)
|
|
// #block(inset: 10pt, fill: rgb("#f0fdf4"), stroke: 1pt + rgb("#22c55e"), radius: 5pt)[
|
|
// Toutes les équations de parité sont vérifiées simultanément.
|
|
// ]
|
|
]
|
|
|
|
#myslide("La Contrainte de Somme Nulle")[
|
|
#set text(size: 18pt)
|
|
|
|
#definition(titre: "Détection d'Erreur", accent: red)[
|
|
Si un bit est inversé, toutes les contraintes associées sont à $1$
|
|
]
|
|
|
|
#v(1cm)
|
|
|
|
#align(center)[
|
|
#let idx_erreur = 10
|
|
#let mot_erronne = mot_valide.enumerate().map(p => if p.first() == idx_erreur { 1 } else { p.last() })
|
|
#scale(150%)[
|
|
#tanner_status(
|
|
scale: 0.55cm,
|
|
v_values: mot_erronne,
|
|
hl_v: (idx_erreur,),
|
|
highlight_edges: true,
|
|
)
|
|
]
|
|
]
|
|
|
|
#v(1.3cm)
|
|
|
|
#align(center)[
|
|
$0 plus.o bold(1) plus.o 0 = bold(1) arrow$ *Erreur détectée*
|
|
]
|
|
|
|
#v(1em)
|
|
#align(center)[
|
|
#move(dy: 11.5pt)[
|
|
#scale(150%)[
|
|
#zoom_contrainte(is_ok: false)
|
|
]
|
|
]
|
|
]
|
|
|
|
// #block(inset: 10pt, fill: rgb("#fef2f2"), stroke: 1pt + red, radius: 5pt)[
|
|
// *Principe du décodage :*
|
|
// Le bit $v_{10}$ est relié à *plusieurs alarmes* (arêtes rouges au premier plan). Il est le suspect idéal pour une correction par "bit-flipping".
|
|
// ]
|
|
]
|
|
|
|
|
|
#myslide("Encodage LDPC : Calcul de G")[
|
|
#set text(size: 18pt)
|
|
|
|
#definition(titre: "Encodage", accent: blue)[
|
|
Mot de code $bold(c)$ généré à partir d'un message $bold(u)$ :
|
|
$bold(c) = bold(u) bold(G)$\
|
|
// $bold(H) bold(G)^top = bold(0)$
|
|
]
|
|
|
|
#v(2em)
|
|
|
|
#align(center)[#scale(135%)[#paradoxe_densite_reel()]]
|
|
|
|
#v(2em)
|
|
|
|
#set text(size: 1em)
|
|
// - Forme Systématique : Par élimination de Gauss sur $bold(H)$, on obtient
|
|
- Forme Systématique
|
|
|
|
#v(1em)
|
|
#align(center)[
|
|
#schema_systematique()
|
|
]
|
|
|
|
#v(1em)
|
|
#set text(size: 1em)
|
|
- La matrice $bold(G)$ devient dense $=>$ encodage en $cal(O)(n^2)$
|
|
|
|
// #v(1em)
|
|
// #block(fill: rgb("#fef2f2"), stroke: 1pt + red, inset: 10pt, radius: 5pt)[
|
|
// *Défi Matériel :* Pour $n=64\,800$ (DVB-S2), $n^2$ est prohibitif. Solution : les codes *quasi-cycliques* (5G).
|
|
// ]
|
|
]
|
|
|
|
#myslide("Décodage : Bit-Flipping")[
|
|
#set text(size: 16pt)
|
|
|
|
#definition(titre: "Décision Stricte (Hard Decision)", accent: black)[
|
|
Algorithme *itératif* : les nœuds *échangent des bits* pour localiser les erreurs.
|
|
]
|
|
|
|
#v(0.2em)
|
|
|
|
#set text(size: 1em)
|
|
|
|
#set text(size: 16pt)
|
|
#definition(titre: "Message Passing", accent: blue)[
|
|
// L'information *circule le long des arêtes* du graphe de Tanner à chaque itération.
|
|
- #icon_var envoie son bit courant à ses voisins #icon_chk
|
|
- #icon_chk renvoie son *verdict de parité* ($0$ ou $1$)
|
|
]
|
|
|
|
#v(0.6em)
|
|
|
|
#set text(1em)
|
|
- Si $v_j$ participe à *trop d'équations non satisfaites* $=>$ on l'inverse.
|
|
|
|
#uncover(2)[
|
|
#grid(
|
|
columns: (1fr, 1fr, 1fr),
|
|
column-gutter: 10pt,
|
|
// On aligne tout par le bas (bottom) pour que les CN soient sur la même ligne
|
|
align: center + bottom,
|
|
[
|
|
#bf_step1_sending()
|
|
#v(-0.5em)
|
|
#text(style: "italic", fill: gray.darken(40%), size: 0.8em)[VN $arrow$ CN]
|
|
],
|
|
[
|
|
#bf_step2_verdict()
|
|
#v(-0.5em)
|
|
#text(style: "italic", fill: gray.darken(40%), size: 0.8em)[CN $arrow$ VN]
|
|
],
|
|
[
|
|
#bf_step3_flip()
|
|
#v(-0.5em)
|
|
#text(style: "italic", fill: gray.darken(40%), size: 0.8em)[Correction]
|
|
],
|
|
)
|
|
]
|
|
// #align(center + horizon)[
|
|
// #scale(100%)[#bp_hard_diagram()]
|
|
// #v(0.4em)
|
|
// #text(
|
|
// size: 0.72em,
|
|
// style: "italic",
|
|
// fill: gray.darken(20%),
|
|
// )[Échanges itératifs entre $V$ (cercles) et $C$ (carrés)]
|
|
// ]
|
|
]
|
|
|
|
#myslide("Bit-Flipping : Graphe de flot de contrôle")[
|
|
#set text(size: 17pt)
|
|
|
|
// #grid(
|
|
// columns: (1.25fr, 0.75fr),
|
|
// gutter: 0.8cm,
|
|
// align: top,
|
|
// [
|
|
// #step_box(1, orange)[
|
|
// *CN Update — Évaluation* \
|
|
// #set text(size: 0.88em)
|
|
// Chaque nœud de contrôle $c_i$ calcule sa parité :
|
|
// $
|
|
// f_i = xor.big_(j in cal(N)(c_i)) v_j in {0, 1}
|
|
// $
|
|
// Si $f_i = 1$ : *l'équation n'est pas satisfaite* $=>$ $c_i$ envoie le message "Erreur" à tous ses voisins.
|
|
// ]
|
|
//
|
|
// #v(0.45em)
|
|
//
|
|
// #step_box(2, blue)[
|
|
// *VN Update — Vote* \
|
|
// #set text(size: 0.88em)
|
|
// Chaque bit $v_j$ compte ses alarmes reçues $k_j$.
|
|
// Si $k_j$ dépasse le seuil (ex. *majorité*) :
|
|
// $
|
|
// v_j arrow.l 1 - v_j quad ("FLIP")
|
|
// $
|
|
// ]
|
|
//
|
|
// #v(0.45em)
|
|
//
|
|
// #step_box(3, green.darken(10%))[
|
|
// *Vérification — Syndrome* \
|
|
// #set text(size: 0.88em)
|
|
// On recalcule $bold(s) = bold(H) bold(r)^top$.
|
|
// - Si $bold(s) = bold(0)$ : *Succès*, on s'arrête.
|
|
// - Sinon : on recommence l'étape ① (jusqu'à `max_iter`).
|
|
// ]
|
|
// ],
|
|
// [
|
|
// #align(center)[
|
|
// #v(0.3em)
|
|
// #scale(96%)[#schema_boucle_bf()]
|
|
// ]
|
|
// ],
|
|
// )
|
|
#align(center + horizon)[
|
|
#move(dx: 2.5cm, dy: -0.5cm)[#scale(95%)[#schema_boucle_bf()]]
|
|
]
|
|
]
|
|
|
|
#let log10(x) = if x < 1e-9 { -9.0 } else { calc.log(x) / calc.log(10) }
|
|
|
|
#let raw_waterfall = (
|
|
(0.0, 0.158461, 0.281269),
|
|
(1.0, 0.130748, 0.247257),
|
|
(2.0, 0.104310, 0.205882),
|
|
(3.0, 0.079301, 0.151808),
|
|
(4.0, 0.056395, 0.063852),
|
|
(4.5, 0.046493, 0.023414),
|
|
(5.0, 0.037572, 0.004078),
|
|
(5.5, 0.029673, 0.000470),
|
|
(6.0, 0.022973, 0.000045),
|
|
(7.0, 0.012519, 0.000002),
|
|
(8.0, 0.006030, 0.000000001),
|
|
// On lisse la fin pour éviter l'effet "escalier"
|
|
(8.5, 0.004200, 0.0),
|
|
(9.0, 0.002800, 0.0),
|
|
(9.5, 0.001800, 0.0),
|
|
(10.0, 0.001100, 0.0),
|
|
)
|
|
|
|
#let pts_unc = raw_waterfall.map(r => (r.at(0), log10(r.at(1))))
|
|
#let pts_bf = raw_waterfall.map(r => (r.at(0), log10(r.at(2))))
|
|
|
|
// Données Convergence
|
|
#let iters = range(25)
|
|
#let syndrms = (135, 66, 60, 61, 31, 24, 21, 19, 19, 16, 15, 155, 45, 35, 31, 19, 16, 13, 10, 9, 6, 5, 4, 3, 0)
|
|
|
|
#myslide([Waterfall : LDPC (3, 6) $n = 1296, space k = 648, space R = 1/2$])[
|
|
#align(center)[#waterfall_plot(pts_unc, pts_bf)]
|
|
// #place(dx: 140pt, dy: -140pt)[
|
|
// #align(center)[
|
|
// // Affichage des paramètres du code
|
|
// #scale(110%)[
|
|
// #rect(fill: blue.lighten(95%), stroke: 0.5pt + blue.lighten(80%), radius: 4pt, inset: 10pt)[
|
|
// #set text(size: 18pt)
|
|
// *LDPC $(3, 6)$* #h(1cm)
|
|
// $n = 1296$, $k = 648$ #h(1cm)
|
|
// Rendement $R = 1/2$
|
|
// ]]
|
|
// ]
|
|
// ]
|
|
]
|
|
|
|
// #myslide([Résultats : Convergence syndrome])[
|
|
// #align(center)[#convergence_plot(iters, syndrms)]
|
|
// ]
|
|
|
|
// #myslide("Bit-Flipping : Analyse")[
|
|
#myslide("Bit-Flipping : Syndrome et Analyse")[
|
|
#place(center + horizon, dx: -2cm, dy: 8cm)[#convergence_plot(iters, syndrms)]
|
|
// TODO PARLER DU GIRTH 4 => MAUVAIS
|
|
#set text(size: 17pt)
|
|
|
|
#uncover(2)[
|
|
#place(dx: 13cm, dy: 1.0cm)[
|
|
#scale(100%)[
|
|
#definition(titre: "Avantages", accent: green.darken(10%), compact: true)[
|
|
#set text(size: 0.88em)
|
|
- *Complexité* : XOR et compteurs
|
|
- $cal(O)(n)$ par itération
|
|
// - *Matériel* : idéal FPGA/ASIC, massivement parallélisable
|
|
// - *Simplicité* : inventé par Gallager (1962)
|
|
]
|
|
]
|
|
|
|
#place(dx: -1.5cm, dy: 1.0cm)[
|
|
#scale(100%)[
|
|
#definition(titre: "Limite", accent: red, compact: true)[
|
|
#set text(size: 0.88em)
|
|
- Ignore la *confiance* du récepteur physique
|
|
- Un bit reçu à $0.51$ V est traité comme $0$
|
|
// - $=>$ Sous-optimal par rapport à la limite de Shannon
|
|
|
|
// #v(0.3em)
|
|
// #align(center)[
|
|
// #box(fill: rgb("#fff7ed"), stroke: (left: 3pt + orange), inset: (x: 8pt, y: 5pt))[
|
|
// #text(
|
|
// size: 0.82em,
|
|
// )[$arrow$ Nécessite le *Soft-Decision* (Belief Propagation) pour exploiter les niveaux de gris du signal]
|
|
// ]
|
|
// ]
|
|
]]
|
|
]]
|
|
]
|
|
|
|
]
|
|
|
|
#myslide("Décodage Soft : Le LLR")[
|
|
#set text(size: 17pt)
|
|
|
|
#definition(titre: "Signal", accent: blue.darken(10%))[
|
|
On reçoit une valeur $y_i$ (ex: $+4.5$V ou $-0.2$V).
|
|
]
|
|
|
|
#v(0.6em)
|
|
|
|
#definition(titre: "Log-Likelihood Ratio (LLR)", accent: black)[
|
|
$
|
|
L(v_i) = ln(display(frac(P(v_i = 0 | y_i), P(v_i = 1 | y_i))))
|
|
$
|
|
]
|
|
|
|
#v(2em)
|
|
|
|
#align(center)[
|
|
#move(dx: 1.05cm)[
|
|
#scale(160%)[#schema_llr_droite()]
|
|
]
|
|
]
|
|
|
|
#v(1.7em)
|
|
|
|
// Blocs de légende centrés
|
|
#align(center)[
|
|
#grid(
|
|
columns: (220pt, 220pt),
|
|
gutter: 1cm,
|
|
block(fill: blue.lighten(92%), stroke: 1pt + blue, radius: 6pt, inset: 12pt)[
|
|
#align(center)[
|
|
#text(fill: blue.darken(20%), weight: "bold")[Signe] \
|
|
#text(size: 0.85em)[Définit la valeur du bit]
|
|
]
|
|
],
|
|
block(fill: orange.lighten(90%), stroke: 1pt + orange, radius: 6pt, inset: 12pt)[
|
|
#align(center)[
|
|
#text(fill: orange.darken(20%), weight: "bold")[|Valeur|] \
|
|
#text(size: 0.85em)[Confiance dans la décision]
|
|
]
|
|
],
|
|
)
|
|
]
|
|
]
|
|
|
|
#myslide("Sum-Product : Belief Propagation")[
|
|
#set text(size: 17pt)
|
|
#v(-0.7em)
|
|
|
|
#definition(titre: "Décodage Optimal")[
|
|
Échange itératif de croyances (LLR) entre les nœuds du graphe
|
|
]
|
|
|
|
#definition(titre: "Information Extrinsèque")[
|
|
Exclure l'avis du destinataire pour éviter l'auto-influence
|
|
]
|
|
|
|
|
|
#block(
|
|
fill: orange.lighten(92%),
|
|
stroke: (left: 4pt + orange),
|
|
radius: 4pt,
|
|
inset: 18pt,
|
|
width: 100%,
|
|
)[
|
|
#set text(size: 1.2em)
|
|
*Mise à jour* \
|
|
#set text(size: 1.1em)
|
|
// $ tanh(m_(c arrow v) / 2) = product_(u != v) tanh(m_(u arrow c) / 2) $
|
|
$ m_(c arrow v) = 2 tanh^(-1) ( product_(u in cal(N)(c) \\ {v}) tanh(m_(u arrow c) / 2) ) $
|
|
]
|
|
|
|
#place(dx: 5.2cm, dy: -5.2cm)[#scale(170%)[#icon_chk]]
|
|
|
|
#block(
|
|
fill: blue.lighten(92%),
|
|
stroke: (left: 4pt + blue),
|
|
radius: 4pt,
|
|
inset: 18pt,
|
|
width: 100%,
|
|
)[
|
|
#set text(size: 1.2em)
|
|
*Mise à jour* \
|
|
#set text(size: 1.1em)
|
|
// $ m_(v arrow c) = L_"canal" + sum_(c' != c) m_(c' arrow v) $
|
|
// $ m_(v arrow c) = L_v^((0)) + sum_(c' in cal(N)(v) \\ {c}) m_(c' arrow v) $
|
|
$ m_(v arrow c) = L_(v"canal") + sum_(c' in cal(N)(v) \\ {c}) m_(c' arrow v) $
|
|
]
|
|
|
|
#place(dx: 5.2cm, dy: -3.85cm)[#scale(170%)[#icon_var]]
|
|
]
|
|
|
|
#myslide("Sum-Product")[
|
|
#set text(size: 16pt)
|
|
|
|
#place(left, dx: 1.5cm, dy: 0cm)[
|
|
#text(weight: "bold", size: 1.1em * 1.3)[Initialisation]
|
|
]
|
|
|
|
#place(left, dx: 1.5cm, dy: 2cm)[
|
|
#scale(130%)[
|
|
#grid(
|
|
columns: 1,
|
|
gutter: 0.2cm,
|
|
align: horizon,
|
|
schema_detailed_init(),
|
|
text(size: 0.9em)[$m_(v_j arrow c_i) = L_"canal"$],
|
|
)
|
|
]
|
|
]
|
|
|
|
#place(right, dx: -4.5cm, dy: 0cm)[
|
|
#text(weight: "bold", fill: orange, size: 1.1em * 1.3)[Échange]
|
|
]
|
|
|
|
#place(dx: 21cm, dy: 0.1cm)[#scale(170%)[#icon_chk]]
|
|
|
|
#place(right, dx: -1cm, dy: 2.7cm)[
|
|
#scale(130%)[
|
|
#schema_detailed_cn()
|
|
]
|
|
]
|
|
|
|
#place(left, dx: 1.5cm, dy: 9cm)[
|
|
#text(weight: "bold", fill: blue, size: 1.1em * 1.3)[Échange]
|
|
]
|
|
|
|
#place(dx: 5.4cm, dy: 9.15cm)[#scale(170%)[#icon_var]]
|
|
|
|
#place(left, dx: 1.5cm, dy: 11cm)[
|
|
#scale(130%)[
|
|
#schema_detailed_vn()
|
|
]
|
|
]
|
|
|
|
#place(right, dx: -3.5cm, dy: 9cm)[
|
|
#text(weight: "bold", fill: green, size: 1.1em * 1.3)[Décision Finale]
|
|
]
|
|
|
|
#place(right, dx: -1cm, dy: 11cm)[
|
|
#scale(145%)[
|
|
#schema_detailed_decision()
|
|
]
|
|
]
|
|
|
|
#place(center + horizon, dx: -0.9cm, dy: 8.2cm)[
|
|
#scale(115%)[
|
|
#cetz.canvas(length: 1cm, {
|
|
import cetz.draw: *
|
|
|
|
let col_iter = gray.darken(50%)
|
|
|
|
arc(
|
|
(0, 0),
|
|
radius: 1.8,
|
|
start: 150deg,
|
|
delta: -300deg,
|
|
stroke: (paint: col_iter, thickness: 2pt, cap: "round"),
|
|
mark: (end: "stealth", fill: col_iter, size: 0.3),
|
|
)
|
|
|
|
content((1.6, -1), [
|
|
#set text(fill: col_iter, weight: "bold", size: 0.8em)
|
|
#set align(center)
|
|
Itérations\
|
|
$i = 1, dots, I_(max)$
|
|
])
|
|
})
|
|
]
|
|
]
|
|
]
|
|
|
|
#myslide([Transmission d'image])[
|
|
#place(center, dy: -2cm)[
|
|
#scale(85%)[
|
|
#simulation_image_flow(
|
|
image("src/origine.png", width: 100%),
|
|
image("src/noisy.png", width: 100%),
|
|
image("src/decoded_R05_1-2.png", width: 100%),
|
|
image("src/decoded_R66_2-3.png", width: 100%),
|
|
image("src/decoded_R75_3-4.png", width: 100%),
|
|
img_w: 230pt,
|
|
gap_top: 7.0,
|
|
gap_bot: 2.0,
|
|
)
|
|
]
|
|
]
|
|
]
|
|
|
|
#myslide("Min-Sum")[
|
|
#set text(size: 15pt)
|
|
|
|
// #grid(
|
|
// columns: (1fr, 1fr),
|
|
// gutter: 0.5cm,
|
|
// definition(titre: "Avantage Matériel", accent: black)[
|
|
// - *Comparateurs* pour le minimum
|
|
// - *XOR* pour le produit des signes
|
|
// #v(0.21cm)
|
|
// ],
|
|
// definition(titre: "Mise à jour des CN", accent: orange)[
|
|
// #set text(size: 19pt)
|
|
// $
|
|
// m_(c arrow v_i) = product_(j != i) "sgn"(m_(v_j arrow c)) times min_(j != i) |m_(v_j arrow c)|
|
|
// $
|
|
// ],
|
|
// definition(titre: "Mise à jour des CN", accent: orange)[
|
|
// #set text(size: 19pt)
|
|
// $
|
|
// m_(c arrow v) = product_(u in cal(N)(c) \\ {v}) "sgn"(m_(u arrow c)) times min_(u in cal(N)(c) \\ {v}) |m_(u arrow c)|
|
|
// $
|
|
// ],
|
|
// definition(titre: "Mise à jour des CN", accent: orange)[
|
|
// #set text(size: 19pt)
|
|
// $
|
|
// m_(c arrow v) = & product_(u in cal(N)(c) \\ {v}) "sgn"(m_(u arrow c)) \
|
|
// & times min_(u in cal(N)(c) \\ {v}) |m_(u arrow c)|
|
|
// $
|
|
// ],
|
|
// )
|
|
#definition(titre: "Avantage Matériel", accent: black, titre_taille: 1.4em)[
|
|
- *Comparateurs* pour le minimum
|
|
- *XOR* pour le produit des signes
|
|
#v(0.21cm)
|
|
]
|
|
|
|
#definition(titre: "Mise à jour des CN", accent: orange, titre_taille: 1.4em)[
|
|
#set text(size: 24pt)
|
|
$
|
|
m_(c arrow v) = product_(u in cal(N)(c) \\ {v}) "sgn"(m_(u arrow c)) times min_(u in cal(N)(c) \\ {v}) |m_(u arrow c)|
|
|
$
|
|
]
|
|
|
|
#v(1.5em)
|
|
|
|
#align(center)[#scale(130%)[#schema_min_sum_complet()]]
|
|
|
|
#v(-0.5em)
|
|
#align(center)[
|
|
#text(size: 1.1em, fill: gray.darken(40%), style: "italic")[
|
|
Pour les VN : $display(m_(v arrow c) = L_"canal" + sum_(c' in cal(N)(v) \\ {c}) m_(c' arrow v))$
|
|
]
|
|
]
|
|
]
|
|
|
|
#let log10(x) = if x <= 1e-9 { -8.0 } else { calc.log(x) / calc.log(10) }
|
|
|
|
#let raw_data = (
|
|
(0.00, 1.2397e-1, 4.9986e-1, 1.1404e-1, 1.2470e-1),
|
|
(0.50, 1.1057e-1, 4.9993e-1, 9.5550e-2, 1.0485e-1),
|
|
(1.00, 9.7682e-2, 4.9978e-1, 7.5017e-2, 8.2555e-2),
|
|
(1.50, 8.4916e-2, 4.9993e-1, 4.6412e-2, 5.1824e-2),
|
|
(2.00, 7.3000e-2, 5.0008e-1, 1.1640e-2, 1.3790e-2),
|
|
(2.50, 6.1705e-2, 4.9987e-1, 4.0818e-4, 5.3380e-4),
|
|
(3.00, 5.1501e-2, 5.0020e-1, 4.8765e-5, 8.0247e-6),
|
|
(3.50, 4.1921e-2, 5.0005e-1, 0, 0),
|
|
(4.00, 3.3645e-2, 4.9959e-1, 0, 0),
|
|
(5.00, 1.9973e-2, 4.9890e-1, 0, 0),
|
|
(6.00, 1.0584e-2, 3.8048e-1, 0, 0),
|
|
(7.00, 4.8994e-3, 4.0660e-2, 0, 0),
|
|
(8.00, 1.8194e-3, 3.8519e-4, 0, 0),
|
|
(9.00, 5.6235e-4, 8.1790e-6, 0, 0),
|
|
(10.00, 1.3133e-4, 6.1728e-7, 0, 0),
|
|
(11.00, 2.5154e-5, 0, 0, 0),
|
|
)
|
|
|
|
#let pts_unc = raw_data.map(d => (d.at(0), log10(d.at(1))))
|
|
#let pts_bf = raw_data.map(d => (d.at(0), log10(d.at(2))))
|
|
#let pts_sp = raw_data.map(d => (d.at(0), log10(d.at(3))))
|
|
#let pts_ms = raw_data.map(d => (d.at(0), log10(d.at(4))))
|
|
|
|
#myslide([Waterfall : LDPC (3, 9) $n = 1296, space k = 864, space R = 2/3$])[
|
|
#align(center)[
|
|
// #rect(fill: gray.lighten(95%), radius: 4pt, inset: 8pt)[
|
|
// #set text(size: 16pt)
|
|
// Comparaison BER : *Bit-Flipping* (Décision dure) vs *Soft-Decisions* (SP & MS)
|
|
// ]
|
|
#comparison_waterfall_plot(pts_unc, pts_bf, pts_sp, pts_ms)
|
|
]
|
|
]
|
|
|
|
// #myslide("QC-LDPC")[
|
|
// #align(center + horizon)[
|
|
// #image("src/construction.jpg", width: 80%)
|
|
// ]
|
|
// ]
|
|
//
|
|
// #myslide("Test réel")[
|
|
// Transmission hackrf, test de diff de debit avec paquets
|
|
// Test de transmission d'image avec différent ldpc non opti et opti (H diff etc)
|
|
// #align(center + horizon)[
|
|
// #image("src/construction.jpg", width: 80%)
|
|
// ]
|
|
// ]
|
|
//
|
|
// #myslide("FPGA")[
|
|
// #align(center + horizon)[
|
|
// #image("src/construction.jpg", width: 80%)
|
|
// ]
|
|
// ]
|
|
|
|
#myslide("La Topologie de H : Le Girth")[
|
|
#set text(size: 20pt)
|
|
|
|
#definition(titre: "Définition : Le Girth (La Maille)", accent: blue)[
|
|
Longueur du plus court cycle dans le graphe de Tanner
|
|
]
|
|
|
|
#v(0.5em)
|
|
|
|
- Le girth est *pair*
|
|
- La valeur minimale est $g = 4$.
|
|
|
|
#v(1em)
|
|
|
|
#align(center)[
|
|
#block(fill: rgb("#f8fafc"), stroke: 1pt + blue.lighten(50%), inset: 10pt, radius: 5pt)[
|
|
Girth élevé $=>$ Meilleure diffusion de l'information.
|
|
]
|
|
]
|
|
|
|
#v(2.5em)
|
|
|
|
#align(center)[
|
|
#scale(140%)[
|
|
#grid(
|
|
columns: (1fr, 1fr),
|
|
gutter: -7cm,
|
|
[
|
|
#schema_girth_4(highlight: false)
|
|
#v(0.5em)
|
|
#text(size: 0.8em, style: "italic")[Graphe de Tanner]
|
|
],
|
|
[
|
|
#schema_girth_4(highlight: true)
|
|
#v(0.5em)
|
|
#text(size: 0.8em, fill: red, weight: "bold")[4-Cycle]
|
|
],
|
|
)
|
|
]
|
|
]
|
|
]
|
|
|
|
#myslide("Méthode de génération de H")[
|
|
#place(center + horizon, dy: 8.1cm)[#graphe_tanner_fond(0.9cm, 1.75)]
|
|
#place(center + horizon, dy: 7cm)[
|
|
#block(width: 100%)[
|
|
#text(size: 1.5em, weight: "bold", fill: black)[
|
|
Gallager \
|
|
|
|
Mackay-Neal \
|
|
|
|
Progressive Edge-Growth
|
|
]
|
|
]
|
|
]
|
|
// #align(center + horizon)[
|
|
// #image("src/construction.jpg", width: 50%)
|
|
// ]
|
|
]
|
|
#myslide("Conclusion")[
|
|
#place(center + horizon, dy: 8.1cm)[#graphe_tanner_fond(0.9cm, 1.75)]
|
|
#place(center + horizon, dy: 7.7cm)[
|
|
#block(width: 100%)[
|
|
#text(size: 1.5em, weight: "bold", fill: black)[
|
|
QC-LDPC Encodage \
|
|
|
|
FPGA \
|
|
|
|
Test Réels
|
|
]
|
|
]
|
|
]
|
|
]
|
|
|
|
#[]<fin>
|
|
|
|
#myslide("Annexe")[
|
|
#align(center + horizon)[
|
|
Annexe
|
|
]
|
|
#align(center + horizon)[
|
|
#image("src/construction.jpg", width: 80%)
|
|
]
|
|
]
|
|
|
|
// #myslide("Définition : Matrice Génératrice")[
|
|
// #definition(titre: "Matrice Génératrice")[
|
|
// $G in cal(M)_(k,n)(FF_2)$ dont les lignes sont une base de $cal(C)$
|
|
// ]
|
|
//
|
|
// #definition(titre: "Encodage")[
|
|
// Pour un message $u in FF_2^k$ le mot de code $c in cal(C)$ est :
|
|
// $
|
|
// c = Phi(u) = u G
|
|
// $
|
|
// ]
|
|
//
|
|
// #definition(titre: "Forme systématique")[
|
|
// // TODO : changer [I_k | P] en un graphique jolie avec I et P dans un carré coloré
|
|
// $
|
|
// #dessiner_matrice($G =$, ((texte: $I_k$, largeur: 2.2, fond: gray.lighten(75%)), (texte: $P$, largeur: 2.2, fond: gray.lighten(75%))))
|
|
// // G = mat(
|
|
// // I_k, P;
|
|
// // augment: #1,
|
|
// // delim: "[",
|
|
// // )
|
|
// $
|
|
// ]
|
|
//
|
|
// #[
|
|
// #set text(size: 1.2em)
|
|
// // - Pour $u in FF_2^k, space display(u dot.o G = mat(u, u dot.o P; augment: #1, delim: "[",))$
|
|
//
|
|
// - Pour $u in FF_2^k, space #dessiner_matrice($u G =$, (
|
|
// (texte: $u$, largeur: 1.1, fond: gray.lighten(75%)),
|
|
// (texte: $u P$, largeur: 3.0, fond: gray.lighten(75%)),
|
|
// ))$
|
|
//
|
|
// - $P in cal(M)_(k ,n-k)(FF_2)$ matrice de parité\
|
|
// ]
|
|
// ]
|
|
//
|
|
// #myslide("Définition : Matrice de Contrôle")[
|
|
// #definition(titre: "Matrice de Contrôle")[
|
|
// // $H = mat(
|
|
// // P^top, I_(n-k);
|
|
// // augment: #1,
|
|
// // delim: "[",
|
|
// // )
|
|
// $
|
|
// #dessiner_matrice($H =$, (
|
|
// (texte: $P^top$, largeur: 2.2, fond: gray.lighten(75%)),
|
|
// (texte: $I_(n-k)$, largeur: 2.2, fond: gray.lighten(75%)),
|
|
// ))
|
|
// $
|
|
//
|
|
// ]
|
|
// #[
|
|
// #set text(size: 1.2em)
|
|
// - $cal(C) = ker(H) = {v in FF_2^n | H v^top = 0}$
|
|
//
|
|
// - $display(G H^top = 0)$
|
|
// ]
|
|
//
|
|
// #definition(titre: "Syndrome")[
|
|
// Pour un vecteur reçu $r = c + e, space s in FF_2^(n - k)$
|
|
// $
|
|
// s = H r^top = H c^top + H e^top = 0 + H e^top
|
|
// $
|
|
// ]
|
|
// #[
|
|
// #set text(size: 1.2em)
|
|
// - Si $s = 0, space r$ est un mot de code valide
|
|
// - Sinon $s$ donne la signature de l'erreur $e$
|
|
// ]
|
|
// // Possible décodage par syndrome
|
|
// ]
|
|
|
|
#myslide("Théorie derrière la définition des codes linaires")[
|
|
Poser les notations algebriques etc...
|
|
]
|
|
|
|
#myslide("Définition du BER et SFR")[
|
|
|
|
]
|
|
|
|
#myslide("Decodage par maximum de vraisemblance")[
|
|
Expliquer, quelle distance ? etc
|
|
]
|
|
|
|
#myslide("Code LDPC non régulier")[
|
|
|
|
]
|
|
|
|
#myslide("Richardson-Urbanke")[
|
|
|
|
]
|
|
|
|
#myslide("CN Update : Formalisme probabiliste")[
|
|
#set text(size: 16pt)
|
|
#v(-0.3em)
|
|
|
|
Soit $(V_u)_(u in cal(N)(c))$ une famille de variables aléatoires mutuellement indépendantes à valeurs dans $bb(F)_2$.
|
|
On cherche à déterminer la loi du message $R_(c arrow v)(b)$ envoyé par le nœud de contrôle $c$.
|
|
|
|
#v(0.5em)
|
|
#definition(titre: "Conditionnement de l'événement de parité", accent: orange)[
|
|
Le message $R_(c arrow v)(b)$ correspond à la probabilité conditionnelle :
|
|
#v(0.5em)
|
|
#align(center)[#scale(105%)[$
|
|
display(R_(c arrow v)(b) = P( limits(xor.big)_(u in cal(N)(c)) V_u = 0 | V_v = b ))
|
|
$]]
|
|
|
|
Par linéarité du XOR, cette condition est équivalente à :
|
|
#v(0.5em)
|
|
#align(center)[#scale(110%)[$ display(P( limits(xor.big)_(u in cal(N)(c) backslash {v}) V_u = b )) $]]
|
|
]
|
|
|
|
Par le théorème des probabilités totales appliqué au système complet d'événements associé aux configurations $x in bb(F)_2^(d_c - 1)$ des voisins :
|
|
|
|
#align(center)[#scale(120%)[
|
|
$
|
|
display(R_(c arrow v)(b) = limits(sum)_(x in bb(F)_2^(d_c - 1) \ limits(xor.big)_(u in cal(N)(c) backslash {v}) x_u = b) limits(product)_(u in cal(N)(c) backslash {v}) P(V_u = x_u))
|
|
$
|
|
]]
|
|
]
|
|
|
|
#myslide("CN Update (1) : Probabilités")[
|
|
#set text(size: 16pt)
|
|
#v(-0.3em)
|
|
|
|
En utilisant les messages entrants du graphe, on définit la probabilité locale $P_(u arrow c)(x_u) = P(V_u = x_u)$.
|
|
|
|
Le message sortant devient :
|
|
|
|
#v(1em)
|
|
#align(center)[#scale(130%)[
|
|
$
|
|
display(R_(c arrow v)(b) = limits(sum)_(x in bb(F)_2^(d_c - 1) \ limits(xor.big)_(u in cal(N)(c) backslash {v}) x_u = b) quad limits(product)_(u in cal(N)(c) backslash {v}) P_(u arrow c)(x_u))
|
|
$
|
|
]]
|
|
|
|
#v(1em)
|
|
Exacte mais complexité est exponentielle en $d_c$. On utilise alors une transformation pour simplifier le calcul (Lemme de Gallager).
|
|
]
|
|
|
|
#myslide("CN Update (2) : Lemme de Gallager")[
|
|
#set text(size: 16pt)
|
|
|
|
#block(
|
|
fill: orange.lighten(94%),
|
|
stroke: (left: 4pt + orange),
|
|
radius: 4pt,
|
|
inset: 20pt,
|
|
width: 100%,
|
|
)[
|
|
*Lemme de Gallager* -- Soient $(X_1, ..., X_n)$ des variables de Bernoulli indépendantes sur $bb(F)_2$.
|
|
#v(0.5em)
|
|
#align(center)[#scale(130%)[
|
|
$ display(P(limits(xor.big)_(i=1)^n X_i = 0) = 1/2 (1 + limits(product)_(i=1)^n E[(-1)^(X_i)])) $
|
|
]]
|
|
]
|
|
|
|
#v(0.8em)
|
|
// L'espérance correspond au biais de la loi, noté $delta_(u arrow c)$ :
|
|
On notes :
|
|
#align(center)[#scale(120%)[
|
|
$ display(E[(-1)^(V_u)] = delta_(u arrow c) = P(V_u = 0) - P(V_u = 1) = 1 - 2 P_(u arrow c)(1)) $
|
|
]]
|
|
|
|
#v(0.8em)
|
|
On en déduit les probabilités marginales conditionnelles pour le nœud $c$ :
|
|
|
|
#align(center)[#scale(120%)[
|
|
$
|
|
display(R_(c arrow v)(0) = 1/2 (1 + limits(product)_(u in cal(N)(c) backslash {v}) delta_(u arrow c)))
|
|
space , space space
|
|
display(R_(c arrow v)(1) = 1/2 (1 - limits(product)_(u in cal(N)(c) backslash {v}) delta_(u arrow c)))
|
|
$
|
|
]]
|
|
]
|
|
|
|
#myslide("CN Update (3) : Passage aux LLR")[
|
|
#set text(size: 16pt)
|
|
|
|
#definition(titre: "Log-Likelihood Ratio (LLR)", accent: blue.darken(10%))[
|
|
Le message LLR entrant $m_(u arrow c)$ au nœud de contrôle est défini par :
|
|
#v(0.5em)
|
|
#align(center)[#scale(130%)[
|
|
$ display(m_(u arrow c) = ln(frac(P(V_u = 0), P(V_u = 1)))) $
|
|
]]
|
|
]
|
|
|
|
#v(0.8em)
|
|
$delta_(u arrow c)$ s'exprime alors :
|
|
#align(center)[#scale(130%)[
|
|
$ display(delta_(u arrow c) = tanh(frac(m_(u arrow c), 2))) $
|
|
]]
|
|
|
|
#v(0.8em)
|
|
On en déduit le LLR du message sortant :
|
|
#align(center)[#scale(130%)[
|
|
$
|
|
display(m_(c arrow v) = ln(frac(R_(c arrow v)(0), R_(c arrow v)(1))) = 2 tanh^(-1) ( limits(product)_(u in cal(N)(c) backslash {v}) tanh(frac(m_(u arrow c), 2)) ))
|
|
$
|
|
]]
|
|
]
|
|
|
|
#myslide("CN Update (4) : Algorithmes")[
|
|
#set text(size: 16pt)
|
|
|
|
#block(
|
|
fill: orange.lighten(92%),
|
|
stroke: (left: 4pt + orange),
|
|
radius: 4pt,
|
|
inset: 15pt,
|
|
width: 100%,
|
|
)[
|
|
*Sum-Product* -- Mise à jour :
|
|
#v(0.5em)
|
|
#align(center)[#scale(130%)[
|
|
$
|
|
display(m_(c arrow v) = 2 tanh^(-1) ( limits(product)_(u in cal(N)(c) backslash {v}) tanh(frac(m_(u arrow c), 2)) ))
|
|
$
|
|
]]
|
|
]
|
|
|
|
#v(1em)
|
|
#block(
|
|
fill: blue.lighten(92%),
|
|
stroke: (left: 4pt + blue),
|
|
radius: 4pt,
|
|
inset: 15pt,
|
|
width: 100%,
|
|
)[
|
|
*Min-Sum* -- Approximation :
|
|
#v(0.5em)
|
|
#align(center)[#scale(130%)[
|
|
$
|
|
display(m_(c arrow v) approx ( limits(product)_(u in cal(N)(c) backslash {v}) op("sgn")(m_(u arrow c)) ) times limits(min)_(u in cal(N)(c) backslash {v}) |m_(u arrow c)|)
|
|
$
|
|
]]
|
|
]
|
|
]
|
|
|
|
#myslide("AWGN")[
|
|
|
|
]
|
|
|
|
#myslide("Gallager")[
|
|
|
|
]
|
|
|
|
#myslide("Mackay-Neal")[
|
|
|
|
]
|
|
|
|
|
|
#myslide("Progressive Edge-growth")[
|
|
|
|
]
|