#import "@preview/polylux:0.4.0": * #import "@preview/cetz:0.5.0" #import "@preview/cetz-plot:0.1.3": plot #set math.mat(delim: "[") // 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() let cur = counter("logical-slide").get().first() let tot = counter("logical-slide").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 n°#numero], [#titre], [#annee], [#(cur - 1) / #(tot - 1)], ) ] } } ] // 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, ..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() ) ] ] } // Graphe de Tanner en filigrane #let graphe_tanner_fond(taille, spread) = { cetz.canvas(length: taille, { import cetz.draw: * let n_var = 18 let n_chk = 9 let var_y = 11 let chk_y = -8 // Calcul automatique pour que le graphe soit centré sur X=0 let dist_v = (n_var - 1) * spread let v_start = -dist_v / 2 let vpos = range(n_var).map(i => (v_start + i * spread, var_y)) let spread_c = dist_v / (n_chk - 1) let c_start = -dist_v / 2 let cpos = range(n_chk).map(i => (c_start + i * spread_c, chk_y)) let edges = ( (0, 0), (0, 4), (0, 8), (1, 1), (1, 5), (1, 0), (2, 2), (2, 6), (2, 1), (3, 3), (3, 7), (3, 2), (4, 4), (4, 8), (4, 3), (5, 5), (5, 0), (5, 4), (6, 6), (6, 1), (6, 5), (7, 7), (7, 2), (7, 6), (8, 8), (8, 3), (8, 7), (9, 0), (9, 3), (9, 6), (10, 1), (10, 4), (10, 7), (11, 2), (11, 5), (11, 8), (12, 0), (12, 5), (12, 7), (13, 1), (13, 3), (13, 8), (14, 2), (14, 4), (14, 6), (15, 0), (15, 4), (15, 7), (16, 1), (16, 5), (16, 8), (17, 2), (17, 3), (17, 6), ) for e in edges { let vp = vpos.at(e.at(0)) let cp = cpos.at(e.at(1)) line((vp.at(0), vp.at(1)), (cp.at(0), cp.at(1)), stroke: 0.45pt + rgb("#e0e0e0")) } for p in vpos { circle((p.at(0), p.at(1)), radius: 0.25, fill: white, stroke: 0.8pt + rgb("#cccccc")) } for p in cpos { let (x, y) = p rect((x - 0.25, y - 0.25), (x + 0.25, y + 0.25), fill: white, stroke: 0.8pt + rgb("#cccccc")) } }) } // Schema Shannon #let canal_shannon_intro() = { 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]) }) } #let plongement_schema() = { 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, -2.6), [$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((rel: (-0.85, 0.1), to: 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((rel: (0.85, -0.1), to: cf.p110), [110], anchor: "north-east", padding: .2) content((4, -2.6), [$FF_2^3$]) }) } #let definition( titre: "Définition", accent: black, titre_taille: 1.13em, corps_taille: 1.2em, contenu, ) = { block( width: 100%, fill: rgb("#f8f9fa"), stroke: 0.5pt + gray.lighten(60%), radius: 8pt, clip: true, grid( columns: (5pt, 1fr), rows: auto, fill: (col, row) => if col == 0 { accent }, [], block( width: 100%, inset: (x: 16pt, y: 15pt), { { set text(fill: accent, weight: 800, size: titre_taille, tracking: 0.5pt) show math.equation: set text(weight: 700, size: 1.05em) titre } v(18pt, weak: true) { set text(size: corps_taille) set par(leading: 0.7em, justify: false) contenu } }, ), ), ) } #let limite_shannon_graphique() = { let col-shannon = red.darken(10%) let col-code-long = blue.darken(20%) let col-code-short = gray.lighten(10%) set text(size: 11pt) move(dx: -5pt, dy: 0pt)[ #cetz.canvas({ import cetz.draw: * plot.plot( size: (23, 15), // 1. On grossit les labels d'axes (15pt) x-label: pad(bottom: 30pt)[#move(dy: 80pt)[#text(size: 18pt)[$E_b/N_0$ (dB)]]], y-label: move(dx: -20pt, dy: -10pt)[#text(size: 18pt)[Bit Error Rate (BER)]], x-min: 0, x-max: 10, y-min: -8.5, y-max: 0.2, x-tick-step: 1, y-tick-step: 2, // Axis x-format: x => move(dy: 14pt)[#text(size: 16pt)[#x]], y-format: y => move(dx: -5pt)[#text(size: 16pt)[$10^(#y)$]], x-grid: true, y-grid: true, // Légende positionnée en bas. legend: "north-east", legend-style: ( stroke: 0.5pt + gray, fill: white, padding: 0.2, offset: (-161.4pt, -45.1pt), ), { // 1. Limite de Shannon (Asymptote) plot.add( ((1.5, -8.5), (1.5, 0.2)), style: (stroke: (paint: col-shannon, thickness: 2pt, dash: "dashed")), label: [Limite de Shannon], ) // 2. Petit bloc linéaire (n ≈ 100) - Ultra-densifié (smooth) plot.add( ( (0.0, 0.00), (0.2, -0.01), (0.4, -0.03), (0.6, -0.05), (0.8, -0.07), (1.0, -0.10), (1.2, -0.13), (1.4, -0.17), (1.6, -0.21), (1.8, -0.25), (2.0, -0.30), (2.2, -0.36), (2.4, -0.43), (2.6, -0.51), (2.8, -0.60), (3.0, -0.70), (3.2, -0.80), (3.4, -0.91), (3.6, -1.03), (3.8, -1.16), (4.0, -1.30), (4.2, -1.44), (4.4, -1.59), (4.6, -1.75), (4.8, -1.92), (5.0, -2.10), (5.2, -2.28), (5.4, -2.47), (5.6, -2.67), (5.8, -2.88), (6.0, -3.10), (6.2, -3.32), (6.4, -3.55), (6.6, -3.79), (6.8, -4.04), (7.0, -4.30), (7.2, -4.56), (7.4, -4.83), (7.6, -5.11), (7.8, -5.40), (8.0, -5.70), (8.2, -6.00), (8.4, -6.31), (8.6, -6.63), (8.8, -6.96), (9.0, -7.30), (9.2, -7.62), (9.4, -7.95), (9.6, -8.29), (9.8, -8.64), (10.0, -9.00), ), style: (stroke: (paint: col-code-short, thickness: 1.5pt)), label: [Code court ($n approx 100$)], ) // 3. Grand bloc linéaire (n = 64 800) - Ultra-densifié (smooth & waterfall net) plot.add( ( (0.0, 0.0), (0.2, -0.005), (0.4, -0.01), (0.6, -0.02), (0.8, -0.035), (1.0, -0.05), (1.1, -0.07), (1.2, -0.10), (1.3, -0.14), (1.4, -0.20), (1.45, -0.28), (1.50, -0.40), (1.52, -0.45), (1.54, -0.52), (1.56, -0.60), (1.58, -0.69), (1.60, -0.80), (1.62, -0.92), (1.64, -1.05), (1.66, -1.19), (1.68, -1.34), (1.70, -1.50), (1.72, -1.69), (1.74, -1.89), (1.76, -2.11), (1.78, -2.35), (1.80, -2.60), (1.82, -2.88), (1.84, -3.18), (1.86, -3.50), (1.88, -3.84), (1.90, -4.20), (1.92, -4.52), (1.94, -4.86), (1.96, -5.22), (1.98, -5.60), (2.00, -6.00), (2.02, -6.32), (2.04, -6.64), (2.06, -6.94), (2.08, -7.23), (2.10, -7.50), (2.12, -7.66), (2.14, -7.81), (2.16, -7.95), (2.18, -8.08), (2.20, -8.20), (2.22, -8.32), (2.24, -8.44), (2.25, -8.50), ), style: (stroke: (paint: col-code-long, thickness: 3.5pt)), label: [Code long ($n = 64\,800$)], ) }, ) }) ] }