avancée++

This commit is contained in:
2026-05-07 11:41:46 +02:00
parent 1b26a0fb57
commit 706061e9b2
3 changed files with 7217 additions and 4239 deletions

View File

@ -217,8 +217,8 @@
#let canal_shannon_intro() = {
// Couleurs
let col-u = blue // Signal propre
let col-p = orange // Signal bruité
let col-u = blue // Signal propre
let col-p = orange // Signal bruité
let C_MAIN = black
let C_BG = rgb("#f8f9fa") // Le gris très clair demandé
let C_LABEL = black
@ -226,17 +226,36 @@
cetz.canvas(length: 1cm, {
import cetz.draw: *
let x_left = 4.0 ; let x_right = 16.0 ; let x_noise = 22.5
let y_top = 14.5 ; let y_mid = 9.0 ; let y_bot = 3.5
let x_left = 4.0
let x_right = 16.0
let x_noise = 22.5
let y_top = 14.5
let y_mid = 9.0
let y_bot = 3.5
// Style des lignes avec flèches
let s_ligne = (stroke: 1.5pt + C_MAIN, mark: (end: "stealth", fill: C_MAIN, size: 0.25))
let s_bruit_fleche = (stroke: (paint: black, thickness: 1.5pt, dash: "dashed"), mark: (end: "stealth", fill: black, size: 0.25))
let s_bruit_fleche = (
stroke: (paint: black, thickness: 1.5pt, dash: "dashed"),
mark: (end: "stealth", fill: black, size: 0.25),
)
// Fonction de bloc avec le nouveau fond
let bloc(pos, txt, stxt, n) = {
content(pos, [#set align(center); #text(C_MAIN, weight: "bold", size: 1.2em)[#txt] \ #text(C_MAIN, size: 0.85em, style: "italic")[#stxt]],
frame: "rect", fill: C_BG, stroke: C_MAIN + 1.5pt, padding: 0.7, radius: 0.3, name: n)
content(
pos,
[#set align(center); #text(C_MAIN, weight: "bold", size: 1.2em)[#txt] \ #text(
C_MAIN,
size: 0.85em,
style: "italic",
)[#stxt]],
frame: "rect",
fill: C_BG,
stroke: C_MAIN + 1.5pt,
padding: 0.7,
radius: 0.3,
name: n,
)
}
// --- ONDES (Bruit dosé : "tremblement" au lieu de "chaos") ---
@ -244,26 +263,29 @@
let n_points = 200
let color = if is_noisy { col-p } else { col-u }
line(..range(n_points + 1).map(i => {
let t = i / n_points
let y = y_start + t * (y_end - y_start)
line(
..range(n_points + 1).map(i => {
let t = i / n_points
let y = y_start + t * (y_end - y_start)
// Enveloppe pour raccord propre
let env = if t < 0.05 { t/0.05 } else if t > 0.95 { (1-t)/0.05 } else { 1.0 }
// Enveloppe pour raccord propre
let env = if t < 0.05 { t / 0.05 } else if t > 0.95 { (1 - t) / 0.05 } else { 1.0 }
let signal = 0.35 * calc.sin(t * 6 * calc.pi)
let signal = 0.35 * calc.sin(t * 6 * calc.pi)
// Bruit dosé : on a baissé les fréquences et l'amplitude
let bruit = if is_noisy {
(0.08 * calc.sin(t * 45 * calc.pi) + 0.05 * calc.cos(t * 97 * calc.pi))
} else { 0 }
// Bruit dosé : on a baissé les fréquences et l'amplitude
let bruit = if is_noisy {
(0.08 * calc.sin(t * 45 * calc.pi) + 0.05 * calc.cos(t * 97 * calc.pi))
} else { 0 }
(x + (signal + bruit) * env, y)
}), stroke: color + 1.6pt)
(x + (signal + bruit) * env, y)
}),
stroke: color + 1.6pt,
)
}
wave_vert(x_right, y_top - 1.5, y_mid + 1, false) // Bleu
wave_vert(x_right, y_mid - 1, y_bot + 1.5, true) // Orange
wave_vert(x_right, y_mid - 1, y_bot + 1.5, true) // Orange
// --- BLOCS ---
bloc((x_left, y_top), "Source", "Information", "src")
@ -279,12 +301,16 @@
line("rec.west", "dest.east", ..s_ligne)
// --- ANNOTATIONS ---
let lab(pos, body, color: C_LABEL, anchor: "center") = content(pos, text(size: 0.95em, fill: color, style: "italic", weight: "medium")[#body], anchor: anchor)
let lab(pos, body, color: C_LABEL, anchor: "center") = content(
pos,
text(size: 0.95em, fill: color, style: "italic", weight: "medium")[#body],
anchor: anchor,
)
lab(((x_left + x_right)/2 - 0.3, y_top + 0.7), "Message")
lab((x_right + 1.2, (y_top + y_mid)/2), "Signal", color: col-u, anchor: "west")
lab((x_right + 1.2, (y_mid + y_bot)/2), "Signal + Bruit", color: col-p, anchor: "west")
lab(((x_left + x_right)/2 + 0.3, y_bot - 0.7), "Message reçu")
lab(((x_left + x_right) / 2 - 0.3, y_top + 0.7), "Message")
lab((x_right + 1.2, (y_top + y_mid) / 2), "Signal", color: col-u, anchor: "west")
lab((x_right + 1.2, (y_mid + y_bot) / 2), "Signal + Bruit", color: col-p, anchor: "west")
lab(((x_left + x_right) / 2 + 0.3, y_bot - 0.7), "Message reçu")
})
}
@ -630,8 +656,16 @@
let offset = k * zoom
if calc.abs(offset) < R {
let half_chord = calc.sqrt(R * R - offset * offset)
line((loupe_x + offset, loupe_y + half_chord), (loupe_x + offset, loupe_y - half_chord), stroke: 0.5pt + col_grid)
line((loupe_x - half_chord, loupe_y + offset), (loupe_x + half_chord, loupe_y + offset), stroke: 0.5pt + col_grid)
line(
(loupe_x + offset, loupe_y + half_chord),
(loupe_x + offset, loupe_y - half_chord),
stroke: 0.5pt + col_grid,
)
line(
(loupe_x - half_chord, loupe_y + offset),
(loupe_x + half_chord, loupe_y + offset),
stroke: 0.5pt + col_grid,
)
}
}
@ -667,14 +701,96 @@
import cetz.draw: *
let points = (
(7,0), (10,0), (15,0), (22,0), (24,0), (29,0), (3,1), (6,1), (18,1), (19,1), (25,1), (27,1),
(5,2), (9,2), (13,2), (14,2), (17,2), (28,2), (0,3), (8,3), (11,3), (16,3), (20,3), (26,3),
(1,4), (2,4), (4,4), (12,4), (21,4), (23,4), (5,5), (6,5), (8,5), (10,5), (21,5), (29,5),
(14,6), (15,6), (16,6), (18,6), (22,6), (28,6), (0,7), (1,7), (4,7), (9,7), (20,7), (26,7),
(2,8), (3,8), (11,8), (12,8), (17,8), (19,8), (7,9), (13,9), (23,9), (24,9), (25,9), (27,9),
(0,10), (6,10), (15,10), (18,10), (21,10), (26,10), (2,11), (7,11), (10,11), (17,11), (22,11), (27,11),
(8,12), (11,12), (14,12), (20,12), (23,12), (29,12), (4,13), (5,13), (9,13), (13,13), (16,13), (19,13),
(1,14), (3,14), (12,14), (24,14), (25,14), (28,14)
(7, 0),
(10, 0),
(15, 0),
(22, 0),
(24, 0),
(29, 0),
(3, 1),
(6, 1),
(18, 1),
(19, 1),
(25, 1),
(27, 1),
(5, 2),
(9, 2),
(13, 2),
(14, 2),
(17, 2),
(28, 2),
(0, 3),
(8, 3),
(11, 3),
(16, 3),
(20, 3),
(26, 3),
(1, 4),
(2, 4),
(4, 4),
(12, 4),
(21, 4),
(23, 4),
(5, 5),
(6, 5),
(8, 5),
(10, 5),
(21, 5),
(29, 5),
(14, 6),
(15, 6),
(16, 6),
(18, 6),
(22, 6),
(28, 6),
(0, 7),
(1, 7),
(4, 7),
(9, 7),
(20, 7),
(26, 7),
(2, 8),
(3, 8),
(11, 8),
(12, 8),
(17, 8),
(19, 8),
(7, 9),
(13, 9),
(23, 9),
(24, 9),
(25, 9),
(27, 9),
(0, 10),
(6, 10),
(15, 10),
(18, 10),
(21, 10),
(26, 10),
(2, 11),
(7, 11),
(10, 11),
(17, 11),
(22, 11),
(27, 11),
(8, 12),
(11, 12),
(14, 12),
(20, 12),
(23, 12),
(29, 12),
(4, 13),
(5, 13),
(9, 13),
(13, 13),
(16, 13),
(19, 13),
(1, 14),
(3, 14),
(12, 14),
(24, 14),
(25, 14),
(28, 14),
)
cetz.canvas(length: 0.45cm, {
@ -696,7 +812,7 @@
let col_mix_bg = col_row_bg.mix(col_col_bg)
// Label "H ="
content((-3.4, -h_height / 2), text(size: 1.6em, weight: "bold")[$bold(H) = $])
content((-3.4, -h_height / 2), text(size: 1.6em, weight: "bold")[$bold(H) =$])
// Sélection visuelle (Focus)
let sel_row = 7
@ -736,20 +852,117 @@
}
// 5. Légendes w_r et w_c
content((h_width + 0.5, -sel_row - 0.5), anchor: "west", text(fill: color_blue, weight: "bold", size: 1.1em)[$w_r = 6$])
content((h_width + 0.5, -sel_row - 0.5), anchor: "west", text(
fill: color_blue,
weight: "bold",
size: 1.1em,
)[$w_r = 6$])
content((sel_col + 0.5, 0.8), anchor: "south", text(fill: color_orange, weight: "bold", size: 1.1em)[$w_c = 3$])
})
}
#let hldpc_dual(row1: 0, row2: 14) = {
import cetz.draw: *
let points = ((7,0), (10,0), (15,0), (22,0), (24,0), (29,0), (3,1), (6,1), (18,1), (19,1), (25,1), (27,1), (5,2), (9,2), (13,2), (14,2), (17,2), (28,2), (0,3), (8,3), (11,3), (16,3), (20,3), (26,3), (1,4), (2,4), (4,4), (12,4), (21,4), (23,4), (5,5), (6,5), (8,5), (10,5), (21,5), (29,5), (14,6), (15,6), (16,6), (18,6), (22,6), (28,6), (0,7), (1,7), (4,7), (9,7), (20,7), (26,7), (2,8), (3,8), (11,8), (12,8), (17,8), (19,8), (7,9), (13,9), (23,9), (24,9), (25,9), (27,9), (0,10), (6,10), (15,10), (18,10), (21,10), (26,10), (2,11), (7,11), (10,11), (17,11), (22,11), (27,11), (8,12), (11,12), (14,12), (20,12), (23,12), (29,12), (4,13), (5,13), (9,13), (13,13), (16,13), (19,13), (1,14), (3,14), (12,14), (24,14), (25,14), (28,14))
let points = (
(7, 0),
(10, 0),
(15, 0),
(22, 0),
(24, 0),
(29, 0),
(3, 1),
(6, 1),
(18, 1),
(19, 1),
(25, 1),
(27, 1),
(5, 2),
(9, 2),
(13, 2),
(14, 2),
(17, 2),
(28, 2),
(0, 3),
(8, 3),
(11, 3),
(16, 3),
(20, 3),
(26, 3),
(1, 4),
(2, 4),
(4, 4),
(12, 4),
(21, 4),
(23, 4),
(5, 5),
(6, 5),
(8, 5),
(10, 5),
(21, 5),
(29, 5),
(14, 6),
(15, 6),
(16, 6),
(18, 6),
(22, 6),
(28, 6),
(0, 7),
(1, 7),
(4, 7),
(9, 7),
(20, 7),
(26, 7),
(2, 8),
(3, 8),
(11, 8),
(12, 8),
(17, 8),
(19, 8),
(7, 9),
(13, 9),
(23, 9),
(24, 9),
(25, 9),
(27, 9),
(0, 10),
(6, 10),
(15, 10),
(18, 10),
(21, 10),
(26, 10),
(2, 11),
(7, 11),
(10, 11),
(17, 11),
(22, 11),
(27, 11),
(8, 12),
(11, 12),
(14, 12),
(20, 12),
(23, 12),
(29, 12),
(4, 13),
(5, 13),
(9, 13),
(13, 13),
(16, 13),
(19, 13),
(1, 14),
(3, 14),
(12, 14),
(24, 14),
(25, 14),
(28, 14),
)
cetz.canvas(length: 0.35cm, {
let nx = 30; let ny = 15
let col_1 = orange; let col_2 = blue
let nx = 30
let ny = 15
let col_1 = orange
let col_2 = blue
content((-3.4, -7.5), text(size: 1.6em )[$H = $])
content((-3.4, -7.5), text(size: 1.6em)[$H =$])
// Fonds de lignes
rect((0, -row1), (nx, -row1 - 1), fill: col_1.lighten(90%), stroke: none)
@ -763,9 +976,544 @@
for (x, y) in points {
let d_col = gray.darken(30%)
let r = 0.15
if y == row1 { d_col = col_1; r = 0.22 }
else if y == row2 { d_col = col_2; r = 0.22 }
if y == row1 {
d_col = col_1
r = 0.22
} else if y == row2 {
d_col = col_2
r = 0.22
}
circle((x + 0.5, -y - 0.5), radius: r, fill: d_col, stroke: none)
}
})
}
// Données de H partagées (mêmes points que hldpc / hldpc_dual)
#let _h_pts = (
(7, 0),
(10, 0),
(15, 0),
(22, 0),
(24, 0),
(29, 0),
(3, 1),
(6, 1),
(18, 1),
(19, 1),
(25, 1),
(27, 1),
(5, 2),
(9, 2),
(13, 2),
(14, 2),
(17, 2),
(28, 2),
(0, 3),
(8, 3),
(11, 3),
(16, 3),
(20, 3),
(26, 3),
(1, 4),
(2, 4),
(4, 4),
(12, 4),
(21, 4),
(23, 4),
(5, 5),
(6, 5),
(8, 5),
(10, 5),
(21, 5),
(29, 5),
(14, 6),
(15, 6),
(16, 6),
(18, 6),
(22, 6),
(28, 6),
(0, 7),
(1, 7),
(4, 7),
(9, 7),
(20, 7),
(26, 7),
(2, 8),
(3, 8),
(11, 8),
(12, 8),
(17, 8),
(19, 8),
(7, 9),
(13, 9),
(23, 9),
(24, 9),
(25, 9),
(27, 9),
(0, 10),
(6, 10),
(15, 10),
(18, 10),
(21, 10),
(26, 10),
(2, 11),
(7, 11),
(10, 11),
(17, 11),
(22, 11),
(27, 11),
(8, 12),
(11, 12),
(14, 12),
(20, 12),
(23, 12),
(29, 12),
(4, 13),
(5, 13),
(9, 13),
(13, 13),
(16, 13),
(19, 13),
(1, 14),
(3, 14),
(12, 14),
(24, 14),
(25, 14),
(28, 14),
)
#let tanner_illustration() = {
cetz.canvas(length: 1.1cm, {
import cetz.draw: *
let vy = 2.6
let cy = 0.0
let vxs = (0.0, 1.2, 2.4, 3.6)
let cxs = (0.9, 2.7)
let edges = ((0, 0), (1, 0), (2, 0), (1, 1), (2, 1), (3, 1))
// Dessin des arêtes
for (vi, ci) in edges {
line(
(vxs.at(vi), vy - 0.28),
(cxs.at(ci), cy + 0.32),
stroke: 0.9pt + gray.darken(10%),
)
}
// Nœuds de contrôle (carrés, orange)
let cnames = ([$c_0$], [$c_1$])
for j in range(2) {
let cx = cxs.at(j)
let s = 0.30
rect(
(cx - s, cy - s),
(cx + s, cy + s),
fill: orange.lighten(75%),
stroke: 1.8pt + orange,
name: "c" + str(j),
)
content(
(cx, cy - s - 0.3),
anchor: "north",
text(size: 0.8em, fill: orange, weight: "bold")[#cnames.at(j)],
)
}
// Nœuds de variable (cercles, bleu)
let vnames = ([$v_0$], [$v_1$], [$v_2$], [$v_3$])
for i in range(4) {
let vx = vxs.at(i)
let r = 0.28
circle(
(vx, vy),
radius: r,
fill: blue.lighten(75%),
stroke: 1.8pt + blue,
name: "v" + str(i),
)
content(
(vx, vy + r + 0.25),
anchor: "south",
text(size: 0.8em, fill: blue, weight: "bold")[#vnames.at(i)],
)
}
})
}
// Mini matrice H avec surbrillance d'une ligne et/ou colonne
#let h_mini_tanner(hl_row: none, hl_col: none) = {
let pts = _h_pts
cetz.canvas(length: 0.215cm, {
import cetz.draw: *
let nx = 30
let ny = 15
content((-7, -7.5), text(size: 1.5em, weight: "bold")[$H =$])
if hl_row != none {
rect((0, -hl_row), (nx, -hl_row - 1), fill: orange.lighten(85%), stroke: none)
}
if hl_col != none {
rect((hl_col, 0), (hl_col + 1, -ny), fill: blue.lighten(85%), stroke: none)
}
set-style(stroke: (thickness: 0.9pt, cap: "round"))
line((0.4, 0.25), (0, 0.25), (0, -ny - 0.25), (0.4, -ny - 0.25))
line((nx - 0.4, 0.25), (nx, 0.25), (nx, -ny - 0.25), (nx - 0.4, -ny - 0.25))
for (x, y) in pts {
let r = 0.13
let col = gray.darken(25%)
if hl_row != none and y == hl_row {
col = orange
r = 0.22
} else if hl_col != none and x == hl_col {
col = blue
r = 0.22
}
circle((x + 0.5, -y - 0.5), radius: r, fill: col, stroke: none)
}
if hl_row != none {
content((nx + 0.5, -hl_row - 0.5), anchor: "west", text(fill: orange, size: 1.0em, weight: "bold")[$c_#hl_row$])
}
if hl_col != none {
content((hl_col + 0.5, 0.70), anchor: "south", text(fill: blue, size: 1.0em, weight: "bold")[$v_#hl_col$])
}
})
}
#let hldpc_dynamic(hl_rows: (), hl_cols: (), show_labels: true, h_show: true) = {
import cetz.draw: *
let points = (
(7, 0),
(10, 0),
(15, 0),
(22, 0),
(24, 0),
(29, 0),
(3, 1),
(6, 1),
(18, 1),
(19, 1),
(25, 1),
(27, 1),
(5, 2),
(9, 2),
(13, 2),
(14, 2),
(17, 2),
(28, 2),
(0, 3),
(8, 3),
(11, 3),
(16, 3),
(20, 3),
(26, 3),
(1, 4),
(2, 4),
(4, 4),
(12, 4),
(21, 4),
(23, 4),
(5, 5),
(6, 5),
(8, 5),
(10, 5),
(21, 5),
(29, 5),
(14, 6),
(15, 6),
(16, 6),
(18, 6),
(22, 6),
(28, 6),
(0, 7),
(1, 7),
(4, 7),
(9, 7),
(20, 7),
(26, 7),
(2, 8),
(3, 8),
(11, 8),
(12, 8),
(17, 8),
(19, 8),
(7, 9),
(13, 9),
(23, 9),
(24, 9),
(25, 9),
(27, 9),
(0, 10),
(6, 10),
(15, 10),
(18, 10),
(21, 10),
(26, 10),
(2, 11),
(7, 11),
(10, 11),
(17, 11),
(22, 11),
(27, 11),
(8, 12),
(11, 12),
(14, 12),
(20, 12),
(23, 12),
(29, 12),
(4, 13),
(5, 13),
(9, 13),
(13, 13),
(16, 13),
(19, 13),
(1, 14),
(3, 14),
(12, 14),
(24, 14),
(25, 14),
(28, 14),
)
cetz.canvas(length: 0.4cm, {
let nx = 30
let ny = 15
let col_row = orange
let col_col = blue
let col_dot_base = gray.darken(30%)
// Marge pour réduire l'épaisseur des bandes (crée le gap visuel)
let gap = 0.1
if h_show {
content((-3.4, -ny / 2), text(size: 1.6em, weight: "bold")[$H =$])
} else {
content((-3.4, -ny / 2), text(size: 1.6em, weight: "bold")[$space space space$])
}
// 1. Dessiner les fonds des lignes (avec gap)
for r in hl_rows {
rect((0, -r - gap), (nx, -r - 1 + gap), fill: col_row.lighten(85%), stroke: none)
}
// 2. Dessiner les fonds des colonnes (avec gap)
for c in hl_cols {
rect((c + gap, 0), (c + 1 - gap, -ny), fill: col_col.lighten(85%), stroke: none)
}
// 3. Dessiner les intersections
for r in hl_rows {
for c in hl_cols {
rect(
(c + gap, -r - gap),
(c + 1 - gap, -r - 1 + gap),
fill: col_row.lighten(85%).mix(col_col.lighten(85%)),
stroke: none,
)
}
}
// 4. Les grands crochets matriciels
let b_w = 0.6
set-style(stroke: (thickness: 1.5pt, cap: "round"))
line((b_w, 0.3), (0, 0.3), (0, -ny - 0.3), (b_w, -ny - 0.3))
line((nx - b_w, 0.3), (nx, 0.3), (nx, -ny - 0.3), (nx - b_w, -ny - 0.3))
// 5. Dessin des points
for (x, y) in points {
let px = x + 0.5
let py = -y - 0.5
let is_row = y in hl_rows
let is_col = x in hl_cols
let d_col = col_dot_base
let r = 0.15
// Détermine la couleur et la taille si le point est dans une zone surlignée
if is_row and is_col {
d_col = col_row.mix(col_col) // Point à l'intersection
r = 0.24
} else if is_row {
d_col = col_row
r = 0.24
} else if is_col {
d_col = col_col
r = 0.24
}
circle((px, py), radius: r, fill: d_col, stroke: none)
}
// 6. Affichage optionnel des labels
if show_labels {
for r in hl_rows {
content((nx + 0.5, -r - 0.5), anchor: "west", text(fill: col_row, weight: "bold", size: 1.1em)[$c_#r$])
}
for c in hl_cols {
content((c + 0.5, -ny - 0.8), anchor: "north", text(fill: col_col, weight: "bold", size: 1.1em)[$v_#c$])
}
}
})
}
// Graphe de Tanner paramétrable
// scale : taille d'une unité cetz
// hl_row : index du check node à mettre en évidence (none = aucun)
// hl_col : index du variable node à mettre en évidence (none = aucun)
// show_all : afficher toutes les arêtes
// colored : colorier tous les nœuds (bleu/orange) même sans highlight
#let tanner_canvas(
scale: 0.43cm,
hl_row: none,
hl_col: none,
show_all: false,
colored: false,
v_c_show: true,
) = {
let pts = _h_pts
cetz.canvas(length: scale, {
import cetz.draw: *
let n_var = 30
let n_chk = 15
let vy = 5.5
let cy = 0.0
// --- Logique de centrage ---
let gap_v = 1.0 // Espacement des cercles
let gap_c = 1.8 // Espacement des carrés (un peu plus large pour l'équilibre visuel)
let width_v = (n_var - 1) * gap_v
let width_c = (n_chk - 1) * gap_c
let offset_c = (width_v - width_c) / 2 // Calcul du décalage pour centrer C sous V
// Noeuds connectés au check ou variable mis en évidence
let hl_var_set = if hl_row != none {
pts.filter(p => p.at(1) == hl_row).map(p => p.at(0))
} else { () }
let hl_chk_set = if hl_col != none {
pts.filter(p => p.at(0) == hl_col).map(p => p.at(1))
} else { () }
// — ARÊTES —
for (vj, ci) in pts {
let vx = vj * gap_v
let ccx = offset_c + (ci * gap_c)
let is_row = hl_row != none and ci == hl_row
let is_col = hl_col != none and vj == hl_col
let do_draw = is_row or is_col or show_all
if do_draw {
let s = if is_row { 1.5pt + orange } else if is_col { 2.0pt + blue } else { 0.50pt + gray.lighten(20%) }
line((vx, vy), (ccx, cy), stroke: s)
}
}
// — NŒUDS DE CONTRÔLE (carrés) —
for j in range(n_chk) {
let ccx = offset_c + (j * gap_c)
let sz = 0.40
let is_main = hl_row != none and j == hl_row
let is_conn = hl_chk_set.contains(j)
let fc = if is_main { orange.lighten(48%) } else if is_conn { blue.lighten(60%) } else if colored {
orange.lighten(76%)
} else { white }
let sc = if is_main { 1.8pt + orange } else if is_conn { 1.8pt + blue } else if colored { 1.2pt + orange } else {
1.0pt + black
}
rect((ccx - sz, cy - sz), (ccx + sz, cy + sz), fill: fc, stroke: sc)
if is_main {
content((ccx, cy - sz - 0.33), anchor: "north", text(size: 0.52em, fill: orange, weight: "bold")[$c_#j$])
} else if is_conn {
content((ccx, cy - sz - 0.33), anchor: "north", text(size: 0.52em, fill: blue, weight: "bold")[$c_#j$])
}
}
// — NŒUDS DE VARIABLE (cercles) —
for i in range(n_var) {
let vx = i * gap_v
let r = 0.33
let is_main = hl_col != none and i == hl_col
let is_conn = hl_var_set.contains(i)
let fc = if is_main { blue.lighten(48%) } else if is_conn { orange.lighten(60%) } else if colored {
blue.lighten(76%)
} else { white }
let sc = if is_main { 1.5pt + blue } else if is_conn { 1.5pt + orange } else if colored { 1.2pt + blue } else {
1.0pt + black
}
circle((vx, vy), radius: r, fill: fc, stroke: sc)
if is_main {
content((vx, vy + r + 0.30), anchor: "south", text(size: 0.52em, fill: blue, weight: "bold")[$v_#i$])
} else if is_conn {
content((vx, vy + r + 0.30), anchor: "south", text(size: 0.52em, fill: orange, weight: "bold")[$v_#i$])
}
}
// Légendes des couches
if v_c_show {
content((-2.0, vy), anchor: "east", text(size: 0.65em, weight: "bold")[$V$])
content((-2.0, cy), anchor: "east", text(size: 0.65em, weight: "bold")[$C$])
}
})
}
// Diagramme passage de messages (Belief Propagation)
#let bp_diagram() = {
cetz.canvas(length: 1.05cm, {
import cetz.draw: *
let vy = 3.0
let cy = 0.0
let vxs = (0.0, 1.3, 2.6, 3.9)
let cxs = (0.65, 2.6)
let edges = ((0, 0), (1, 0), (2, 0), (1, 1), (2, 1), (3, 1))
let mk_bl = (end: "stealth", fill: blue, size: 0.17)
let mk_or = (end: "stealth", fill: orange, size: 0.17)
// Flèches bidirectionnelles décalées
for (vi, ci) in edges {
let vx = vxs.at(vi)
let cx = cxs.at(ci)
// V → C (bleu, décalé à gauche)
line((vx - 0.06, vy - 0.32), (cx - 0.06, cy + 0.38), mark: mk_bl, stroke: 1.4pt + blue.lighten(15%))
// C → V (orange, décalé à droite)
line((cx + 0.06, cy + 0.38), (vx + 0.06, vy - 0.32), mark: mk_or, stroke: 1.4pt + orange.lighten(10%))
}
// Nœuds de variable
let vnames = ([$v_0$], [$v_1$], [$v_2$], [$v_3$])
for i in range(4) {
let vx = vxs.at(i)
let r = 0.30
circle((vx, vy), radius: r, fill: blue.lighten(72%), stroke: 1.6pt + blue)
content((vx, vy + r + 0.20), anchor: "south", text(size: 0.70em, fill: blue, weight: "bold")[#vnames.at(i)])
}
// Nœuds de contrôle
let cnames = ([$c_0$], [$c_1$])
for j in range(2) {
let cx = cxs.at(j)
let s = 0.33
rect((cx - s, cy - s), (cx + s, cy + s), fill: orange.lighten(72%), stroke: 1.6pt + orange)
content((cx, cy - s - 0.22), anchor: "north", text(size: 0.70em, fill: orange, weight: "bold")[#cnames.at(j)])
}
// Légendes des flèches
content((4.45, vy - 0.5), anchor: "west", text(size: 0.65em, fill: blue, weight: "bold")[$mu_(j arrow i)$])
content((4.45, cy + 0.4), anchor: "west", text(size: 0.65em, fill: orange, weight: "bold")[$nu_(i arrow j)$])
})
}
#let icon_var = box(baseline: 20%)[
#cetz.canvas({
import cetz.draw: *
circle((0, 0), radius: 0.35em, fill: blue.lighten(88%), stroke: 1.5pt + blue)
})
]
#let icon_chk = box(baseline: 20%)[
#cetz.canvas({
import cetz.draw: *
rect((-0.35em, -0.35em), (0.35em, 0.35em), fill: orange.lighten(88%), stroke: 1.5pt + orange)
})
]

10133
main.pdf

File diff suppressed because it is too large Load Diff

393
main.typ
View File

@ -41,9 +41,13 @@
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],
))
[Introduction],
[Codes linéaires],
[LDPC],
[Codage],
[Décodage],
[Analyse],
)),
)
]
@ -249,40 +253,40 @@
#let colp = orange
#place(dx: 0cm, dy: 2.0cm)[
#set text(size: 1.1em)
Enfin
#set text(size: 1.1em)
Enfin
$
H = #math.mat(
(text(fill: colp)[1], text(fill: colp)[0], 1, 0, 0),
(text(fill: colp)[1], text(fill: colp)[1], 0, 1, 0),
(text(fill: colp)[0], text(fill: colp)[1], 0, 0, 1),
augment: 2,
)
$
$
H = #math.mat(
(text(fill: colp)[1], text(fill: colp)[0], 1, 0, 0),
(text(fill: colp)[1], text(fill: colp)[1], 0, 1, 0),
(text(fill: colp)[0], text(fill: colp)[1], 0, 0, 1),
augment: 2,
)
$
#v(0.8em)
#v(0.8em)
Vérification du mot de code $display(c = mat(#text(fill: colu)[1], #text(fill: colu)[1], #text(fill: colp)[1], #text(fill: colp)[0], #text(fill: colp)[1]))$
Vérification du mot de code $display(c = mat(#text(fill: colu)[1], #text(fill: colu)[1], #text(fill: colp)[1], #text(fill: colp)[0], #text(fill: colp)[1]))$
#v(0.8em)
#v(0.8em)
$
H c^top = mat(
1, 0, 1, 0, 0;
1, 1, 0, 1, 0;
0, 1, 0, 0, 1
) mat(#text(fill: colu)[1], #text(fill: colu)[1], #text(fill: colp)[1], #text(fill: colp)[0], #text(fill: colp)[1])^top
= mat(
1 plus.o 0 plus.o 1 plus.o 0 plus.o 0;
1 plus.o 1 plus.o 0 plus.o 0 plus.o 0;
0 plus.o 1 plus.o 0 plus.o 0 plus.o 1
)
= mat(0; 0; 0)
$
$
H c^top = mat(
1, 0, 1, 0, 0;
1, 1, 0, 1, 0;
0, 1, 0, 0, 1
) mat(#text(fill: colu)[1], #text(fill: colu)[1], #text(fill: colp)[1], #text(fill: colp)[0], #text(fill: colp)[1])^top
= mat(
1 plus.o 0 plus.o 1 plus.o 0 plus.o 0;
1 plus.o 1 plus.o 0 plus.o 0 plus.o 0;
0 plus.o 1 plus.o 0 plus.o 0 plus.o 1
)
= 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")[
@ -300,52 +304,52 @@
#myslide("Le Mur de la Complexité")[
#set text(size: 19pt)
#definition(titre: [Décodage par Maximum de Vraisemblance (MDL)], 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)) $
]
#definition(titre: [Décodage par Maximum de Vraisemblance (MDL)], 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)) $
]
- Équivalent à chercher l'erreur $bold(e)$ de poids minimal tel que $bold(H) bold(e)^top = bold(s)$.
- Équivalent à chercher l'erreur $bold(e)$ de poids minimal tel que $bold(H) bold(e)^top = bold(s)$.
#v(0.5em)
#v(0.5em)
#definition(titre: "Le Problème du décodage par Syndrome")[
NP-Difficile et pour $H$ quelconque : $cal(O)(2^k)$
]
#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.
- Pour $k=100$ bits, $2^100 approx 10^30$ opérations nécessaires.
]
#myslide("Définition des Codes LDPC")[
#definition(titre: [Formalisation des Codes LDPC Réguliers])[
Code linéaire en bloc avec une matrice de contrôle $bold(H)$ est *clairsemée*.
]
- *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$
]
#definition(titre : "Rendement")[
$ display(R = (n - op("rg")(H)) / n >= 1 - m / n) $
]
#definition(titre: [Formalisation des Codes LDPC Réguliers])[
Code linéaire en bloc avec une matrice de contrôle $bold(H)$ est *clairsemée*.
]
#myslide([Matrice de contrôle])[
#definition(titre : [Code LDPC $(6, 3)$])[
- *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$
]
#definition(titre: "Rendement")[
$ display(R = (n - op("rg")(H)) / n >= 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)$
]
#v(2cm)
#place(center + horizon, dx: 0cm, dy: 7.3cm)[
#scale(140%)[#hldpc()]
#scale(140%)[#hldpc()]
]
]
@ -364,12 +368,14 @@
[
// #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
) $
]
]
$
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
)
$
]
],
)
]
]
@ -395,34 +401,34 @@
#myslide("L'Entrelacement des Contraintes")[
#set text(size: 17pt)
#align(center)[
#move(dx: -1.2cm)[
#scale(115%)[#hldpc_dual(row1: 0, row2: 14)]
#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
#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(
#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)$],
#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)
#v(1cm)
#set align(left)
#set text(size: 1.1em)
@ -489,4 +495,229 @@
]
#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$], E)$
:
#v(4pt)
$ (#text(fill: blue)[$v_j$], #text(fill: orange)[$c_i$]) in E 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*],
[- $|E| = 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: false)
]
]
// #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$
],
)
]
]
]
// HARD DECISION
// #myslide("Graphe de Tanner : Utilité")[
// #grid(
// columns: (1.55fr, 1fr),
// column-gutter: 0.5cm,
// align: top,
// [
// #definition(titre: "Support du Passage de Messages")[
// Le graphe de Tanner est le *cadre naturel* des algorithmes de décodage itératifs — il rend la structure du code *explicite et locale*
// ]
//
// #v(0.45em)
//
// #[
// #set text(size: 1.05em)
// - *Localité* : chaque nœud n'opère qu'avec ses *voisins directs*
//
// - *Itérations — à chaque tour :*
// #pad(left: 0.9em)[
// #text(fill: blue, weight: "bold")[V → C :] $v_j$ envoie son estimation (LLR) aux $c_i$ voisins \
// #text(fill: orange, weight: "bold")[C → V :] $c_i$ renvoie une correction aux $v_j$ voisins
// ]
//
// - *Convergence* vers le mot de code le plus vraisemblable
//
// - *Complexité* : $cal(O)(n dot w_c)$ par itération \ vs $cal(O)(2^k)$ pour le MDL — gain *exponentiel*
// ]
// ],
// [
// #v(0.6em)
// #align(center)[
// #bp_diagram()
// #v(0.5em)
// #set text(size: 0.79em)
// #stack(
// dir: ttb,
// spacing: 0.25em,
// [#box(width: 1.3em, height: 2pt, fill: blue)
// #h(0.3em) #text(fill: blue, weight: "bold")[$mu_(j arrow i)$ : V → C] (LLR)],
// [#box(width: 1.3em, height: 2pt, fill: orange)
// #h(0.3em) #text(fill: orange, weight: "bold")[$nu_(i arrow j)$ : C → V] (correction)],
// )
// ]
// ],
// )
// ]