analyse complete
This commit is contained in:
@ -0,0 +1,208 @@
|
|||||||
|
use crate::channel::Channel;
|
||||||
|
use crate::code::LdpcCode;
|
||||||
|
use crate::construction::random::generate_random_h_for_k;
|
||||||
|
use crate::decoder::bit_flip::BitFlipDecoder;
|
||||||
|
use crate::encoder::dense::DenseEncoder;
|
||||||
|
use rand::{Rng, RngExt};
|
||||||
|
use rayon::prelude::*;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum DecoderAlgorithm {
|
||||||
|
BitFlipping,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AnalysisConfig {
|
||||||
|
pub k_values: Vec<usize>,
|
||||||
|
pub wc_values: Vec<usize>,
|
||||||
|
pub wr_values: Vec<usize>,
|
||||||
|
pub min_error_prob: f64,
|
||||||
|
pub max_error_prob: f64,
|
||||||
|
pub steps: usize,
|
||||||
|
pub frames_per_step: usize,
|
||||||
|
pub max_iter: usize,
|
||||||
|
pub algorithm: DecoderAlgorithm,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SimulationPoint {
|
||||||
|
pub k_config: usize,
|
||||||
|
pub n_real: usize,
|
||||||
|
pub wc: usize,
|
||||||
|
pub wr: usize,
|
||||||
|
pub rate: f64,
|
||||||
|
pub error_rate: f64,
|
||||||
|
pub ber: f64,
|
||||||
|
pub fer: f64,
|
||||||
|
pub avg_iter: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Analyzer;
|
||||||
|
|
||||||
|
impl Analyzer {
|
||||||
|
pub fn run_batch(config: AnalysisConfig) -> Vec<SimulationPoint> {
|
||||||
|
let mut tasks = Vec::new();
|
||||||
|
|
||||||
|
for &k in &config.k_values {
|
||||||
|
for &wc in &config.wc_values {
|
||||||
|
for &wr in &config.wr_values {
|
||||||
|
if wr <= wc {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k * wr) % (wr - wc) != 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tasks.push((k, wc, wr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Configurations valides : {}", tasks.len());
|
||||||
|
println!("Execution sur {} coeurs...", rayon::current_num_threads());
|
||||||
|
|
||||||
|
let results: Vec<SimulationPoint> = tasks
|
||||||
|
.par_iter()
|
||||||
|
.flat_map(|&(k_target, wc, wr)| {
|
||||||
|
let h_matrix = generate_random_h_for_k(k_target, wc, wr);
|
||||||
|
let ldpc = LdpcCode::new(h_matrix);
|
||||||
|
let encoder = DenseEncoder::new(&ldpc);
|
||||||
|
|
||||||
|
let k_real = encoder.k;
|
||||||
|
let n_real = encoder.n;
|
||||||
|
let rate_theoretical = k_real as f64 / n_real as f64;
|
||||||
|
|
||||||
|
let step_size = if config.steps > 1 {
|
||||||
|
(config.max_error_prob - config.min_error_prob) / (config.steps as f64 - 1.0)
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
(0..config.steps)
|
||||||
|
.into_par_iter()
|
||||||
|
.map(|i| {
|
||||||
|
let p = config.min_error_prob + (i as f64 * step_size);
|
||||||
|
|
||||||
|
let point = Self::simulate_point(
|
||||||
|
&encoder,
|
||||||
|
&ldpc,
|
||||||
|
p,
|
||||||
|
&config,
|
||||||
|
k_real,
|
||||||
|
k_target,
|
||||||
|
n_real,
|
||||||
|
wc,
|
||||||
|
wr,
|
||||||
|
rate_theoretical,
|
||||||
|
);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Termine : k={} wc={} wr={} p={:.3} -> BER={:.5}",
|
||||||
|
point.k_config, point.wc, point.wr, point.error_rate, point.ber
|
||||||
|
);
|
||||||
|
|
||||||
|
point
|
||||||
|
})
|
||||||
|
.collect::<Vec<SimulationPoint>>()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
println!("Simulation terminee. {} points generes.", results.len());
|
||||||
|
results
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simulate_point(
|
||||||
|
encoder: &DenseEncoder,
|
||||||
|
ldpc: &LdpcCode,
|
||||||
|
p: f64,
|
||||||
|
config: &AnalysisConfig,
|
||||||
|
k_real: usize,
|
||||||
|
k_orig: usize,
|
||||||
|
n: usize,
|
||||||
|
wc: usize,
|
||||||
|
wr: usize,
|
||||||
|
rate: f64,
|
||||||
|
) -> SimulationPoint {
|
||||||
|
let channel = Channel::new(p);
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
|
let mut total_bit_errors = 0;
|
||||||
|
let mut total_frame_errors = 0;
|
||||||
|
let mut total_iterations = 0;
|
||||||
|
let mut converged_count = 0;
|
||||||
|
|
||||||
|
for _ in 0..config.frames_per_step {
|
||||||
|
let message: Vec<u8> = (0..k_real).map(|_| rng.random_range(0..2)).collect();
|
||||||
|
let codeword = encoder.encode(&message);
|
||||||
|
let received = channel.add_noise(&codeword);
|
||||||
|
|
||||||
|
let (decoded, iters) = match config.algorithm {
|
||||||
|
DecoderAlgorithm::BitFlipping => {
|
||||||
|
let decoder = BitFlipDecoder::new(ldpc);
|
||||||
|
let res = decoder.decode(&received, config.max_iter);
|
||||||
|
(res, 0)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match decoded {
|
||||||
|
Some(res_code) => {
|
||||||
|
if res_code != codeword {
|
||||||
|
total_frame_errors += 1;
|
||||||
|
total_bit_errors += Channel::count_errors(&codeword, &res_code);
|
||||||
|
} else {
|
||||||
|
converged_count += 1;
|
||||||
|
total_iterations += iters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
total_frame_errors += 1;
|
||||||
|
total_bit_errors += Channel::count_errors(&codeword, &received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let total_bits = (config.frames_per_step * n) as f64;
|
||||||
|
let avg_iter = if converged_count > 0 {
|
||||||
|
total_iterations as f64 / converged_count as f64
|
||||||
|
} else {
|
||||||
|
config.max_iter as f64
|
||||||
|
};
|
||||||
|
|
||||||
|
SimulationPoint {
|
||||||
|
k_config: k_orig,
|
||||||
|
n_real: n,
|
||||||
|
wc,
|
||||||
|
wr,
|
||||||
|
rate,
|
||||||
|
error_rate: p,
|
||||||
|
ber: total_bit_errors as f64 / total_bits,
|
||||||
|
fer: total_frame_errors as f64 / config.frames_per_step as f64,
|
||||||
|
avg_iter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_csv(results: &[SimulationPoint], filename: &str) {
|
||||||
|
let mut sorted_results = results.to_vec();
|
||||||
|
sorted_results.sort_by(|a, b| {
|
||||||
|
a.k_config
|
||||||
|
.cmp(&b.k_config)
|
||||||
|
.then(a.wc.cmp(&b.wc))
|
||||||
|
.then(a.wr.cmp(&b.wr))
|
||||||
|
.then(a.error_rate.partial_cmp(&b.error_rate).unwrap())
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut file = File::create(filename).expect("Erreur fichier");
|
||||||
|
writeln!(file, "k,n,wc,wr,rate,p,ber,fer,avg_iter").unwrap();
|
||||||
|
|
||||||
|
for r in sorted_results {
|
||||||
|
writeln!(
|
||||||
|
file,
|
||||||
|
"{},{},{},{},{:.4},{:.6},{:.8},{:.8},{:.2}",
|
||||||
|
r.k_config, r.n_real, r.wc, r.wr, r.rate, r.error_rate, r.ber, r.fer, r.avg_iter
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
println!("Resultats sauvegardes dans '{}'", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user