use crate::quantum_ops::{content_hash, DecodeReceipt, GrantRef};
use ed25519_dalek::SigningKey;
pub const QEC_FRAC: u32 = 12;
const SCALE: i64 = 1 << QEC_FRAC;
const L0: i64 = SCALE;
const MSG_MAX: i64 = 64 * SCALE;
const ALPHA_NUM: i64 = 7;
const GAMMA_MIN: i64 = -(6 * SCALE) / 10;
const GAMMA_MAX: i64 = (9 * SCALE) / 10;
fn splitmix64(state: &mut u64) -> u64 {
*state = state.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = *state;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
#[derive(Clone, Debug)]
pub struct Gf2Basis {
words: usize,
rows: Vec<Vec<u64>>,
pivots: Vec<usize>,
}
fn bit_get(row: &[u64], i: usize) -> bool {
(row[i >> 6] >> (i & 63)) & 1 == 1
}
fn bit_set(row: &mut [u64], i: usize) {
row[i >> 6] |= 1u64 << (i & 63);
}
fn bit_xor(dst: &mut [u64], src: &[u64]) {
for (d, s) in dst.iter_mut().zip(src) {
*d ^= *s;
}
}
fn is_zero(row: &[u64]) -> bool {
row.iter().all(|&w| w == 0)
}
impl Gf2Basis {
pub fn from_rows(rows_cols: &[Vec<usize>], ncols: usize) -> Gf2Basis {
let words = ncols.div_ceil(64).max(1);
let mut basis: Vec<Vec<u64>> = Vec::new();
let mut pivots: Vec<usize> = Vec::new();
for cols in rows_cols {
let mut v = vec![0u64; words];
for &c in cols {
bit_set(&mut v, c);
}
for (bi, br) in basis.iter().enumerate() {
if bit_get(&v, pivots[bi]) {
bit_xor(&mut v, br);
}
}
if let Some(p) = Self::lowest_set(&v) {
for br in basis.iter_mut() {
if bit_get(br, p) {
bit_xor(br, &v);
}
}
basis.push(v);
pivots.push(p);
}
}
Gf2Basis { words, rows: basis, pivots }
}
fn lowest_set(v: &[u64]) -> Option<usize> {
for (w, &word) in v.iter().enumerate() {
if word != 0 {
return Some(w * 64 + word.trailing_zeros() as usize);
}
}
None
}
pub fn rank(&self) -> usize {
self.rows.len()
}
pub fn contains(&self, cols: &[usize]) -> bool {
let mut v = vec![0u64; self.words];
for &c in cols {
bit_set(&mut v, c);
}
for (bi, br) in self.rows.iter().enumerate() {
if bit_get(&v, self.pivots[bi]) {
bit_xor(&mut v, br);
}
}
is_zero(&v)
}
}
#[derive(Clone, Debug)]
pub struct CssCode {
pub id: String,
pub n: usize,
pub checks: Vec<Vec<usize>>,
pub stabs: Vec<Vec<usize>>,
stab_basis: Gf2Basis,
pub k: usize,
}
impl CssCode {
fn new(id: String, n: usize, checks: Vec<Vec<usize>>, stab: Vec<Vec<usize>>) -> CssCode {
let stab_basis = Gf2Basis::from_rows(&stab, n);
let check_basis = Gf2Basis::from_rows(&checks, n);
let k = n.saturating_sub(check_basis.rank() + stab_basis.rank());
CssCode { id, n, checks, stabs: stab, stab_basis, k }
}
pub fn check_matrix_bytes(&self) -> Vec<u8> {
let mut b = Vec::new();
b.extend_from_slice(b"wai:qec-checks\x01");
b.extend_from_slice(&(self.n as u64).to_le_bytes());
for row in &self.checks {
b.extend_from_slice(&(row.len() as u32).to_le_bytes());
for &c in row {
b.extend_from_slice(&(c as u32).to_le_bytes());
}
}
b
}
pub fn is_trivial(&self, residual_cols: &[usize]) -> bool {
self.stab_basis.contains(residual_cols)
}
pub fn toric(l: usize) -> CssCode {
let n = 2 * l * l;
let h = |i: usize, j: usize| (i % l) * l + (j % l); let v = |i: usize, j: usize| l * l + (i % l) * l + (j % l); let mut plaq = Vec::with_capacity(l * l); let mut star = Vec::with_capacity(l * l); for i in 0..l {
for j in 0..l {
let mut p = vec![h(i, j), h(i + 1, j), v(i, j), v(i, j + 1)];
p.sort_unstable();
p.dedup();
plaq.push(p);
let mut s = vec![h(i, j), h(i, j + l - 1), v(i, j), v(i + l - 1, j)];
s.sort_unstable();
s.dedup();
star.push(s);
}
}
CssCode::new(format!("toric:L{l}"), n, plaq, star)
}
pub fn surface(d: usize) -> CssCode {
assert!(d >= 3 && d % 2 == 1, "rotated surface code needs an odd distance >= 3");
let n = d * d;
let q = |r: usize, c: usize| r * d + c;
let mut z_checks: Vec<Vec<usize>> = Vec::new();
let mut x_stabs: Vec<Vec<usize>> = Vec::new();
for r in 0..d - 1 {
for c in 0..d - 1 {
let face = vec![q(r, c), q(r, c + 1), q(r + 1, c), q(r + 1, c + 1)];
if (r + c) % 2 == 0 {
z_checks.push(face);
} else {
x_stabs.push(face);
}
}
}
for c in (0..d - 1).step_by(2) {
x_stabs.push(vec![q(0, c), q(0, c + 1)]);
}
for c in (1..d - 1).step_by(2) {
x_stabs.push(vec![q(d - 1, c), q(d - 1, c + 1)]);
}
for r in (1..d - 1).step_by(2) {
z_checks.push(vec![q(r, 0), q(r + 1, 0)]);
}
for r in (0..d - 1).step_by(2) {
z_checks.push(vec![q(r, d - 1), q(r + 1, d - 1)]);
}
for v in z_checks.iter_mut().chain(x_stabs.iter_mut()) {
v.sort_unstable();
v.dedup();
}
CssCode::new(format!("surface:d{d}"), n, z_checks, x_stabs)
}
pub fn bivariate_bicycle(l: usize, m: usize, a: &[(usize, usize)], b: &[(usize, usize)]) -> CssCode {
let lm = l * m;
let n = 2 * lm;
let cell = |i: usize, j: usize| (i % l) * m + (j % m);
let build = |monos: &[(usize, usize)]| -> Vec<Vec<usize>> {
let mut rows = vec![Vec::new(); lm];
for i in 0..l {
for j in 0..m {
let col = cell(i, j);
for &(px, py) in monos {
let row = cell(i + px, j + py);
rows[row].push(col);
}
}
}
for r in rows.iter_mut() {
r.sort_unstable();
r.dedup();
}
rows
};
let a_rows = build(a);
let b_rows = build(b);
let transpose = |rows: &[Vec<usize>]| -> Vec<Vec<usize>> {
let mut t = vec![Vec::new(); lm];
for (r, cols) in rows.iter().enumerate() {
for &c in cols {
t[c].push(r);
}
}
for x in t.iter_mut() {
x.sort_unstable();
}
t
};
let at = transpose(&a_rows);
let bt = transpose(&b_rows);
let hx: Vec<Vec<usize>> = (0..lm)
.map(|r| {
let mut row: Vec<usize> = a_rows[r].clone();
row.extend(b_rows[r].iter().map(|&c| c + lm));
row.sort_unstable();
row
})
.collect();
let hz: Vec<Vec<usize>> = (0..lm)
.map(|r| {
let mut row: Vec<usize> = bt[r].clone();
row.extend(at[r].iter().map(|&c| c + lm));
row.sort_unstable();
row
})
.collect();
let code = CssCode::new(String::new(), n, hz, hx);
CssCode { id: format!("bb:[[{},{}]]", code.n, code.k), ..code }
}
pub fn gross() -> CssCode {
CssCode::bivariate_bicycle(6, 6, &[(3, 0), (0, 1), (0, 2)], &[(0, 3), (1, 0), (2, 0)])
}
}
struct Tanner {
n: usize,
n_edges: usize,
e_var: Vec<u32>, chk_range: Vec<(u32, u32)>, var_edges: Vec<Vec<u32>>, }
impl Tanner {
fn build(checks: &[Vec<usize>], n: usize) -> Tanner {
let mut e_var = Vec::new();
let mut chk_range = Vec::with_capacity(checks.len());
let mut var_edges = vec![Vec::new(); n];
for cols in checks {
let start = e_var.len() as u32;
for &v in cols {
var_edges[v].push(e_var.len() as u32);
e_var.push(v as u32);
}
chk_range.push((start, e_var.len() as u32));
}
let n_edges = e_var.len();
Tanner { n, n_edges, e_var, chk_range, var_edges }
}
}
#[allow(clippy::too_many_arguments)]
fn bp_leg(
t: &Tanner,
syndrome: &[bool],
gamma: &[i64],
max_iter: u32,
mu_v2c: &mut [i64],
mu_c2v: &mut [i64],
) -> (Vec<bool>, bool, u32, u64) {
let mut hard = vec![false; t.n];
let mut messages = 0u64;
let mut iters = 0;
for _ in 0..max_iter {
iters += 1;
for (&(a, b), &s) in t.chk_range.iter().zip(syndrome) {
let (mut min1, mut min2) = (i64::MAX, i64::MAX);
let mut arg = a;
let mut neg_parity = false;
for e in a..b {
let x = mu_v2c[e as usize];
if x < 0 {
neg_parity = !neg_parity;
}
let mag = x.abs();
if mag < min1 {
min2 = min1;
min1 = mag;
arg = e;
} else if mag < min2 {
min2 = mag;
}
}
for e in a..b {
let x = mu_v2c[e as usize];
let base = if e == arg { min2 } else { min1 };
let mag = (base * ALPHA_NUM) >> 3;
let is_neg = neg_parity ^ (x < 0) ^ s;
mu_c2v[e as usize] = if is_neg { -mag } else { mag };
}
}
for v in 0..t.n {
let mut total = L0;
for &e in &t.var_edges[v] {
total += mu_c2v[e as usize];
}
hard[v] = total < 0;
let g = gamma[v];
for &e in &t.var_edges[v] {
let target = total - mu_c2v[e as usize];
let nv = if g == 0 {
target
} else {
(g * mu_v2c[e as usize] + (SCALE - g) * target) >> QEC_FRAC
};
mu_v2c[e as usize] = nv.clamp(-MSG_MAX, MSG_MAX);
}
}
messages += 2 * t.n_edges as u64;
let mut ok = true;
for (&(a, b), &s) in t.chk_range.iter().zip(syndrome) {
let mut par = false;
for e in a..b {
par ^= hard[t.e_var[e as usize] as usize];
}
if par != s {
ok = false;
break;
}
}
if ok {
return (hard, true, iters, messages);
}
}
(hard, false, iters, messages)
}
struct DecodeCore {
correction: Vec<bool>,
converged: bool,
legs: u32,
iters: u32,
messages: u64,
}
fn relay_bp(
t: &Tanner,
syndrome: &[bool],
seed: u64,
max_iter: u32,
max_legs: u32,
) -> DecodeCore {
let mut mu_v2c = vec![L0; t.n_edges];
let mut mu_c2v = vec![0i64; t.n_edges];
let gamma0 = vec![0i64; t.n];
let (mut hard, mut conv, mut it, mut msg) =
bp_leg(t, syndrome, &gamma0, max_iter, &mut mu_v2c, &mut mu_c2v);
let mut legs = 1u32;
let (mut tot_it, mut tot_msg) = (it, msg);
while !conv && legs < max_legs {
let mut gamma = vec![0i64; t.n];
let mut st = seed
.wrapping_mul(0x100_0001)
.wrapping_add(legs as u64)
.wrapping_add(0xD15EA5E);
let span = (GAMMA_MAX - GAMMA_MIN) as u64 + 1;
for gv in gamma.iter_mut() {
let r = splitmix64(&mut st);
*gv = GAMMA_MIN + (r % span) as i64;
}
let out = bp_leg(t, syndrome, &gamma, max_iter, &mut mu_v2c, &mut mu_c2v);
hard = out.0;
conv = out.1;
it = out.2;
msg = out.3;
tot_it += it;
tot_msg += msg;
legs += 1;
}
let _ = it;
let _ = msg;
DecodeCore { correction: hard, converged: conv, legs, iters: tot_it, messages: tot_msg }
}
#[derive(Clone, Copy, Debug)]
pub struct DecodeConfig {
pub p_fx: i64,
pub max_iter: u32,
pub max_legs: u32,
}
impl DecodeConfig {
pub fn from_p(p: f64) -> DecodeConfig {
DecodeConfig { p_fx: (p * SCALE as f64) as i64, max_iter: 32, max_legs: 12 }
}
}
#[derive(Clone, Debug)]
pub struct DecodeResult {
pub code_id: String,
pub n: usize,
pub error: Vec<u32>, pub correction: Vec<u32>, pub syndrome: Vec<u32>, pub converged: bool,
pub logical_success: bool,
pub legs: u32,
pub iters: u32,
pub messages: u64,
syndrome_bits: Vec<bool>,
correction_bits: Vec<bool>,
check_matrix_hash: [u8; 32],
}
fn sample_error(n: usize, p_fx: i64, seed: u64) -> Vec<bool> {
let mut e = vec![false; n];
let mut st = seed.wrapping_mul(0x2545_F491_4F6C_DD1D).wrapping_add(1);
for ei in e.iter_mut() {
let r = (splitmix64(&mut st) >> (64 - QEC_FRAC)) as i64; if r < p_fx {
*ei = true;
}
}
e
}
fn syndrome_of(checks: &[Vec<usize>], e: &[bool]) -> Vec<bool> {
checks
.iter()
.map(|row| row.iter().fold(false, |acc, &q| acc ^ e[q]))
.collect()
}
fn bits_to_ids(bits: &[bool]) -> Vec<u32> {
bits.iter()
.enumerate()
.filter(|&(_, &b)| b)
.map(|(i, _)| i as u32)
.collect()
}
fn canonical_bits(tag: &[u8], bits: &[bool]) -> Vec<u8> {
let mut out = tag.to_vec();
out.extend_from_slice(&(bits.len() as u64).to_le_bytes());
for chunk in bits.chunks(8) {
let mut byte = 0u8;
for (i, &b) in chunk.iter().enumerate() {
if b {
byte |= 1 << i;
}
}
out.push(byte);
}
out
}
pub fn decode_once(code: &CssCode, cfg: &DecodeConfig, seed: u64) -> DecodeResult {
let t = Tanner::build(&code.checks, code.n);
let error = sample_error(code.n, cfg.p_fx, seed);
let syndrome_bits = syndrome_of(&code.checks, &error);
let core = relay_bp(&t, &syndrome_bits, seed, cfg.max_iter, cfg.max_legs);
let residual: Vec<usize> = (0..code.n)
.filter(|&i| error[i] ^ core.correction[i])
.collect();
let logical_success = core.converged && code.is_trivial(&residual);
DecodeResult {
code_id: code.id.clone(),
n: code.n,
error: bits_to_ids(&error),
correction: bits_to_ids(&core.correction),
syndrome: bits_to_ids(&syndrome_bits),
converged: core.converged,
logical_success,
legs: core.legs,
iters: core.iters,
messages: core.messages,
syndrome_bits,
correction_bits: core.correction.clone(),
check_matrix_hash: content_hash(&code.check_matrix_bytes()),
}
}
impl DecodeResult {
pub fn seal(
&self,
signer: &SigningKey,
signer_id: impl Into<String>,
joules_micro: u64,
grant: GrantRef,
) -> DecodeReceipt {
DecodeReceipt::seal(
signer,
signer_id,
self.code_id.clone(),
"relay-bp.min-sum",
self.check_matrix_hash,
content_hash(&canonical_bits(b"wai:qec-syndrome\x01", &self.syndrome_bits)),
content_hash(&canonical_bits(b"wai:qec-correction\x01", &self.correction_bits)),
self.converged,
self.legs,
self.messages,
joules_micro,
grant,
None,
)
}
pub fn correction_bytes(&self) -> Vec<u8> {
canonical_bits(b"wai:qec-correction\x01", &self.correction_bits)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BenchResult {
pub trials: u32,
pub plain_logical_failures: u32,
pub relay_logical_failures: u32,
pub relay_total_messages: u64,
}
pub fn union_find_correct(code: &CssCode, syndrome: &[bool]) -> Option<Vec<bool>> {
let m = code.checks.len();
let boundary = m; let nodes = m + 1;
let mut owners: Vec<Vec<usize>> = vec![Vec::new(); code.n];
for (ci, chk) in code.checks.iter().enumerate() {
for &q in chk {
owners[q].push(ci);
}
}
let mut edges: Vec<(usize, usize, usize)> = Vec::new();
for (q, own) in owners.iter().enumerate() {
match own.len() {
0 => {}
1 => edges.push((own[0], boundary, q)),
2 => edges.push((own[0], own[1], q)),
_ => return None, }
}
let mut parent: Vec<usize> = (0..nodes).collect();
fn find(parent: &mut Vec<usize>, mut x: usize) -> usize {
while parent[x] != x {
parent[x] = parent[parent[x]];
x = parent[x];
}
x
}
let mut syn: Vec<bool> = (0..nodes).map(|i| i < m && syndrome.get(i).copied().unwrap_or(false)).collect();
let mut grown: Vec<u8> = vec![0; edges.len()];
let mut incident: Vec<Vec<usize>> = vec![Vec::new(); nodes];
for (ei, &(a, b, _)) in edges.iter().enumerate() {
incident[a].push(ei);
incident[b].push(ei);
}
for _ in 0..(4 * nodes + 8) {
let mut parity = vec![false; nodes];
let mut touches = vec![false; nodes];
for v in 0..nodes {
let r = find(&mut parent, v);
if syn[v] {
parity[r] ^= true;
}
if v == boundary {
touches[r] = true;
}
}
let odd: Vec<usize> = (0..nodes)
.filter(|&v| find(&mut parent, v) == v && parity[v] && !touches[v])
.collect();
if odd.is_empty() {
break;
}
let mut to_union: Vec<usize> = Vec::new();
for (ei, &(a, b, _)) in edges.iter().enumerate() {
if grown[ei] >= 2 {
continue;
}
let (ra, rb) = (find(&mut parent, a), find(&mut parent, b));
let odd_a = parity[ra] && !touches[ra];
let odd_b = parity[rb] && !touches[rb];
let inc = if ra == rb {
u8::from(odd_a)
} else {
u8::from(odd_a) + u8::from(odd_b)
};
if inc > 0 {
grown[ei] += inc;
if grown[ei] >= 2 {
to_union.push(ei);
}
}
}
for ei in to_union {
let (a, b, _) = edges[ei];
let (ra, rb) = (find(&mut parent, a), find(&mut parent, b));
if ra != rb {
parent[ra] = rb;
}
}
}
let mut adj: Vec<Vec<(usize, usize)>> = vec![Vec::new(); nodes]; for (ei, &(a, b, _)) in edges.iter().enumerate() {
if grown[ei] >= 2 {
adj[a].push((b, ei));
adj[b].push((a, ei));
}
}
let mut correction = vec![false; code.n];
let mut seen = vec![false; nodes];
let roots: Vec<usize> = std::iter::once(boundary).chain(0..m).collect();
for root in roots {
if seen[root] {
continue;
}
let mut order = vec![root];
let mut parent_edge: Vec<Option<(usize, usize)>> = vec![None; nodes]; seen[root] = true;
let mut i = 0;
while i < order.len() {
let v = order[i];
i += 1;
for &(w, ei) in &adj[v] {
if !seen[w] {
seen[w] = true;
parent_edge[w] = Some((v, ei));
order.push(w);
}
}
}
for &v in order.iter().rev() {
if v == root || !syn[v] {
continue;
}
if let Some((u, ei)) = parent_edge[v] {
correction[edges[ei].2] ^= true;
syn[v] = false;
syn[u] ^= true;
}
}
}
Some(correction)
}
pub fn decode_once_uf(code: &CssCode, cfg: &DecodeConfig, seed: u64) -> DecodeResult {
let error = sample_error(code.n, cfg.p_fx, seed);
let syndrome_bits = syndrome_of(&code.checks, &error);
let (correction, converged) = match union_find_correct(code, &syndrome_bits) {
Some(c) => (c, true),
None => (vec![false; code.n], false),
};
let residual: Vec<usize> = (0..code.n).filter(|&i| error[i] ^ correction[i]).collect();
let logical_success = converged && code.is_trivial(&residual);
DecodeResult {
code_id: code.id.clone(),
n: code.n,
error: bits_to_ids(&error),
correction: bits_to_ids(&correction),
syndrome: bits_to_ids(&syndrome_bits),
converged,
logical_success,
legs: 0,
iters: 0,
messages: 0,
syndrome_bits,
correction_bits: correction,
check_matrix_hash: content_hash(&code.check_matrix_bytes()),
}
}
pub fn benchmark_uf(code: &CssCode, p: f64, trials: u32, seed: u64) -> (u32, u32) {
let cfg = DecodeConfig::from_p(p);
let mut fails = 0;
for tix in 0..trials {
let s = seed.wrapping_add(tix as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
if !decode_once_uf(code, &cfg, s).logical_success {
fails += 1;
}
}
(trials, fails)
}
pub fn benchmark(code: &CssCode, p: f64, trials: u32, seed: u64, max_legs: u32) -> BenchResult {
let base = DecodeConfig::from_p(p);
let plain = DecodeConfig { max_legs: 1, ..base };
let relay = DecodeConfig { max_legs, ..base };
let mut pf = 0;
let mut rf = 0;
let mut msg = 0u64;
for tix in 0..trials {
let s = seed.wrapping_add(tix as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
if !decode_once(code, &plain, s).logical_success {
pf += 1;
}
let r = decode_once(code, &relay, s);
if !r.logical_success {
rf += 1;
}
msg += r.messages;
}
BenchResult { trials, plain_logical_failures: pf, relay_logical_failures: rf, relay_total_messages: msg }
}
#[cfg(test)]
mod tests {
use super::*;
fn key(s: u8) -> SigningKey {
SigningKey::from_bytes(&[s; 32])
}
#[test]
fn gf2_membership() {
let basis = Gf2Basis::from_rows(&[vec![0, 1], vec![1, 2]], 3);
assert_eq!(basis.rank(), 2);
assert!(basis.contains(&[0, 1]));
assert!(basis.contains(&[1, 2]));
assert!(basis.contains(&[0, 2]));
assert!(basis.contains(&[])); assert!(!basis.contains(&[0]));
assert!(!basis.contains(&[2]));
}
#[test]
fn surface_code_is_a_valid_css_code() {
for d in [3usize, 5, 7] {
let code = CssCode::surface(d);
assert_eq!(code.n, d * d, "d={d} qubit count");
assert_eq!(code.k, 1, "d={d} must encode exactly one logical qubit");
let x: Vec<&Vec<usize>> = code.stabs.iter().collect();
for zc in &code.checks {
for xs in &x {
let overlap = zc.iter().filter(|q| xs.contains(q)).count();
assert_eq!(overlap % 2, 0, "d={d}: X{xs:?} and Z{zc:?} anticommute");
}
}
assert_eq!(code.checks.len(), (d * d - 1) / 2, "d={d} Z-check count");
assert_eq!(x.len(), (d * d - 1) / 2, "d={d} X-stabilizer count");
for v in code.checks.iter().chain(x.iter().copied()) {
assert!(v.len() == 4 || v.len() == 2, "d={d}: weight {} stabilizer", v.len());
}
}
}
#[test]
fn surface_code_decodes() {
let d3 = CssCode::surface(3);
let r = benchmark(&d3, 0.01, 500, 7, 4);
let relay = r.relay_logical_failures as f64 / r.trials as f64;
assert!(relay <= 0.05, "d=3 at p=0.01 should rarely fail: {relay}");
assert!(
r.relay_logical_failures <= r.plain_logical_failures,
"relay {} must not do worse than plain BP {}",
r.relay_logical_failures,
r.plain_logical_failures
);
}
#[test]
fn relay_beats_plain_bp_on_qldpc() {
let bb = CssCode::gross();
let r = benchmark(&bb, 0.06, 400, 11, 16);
assert!(
r.relay_logical_failures < r.plain_logical_failures,
"relay {} should beat plain BP {} on a qLDPC code",
r.relay_logical_failures,
r.plain_logical_failures
);
}
#[test]
#[ignore]
fn probe_surface_threshold() {
println!("\n-- relay legs on the code Relay-BP was designed for: BB [[72,12]] --");
let bb = CssCode::gross();
println!(" p legs=1(plain) legs=4 legs=16");
for &pp in &[0.02f64, 0.04, 0.06] {
let f = |legs: u32| {
let r = benchmark(&bb, pp, 400, 11, legs);
r.relay_logical_failures as f64 / r.trials as f64
};
let plain = {
let r = benchmark(&bb, pp, 400, 11, 4);
r.plain_logical_failures as f64 / r.trials as f64
};
println!(" {pp:<8} {plain:<13.4} {:<9.4} {:<9.4}", f(4), f(16));
}
println!("\n-- the same sweep on topological codes --");
println!(" p surf d=3 surf d=5 toric L=3 toric L=5");
for &pp in &[0.001f64, 0.005, 0.01] {
let sf = |d: usize| {
let r = benchmark(&CssCode::surface(d), pp, 1500, 11, 16);
r.relay_logical_failures as f64 / r.trials as f64
};
let tf = |l: usize| {
let r = benchmark(&CssCode::toric(l), pp, 1500, 11, 16);
r.relay_logical_failures as f64 / r.trials as f64
};
println!(" {pp:<8} {:<9.4} {:<9.4} {:<9.4} {:<9.4}", sf(3), sf(5), tf(3), tf(5));
}
}
#[test]
fn union_find_makes_distance_count() {
let p = 0.01;
let rate = |d: usize| {
let (t, f) = benchmark_uf(&CssCode::surface(d), p, 1500, 11);
f as f64 / t as f64
};
let (r3, r5) = (rate(3), rate(5));
assert!(r5 < r3, "d=5 ({r5}) must beat d=3 ({r3}) below threshold");
assert!(r5 <= 0.005, "d=5 at p={p} should almost never fail: {r5}");
}
#[test]
fn union_find_beats_bp_on_topological_codes() {
let p = 0.02;
for d in [5usize, 7] {
let code = CssCode::surface(d);
let bp = {
let r = benchmark(&code, p, 1000, 11, 16);
r.relay_logical_failures as f64 / r.trials as f64
};
let (t, f) = benchmark_uf(&code, p, 1000, 11);
let uf = f as f64 / t as f64;
assert!(uf < bp, "d={d}: union-find {uf} should beat Relay-BP {bp}");
}
}
#[test]
fn union_find_refuses_non_matching_codes() {
assert!(
union_find_correct(&CssCode::gross(), &vec![false; CssCode::gross().checks.len()]).is_none(),
"a bivariate-bicycle qubit sits in three checks; UF must decline"
);
assert!(union_find_correct(&CssCode::surface(5), &vec![false; 12]).is_some());
}
#[test]
fn union_find_corrects_every_single_qubit_error() {
for d in [3usize, 5] {
let code = CssCode::surface(d);
for q in 0..code.n {
let mut err = vec![false; code.n];
err[q] = true;
let syn = syndrome_of(&code.checks, &err);
let corr = union_find_correct(&code, &syn).expect("matching graph");
let residual: Vec<usize> = (0..code.n).filter(|&i| err[i] ^ corr[i]).collect();
assert!(
code.is_trivial(&residual),
"d={d}: single error on qubit {q} left a logical residual {residual:?}"
);
}
}
}
#[test]
#[ignore]
fn probe_union_find_vs_bp() {
println!("\n surface code — logical failure rate");
println!(" p d=3 BP d=3 UF d=5 BP d=5 UF d=7 BP d=7 UF");
for &pp in &[0.001f64, 0.005, 0.01, 0.02, 0.05] {
let bp = |d: usize| {
let r = benchmark(&CssCode::surface(d), pp, 2000, 11, 16);
r.relay_logical_failures as f64 / r.trials as f64
};
let uf = |d: usize| {
let (t, f) = benchmark_uf(&CssCode::surface(d), pp, 2000, 11);
f as f64 / t as f64
};
println!(" {pp:<8} {:<9.4} {:<9.4} {:<9.4} {:<9.4} {:<9.4} {:<9.4}",
bp(3), uf(3), bp(5), uf(5), bp(7), uf(7));
}
println!("\n toric code — UF");
for &pp in &[0.005f64, 0.02] {
let uf = |l: usize| { let (t,f)=benchmark_uf(&CssCode::toric(l), pp, 2000, 11); f as f64/t as f64 };
println!(" p={pp:<7} L=3 {:<8.4} L=5 {:<8.4}", uf(3), uf(5));
}
}
#[test]
fn toric_code_shape() {
let c = CssCode::toric(5);
assert_eq!(c.n, 50);
assert_eq!(c.checks.len(), 25);
assert_eq!(c.k, 2, "toric code encodes 2 logical qubits");
assert!(c.checks.iter().all(|r| r.len() == 4));
}
#[test]
fn gross_code_is_72_12() {
let c = CssCode::gross();
assert_eq!(c.n, 72);
assert_eq!(c.k, 12, "the gross-style BB code encodes 12 logical qubits");
assert!(c.checks.iter().all(|r| r.len() == 6));
}
#[test]
fn css_orthogonality_gross() {
let c = CssCode::gross();
let hx = CssCode::bivariate_bicycle(6, 6, &[(3, 0), (0, 1), (0, 2)], &[(0, 3), (1, 0), (2, 0)]);
for zc in &c.checks {
let zset: std::collections::HashSet<usize> = zc.iter().copied().collect();
for xs in raw_hx(&hx) {
let overlap = xs.iter().filter(|q| zset.contains(q)).count();
assert_eq!(overlap % 2, 0, "CSS orthogonality violated");
}
}
}
fn raw_hx(_c: &CssCode) -> Vec<Vec<usize>> {
let (l, m) = (6usize, 6usize);
let a = [(3usize, 0usize), (0, 1), (0, 2)];
let b = [(0usize, 3usize), (1, 0), (2, 0)];
let lm = l * m;
let cell = |i: usize, j: usize| (i % l) * m + (j % m);
let build = |monos: &[(usize, usize)]| -> Vec<Vec<usize>> {
let mut rows = vec![Vec::new(); lm];
for i in 0..l {
for j in 0..m {
let col = cell(i, j);
for &(px, py) in monos {
rows[cell(i + px, j + py)].push(col);
}
}
}
rows
};
let ar = build(&a);
let br = build(&b);
(0..lm)
.map(|r| {
let mut row = ar[r].clone();
row.extend(br[r].iter().map(|&c| c + lm));
row.sort_unstable();
row
})
.collect()
}
#[test]
fn decode_recovers_low_weight_errors() {
let c = CssCode::toric(5);
let cfg = DecodeConfig::from_p(0.02);
let mut fails = 0;
for s in 0..200u64 {
if !decode_once(&c, &cfg, s.wrapping_mul(0x9E37_79B9)).logical_success {
fails += 1;
}
}
assert!(fails < 20, "too many logical failures at p=0.02: {fails}/200");
}
#[test]
fn decode_is_deterministic() {
let c = CssCode::gross();
let cfg = DecodeConfig::from_p(0.03);
let a = decode_once(&c, &cfg, 12345);
let b = decode_once(&c, &cfg, 12345);
assert_eq!(a.correction, b.correction);
assert_eq!(a.messages, b.messages);
assert_eq!(a.legs, b.legs);
}
#[test]
fn relay_beats_plain_bp() {
let c = CssCode::gross();
let bench = benchmark(&c, 0.04, 150, 0xBEEF, 12);
assert!(
bench.relay_logical_failures <= bench.plain_logical_failures,
"relay {} must not exceed plain {}",
bench.relay_logical_failures, bench.plain_logical_failures
);
}
#[test]
fn decode_seals_verifying_receipt() {
let c = CssCode::gross();
let cfg = DecodeConfig::from_p(0.03);
let r = decode_once(&c, &cfg, 7);
let rec = r.seal(&key(1), "did:key:lab", 500_000, GrantRef::unbounded("quantum.decode"));
assert!(rec.verify());
assert!(rec.correction_matches(&r.correction_bytes()));
assert_eq!(rec.code_id, "bb:[[72,12]]");
assert_eq!(rec.work_messages, r.messages);
}
}