vu global

This commit is contained in:
2026-05-04 17:02:46 +02:00
parent a418e45116
commit 09e4bfabdb
4 changed files with 457 additions and 0 deletions

43
pres.md Normal file
View File

@ -0,0 +1,43 @@
# Introduction
## 1
1. L'Amorce (Le défi physique)
Contexte : Le pilotage de drones FPV impose une transmission sous de fortes contraintes : un canal hautement bruité couplé à une exigence stricte de très faible latence.
2. Le Fondement Théorique
Le problème : L'environnement physique altère inévitablement les bits. La solution réside dans le FEC (Forward Error Correction) : l'injection de redondance intelligente.
Le théorème de Shannon (1948) : Il démontre qu'une transmission sans erreur est mathématiquement possible, à condition que le débit d'information soit inférieur à la limite théorique appelée "capacité du canal".
3. Le Paysage des Codes Correcteurs
Diversité : Le code de Hamming a initié la famille des codes linéaires. Depuis, d'autres familles dominent selon les applications : codes algébriques structurés (Reed-Solomon) ou approches itératives (Turbo-codes).
Transition vers le sujet : L'objectif ultime est de saturer la limite de Shannon tout en garantissant un décodage rapide. C'est exactement la promesse des codes LDPC, que nous allons maintenant définir mathématiquement.
# Problématique
## 1
...
# Définition Codes Linéaires
## 1
On "plonge" l'information dans un espace de dimension supérieure. Le code C est un sous-espace vectoriel de dimension k de l'espace F2n. La redondance ajoutée est de m=nk bits.
Lien entre distance de Hamming et nombre d'arrete qu'il faut pour passer d'un mot à un autre.
Phi injective pour pas avoir 2 message disctincts qui represente le meme mot.
## 2
C est un sous espace vectoriel de dim k plongé dans F_2^n
On peut définir tout ça bien à base de frome linaire et adjoint... perche
## 3
Linéarité => decodage par syndrome
# Redondance et limite theorique
## 1
Ajouter de la redondance coûte cher en débit, c'est ce que l'on appelle l'overhead. Pour garder un débit élevé tout en corrigeant beaucoup d'erreurs, la solution est d'utiliser des codes de très grande taille. En augmentant la longueur du bloc N, nous permettons au décodeur de traiter l'information de manière statistique et de nous approcher très près de la capacité limite du canal.
## 2
La correction d'erreur n'est pas gratuite : elle se paie en débit. Pour ne pas gaspiller de bande passante tout en restant fiable, la théorie de Shannon nous montre qu'il faut utiliser des codes de très grande taille. Un bloc long permet de mieux diluer l'impact du bruit. C'est pour cette raison que les standards modernes (5G, Wi-Fi) utilisent des codes LDPC massifs : ils offrent le meilleur ratio 'correction / sacrifice de débit' possible à ce jour.
# MDL
## 1
## 2
Mathématiquement, le décodeur idéal est celui du Maximum de Vraisemblance (ML). Il garantit le taux d'erreur le plus bas, mais au prix d'une complexité exponentielle en O(2k). Pour les codes modernes à gros blocs, c'est un problème NP-complet insoluble. C'est ici que réside le génie des LDPC : en imposant une matrice H très creuse, on peut utiliser des algorithmes de propagation de croyance qui transforment ce mur de complexité en une simple progression linéaire, rendant le décodage haute performance physiquement possible dans un drone ou un smartphone.

Binary file not shown.

414
presentation.typ Normal file
View File

