This commit is contained in:
2026-06-09 18:47:17 +02:00
parent 6da683f311
commit 899f848626
3 changed files with 250 additions and 0 deletions

View File

@ -64,6 +64,7 @@ pub enum GenerationMethod {
Gallager,
// Ajout de colonnes de poids fixe, rejet si cycle4 créé
MacKayNeal { max_attempts: usize },
Peg,
}
// Forme systématique
@ -96,6 +97,7 @@ impl LdpcCode {
GenerationMethod::MacKayNeal { max_attempts } => {
generate_mackay_neal(&params, *max_attempts, &mut rng)?
}
GenerationMethod::Peg => generate_peg(&params, &mut rng)?,
};
let graph = TannerGraph::from_matrix(&h);
Ok(Self {
@ -324,6 +326,119 @@ fn generate_mackay_neal(
Ok(SparseMatrixGF2::from_positions(m, n, ones))
}
// Progressive Edge Growth
fn generate_peg(params: &LdpcParams, rng: &mut impl rand::Rng) -> Result<SparseMatrixGF2> {
let CodeTopology::Regular { wc, wr } = params.topology else {
return Err(LdpcError::InvalidParameters(
"PEG nécessite un code régulier".into(),
));
};
let n = params.n;
let m = params.m();
let mut check_adj: Vec<Vec<usize>> = vec![vec![]; m];
let mut var_adj: Vec<Vec<usize>> = vec![vec![]; n];
for j in 0..n {
for _edge_idx in 0..wc {
let c_star = peg_select_check(j, &var_adj, &check_adj, m, wr, rng)
.ok_or(LdpcError::GenerationFailed { attempts: wc })?;
var_adj[j].push(c_star);
check_adj[c_star].push(j);
}
}
let ones: Vec<(usize, usize)> = check_adj
.iter()
.enumerate()
.flat_map(|(c, vars)| vars.iter().map(move |&v| (c, v)))
.collect();
Ok(SparseMatrixGF2::from_positions(m, n, ones))
}
/// BFS dans le graphe bipartite courant depuis vj
/// Retourne le check node à relier à vj selon le critère PEG
fn peg_select_check(
vj: usize,
var_adj: &[Vec<usize>],
check_adj: &[Vec<usize>],
m: usize,
wr: usize,
rng: &mut impl rand::Rng,
) -> Option<usize> {
use std::collections::HashSet;
let mut visited_checks = HashSet::<usize>::new();
let mut visited_vars = HashSet::<usize>::new();
visited_vars.insert(vj);
let mut var_frontier: Vec<usize> = vec![vj];
let mut last_check_frontier: Vec<usize> = vec![];
loop {
// expand : nouveaux check nodes
let new_checks: Vec<usize> = var_frontier
.iter()
.flat_map(|&v| var_adj[v].iter().copied())
.filter(|&c| visited_checks.insert(c))
.collect();
if new_checks.is_empty() {
// vj a pas encore d'aretes, ou plus d'expansion possible
break;
}
last_check_frontier = new_checks.clone();
if visited_checks.len() == m {
// Tous les check nodes sont dans l'arbre
break;
}
let new_vars: Vec<usize> = new_checks
.iter()
.flat_map(|&c| check_adj[c].iter().copied())
.filter(|&v| visited_vars.insert(v))
.collect();
if new_vars.is_empty() {
break;
}
var_frontier = new_vars;
}
// Selection du check node opi
let candidates: Vec<usize> = if visited_checks.len() < m {
(0..m)
.filter(|&c| !visited_checks.contains(&c) && check_adj[c].len() < wr)
.collect()
} else {
// Tous atteints : on choisit dans la frontière la plus profonde
// → minimise l'allongement du plus court cycle potentiel
last_check_frontier
.into_iter()
.filter(|&c| check_adj[c].len() < wr)
.collect()
};
peg_pick_min_degree(candidates, check_adj, rng)
}
fn peg_pick_min_degree(
candidates: Vec<usize>,
check_adj: &[Vec<usize>],
rng: &mut impl rand::Rng,
) -> Option<usize> {
use rand::seq::SliceRandom;
let min_deg = candidates.iter().map(|&c| check_adj[c].len()).min()?;
let tied: Vec<usize> = candidates
.into_iter()
.filter(|&c| check_adj[c].len() == min_deg)
.collect();
tied.choose(rng).copied()
}
fn default_graph() -> TannerGraph {
TannerGraph::from_matrix(&SparseMatrixGF2::zeros(1, 1))
}

View File

@ -0,0 +1,22 @@
0.029351162s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: stale: changed "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/code.rs"
0.029360467s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: (vs) "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/target/debug/.fingerprint/ldpc-b352954ef2586175/dep-lib-ldpc"
0.029362608s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: FileTime { seconds: 1780948622, nanos: 714654968 } < FileTime { seconds: 1780950346, nanos: 459070742 }
0.029411218s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: false }/TargetInner { name_inferred: true, ..: lib_target("ldpc", ["lib"], "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/lib.rs", Edition2021) }
0.029418167s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleItem(ChangedFile { reference: "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/target/debug/.fingerprint/ldpc-b352954ef2586175/dep-lib-ldpc", reference_mtime: FileTime { seconds: 1780948622, nanos: 714654968 }, stale: "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/code.rs", stale_mtime: FileTime { seconds: 1780950346, nanos: 459070742 } }))
0.031783929s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: stale: changed "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/code.rs"
0.031788513s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: (vs) "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/target/debug/.fingerprint/ldpc-eee857b18c023b6c/dep-test-lib-ldpc"
0.031790327s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: FileTime { seconds: 1780948622, nanos: 714654968 } < FileTime { seconds: 1780950346, nanos: 459070742 }
0.031808097s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: true }/TargetInner { name_inferred: true, ..: lib_target("ldpc", ["lib"], "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/lib.rs", Edition2021) }
0.031813154s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleItem(ChangedFile { reference: "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/target/debug/.fingerprint/ldpc-eee857b18c023b6c/dep-test-lib-ldpc", reference_mtime: FileTime { seconds: 1780948622, nanos: 714654968 }, stale: "/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/code.rs", stale_mtime: FileTime { seconds: 1780950346, nanos: 459070742 } }))
0.032070702s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="generator"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: false }/TargetInner { name: "generator", doc: true, ..: with_path("/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/bin/generator.rs", Edition2021) }
0.032076711s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="generator"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "ldpc" })
0.032300350s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="generator"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: true }/TargetInner { name: "generator", doc: true, ..: with_path("/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/bin/generator.rs", Edition2021) }
0.032305502s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="generator"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "ldpc" })
0.032528690s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: false }/TargetInner { name: "ldpc", doc: true, ..: with_path("/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/main.rs", Edition2021) }
0.032533240s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "ldpc" })
0.032724967s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: fingerprint dirty for ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)/Check { test: true }/TargetInner { name: "ldpc", doc: true, ..: with_path("/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc/src/main.rs", Edition2021) }
0.032729456s INFO prepare_target{force=false package_id=ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc) target="ldpc"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "ldpc" })
Checking ldpc v0.1.0 (/home/zefad/Documents/CLP/MPI2/TIPE2/ldpc)
error: could not compile `ldpc` (lib test) due to 3 previous errors; 3 warnings emitted
warning: build failed, waiting for other jobs to finish...
error: could not compile `ldpc` (lib) due to 3 previous errors; 3 warnings emitted

File diff suppressed because one or more lines are too long