Some checks failed
WAI conformance / cargo-class corpora · linux (push) Successful in 28s
WAI conformance / cross-arch byte-equality · linux (push) Successful in 14s
WAI conformance / cargo-class corpora · linux-arm64 (push) Successful in 1m11s
WAI conformance / cross-arch byte-equality · linux-arm64 (push) Successful in 46s
WAI conformance / cargo-class corpora · macos (push) Successful in 1m19s
WAI conformance / cross-arch byte-equality · macos (push) Successful in 41s
WAI conformance / cargo-class corpora · windows (push) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (push) Has been cancelled
The exponential sample-complexity separation for Pauli-channel learning (Chen-Cotler-Huang-Li / Huang Science 2022), surfaced as a first-class quantum-ML capability: estimating an n-qubit channel's 2^n fidelities to accuracy epsilon needs Omega(2^n) copies WITHOUT quantum memory but O(1/eps^2) n-independent copies WITH a two-copy Bell measurement. Both estimators simulated exactly (deterministic in seed); the demo shows Bell resolving all fidelities in a fixed copy budget while the entanglement-free strategy is starved. A data-access advantage that survives dequantization — and exactly why noise_learn's Bell/CB sampling is data-efficient. wai-web QDataSeparation; live /quantum-ml panel tying the separation to the deployed wai.quantum.cal.noise_learn (verified receipt + byte-exact model hash). Co-Authored-By: Claude Opus 4.8 <[email protected]>
69 lines
2.6 KiB
Rust
69 lines
2.6 KiB
Rust
//! Learning from quantum data in the browser (`wai.quantum.qdata`) — the
|
|
//! exponential sample-complexity separation for Pauli-channel learning. Simulate
|
|
//! both estimators and watch the two-copy Bell strategy resolve all `2^n`
|
|
//! fidelities with `n`-independent copies while the entanglement-free strategy is
|
|
//! starved. This is the advantage that survives dequantization, and why the
|
|
//! deployed `wai.quantum.cal.noise_learn` (Bell / Cycle-Benchmarking sampling) is
|
|
//! data-efficient.
|
|
|
|
use wai::quantum_qdata as qd;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
/// A fixed geometric budget grid (channel uses) shared by both strategies.
|
|
const GRID: [u64; 12] = [
|
|
64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072,
|
|
];
|
|
|
|
#[wasm_bindgen]
|
|
pub struct QDataSeparation {
|
|
n: u32,
|
|
points: Vec<qd::SepPoint>,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
impl QDataSeparation {
|
|
/// Simulate the separation for an `n`-qubit demo channel over the copy grid.
|
|
#[wasm_bindgen(constructor)]
|
|
pub fn new(n: u32, seed: f64) -> QDataSeparation {
|
|
let n = n.clamp(2, 10);
|
|
let points = qd::separation_curve(n, seed as u64, &GRID);
|
|
QDataSeparation { n, points }
|
|
}
|
|
|
|
/// `2^n` — the number of Pauli fidelities to learn (the conventional cost floor).
|
|
pub fn dim(&self) -> f64 {
|
|
(1u64 << self.n) as f64
|
|
}
|
|
|
|
/// The copy budgets (x-axis).
|
|
pub fn copies(&self) -> Vec<f64> {
|
|
self.points.iter().map(|p| p.copies as f64).collect()
|
|
}
|
|
/// Worst-case fidelity error of the two-copy **Bell** (quantum-memory) estimator.
|
|
pub fn bell_err(&self) -> Vec<f64> {
|
|
self.points.iter().map(|p| p.bell_err).collect()
|
|
}
|
|
/// Worst-case fidelity error of the **entanglement-free** (conventional) estimator.
|
|
pub fn conv_err(&self) -> Vec<f64> {
|
|
self.points.iter().map(|p| p.conventional_err).collect()
|
|
}
|
|
|
|
/// Smallest Bell copies to reach worst-case error `≤ eps` (0 = grid ceiling
|
|
/// insufficient).
|
|
pub fn bell_copies_for(&self, eps: f64, seed: f64) -> f64 {
|
|
qd::copies_to_epsilon(self.n, seed as u64, eps, 8_000_000).0 as f64
|
|
}
|
|
/// Smallest conventional copies to reach `≤ eps`.
|
|
pub fn conv_copies_for(&self, eps: f64, seed: f64) -> f64 {
|
|
qd::copies_to_epsilon(self.n, seed as u64, eps, 8_000_000).1 as f64
|
|
}
|
|
/// The copies ratio `conventional / Bell ≈ 2^n` — the exponential price of no
|
|
/// quantum memory.
|
|
pub fn ratio_for(&self, eps: f64, seed: f64) -> f64 {
|
|
let (b, c) = qd::copies_to_epsilon(self.n, seed as u64, eps, 8_000_000);
|
|
if b == 0 {
|
|
return 0.0;
|
|
}
|
|
c as f64 / b as f64
|
|
}
|
|
}
|