@ -0,0 +1,414 @@
#import "@preview/polylux:0.4.0": *
#import "@preview/cetz:0.5.0"
#set page(
paper: "presentation-4-3",
margin: 0cm,
)
// Font
#set text(
font: "New Computer Modern",
size: 20pt,
fill: black,
)
// Infos
#let auteur = "Anthony PERRONI"
#let numero = "49871"
#let titre = "Codes LDPC"
#let annee = "2025 - 2026"
// Template
#let myslide(partie, contenu) = slide[
// Header
#block(width: 100%, fill: black, inset: (top: 0.6cm, bottom: 0.6cm, left: 1.5cm, right: 1.5cm))[
#set text(fill: white, size: 28pt, weight: "bold")
#partie
]
// Contenu
#pad(x: 1.5cm, top: 0.2cm)[
#set text(size: 20pt)
#contenu
]
// Footer
#v(1fr)
#context {
let cur = counter(page).get().first()
let tot = counter(page).final().first()
if cur > 1 {
block(width: 100%, fill: black, inset: (top: 0.2cm, bottom: 0.2cm, left: 1.5cm, right: 1.5cm))[
#set text(fill: white, size: 12pt, weight: "bold")
#grid(
columns: (1.5fr, 2fr, 1fr, auto),
align: (left, center, center, right),
[#auteur #numero], [#titre], [#annee], [#(cur - 1) / #(tot - 1)],
)
]
}
}
]
// Plan
// Plan
#let design_plan(items) = {
let r = 6pt
let epaisseur = 2pt
let hauteur_ligne = 2.5em
let espace_vertical = 20pt
pad(left: 1cm, top: 1cm)[
#block[
#place(dx: r, dy: hauteur_ligne / 2)[
#line(
length: (items.len() - 1) * (hauteur_ligne + espace_vertical),
angle: 90deg,
stroke: epaisseur + black,
)
]
#grid(
columns: (2 * r, auto),
column-gutter: 20pt,
row-gutter: espace_vertical, // On applique la variable ici
..items
.map(item => (
box(height: hauteur_ligne, align(center + horizon)[
#circle(radius: r, fill: white, stroke: epaisseur + black)
]),
box(height: hauteur_ligne, align(left + horizon)[
#text(weight: "bold", size: 1.1em)[#item]
]),
))
.flatten()
)
]
]
}
// Page de garde
#slide[
#v(1fr)
#align(center)[
#pad(x: 1.5cm)[
#text(size: 3em, weight: "bold")[#titre]
#v(0cm)
#text(size: 1.4em)[*#auteur n°#numero*] \
#v(1cm)
#text(size: 1.1em)[#annee]
]
]
#v(1fr)
]
#myslide("Plan")[
#design_plan((
[Introduction],
[Codes linéaires],
[LDPC],
[Codage],
[Décodage],
[Analyse],
))
]
#myslide("Introduction : transmission numérique")[
// Schema Shannon
#align(center + horizon)[
#cetz.canvas({
import cetz.draw: *
// Styles
let s = (stroke: 2pt + black)
let s_fleche = (stroke: 2pt + black)
let pointe_pleine = (end: "stealth", fill: black)
let espacement = 5.5
// Blocs
content((0, 0), [Source], name: "src", frame: "rect", ..s, padding: .3)
content((espacement, 0), [Emetteur], name: "em", frame: "rect", ..s, padding: .3)
content((espacement * 2, 0), [Canal], name: "chan", frame: "rect", ..s, padding: .3)
content((espacement * 3, 0), [Récepteur], name: "rec", frame: "rect", ..s, padding: .3)
content((espacement * 4, 0), [Destinataire], name: "dest", frame: "rect", ..s, padding: .3)
// Bruit
content((rel: (0, 1.8), to: "chan"), [Bruit], name: "bruit", frame: "rect", ..s, padding: .3)
// Codage / Décodage
content((rel: (0, 1), to: "em"), [*Codage*])
content((rel: (0, 1), to: "rec"), [*Décodage*])
// Flèches (On utilise s_fleche et pointe_pleine)
line("src.east", "em.west", mark: pointe_pleine, ..s_fleche)
line("em.east", "chan.west", mark: pointe_pleine, ..s_fleche)
line("chan.east", "rec.west", mark: pointe_pleine, ..s_fleche)
line("rec.east", "dest.west", mark: pointe_pleine, ..s_fleche)
line("bruit.south", "chan.north", mark: pointe_pleine, ..s_fleche)
// Annotation
let note-style = (size: 0.75em, style: "italic")
content((espacement * 0.5, -0.5), text(..note-style)[Message])
content((espacement * 1.5, -0.5), text(..note-style)[Signal])
content((espacement * 2.5, -0.5), text(..note-style)[Signal])
content((espacement * 3.5, -0.5), text(..note-style)[Message])
})
]
#v(5cm)
image de mon drone FPV, 5G
]
#myslide("Problématique")[
#align(center)[
Comment utiliser les codes LDPC pour garantir la fiabilité d'une transmission en présence de
bruit ?
]
]
#myslide("Définition : Codes Linéaires")[
$cal(C)$ de paramètres $(n, k) in NN^2$, ($n > k$)
// $Phi : & FF_2^k --> FF_2^n \
// & x arrow.long.bar Phi(x) = c$
// $Phi : #box(baseline: 1.6em)[$ cases(
// delim: "|",
// bb(F)_2^k & arrow bb(F)_2^n,
// x & arrow.long.bar Phi(x)
// ) $]$
// $Phi$ linéaire et injective
Espace des messages : $FF_2^k$\
Espace des mots transmis :$FF_2^n$
Redondance de $n - k$ bits
Rendement $display(R = k / n)$
#align(center)[
#cetz.canvas(length: 1.5cm, {
import cetz.draw: *
// Styles
let style-pointille = (stroke: (paint: black, thickness: 1.2pt, dash: "dashed"))
let style-point = (fill: black, stroke: none)
let rayon-point = 0.08
let pointe-fleche = (end: "stealth", fill: black)
let m = (
p00: (-4, 0),
p01: (-2, 0),
p11: (-2, -2),
p10: (-4, -2),
)
// Arêtes pointillés
line(m.p00, m.p01, m.p11, m.p10, close: true, ..style-pointille)
// Points sur les sommets
circle(m.p00, radius: rayon-point, ..style-point)
circle(m.p01, radius: rayon-point, ..style-point)
circle(m.p11, radius: rayon-point, ..style-point)
circle(m.p10, radius: rayon-point, ..style-point)
// Étiquettes
content(m.p00, [00], anchor: "south-east", padding: .2)
content(m.p01, [01], anchor: "south-west", padding: .2)
content(m.p11, [11], anchor: "north-west", padding: .2)
content(m.p10, [10], anchor: "north-east", padding: .2)
content((-3, -3), [$FF_2^2$])
line((-1.2, -1), (1.2, -1), mark: pointe-fleche, stroke: 1.5pt + black)
content((0, -0.6), [*Plongement*])
// Sommets face arrière
let cb = (p000: (2.5, 0), p001: (4.5, 0), p011: (4.5, -2), p010: (2.5, -2))
// Sommets face avant (décalés)
let cf = (p100: (3.5, 1), p101: (5.5, 1), p111: (5.5, -1), p110: (3.5, -1))
// Arêtes pointillés du cube
line(cb.p000, cb.p001, cb.p011, cb.p010, close: true, ..style-pointille) // Face arrière
line(cf.p100, cf.p101, cf.p111, cf.p110, close: true, ..style-pointille) // Face avant
line(cb.p000, cf.p100, ..style-pointille) // Liaisons
line(cb.p001, cf.p101, ..style-pointille)
line(cb.p011, cf.p111, ..style-pointille)
line(cb.p010, cf.p110, ..style-pointille)
// Points sur les sommets du cube
circle(cb.p000, radius: rayon-point, ..style-point)
circle(cb.p001, radius: rayon-point, ..style-point)
circle(cb.p011, radius: rayon-point, ..style-point)
circle(cb.p010, radius: rayon-point, ..style-point)
circle(cf.p100, radius: rayon-point, ..style-point)
circle(cf.p101, radius: rayon-point, ..style-point)
circle(cf.p111, radius: rayon-point, ..style-point)
circle(cf.p110, radius: rayon-point, ..style-point)
// Étiquettes du cube
content(cb.p000, [000], anchor: "south-east", padding: .2)
content(cb.p001, [001], anchor: "south-west", padding: .2)
content(cb.p011, [011], anchor: "north-west", padding: .2)
content(cb.p010, [010], anchor: "north-east", padding: .2)
content(cf.p100, [100], anchor: "south-east", padding: .2)
content(cf.p101, [101], anchor: "south-west", padding: .2)
content(cf.p111, [111], anchor: "north-west", padding: .2)
content(cf.p110, [110], anchor: "north-east", padding: .2)
content((4, -3), [$FF_2^3$])
})
]
]
// #myslide("Définition : Codes Linéaires")[
// // Matrice génératrice : $op("Mat")_cal(B)(Phi) = G in cal(M)_(k, n)(FF_2)$, $op("rg")(G) = k$
//
// // $cal(C) = op("Im")(Phi) = {x G | x in FF_2^k}$
//
// Forme bilinéaire symétrique :
// $forall x, y in FF_2^n, space (x|y)_(FF_2^n) = display(sum_(i=0)^n x_i y_i)$
//
// Encodage :
// $Phi : #box(baseline: 1.6em)[$ cases(
// delim: "|",
// FF_2^k & -> FF_2^n,
// x & arrow.long.bar Phi(x)
// ) $]$
//
// $Phi in cal(L)(FF_2^k, FF_2^n)$, $op("rg")(Phi) = k$, $Phi$ injective
//
// $cal(C) = op("Im")(Phi)$
//
// $G = op("Mat")_cal(B)(Phi) in cal(M)_(k,n)(FF_2)$
// Pour $x in FF_2^k, Phi(x) = x G$
//
// $Phi$ admet un unique adjoint $Phi^*$,
// $
// forall x in FF_2^k, forall y in FF_2^n, (Phi(x) | y)_(FF_2^n) = (x, Phi(y)^*)_(FF_2^k)
// $
// de plus $cal(C)^bot = op("Im")(Phi)^bot = ker(Phi^*)$ et $dim(cal(C)^bot) = n - k$
//
// Equation du code dual : $y in cal(C^bot) <==> Phi(y)^* = 0 <==> y G^T = 0$
//
// De plus $display((cal(C)^bot)^bot) = cal(C)$ (car non dégénérée)
//
//
// ]
//
// #myslide("Définition : Codes Linéaires")[
//
// $(h_1, ..., h_(n-k))$ base de $cal(C)^bot$
// Définisson $H in cal(M)_(n-k, n)(FF_2)$ avec les $h_i$ comme lignes
// $H$ : matrice de contrôle de parité
//
// $forall c in FF_2^n, c in cal(C) <==> c H^T = 0$
//
// $S : #box(baseline: 1.6em)[$ cases(
// delim: "|",
// FF_2^n & -> FF_2^(n-k),
// y & arrow.long.bar y H^T
// ) $]$
// et $ker(S) = cal(C)$ ...
//
// ]
#myslide("Définition : Codes Linéaires")[
faire un truc plus theoriques...
]
#myslide("Définition : Codes Linéaires")[
- Matrice génératrice
$G in cal(M)_(k,n)(FF_2)$
- Encodage : $m in FF_2^k, c = m dot.o G$
- Forme systématique : $G = [I_k | P]$ avec $P$ matrice de parité
- Matrice de contrôle de parité $H = [- P^top | I_(n-k)]$
$c in FF_2^n$ est un mot de code valide $<==>$ $c^top dot.o H = 0$
De plus $G dot.o H^T = 0$
]
#myslide("Définition : Codes Linéaires")[
Reception de $r = c + e$ avec $c in cal(C), e in FF_2^n$
$r^top dot.o H = s$ le syndrome
$(c + e)^top H = c^top H + e^top H = e^top H$
]
#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("Décodage par Maximum de Vraisemblance")[
Trouver le message envoyer le + probable sachant le message recu : NP-COMPLET (Max)
Decodage par syndrome d'une code lin'aire général est NP-Complet
Complexité $O(2^k)$
]
#myslide("LDPC")[
Matrice $H$ clairsemée(low density) donc complexité mointre, pas de produit de matrice mais algorithme itératif efficace quasi linéaire
Graphique d'un H très grand clairesemée avec plein de 0, généré en rust par exemple où les 1 sont des points noir et le reste du blanc
Défniition avec (w_r,w_c)
]
#myslide("Graphe de Tanner")[
Il existe un isomorphisme entre H et le Graphe de Tanner
Graphe de tanner (cetz)
Contrainte de somme nulle
]
#myslide("Encodage")[
]
#myslide("Décodage")[
Canal d'étude (AWGN) analogique, tension etc, ce qui se passe en radio dans les cables etc
]
#myslide("Hard decoding")[
Nul (0 ou 1)
transition perte d'information
]
#myslide("Implementation")[
]
#myslide("Soft decoding")[
belief propagation, log ou virgule fixe, explication resultat meilleur
]
#myslide("Implementation")[
]
#myslide("Test")[
Irl hackrf, test de diff de debit avec des paquets
]
#myslide("Image")[
Test de transmission d'image avec différent ldpc non opti et opti (le H)
]
#myslide("Annexe")[
Annexe
]
#myslide("Théorie deriere la définition des codes linaires")[
Poser les notations algebriques
]
#myslide("Unicité de l'adjoint")[
Unicité de l'adjoint pour une forme bilinéaire symétrique non dégénérée.
]

View File