Compare commits
4 Commits
33a376967a
...
2096cff73c
| Author | SHA1 | Date | |
|---|---|---|---|
| 2096cff73c | |||
| 22db186237 | |||
| a7ce4a1a17 | |||
| a6b2690721 |
32
Code/ldpc/src/channel.rs
Normal file
32
Code/ldpc/src/channel.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use std::usize;
|
||||||
|
|
||||||
|
use rand::{Rng, RngExt};
|
||||||
|
|
||||||
|
pub struct Channel {
|
||||||
|
pub error_prob: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Channel {
|
||||||
|
pub fn new(error_prob: f64) -> Self {
|
||||||
|
assert!(error_prob >= 0.0 && error_prob <= 1.0, "0 <= p <= 1");
|
||||||
|
Self { error_prob }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_noise(&self, input: &[u8]) -> Vec<u8> {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
let mut out = input.to_vec();
|
||||||
|
|
||||||
|
for b in out.iter_mut() {
|
||||||
|
let r_v: f64 = rng.random_range(0.0..1.0);
|
||||||
|
if r_v < self.error_prob {
|
||||||
|
*b ^= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn count_errors(original: &[u8], other: &[u8]) -> usize {
|
||||||
|
assert_eq!(original.len(), other.len(), "Slice pas de la même taille");
|
||||||
|
original.iter().zip(other).filter(|(a, b)| a != b).count()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,74 +1,13 @@
|
|||||||
mod analysis;
|
mod analysis;
|
||||||
|
mod channel;
|
||||||
mod code;
|
mod code;
|
||||||
mod construction;
|
mod construction;
|
||||||
mod decoder;
|
mod decoder;
|
||||||
mod encoder;
|
mod encoder;
|
||||||
mod matrix;
|
mod matrix;
|
||||||
|
mod simulation;
|
||||||
mod tanner;
|
mod tanner;
|
||||||
|
|
||||||
use code::LdpcCode;
|
|
||||||
use construction::random::generate_random_h;
|
|
||||||
use decoder::bit_flip::BitFlipDecoder;
|
|
||||||
use encoder::dense::DenseEncoder;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// TODO : Changer la logique pour trouver k => calculer n selon la longueur du message k (en
|
simulation::run_simulation(6, 2, 4, 0.1);
|
||||||
// rapport des poids) n = (k * w_r) / (w_r - w_c)
|
|
||||||
println!("LDPC\n");
|
|
||||||
|
|
||||||
let n = 12;
|
|
||||||
let m = 6;
|
|
||||||
let wc = 2;
|
|
||||||
let wr = 4;
|
|
||||||
|
|
||||||
let mut h_matrix = generate_random_h(m, n, wc, wr);
|
|
||||||
println!("H aléatoire {m}x{n} :");
|
|
||||||
h_matrix.print();
|
|
||||||
|
|
||||||
let ldpc = LdpcCode::new(h_matrix.clone());
|
|
||||||
println!("\nLDPC instancié");
|
|
||||||
|
|
||||||
println!("Extraction de G");
|
|
||||||
let encoder = DenseEncoder::new(&ldpc);
|
|
||||||
|
|
||||||
println!("\n-> Matrcie H après Gauss-Jordan avec inversion de colonne de la forme [I | A]");
|
|
||||||
encoder.h_reduced.print();
|
|
||||||
|
|
||||||
println!("G {}x{}", encoder.k, encoder.n);
|
|
||||||
encoder.g_matrix.print();
|
|
||||||
|
|
||||||
let message = vec![1; encoder.k];
|
|
||||||
let codeword = encoder.encode(&message);
|
|
||||||
|
|
||||||
println!("\nMessage u : {:?}", message);
|
|
||||||
println!("\nCodeword s : {:?}", codeword);
|
|
||||||
|
|
||||||
let is_valid = (0..m).all(|r| {
|
|
||||||
let sum = codeword
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.fold(0, |acc, (c, &bit)| acc ^ (bit & h_matrix.get(r, c)));
|
|
||||||
sum == 0
|
|
||||||
});
|
|
||||||
|
|
||||||
println!("\n{}", if is_valid { "Vrai" } else { "Faux" });
|
|
||||||
|
|
||||||
println!("\nCorrection (bit-flipping)");
|
|
||||||
|
|
||||||
let decoder = BitFlipDecoder::new(&ldpc);
|
|
||||||
let max_iter = 50;
|
|
||||||
let receiver_codeword = codeword.clone();
|
|
||||||
|
|
||||||
match decoder.decode(&receiver_codeword, max_iter) {
|
|
||||||
Some(corrected_codeword) => {
|
|
||||||
if corrected_codeword == codeword {
|
|
||||||
println!("Code reconstrui");
|
|
||||||
} else {
|
|
||||||
println!("Convergence mais mauvais codeword")
|
|
||||||
}
|
|
||||||
println!("Message original : {:?}", codeword);
|
|
||||||
println!("Message original : {:?}", corrected_codeword);
|
|
||||||
}
|
|
||||||
None => println!("Pas de convergence..."),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
83
Code/ldpc/src/simulation.rs
Normal file
83
Code/ldpc/src/simulation.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use core::panic::PanicMessage;
|
||||||
|
use std::sync::mpsc::Receiver;
|
||||||
|
|
||||||
|
use crate::channel::Channel;
|
||||||
|
use crate::code::{self, LdpcCode};
|
||||||
|
use crate::construction::random::{generate_random_h, generate_random_h_for_k};
|
||||||
|
use crate::decoder::bit_flip::BitFlipDecoder;
|
||||||
|
use crate::encoder::dense::DenseEncoder;
|
||||||
|
use rand::{Rng, RngExt};
|
||||||
|
|
||||||
|
pub fn run_simulation(k: usize, wc: usize, wr: usize, error_prob: f64) {
|
||||||
|
println!(
|
||||||
|
"Simulation LDPC : k = {} bits, wc = {}, wr = {}, p = {:.2}",
|
||||||
|
k, wc, wr, error_prob
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("Construction");
|
||||||
|
|
||||||
|
let h_matrix = generate_random_h_for_k(k, wc, wr);
|
||||||
|
let ldpc = LdpcCode::new(h_matrix);
|
||||||
|
|
||||||
|
let encoder = DenseEncoder::new(&ldpc);
|
||||||
|
|
||||||
|
if encoder.k != k {
|
||||||
|
println!("Erreur: la matrice donne k = {} != {}", encoder.k, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
" -> Code généré : n = {}, k = {}, k/n = {}",
|
||||||
|
encoder.n,
|
||||||
|
encoder.k,
|
||||||
|
(encoder.k as f64 / encoder.n as f64)
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("Encodage");
|
||||||
|
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
let message: Vec<u8> = (0..k).map(|_| rng.random_range(0..2)).collect();
|
||||||
|
|
||||||
|
let codeword = encoder.encode(&message);
|
||||||
|
|
||||||
|
println!(" -> Message u ({:02} bits) : {:?}", k, message);
|
||||||
|
println!(" -> Codeword s ({:02} bits) : {:?}", encoder.n, codeword);
|
||||||
|
|
||||||
|
println!("\nCanal bruité (p = {})", error_prob);
|
||||||
|
|
||||||
|
let channel = Channel::new(error_prob);
|
||||||
|
let received = channel.add_noise(&codeword);
|
||||||
|
|
||||||
|
let nb_errors = Channel::count_errors(&codeword, &received);
|
||||||
|
if nb_errors == 0 {
|
||||||
|
println!(" -> Aucune erreur.")
|
||||||
|
} else {
|
||||||
|
println!(" -> {} erreurs !", nb_errors);
|
||||||
|
println!(" -> Recu r ({:02} bits) : {:?}", received.len(), received);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\n Décodage (bit-flipping)");
|
||||||
|
|
||||||
|
if nb_errors == 0 {
|
||||||
|
println!(" -> Pas besoin de correction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoder = BitFlipDecoder::new(&ldpc);
|
||||||
|
let max_iter = 50;
|
||||||
|
|
||||||
|
match decoder.decode(&received, max_iter) {
|
||||||
|
Some(decoded) => {
|
||||||
|
if decoded == codeword {
|
||||||
|
println!(" -> Réussite");
|
||||||
|
} else {
|
||||||
|
println!(" -> Echec : le decoder a convergé vers un mauvais codeword");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!(
|
||||||
|
" -> Echec : impossible decorriger après {} itérations",
|
||||||
|
max_iter
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user