use blr_core::{
features, fit,
noise_estimation::{estimate_noise_with_confidence, estimate_sensor_noise},
ArdConfig,
};
fn next_gaussian(state: &mut u64) -> f64 {
let uniform = |s: &mut u64| -> f64 {
*s = s
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
((*s >> 11) as f64 + 0.5) / (1u64 << 53) as f64
};
let u1 = uniform(state);
let u2 = uniform(state);
(-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
}
fn main() {
let true_noise_levels = [0.05_f64, 0.20, 0.50];
let n = 16_usize; let degree = 3;
let x: Vec<f64> = (0..n)
.map(|i| -2.0 + 4.0 * (i as f64) / (n as f64 - 1.0))
.collect();
let (phi, d) = features::polynomial(&x, degree);
println!("Noise Estimation Workflow");
println!("════════════════════════════════════════════════════════════");
println!(" N = {n} observations, D = {d} polynomial features (degree {degree})");
println!(" True signal: f(x) = 1 + x − 0.5x² + 0.1x³ (cubic)");
println!("════════════════════════════════════════════════════════════\n");
for &sigma_true in &true_noise_levels {
println!("── True noise σ = {sigma_true:.2} ──────────────────────────────────────────");
let mut state: u64 = 0x1234567890abcdef_u64.wrapping_add(sigma_true.to_bits());
let y: Vec<f64> = x
.iter()
.map(|xi| {
let fx = 1.0 + xi - 0.5 * xi.powi(2) + 0.1 * xi.powi(3);
fx + sigma_true * next_gaussian(&mut state)
})
.collect();
let config = ArdConfig {
max_iter: 300,
tol: 1e-6,
..ArdConfig::default()
};
let fitted = fit(&phi, &y, n, d, &config).expect("fit should succeed on valid input");
let beta = fitted.beta;
let sigma_point =
estimate_sensor_noise(beta).expect("beta should be positive after fitting");
let estimate = estimate_noise_with_confidence(beta, n, d);
println!(" β (noise precision): {:.4}", beta);
println!(
" σ_noise (point est): {:.4} (true: {:.2})",
sigma_point, sigma_true
);
println!(
" 95% heuristic interval: [{:.4}, {:.4}]",
estimate.lower_bound, estimate.upper_bound
);
println!(" Confidence label: {}", estimate.confidence);
let error_pct = ((sigma_point - sigma_true) / sigma_true * 100.0).abs();
let status = if error_pct < 10.0 {
"✓ accurate"
} else if error_pct < 25.0 {
"~ acceptable"
} else {
"✗ inaccurate (more data needed)"
};
println!(" Recovery error: {:.1}% {}", error_pct, status);
println!();
}
println!("════════════════════════════════════════════════════════════");
println!("Guidance:");
println!(" • 'preliminary' (n<30): use as rough guide only");
println!(" • 'transitional' (30–50): reasonable for most applications");
println!(" • 'stable' (n>50): reliable for precision calibration");
println!(" • Recovery error <10%: BLR+ARD noise estimate is accurate");
println!(" • If error >25%: try more training points or");
println!(" adjust feature set to reduce underfitting");
println!("════════════════════════════════════════════════════════════");
println!("\nDone. See noise_estimation module docs for the underlying formula.");
}