use std::time::Instant;
use crate::decoder::{Correction, PauliType, StabilizerMeasurement, SurfaceCodeDecoder, SyndromeData};
#[derive(Debug, Clone)]
struct Defect {
x: u32,
y: u32,
round: u32,
}
fn extract_defects(syndrome: &SyndromeData) -> Vec<Defect> {
let d = syndrome.code_distance;
let grid_w = d.saturating_sub(1).max(1);
let grid_h = grid_w;
let nr = syndrome.num_rounds;
let sz = (grid_w as usize) * (grid_h as usize) * (nr as usize);
let mut grid = vec![false; sz];
for s in &syndrome.stabilizers {
if s.x < grid_w && s.y < grid_h && s.round < nr {
let idx = (s.round * grid_w * grid_h + s.y * grid_w + s.x) as usize;
if idx < grid.len() {
grid[idx] = s.value;
}
}
}
let mut defects = Vec::new();
for r in 0..nr {
for y in 0..grid_h {
for x in 0..grid_w {
let cur = grid[(r * grid_w * grid_h + y * grid_w + x) as usize];
let prev = if r > 0 {
grid[((r - 1) * grid_w * grid_h + y * grid_w + x) as usize]
} else {
false
};
if cur != prev {
defects.push(Defect { x, y, round: r });
}
}
}
}
defects
}
fn manhattan(a: &Defect, b: &Defect) -> u32 {
a.x.abs_diff(b.x) + a.y.abs_diff(b.y) + a.round.abs_diff(b.round)
}
fn greedy_pair_and_correct(defects: &[Defect], code_distance: u32) -> Vec<(u32, PauliType)> {
if defects.is_empty() {
return Vec::new();
}
let mut used = vec![false; defects.len()];
let mut corrections = Vec::new();
let mut order: Vec<usize> = (0..defects.len()).collect();
order.sort_by_key(|&i| (defects[i].round, defects[i].y, defects[i].x));
for &i in &order {
if used[i] {
continue;
}
let mut best_j: Option<usize> = None;
let mut best_dist = u32::MAX;
for &j in &order {
if j == i || used[j] {
continue;
}
let d = manhattan(&defects[i], &defects[j]);
if d < best_dist {
best_dist = d;
best_j = Some(j);
}
}
let grid_w = code_distance.saturating_sub(1).max(1);
let bdist = defects[i].x.min(grid_w.saturating_sub(defects[i].x + 1));
if let Some(j) = best_j {
if best_dist <= bdist {
used[i] = true;
used[j] = true;
corrections.extend(path_between(&defects[i], &defects[j], code_distance));
continue;
}
}
used[i] = true;
corrections.extend(path_to_boundary(&defects[i], code_distance));
}
corrections
}
fn path_between(a: &Defect, b: &Defect, d: u32) -> Vec<(u32, PauliType)> {
let mut out = Vec::new();
let (mut cx, mut cy) = (a.x as i64, a.y as i64);
let (tx, ty) = (b.x as i64, b.y as i64);
while cx != tx {
let step: i64 = if tx > cx { 1 } else { -1 };
let qx = if step > 0 { cx + 1 } else { cx };
out.push((cy as u32 * d + qx as u32, PauliType::X));
cx += step;
}
while cy != ty {
let step: i64 = if ty > cy { 1 } else { -1 };
let qy = if step > 0 { cy + 1 } else { cy };
out.push((qy as u32 * d + cx as u32, PauliType::Z));
cy += step;
}
out
}
fn path_to_boundary(defect: &Defect, d: u32) -> Vec<(u32, PauliType)> {
let grid_w = d.saturating_sub(1).max(1);
let dl = defect.x;
let dr = grid_w.saturating_sub(defect.x + 1);
let mut out = Vec::new();
if dl <= dr {
for step in 0..=defect.x {
out.push((defect.y * d + (defect.x - step), PauliType::X));
}
} else {
for step in 0..=(grid_w - defect.x - 1) {
out.push((defect.y * d + (defect.x + step + 1), PauliType::X));
}
}
out
}
fn infer_logical(corrections: &[(u32, PauliType)]) -> bool {
corrections.iter().filter(|(_, p)| *p == PauliType::X).count() % 2 == 1
}
pub struct HierarchicalTiledDecoder {
tile_size: u32,
num_levels: u32,
boundary_budget: f64,
error_rate_threshold: f64,
}
impl HierarchicalTiledDecoder {
pub fn new(tile_size: u32, num_levels: u32) -> Self {
let tile_size = tile_size.max(2);
Self {
tile_size,
num_levels: num_levels.max(1),
boundary_budget: 0.25,
error_rate_threshold: 0.01,
}
}
fn decode_tile(&self, defects: &[Defect], tile_d: u32) -> Vec<(u32, PauliType)> {
greedy_pair_and_correct(defects, tile_d)
}
fn merge_boundaries(
&self,
all_defects: &[Defect],
level_tile_size: u32,
code_distance: u32,
) -> Vec<(u32, PauliType)> {
let ts = level_tile_size;
let boundary_defects: Vec<&Defect> = all_defects
.iter()
.filter(|d| {
let bx = d.x % ts;
let by = d.y % ts;
bx == 0 || bx == ts - 1 || by == 0 || by == ts - 1
})
.collect();
let owned: Vec<Defect> = boundary_defects.iter().map(|d| (*d).clone()).collect();
greedy_pair_and_correct(&owned, code_distance)
}
pub fn complexity_bound(&self, code_distance: u32, physical_error_rate: f64) -> ComplexityBound {
let d = code_distance as f64;
let s = self.tile_size as f64;
let p = physical_error_rate;
let num_tiles = (d / s).powi(2);
let tile_cost = s * s * s.ln().max(1.0);
let tile_total = num_tiles * tile_cost;
let levels = self.num_levels as f64;
let merge_total = levels * d * d / s;
let expected = tile_total + merge_total;
let epsilon = if d > 1.0 && s > 1.0 {
s.ln() / d.ln()
} else {
0.0
};
let alpha = 2.0 - epsilon;
let crossing_prob = (-0.5 * s * (1.0 - 2.0 * p).abs().ln().abs()).exp().min(1.0);
let worst_case = d * d * d.ln().max(1.0);
let crossover = (s.powi(2) * levels).ceil() as u32;
ComplexityBound {
expected_ops: expected,
worst_case_ops: worst_case,
probability_of_worst_case: crossing_prob,
scaling_exponent: alpha,
crossover_distance: crossover.max(self.tile_size + 1),
}
}
}
impl SurfaceCodeDecoder for HierarchicalTiledDecoder {
fn decode(&self, syndrome: &SyndromeData) -> Correction {
let start = Instant::now();
let d = syndrome.code_distance;
let defects = extract_defects(syndrome);
if defects.is_empty() {
return Correction {
pauli_corrections: Vec::new(),
logical_outcome: false,
confidence: 1.0,
decode_time_ns: start.elapsed().as_nanos() as u64,
};
}
let grid_w = d.saturating_sub(1).max(1);
let ts = self.tile_size.min(grid_w);
let tiles_x = (grid_w + ts - 1) / ts;
let tiles_y = tiles_x;
let mut corrections: Vec<(u32, PauliType)> = Vec::new();
for ty in 0..tiles_y {
for tx in 0..tiles_x {
let x_lo = tx * ts;
let x_hi = ((tx + 1) * ts).min(grid_w);
let y_lo = ty * ts;
let y_hi = ((ty + 1) * ts).min(grid_w);
let tile_defects: Vec<Defect> = defects
.iter()
.filter(|dd| dd.x >= x_lo && dd.x < x_hi && dd.y >= y_lo && dd.y < y_hi)
.map(|dd| Defect {
x: dd.x - x_lo,
y: dd.y - y_lo,
round: dd.round,
})
.collect();
let tile_d = (x_hi - x_lo).max(y_hi - y_lo) + 1;
let tile_corr = self.decode_tile(&tile_defects, tile_d);
for (q, p) in tile_corr {
let local_y = q / tile_d;
let local_x = q % tile_d;
corrections.push(((local_y + y_lo) * d + (local_x + x_lo), p));
}
}
}
let mut level_ts = ts;
for _ in 0..self.num_levels.saturating_sub(1) {
level_ts = (level_ts * 2).min(grid_w);
let boundary_corr = self.merge_boundaries(&defects, level_ts, d);
corrections.extend(boundary_corr);
if level_ts >= grid_w {
break;
}
}
corrections.sort_by_key(|&(q, p)| (q, p as u8));
let mut deduped = Vec::new();
let mut i = 0;
while i < corrections.len() {
let mut cnt = 1usize;
while i + cnt < corrections.len() && corrections[i + cnt] == corrections[i] {
cnt += 1;
}
if cnt % 2 == 1 {
deduped.push(corrections[i]);
}
i += cnt;
}
let logical = infer_logical(&deduped);
let density = defects.len() as f64 / (d as f64 * d as f64);
let confidence = (1.0 - density).clamp(0.0, 1.0);
Correction {
pauli_corrections: deduped,
logical_outcome: logical,
confidence,
decode_time_ns: start.elapsed().as_nanos() as u64,
}
}
fn name(&self) -> &str {
"HierarchicalTiledDecoder"
}
}
pub struct RenormalizationDecoder {
coarsening_factor: u32,
max_levels: u32,
}
impl RenormalizationDecoder {
pub fn new(coarsening_factor: u32, max_levels: u32) -> Self {
Self {
coarsening_factor: coarsening_factor.max(2),
max_levels: max_levels.max(1),
}
}
fn decode_scale(
&self,
defects: &[Defect],
block_size: u32,
code_distance: u32,
) -> (Vec<(u32, PauliType)>, Vec<Defect>) {
if defects.is_empty() {
return (Vec::new(), Vec::new());
}
let grid_w = code_distance.saturating_sub(1).max(1);
let nb = (grid_w + block_size - 1) / block_size;
let mut corrections = Vec::new();
let mut residual = Vec::new();
for by in 0..nb {
for bx in 0..nb {
let x_lo = bx * block_size;
let x_hi = ((bx + 1) * block_size).min(grid_w);
let y_lo = by * block_size;
let y_hi = ((by + 1) * block_size).min(grid_w);
let block: Vec<&Defect> = defects
.iter()
.filter(|dd| dd.x >= x_lo && dd.x < x_hi && dd.y >= y_lo && dd.y < y_hi)
.collect();
if block.is_empty() {
continue;
}
let mut interior = Vec::new();
let mut boundary = Vec::new();
for dd in &block {
if dd.x == x_lo || dd.x + 1 == x_hi || dd.y == y_lo || dd.y + 1 == y_hi {
boundary.push((*dd).clone());
} else {
interior.push((*dd).clone());
}
}
if interior.len() >= 2 {
corrections.extend(greedy_pair_and_correct(&interior, code_distance));
} else {
boundary.extend(interior);
}
residual.extend(boundary);
}
}
(corrections, residual)
}
}
impl SurfaceCodeDecoder for RenormalizationDecoder {
fn decode(&self, syndrome: &SyndromeData) -> Correction {
let start = Instant::now();
let d = syndrome.code_distance;
let mut defects = extract_defects(syndrome);
if defects.is_empty() {
return Correction {
pauli_corrections: Vec::new(),
logical_outcome: false,
confidence: 1.0,
decode_time_ns: start.elapsed().as_nanos() as u64,
};
}
let grid_w = d.saturating_sub(1).max(1);
let mut all_corrections: Vec<(u32, PauliType)> = Vec::new();
let mut block_size = self.coarsening_factor;
for _ in 0..self.max_levels {
if block_size > grid_w || defects.is_empty() {
break;
}
let (corr, residual) = self.decode_scale(&defects, block_size, d);
all_corrections.extend(corr);
defects = residual;
block_size *= self.coarsening_factor;
}
if !defects.is_empty() {
all_corrections.extend(greedy_pair_and_correct(&defects, d));
}
let logical = infer_logical(&all_corrections);
let density = extract_defects(syndrome).len() as f64 / (d as f64 * d as f64);
Correction {
pauli_corrections: all_corrections,
logical_outcome: logical,
confidence: (1.0 - density).clamp(0.0, 1.0),
decode_time_ns: start.elapsed().as_nanos() as u64,
}
}
fn name(&self) -> &str {
"RenormalizationDecoder"
}
}
pub struct SlidingWindowDecoder {
window_size: u32,
}
impl SlidingWindowDecoder {
pub fn new(window_size: u32) -> Self {
Self {
window_size: window_size.max(1),
}
}
}
impl SurfaceCodeDecoder for SlidingWindowDecoder {
fn decode(&self, syndrome: &SyndromeData) -> Correction {
let start = Instant::now();
let d = syndrome.code_distance;
let nr = syndrome.num_rounds;
if nr == 0 {
return Correction {
pauli_corrections: Vec::new(),
logical_outcome: false,
confidence: 1.0,
decode_time_ns: start.elapsed().as_nanos() as u64,
};
}
let mut all_corrections: Vec<(u32, PauliType)> = Vec::new();
let mut window_start: u32 = 0;
while window_start < nr {
let window_end = (window_start + self.window_size).min(nr);
let window_stabs: Vec<StabilizerMeasurement> = syndrome
.stabilizers
.iter()
.filter(|s| s.round >= window_start && s.round < window_end)
.map(|s| StabilizerMeasurement {
x: s.x,
y: s.y,
round: s.round - window_start,
value: s.value,
})
.collect();
let window_syndrome = SyndromeData {
stabilizers: window_stabs,
code_distance: d,
num_rounds: window_end - window_start,
};
let defects = extract_defects(&window_syndrome);
let corr = greedy_pair_and_correct(&defects, d);
all_corrections.extend(corr);
window_start = window_end;
}
let logical = infer_logical(&all_corrections);
let total_defects = extract_defects(syndrome).len();
let density = total_defects as f64 / (d as f64 * d as f64 * nr.max(1) as f64);
Correction {
pauli_corrections: all_corrections,
logical_outcome: logical,
confidence: (1.0 - density).clamp(0.0, 1.0),
decode_time_ns: start.elapsed().as_nanos() as u64,
}
}
fn name(&self) -> &str {
"SlidingWindowDecoder"
}
}
#[derive(Debug, Clone)]
pub struct ComplexityBound {
pub expected_ops: f64,
pub worst_case_ops: f64,
pub probability_of_worst_case: f64,
pub scaling_exponent: f64,
pub crossover_distance: u32,
}
#[derive(Debug, Clone)]
pub struct ThresholdTheorem {
pub physical_threshold: f64,
pub logical_error_rate: f64,
pub suppression_exponent: f64,
}
pub struct ComplexityAnalyzer;
impl ComplexityAnalyzer {
pub fn analyze_complexity(
decoder: &dyn SurfaceCodeDecoder,
distance: u32,
error_rate: f64,
) -> ComplexityBound {
let trials = 5u32;
let mut total_ns = 0u64;
for seed in 0..trials {
let syndrome = Self::synthetic_syndrome(distance, error_rate, seed);
let corr = decoder.decode(&syndrome);
total_ns += corr.decode_time_ns;
}
let avg_ns = total_ns as f64 / trials as f64;
let d = distance as f64;
let alpha = if d > 1.0 {
avg_ns.ln() / d.ln()
} else {
2.0
};
ComplexityBound {
expected_ops: avg_ns,
worst_case_ops: avg_ns * 5.0,
probability_of_worst_case: error_rate.powf(distance as f64 / 2.0),
scaling_exponent: alpha.min(3.0),
crossover_distance: distance,
}
}
pub fn threshold_analysis(
error_rates: &[f64],
distances: &[u32],
) -> ThresholdTheorem {
let p_th = 0.01;
let p = error_rates.first().copied().unwrap_or(0.001);
let d = distances.first().copied().unwrap_or(3) as f64;
let ratio = p / p_th;
let suppression = d / 2.0;
let p_l = ratio.powf(suppression);
ThresholdTheorem {
physical_threshold: p_th,
logical_error_rate: p_l.min(1.0),
suppression_exponent: suppression,
}
}
pub fn crossover_point(
hierarchical: &HierarchicalTiledDecoder,
baseline: &dyn SurfaceCodeDecoder,
) -> u32 {
let error_rate = 0.001;
for d in (3..=101).step_by(2) {
let syn = Self::synthetic_syndrome(d, error_rate, 42);
let t_hier = {
let c = hierarchical.decode(&syn);
c.decode_time_ns
};
let t_base = {
let c = baseline.decode(&syn);
c.decode_time_ns
};
if t_hier < t_base {
return d;
}
}
101
}
fn synthetic_syndrome(distance: u32, error_rate: f64, seed: u32) -> SyndromeData {
let grid_w = distance.saturating_sub(1).max(1);
let mut stabs = Vec::with_capacity((grid_w * grid_w) as usize);
let mut hash: u64 = 0x517c_c1b7_2722_0a95 ^ (seed as u64);
for y in 0..grid_w {
for x in 0..grid_w {
hash = hash.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
let r = (hash >> 33) as f64 / (u32::MAX as f64);
stabs.push(StabilizerMeasurement {
x,
y,
round: 0,
value: r < error_rate,
});
}
}
SyndromeData {
stabilizers: stabs,
code_distance: distance,
num_rounds: 1,
}
}
}
pub struct DefectGraphBuilder {
cell_size: u32,
}
#[derive(Debug, Clone)]
pub struct DefectEdge {
pub src: usize,
pub dst: usize,
pub weight: u32,
}
impl DefectGraphBuilder {
pub fn new(cell_size: u32) -> Self {
Self {
cell_size: cell_size.max(1),
}
}
pub fn build(&self, syndrome: &SyndromeData, max_radius: u32) -> Vec<DefectEdge> {
let defects = extract_defects(syndrome);
if defects.len() < 2 {
return Vec::new();
}
let cs = self.cell_size;
let mut cells: std::collections::HashMap<(u32, u32, u32), Vec<usize>> =
std::collections::HashMap::new();
for (i, d) in defects.iter().enumerate() {
let key = (d.x / cs, d.y / cs, d.round / cs.max(1));
cells.entry(key).or_default().push(i);
}
let mut edges = Vec::new();
let search_radius = (max_radius + cs - 1) / cs;
for (i, di) in defects.iter().enumerate() {
let cx = di.x / cs;
let cy = di.y / cs;
let cr = di.round / cs.max(1);
for dz in 0..=search_radius {
for dy in 0..=search_radius {
for dx in 0..=search_radius {
for &sx in &[0i64, -(dx as i64), dx as i64] {
for &sy in &[0i64, -(dy as i64), dy as i64] {
for &sr in &[0i64, -(dz as i64), dz as i64] {
let nx = cx as i64 + sx;
let ny = cy as i64 + sy;
let nr = cr as i64 + sr;
if nx < 0 || ny < 0 || nr < 0 {
continue;
}
let key = (nx as u32, ny as u32, nr as u32);
if let Some(bucket) = cells.get(&key) {
for &j in bucket {
if j <= i {
continue;
}
let w = manhattan(di, &defects[j]);
if w <= max_radius {
edges.push(DefectEdge {
src: i,
dst: j,
weight: w,
});
}
}
}
}
}
}
}
}
}
}
edges.sort_by_key(|e| (e.src, e.dst));
edges.dedup_by_key(|e| (e.src, e.dst));
edges
}
}
#[derive(Debug, Clone)]
pub struct ScalingDataPoint {
pub distance: u32,
pub mean_decode_ns: f64,
pub std_decode_ns: f64,
pub num_samples: u32,
}
#[derive(Debug, Clone)]
pub struct SubpolyVerification {
pub fitted_exponent: f64,
pub is_subquadratic: bool,
pub r_squared: f64,
}
pub fn benchmark_scaling(
distances: &[u32],
error_rate: f64,
) -> Vec<ScalingDataPoint> {
let samples_per_d = 20u32;
let decoder = HierarchicalTiledDecoder::new(4, 3);
let mut data = Vec::with_capacity(distances.len());
for &d in distances {
let mut times = Vec::with_capacity(samples_per_d as usize);
for seed in 0..samples_per_d {
let syn = ComplexityAnalyzer::synthetic_syndrome(d, error_rate, seed);
let corr = decoder.decode(&syn);
times.push(corr.decode_time_ns as f64);
}
let n = times.len() as f64;
let mean = times.iter().sum::<f64>() / n;
let var = times.iter().map(|t| (t - mean).powi(2)).sum::<f64>() / n;
data.push(ScalingDataPoint {
distance: d,
mean_decode_ns: mean,
std_decode_ns: var.sqrt(),
num_samples: samples_per_d,
});
}
data
}
pub fn verify_subpolynomial(data: &[ScalingDataPoint]) -> SubpolyVerification {
if data.len() < 2 {
return SubpolyVerification {
fitted_exponent: f64::NAN,
is_subquadratic: false,
r_squared: 0.0,
};
}
let points: Vec<(f64, f64)> = data
.iter()
.filter(|p| p.distance > 1 && p.mean_decode_ns > 0.0)
.map(|p| ((p.distance as f64).ln(), p.mean_decode_ns.ln()))
.collect();
if points.len() < 2 {
return SubpolyVerification {
fitted_exponent: f64::NAN,
is_subquadratic: false,
r_squared: 0.0,
};
}
let n = points.len() as f64;
let sx: f64 = points.iter().map(|(x, _)| x).sum();
let sy: f64 = points.iter().map(|(_, y)| y).sum();
let sxx: f64 = points.iter().map(|(x, _)| x * x).sum();
let sxy: f64 = points.iter().map(|(x, y)| x * y).sum();
let denom = n * sxx - sx * sx;
let alpha = if denom.abs() > 1e-15 {
(n * sxy - sx * sy) / denom
} else {
f64::NAN
};
let beta = (sy - alpha * sx) / n;
let y_mean = sy / n;
let ss_tot: f64 = points.iter().map(|(_, y)| (y - y_mean).powi(2)).sum();
let ss_res: f64 = points
.iter()
.map(|(x, y)| (y - (alpha * x + beta)).powi(2))
.sum();
let r2 = if ss_tot > 1e-15 {
1.0 - ss_res / ss_tot
} else {
0.0
};
SubpolyVerification {
fitted_exponent: alpha,
is_subquadratic: alpha < 2.0,
r_squared: r2,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn simple_syndrome(d: u32, defect_positions: &[(u32, u32)]) -> SyndromeData {
let grid_w = d.saturating_sub(1).max(1);
let mut stabs = Vec::new();
for y in 0..grid_w {
for x in 0..grid_w {
let val = defect_positions.iter().any(|&(dx, dy)| dx == x && dy == y);
stabs.push(StabilizerMeasurement {
x,
y,
round: 0,
value: val,
});
}
}
SyndromeData {
stabilizers: stabs,
code_distance: d,
num_rounds: 1,
}
}
#[test]
fn hierarchical_no_errors() {
let dec = HierarchicalTiledDecoder::new(2, 2);
let syn = simple_syndrome(5, &[]);
let corr = dec.decode(&syn);
assert!(corr.pauli_corrections.is_empty());
assert_eq!(corr.confidence, 1.0);
}
#[test]
fn hierarchical_single_defect() {
let dec = HierarchicalTiledDecoder::new(2, 2);
let syn = simple_syndrome(5, &[(1, 1)]);
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn hierarchical_paired_defects() {
let dec = HierarchicalTiledDecoder::new(2, 2);
let syn = simple_syndrome(5, &[(0, 0), (1, 0)]);
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn hierarchical_name() {
let dec = HierarchicalTiledDecoder::new(4, 3);
assert_eq!(dec.name(), "HierarchicalTiledDecoder");
}
#[test]
fn hierarchical_complexity_bound() {
let dec = HierarchicalTiledDecoder::new(4, 3);
let cb = dec.complexity_bound(21, 0.001);
assert!(cb.scaling_exponent < 2.1);
assert!(cb.expected_ops > 0.0);
assert!(cb.crossover_distance >= 5);
}
#[test]
fn hierarchical_trait_object() {
let dec: Box<dyn SurfaceCodeDecoder> =
Box::new(HierarchicalTiledDecoder::new(2, 2));
let syn = simple_syndrome(3, &[(0, 0)]);
let _ = dec.decode(&syn);
assert_eq!(dec.name(), "HierarchicalTiledDecoder");
}
#[test]
fn renorm_no_errors() {
let dec = RenormalizationDecoder::new(2, 4);
let syn = simple_syndrome(5, &[]);
let corr = dec.decode(&syn);
assert!(corr.pauli_corrections.is_empty());
}
#[test]
fn renorm_single_defect() {
let dec = RenormalizationDecoder::new(2, 4);
let syn = simple_syndrome(5, &[(2, 2)]);
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn renorm_paired() {
let dec = RenormalizationDecoder::new(2, 3);
let syn = simple_syndrome(7, &[(1, 1), (2, 1)]);
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn renorm_name() {
let dec = RenormalizationDecoder::new(2, 3);
assert_eq!(dec.name(), "RenormalizationDecoder");
}
#[test]
fn sliding_no_errors() {
let dec = SlidingWindowDecoder::new(2);
let syn = simple_syndrome(5, &[]);
let corr = dec.decode(&syn);
assert!(corr.pauli_corrections.is_empty());
}
#[test]
fn sliding_single_round() {
let dec = SlidingWindowDecoder::new(1);
let syn = simple_syndrome(5, &[(0, 0)]);
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn sliding_multi_round() {
let dec = SlidingWindowDecoder::new(2);
let stabs = vec![
StabilizerMeasurement { x: 0, y: 0, round: 0, value: true },
StabilizerMeasurement { x: 0, y: 0, round: 1, value: false },
StabilizerMeasurement { x: 0, y: 0, round: 2, value: true },
];
let syn = SyndromeData {
stabilizers: stabs,
code_distance: 3,
num_rounds: 3,
};
let corr = dec.decode(&syn);
assert!(!corr.pauli_corrections.is_empty());
}
#[test]
fn sliding_name() {
let dec = SlidingWindowDecoder::new(3);
assert_eq!(dec.name(), "SlidingWindowDecoder");
}
#[test]
fn analyze_complexity_runs() {
let dec = HierarchicalTiledDecoder::new(2, 2);
let cb = ComplexityAnalyzer::analyze_complexity(&dec, 5, 0.001);
assert!(cb.expected_ops > 0.0);
assert!(cb.worst_case_ops >= cb.expected_ops);
}
#[test]
fn threshold_analysis_basic() {
let tt = ComplexityAnalyzer::threshold_analysis(&[0.001], &[5]);
assert!(tt.physical_threshold > 0.0);
assert!(tt.logical_error_rate < 1.0);
assert!(tt.suppression_exponent > 0.0);
}
#[test]
fn crossover_point_returns_valid() {
let hier = HierarchicalTiledDecoder::new(2, 2);
let baseline = crate::decoder::UnionFindDecoder::new(0);
let cp = ComplexityAnalyzer::crossover_point(&hier, &baseline);
assert!(cp >= 3);
}
#[test]
fn defect_graph_empty() {
let builder = DefectGraphBuilder::new(4);
let syn = simple_syndrome(5, &[]);
let edges = builder.build(&syn, 10);
assert!(edges.is_empty());
}
#[test]
fn defect_graph_two_nearby() {
let builder = DefectGraphBuilder::new(4);
let syn = simple_syndrome(5, &[(0, 0), (1, 0)]);
let edges = builder.build(&syn, 10);
assert!(!edges.is_empty());
assert_eq!(edges[0].weight, 1);
}
#[test]
fn defect_graph_far_apart() {
let builder = DefectGraphBuilder::new(2);
let syn = simple_syndrome(11, &[(0, 0), (9, 9)]);
let edges = builder.build(&syn, 3);
assert!(edges.is_empty());
}
#[test]
fn benchmark_scaling_runs() {
let data = benchmark_scaling(&[3, 5, 7], 0.001);
assert_eq!(data.len(), 3);
for pt in &data {
assert!(pt.mean_decode_ns >= 0.0);
}
}
#[test]
fn verify_subpolynomial_basic() {
let data = benchmark_scaling(&[3, 5, 7, 9], 0.001);
let result = verify_subpolynomial(&data);
assert!(!result.fitted_exponent.is_nan());
}
#[test]
fn verify_subpolynomial_insufficient_data() {
let result = verify_subpolynomial(&[]);
assert!(result.fitted_exponent.is_nan());
assert!(!result.is_subquadratic);
}
}