wai-quantum 0.4.0

A deterministic quantum stack in pure Rust: byte-exact circuit simulation (statevector / stabilizer / tensor-network MPS / sparse-Pauli backends), sparse Pauli dynamics at utility scale (arbitrary angles, 1024 qubits), belief-propagation tensor networks on the hardware graph, error mitigation, qLDPC decoding, noise learning, circuit-equivalence proofs, a phasor interference-ML layer, information-theoretic limits, noisy channels and state tomography, and signed energy-accounted receipts. No QPU, no cloud, no system libraries — identical results native, in the browser, and as a WASI component at the edge.
Documentation
//! Run a bivariate-bicycle memory experiment at circuit level and decode it
//! with BP-OSD: logical failures per shot and per syndrome cycle.
//!
//! ```text
//! cargo run --release --example ldpc_memory --features quantum_ldpc -- CODE P CYCLES SHOTS [THREADS] [MAX_ITER]
//! ```
//! CODE is 72, 90, 108, 144 or 288.
use wai_quantum::quantum_frame::Basis;
use wai_quantum::quantum_ldpc::{memory_experiment, BbCode, BpOsdConfig};

fn main() {
    let a: Vec<String> = std::env::args().collect();
    let code = match a[1].as_str() {
        "72" => BbCode::bb72(),
        "90" => BbCode::bb90(),
        "108" => BbCode::bb108(),
        "144" => BbCode::bb144(),
        "288" => BbCode::bb288(),
        other => panic!("unknown code {other}"),
    };
    let p: f64 = a[2].parse().unwrap();
    let cycles: u32 = a[3].parse().unwrap();
    let shots: usize = a[4].parse().unwrap();
    let threads: usize = a.get(5).map_or(8, |x| x.parse().unwrap());
    let max_iter: u32 = a.get(6).map_or(10_000, |x| x.parse().unwrap());
    let cfg = BpOsdConfig { max_iter, ..BpOsdConfig::default() };
    let mut both_ok = 1.0;
    for (name, basis, seed) in [("Z", Basis::Z, 1u64 << 32), ("X", Basis::X, 2u64 << 32)] {
        let t0 = std::time::Instant::now();
        let r = memory_experiment(&code, cycles, p, basis, shots, seed, cfg, threads).unwrap();
        let dt = t0.elapsed().as_secs_f64();
        both_ok *= 1.0 - r.per_shot();
        println!(
            "{name}-basis  shots {}  failures {}  per shot {:.5}  per cycle {:.3e}  bp-converged {:.3}  {:.1} ms/shot",
            r.shots,
            r.failures,
            r.per_shot(),
            r.per_cycle(),
            r.converged as f64 / r.shots as f64,
            1e3 * dt * threads as f64 / shots as f64
        );
    }
    let p_shot = 1.0 - both_ok;
    println!("either     per shot {:.5}  per cycle {:.3e}", p_shot, 1.0 - (1.0 - p_shot).powf(1.0 / f64::from(cycles)));
}