Compare commits
3 Commits
826cfe8569
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e997b58d9 | |||
| b343675fa7 | |||
| 8c2abd902c |
@ -12,7 +12,9 @@ pub fn generate_random_h(rows: usize, cols: usize, wc: usize, wr: usize) -> Matr
|
|||||||
|
|
||||||
for c in 0..cols {
|
for c in 0..cols {
|
||||||
let mut ones_placed = 0;
|
let mut ones_placed = 0;
|
||||||
let mut avail_rows: Vec<usize> = (0..rows).filter(|&r| row_w[r] < wr).collect();
|
let mut avail_rows: Vec<usize> = (0..rows)
|
||||||
|
.filter(|&r| row_w[r] < wr && !creates_cycle_4(rows, cols, &data, r, c))
|
||||||
|
.collect();
|
||||||
|
|
||||||
if avail_rows.len() < wc {
|
if avail_rows.len() < wc {
|
||||||
// Les problèmes...
|
// Les problèmes...
|
||||||
@ -60,3 +62,16 @@ pub fn generate_random_h_for_k(k: usize, wc: usize, wr: usize) -> MatrixGF2 {
|
|||||||
}
|
}
|
||||||
best_h
|
best_h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn creates_cycle_4(rows: usize, cols: usize, data: &[u8], row: usize, col: usize) -> bool {
|
||||||
|
for r2 in 0..rows {
|
||||||
|
if r2 != row && data[r2 * cols + col] == 1 {
|
||||||
|
for c2 in 0..col {
|
||||||
|
if data[row * cols + c2] == 1 && data[r2 * cols + c2] == 1 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use rand::RngExt;
|
||||||
|
|
||||||
use crate::code::LdpcCode;
|
use crate::code::LdpcCode;
|
||||||
|
|
||||||
pub struct BitFlipDecoder<'a> {
|
pub struct BitFlipDecoder<'a> {
|
||||||
@ -35,6 +37,7 @@ impl<'a> BitFlipDecoder<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// println!("poid syndome: {s_w}");
|
||||||
// Aucune erreurs
|
// Aucune erreurs
|
||||||
if s_w == 0 {
|
if s_w == 0 {
|
||||||
return Some(curr_bits);
|
return Some(curr_bits);
|
||||||
@ -65,8 +68,21 @@ impl<'a> BitFlipDecoder<'a> {
|
|||||||
curr_bits[i] ^= 1; // Bit flip
|
curr_bits[i] ^= 1; // Bit flip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Seuil de 3
|
||||||
|
// if max_cpt >= 3 {
|
||||||
|
// for i in 0..n {
|
||||||
|
// if cpt[i] == max_cpt {
|
||||||
|
// curr_bits[i] ^= 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if max_cpt > 0 {
|
||||||
|
// if let Some(idx) = cpt.iter().position(|&x| x == max_cpt) {
|
||||||
|
// curr_bits[idx] ^= 1;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
None
|
||||||
return Some(curr_bits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ pub struct DenseEncoder {
|
|||||||
pub k: usize,
|
pub k: usize,
|
||||||
pub n: usize,
|
pub n: usize,
|
||||||
pub col_swaps: Vec<(usize, usize)>,
|
pub col_swaps: Vec<(usize, usize)>,
|
||||||
|
pub rank: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DenseEncoder {
|
impl DenseEncoder {
|
||||||
@ -33,6 +34,7 @@ impl DenseEncoder {
|
|||||||
k,
|
k,
|
||||||
n,
|
n,
|
||||||
col_swaps,
|
col_swaps,
|
||||||
|
rank,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +50,25 @@ impl DenseEncoder {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Reverse les changement de colonnes
|
// Reverse les changement de colonnes
|
||||||
for &(c1, c2) in self.col_swaps.iter().rev() {
|
// for &(c1, c2) in self.col_swaps.iter().rev() {
|
||||||
codeword.swap(c1, c2);
|
// codeword.swap(c1, c2);
|
||||||
}
|
// }
|
||||||
|
self.g_matrix
|
||||||
|
.apply_inverse_permutation(&mut codeword, &self.col_swaps);
|
||||||
|
|
||||||
codeword
|
codeword
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extract_message(&self, decoded_codeword: &[u8]) -> Vec<u8> {
|
||||||
|
let mut working_copy = decoded_codeword.to_vec();
|
||||||
|
|
||||||
|
self.g_matrix
|
||||||
|
.apply_permutation(&mut working_copy, &self.col_swaps);
|
||||||
|
|
||||||
|
let mut message = Vec::with_capacity(self.k);
|
||||||
|
for i in 0..self.k {
|
||||||
|
message.push(working_copy[self.rank + i]);
|
||||||
|
}
|
||||||
|
message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,25 +7,28 @@ mod encoder;
|
|||||||
mod matrix;
|
mod matrix;
|
||||||
mod simulation;
|
mod simulation;
|
||||||
mod tanner;
|
mod tanner;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use analysis::{AnalysisConfig, Analyzer, DecoderAlgorithm};
|
use analysis::{AnalysisConfig, Analyzer, DecoderAlgorithm};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Analyse des performences");
|
// println!("Analyse des performences");
|
||||||
|
|
||||||
let config = AnalysisConfig {
|
// let config = AnalysisConfig {
|
||||||
k_values: vec![50, 200, 400, 800, 1000],
|
// k_values: vec![50, 200, 400, 800, 1000],
|
||||||
wc_values: vec![3, 4, 5],
|
// wc_values: vec![3, 4, 5],
|
||||||
wr_values: vec![6, 8, 9, 12, 15, 16],
|
// wr_values: vec![6, 8, 9, 12, 15, 16],
|
||||||
min_error_prob: 0.00,
|
// min_error_prob: 0.00,
|
||||||
max_error_prob: 0.12,
|
// max_error_prob: 0.12,
|
||||||
steps: 15,
|
// steps: 15,
|
||||||
frames_per_step: 1000,
|
// frames_per_step: 1000,
|
||||||
max_iter: 50,
|
// max_iter: 50,
|
||||||
algorithm: DecoderAlgorithm::BitFlipping,
|
// algorithm: DecoderAlgorithm::BitFlipping,
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
|
// let res = Analyzer::run_batch(config);
|
||||||
|
// Analyzer::save_csv(&res, "ldpc_analysis_results.csv");
|
||||||
|
|
||||||
let res = Analyzer::run_batch(config);
|
let message = "Je suis un test";
|
||||||
Analyzer::save_csv(&res, "ldpc_analysis_results.csv");
|
simulation::run_simulation(message, 3, 6, 0.01);
|
||||||
// simulation::run_simulation(1000, 3, 6, 0.005);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,4 +130,16 @@ impl MatrixGF2 {
|
|||||||
}
|
}
|
||||||
(rank, col_swaps)
|
(rank, col_swaps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_inverse_permutation(&self, data: &mut [u8], swaps: &[(usize, usize)]) {
|
||||||
|
for &(c1, c2) in swaps.iter().rev() {
|
||||||
|
data.swap(c1, c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_permutation(&self, data: &mut [u8], swaps: &[(usize, usize)]) {
|
||||||
|
for &(c1, c2) in swaps.iter() {
|
||||||
|
data.swap(c1, c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,12 +6,15 @@ use crate::code::{self, LdpcCode};
|
|||||||
use crate::construction::random::{generate_random_h, generate_random_h_for_k};
|
use crate::construction::random::{generate_random_h, generate_random_h_for_k};
|
||||||
use crate::decoder::bit_flip::BitFlipDecoder;
|
use crate::decoder::bit_flip::BitFlipDecoder;
|
||||||
use crate::encoder::dense::DenseEncoder;
|
use crate::encoder::dense::DenseEncoder;
|
||||||
|
use crate::utils;
|
||||||
use rand::{Rng, RngExt};
|
use rand::{Rng, RngExt};
|
||||||
|
|
||||||
pub fn run_simulation(k: usize, wc: usize, wr: usize, error_prob: f64) {
|
pub fn run_simulation(text: &str, wc: usize, wr: usize, error_prob: f64) {
|
||||||
|
let mut message_bits = utils::string_to_bits(text);
|
||||||
|
let k = message_bits.len();
|
||||||
println!(
|
println!(
|
||||||
"\nSimulation LDPC : k = {} bits, wc = {}, wr = {}, p = {:.2}",
|
"\nSimulation LDPC : k = {} bits, wc = {}, wr = {}, p = {:.2}, text : {}",
|
||||||
k, wc, wr, error_prob
|
k, wc, wr, error_prob, text
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Construction");
|
println!("Construction");
|
||||||
@ -36,7 +39,9 @@ pub fn run_simulation(k: usize, wc: usize, wr: usize, error_prob: f64) {
|
|||||||
println!("Encodage");
|
println!("Encodage");
|
||||||
|
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
let message: Vec<u8> = (0..k).map(|_| rng.random_range(0..2)).collect();
|
// let message: Vec<u8> = (0..k).map(|_| rng.random_range(0..2)).collect();
|
||||||
|
let mut message = message_bits.clone();
|
||||||
|
message.resize(encoder.k, 0);
|
||||||
|
|
||||||
let codeword = encoder.encode(&message);
|
let codeword = encoder.encode(&message);
|
||||||
|
|
||||||
@ -64,21 +69,27 @@ pub fn run_simulation(k: usize, wc: usize, wr: usize, error_prob: f64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let decoder = BitFlipDecoder::new(&ldpc);
|
let decoder = BitFlipDecoder::new(&ldpc);
|
||||||
let max_iter = 50;
|
let max_iter = 100;
|
||||||
|
|
||||||
match decoder.decode(&received, max_iter) {
|
match decoder.decode(&received, max_iter) {
|
||||||
Some(decoded) => {
|
Some(decoded) => {
|
||||||
|
let decoded_message_bits = encoder.extract_message(&decoded);
|
||||||
|
let res_text = utils::bits_to_string(&decoded_message_bits);
|
||||||
if decoded == codeword {
|
if decoded == codeword {
|
||||||
println!(" -> Réussite");
|
println!(" -> Réussite");
|
||||||
} else {
|
} else {
|
||||||
println!(" -> Echec : le decoder a convergé vers un mauvais codeword");
|
println!(" -> Echec : le decoder a convergé vers un mauvais codeword");
|
||||||
}
|
}
|
||||||
|
println!(" -> Texte recu : {}", res_text);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
let rec_bits = encoder.extract_message(&received);
|
||||||
|
let failed_text = utils::bits_to_string(&rec_bits);
|
||||||
println!(
|
println!(
|
||||||
" -> Echec : impossible decorriger après {} itérations",
|
" -> Echec : impossible decorriger après {} itérations",
|
||||||
max_iter
|
max_iter
|
||||||
);
|
);
|
||||||
|
println!(" -> Texte recu : {}", failed_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
Code/ldpc/src/utils.rs
Normal file
26
Code/ldpc/src/utils.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
pub fn string_to_bits(s: &str) -> Vec<u8> {
|
||||||
|
let mut bits = Vec::new();
|
||||||
|
for byte in s.as_bytes() {
|
||||||
|
for i in (0..8).rev() {
|
||||||
|
bits.push((byte >> i) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bits_to_string(bits: &[u8]) -> String {
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
for chunk in bits.chunks(8) {
|
||||||
|
if chunk.len() < 8 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let mut byte = 0u8;
|
||||||
|
for (i, &bit) in chunk.iter().enumerate() {
|
||||||
|
if bit == 1 {
|
||||||
|
byte |= 1 << (7 - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes.push(byte);
|
||||||
|
}
|
||||||
|
String::from_utf8_lossy(&bytes).into_owned()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user