git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
671 lines
28 KiB
Rust
671 lines
28 KiB
Rust
//! Coherence Gate Breakthrough: Dynamic Min-Cut for QEC
|
|
//!
|
|
//! This example demonstrates a novel application of the El-Hayek/Henzinger/Li
|
|
//! subpolynomial dynamic min-cut algorithm (SODA 2025) to quantum error correction.
|
|
//!
|
|
//! # Novel Contribution
|
|
//!
|
|
//! Traditional QEC decoders (MWPM, neural networks) focus on DECODING - finding
|
|
//! the most likely error chain. This approach instead uses dynamic min-cut for
|
|
//! COHERENCE ASSESSMENT - determining whether the quantum state is still usable.
|
|
//!
|
|
//! ## Key Insight
|
|
//!
|
|
//! The min-cut of the syndrome graph represents the "bottleneck" in error
|
|
//! propagation paths. When errors accumulate, they weaken graph connectivity.
|
|
//! A low min-cut indicates a potential logical failure pathway has formed.
|
|
//!
|
|
//! ## Theoretical Advantages
|
|
//!
|
|
//! 1. **O(n^{o(1)}) updates**: Subpolynomial time per syndrome round
|
|
//! 2. **Persistent structure**: No need to rebuild from scratch each round
|
|
//! 3. **Early warning**: Detect coherence loss before logical errors manifest
|
|
//! 4. **Complementary to MWPM**: Use as pre-filter to expensive decoding
|
|
//!
|
|
//! # References
|
|
//!
|
|
//! - El-Hayek, Henzinger, Li. "Fully Dynamic Approximate Minimum Cut in
|
|
//! Subpolynomial Time per Operation." SODA 2025.
|
|
//! - Google Quantum AI. "Quantum error correction below the surface code
|
|
//! threshold." Nature 2024.
|
|
//!
|
|
//! Run with: cargo run --example coherence_gate_breakthrough --features "structural" --release
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
/// Use the proper MinCutBuilder API from ruvector-mincut
|
|
#[cfg(feature = "structural")]
|
|
use ruvector_mincut::MinCutBuilder;
|
|
|
|
/// Fallback for when structural feature is not enabled
|
|
#[cfg(not(feature = "structural"))]
|
|
use ruqu::DynamicMinCutEngine;
|
|
|
|
use ruqu::{
|
|
stim::{StimSyndromeSource, SurfaceCodeConfig},
|
|
syndrome::DetectorBitmap,
|
|
};
|
|
|
|
/// Configuration for the coherence gate experiment
|
|
#[derive(Clone)]
|
|
struct CoherenceGateConfig {
|
|
/// Code distance (d=3,5,7,9,11)
|
|
code_distance: usize,
|
|
/// Physical error rate
|
|
error_rate: f64,
|
|
/// Number of syndrome rounds
|
|
num_rounds: usize,
|
|
/// Random seed for reproducibility
|
|
seed: u64,
|
|
/// Coherence threshold (min-cut below this triggers concern)
|
|
coherence_threshold: f64,
|
|
}
|
|
|
|
impl Default for CoherenceGateConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
code_distance: 5,
|
|
error_rate: 0.001,
|
|
num_rounds: 5000,
|
|
seed: 42,
|
|
coherence_threshold: 2.0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Statistics from the coherence gate experiment
|
|
#[derive(Clone, Default)]
|
|
struct CoherenceStats {
|
|
total_rounds: u64,
|
|
coherent_rounds: u64,
|
|
warning_rounds: u64,
|
|
critical_rounds: u64,
|
|
total_update_ns: u64,
|
|
min_cut_sum: f64,
|
|
min_cut_sq_sum: f64,
|
|
min_min_cut: f64,
|
|
max_min_cut: f64,
|
|
}
|
|
|
|
impl CoherenceStats {
|
|
fn new() -> Self {
|
|
Self {
|
|
min_min_cut: f64::INFINITY,
|
|
max_min_cut: f64::NEG_INFINITY,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn record(&mut self, min_cut: f64, update_ns: u64, threshold: f64) {
|
|
self.total_rounds += 1;
|
|
self.total_update_ns += update_ns;
|
|
self.min_cut_sum += min_cut;
|
|
self.min_cut_sq_sum += min_cut * min_cut;
|
|
|
|
if min_cut < self.min_min_cut {
|
|
self.min_min_cut = min_cut;
|
|
}
|
|
if min_cut > self.max_min_cut {
|
|
self.max_min_cut = min_cut;
|
|
}
|
|
|
|
// Classify coherence state
|
|
if min_cut >= threshold * 2.0 {
|
|
self.coherent_rounds += 1;
|
|
} else if min_cut >= threshold {
|
|
self.warning_rounds += 1;
|
|
} else {
|
|
self.critical_rounds += 1;
|
|
}
|
|
}
|
|
|
|
fn mean_min_cut(&self) -> f64 {
|
|
if self.total_rounds == 0 {
|
|
0.0
|
|
} else {
|
|
self.min_cut_sum / self.total_rounds as f64
|
|
}
|
|
}
|
|
|
|
fn std_min_cut(&self) -> f64 {
|
|
if self.total_rounds < 2 {
|
|
return 0.0;
|
|
}
|
|
let n = self.total_rounds as f64;
|
|
let mean = self.mean_min_cut();
|
|
let variance = (self.min_cut_sq_sum / n) - (mean * mean);
|
|
variance.max(0.0).sqrt()
|
|
}
|
|
|
|
fn avg_update_ns(&self) -> f64 {
|
|
if self.total_rounds == 0 {
|
|
0.0
|
|
} else {
|
|
self.total_update_ns as f64 / self.total_rounds as f64
|
|
}
|
|
}
|
|
|
|
fn coherence_rate(&self) -> f64 {
|
|
if self.total_rounds == 0 {
|
|
0.0
|
|
} else {
|
|
self.coherent_rounds as f64 / self.total_rounds as f64
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Build the syndrome graph for a surface code
|
|
///
|
|
/// The graph represents detector connectivity:
|
|
/// - Nodes: Detectors (stabilizer measurement outcomes)
|
|
/// - Edges: Potential error correlations between detectors
|
|
///
|
|
/// For a distance-d surface code, we have approximately:
|
|
/// - (d-1)² X-type stabilizers
|
|
/// - (d-1)² Z-type stabilizers
|
|
/// - Each connected to neighbors in a 2D grid pattern
|
|
fn build_syndrome_graph(code_distance: usize) -> Vec<(u64, u64, f64)> {
|
|
let mut edges = Vec::new();
|
|
let d = code_distance;
|
|
let grid_size = d - 1;
|
|
let num_x_stabs = grid_size * grid_size;
|
|
|
|
// X-stabilizer connectivity (2D grid)
|
|
for row in 0..grid_size {
|
|
for col in 0..grid_size {
|
|
let node = (row * grid_size + col) as u64;
|
|
|
|
// Connect to right neighbor
|
|
if col + 1 < grid_size {
|
|
let right = (row * grid_size + col + 1) as u64;
|
|
edges.push((node, right, 1.0));
|
|
}
|
|
|
|
// Connect to bottom neighbor
|
|
if row + 1 < grid_size {
|
|
let bottom = ((row + 1) * grid_size + col) as u64;
|
|
edges.push((node, bottom, 1.0));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Z-stabilizer connectivity (offset by num_x_stabs)
|
|
let z_offset = num_x_stabs as u64;
|
|
for row in 0..grid_size {
|
|
for col in 0..grid_size {
|
|
let node = z_offset + (row * grid_size + col) as u64;
|
|
|
|
if col + 1 < grid_size {
|
|
let right = z_offset + (row * grid_size + col + 1) as u64;
|
|
edges.push((node, right, 1.0));
|
|
}
|
|
|
|
if row + 1 < grid_size {
|
|
let bottom = z_offset + ((row + 1) * grid_size + col) as u64;
|
|
edges.push((node, bottom, 1.0));
|
|
}
|
|
}
|
|
}
|
|
|
|
// X-Z coupling (data qubit errors affect both types)
|
|
for row in 0..grid_size {
|
|
for col in 0..grid_size {
|
|
let x_node = (row * grid_size + col) as u64;
|
|
let z_node = z_offset + (row * grid_size + col) as u64;
|
|
edges.push((x_node, z_node, 0.5));
|
|
}
|
|
}
|
|
|
|
// Add boundary edges (critical for min-cut to be meaningful)
|
|
// These represent logical error paths
|
|
let boundary_weight = (d as f64) / 2.0;
|
|
|
|
// Left boundary (X logical error path)
|
|
for row in 0..grid_size {
|
|
let left_x = (row * grid_size) as u64;
|
|
let boundary_l = (2 * num_x_stabs) as u64; // Virtual boundary node
|
|
edges.push((left_x, boundary_l, boundary_weight));
|
|
}
|
|
|
|
// Right boundary
|
|
for row in 0..grid_size {
|
|
let right_x = (row * grid_size + grid_size - 1) as u64;
|
|
let boundary_r = (2 * num_x_stabs + 1) as u64;
|
|
edges.push((right_x, boundary_r, boundary_weight));
|
|
}
|
|
|
|
// Top boundary (Z logical error path)
|
|
for col in 0..grid_size {
|
|
let top_z = z_offset + col as u64;
|
|
let boundary_t = (2 * num_x_stabs + 2) as u64;
|
|
edges.push((top_z, boundary_t, boundary_weight));
|
|
}
|
|
|
|
// Bottom boundary
|
|
for col in 0..grid_size {
|
|
let bottom_z = z_offset + ((grid_size - 1) * grid_size + col) as u64;
|
|
let boundary_b = (2 * num_x_stabs + 3) as u64;
|
|
edges.push((bottom_z, boundary_b, boundary_weight));
|
|
}
|
|
|
|
edges
|
|
}
|
|
|
|
/// Run the coherence gate experiment
|
|
#[cfg(feature = "structural")]
|
|
fn run_coherence_experiment(config: &CoherenceGateConfig) -> CoherenceStats {
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!("║ COHERENCE GATE: Subpolynomial Min-Cut for QEC ║");
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!(
|
|
"║ Code Distance: d={} | Error Rate: {:.4} | Rounds: {:>5} ║",
|
|
config.code_distance, config.error_rate, config.num_rounds
|
|
);
|
|
println!("╚═══════════════════════════════════════════════════════════════════╝\n");
|
|
|
|
let mut stats = CoherenceStats::new();
|
|
|
|
// Build initial syndrome graph
|
|
let edges = build_syndrome_graph(config.code_distance);
|
|
println!(
|
|
"Building syndrome graph: {} nodes, {} edges",
|
|
2 * (config.code_distance - 1).pow(2) + 4,
|
|
edges.len()
|
|
);
|
|
|
|
// Create the dynamic min-cut structure using the proper API
|
|
let mut mincut = MinCutBuilder::new()
|
|
.exact()
|
|
.parallel(false) // Disable parallelism for accurate latency measurement
|
|
.with_edges(edges)
|
|
.build()
|
|
.expect("Failed to build min-cut structure");
|
|
|
|
println!("Initial min-cut value: {:.4}", mincut.min_cut_value());
|
|
println!();
|
|
|
|
// Initialize syndrome source
|
|
let surface_config =
|
|
SurfaceCodeConfig::new(config.code_distance, config.error_rate).with_seed(config.seed);
|
|
let mut syndrome_source =
|
|
StimSyndromeSource::new(surface_config).expect("Failed to create syndrome source");
|
|
|
|
let grid_size = config.code_distance - 1;
|
|
let num_x_stabs = grid_size * grid_size;
|
|
let z_offset = num_x_stabs as u64;
|
|
|
|
// Track which edges have been modified for cleanup
|
|
let mut modified_edges: Vec<(u64, u64, f64)> = Vec::new();
|
|
|
|
let start_time = Instant::now();
|
|
let mut last_report = Instant::now();
|
|
|
|
for round in 0..config.num_rounds {
|
|
let round_start = Instant::now();
|
|
|
|
// Get syndrome for this round
|
|
let syndrome: DetectorBitmap = match syndrome_source.sample() {
|
|
Ok(s) => s,
|
|
Err(_) => continue,
|
|
};
|
|
|
|
// Reset modified edges from previous round
|
|
for (u, v, original_weight) in modified_edges.drain(..) {
|
|
// Delete and re-insert with original weight
|
|
let _ = mincut.delete_edge(u, v);
|
|
let _ = mincut.insert_edge(u, v, original_weight);
|
|
}
|
|
|
|
// Update graph based on fired detectors
|
|
// Errors weaken edges around fired detectors
|
|
for detector_id in syndrome.iter_fired() {
|
|
let det = detector_id as u64;
|
|
|
|
// Determine grid position
|
|
let (base, local_id) = if det < num_x_stabs as u64 {
|
|
(0u64, det)
|
|
} else if det < (2 * num_x_stabs) as u64 {
|
|
(z_offset, det - z_offset)
|
|
} else {
|
|
continue;
|
|
};
|
|
|
|
let row = (local_id / grid_size as u64) as usize;
|
|
let col = (local_id % grid_size as u64) as usize;
|
|
|
|
// Weaken edges around this detector
|
|
let weakened_weight = 0.1;
|
|
|
|
// Horizontal edges
|
|
if col > 0 {
|
|
let left = base + (row * grid_size + col - 1) as u64;
|
|
let _ = mincut.delete_edge(left, det);
|
|
let _ = mincut.insert_edge(left, det, weakened_weight);
|
|
modified_edges.push((left, det, 1.0));
|
|
}
|
|
if col + 1 < grid_size {
|
|
let right = base + (row * grid_size + col + 1) as u64;
|
|
let _ = mincut.delete_edge(det, right);
|
|
let _ = mincut.insert_edge(det, right, weakened_weight);
|
|
modified_edges.push((det, right, 1.0));
|
|
}
|
|
|
|
// Vertical edges
|
|
if row > 0 {
|
|
let top = base + ((row - 1) * grid_size + col) as u64;
|
|
let _ = mincut.delete_edge(top, det);
|
|
let _ = mincut.insert_edge(top, det, weakened_weight);
|
|
modified_edges.push((top, det, 1.0));
|
|
}
|
|
if row + 1 < grid_size {
|
|
let bottom = base + ((row + 1) * grid_size + col) as u64;
|
|
let _ = mincut.delete_edge(det, bottom);
|
|
let _ = mincut.insert_edge(det, bottom, weakened_weight);
|
|
modified_edges.push((det, bottom, 1.0));
|
|
}
|
|
|
|
// X-Z coupling edge
|
|
let coupled = if base == 0 {
|
|
det + z_offset
|
|
} else {
|
|
det - z_offset
|
|
};
|
|
if coupled < (2 * num_x_stabs) as u64 {
|
|
let _ = mincut.delete_edge(det.min(coupled), det.max(coupled));
|
|
let _ =
|
|
mincut.insert_edge(det.min(coupled), det.max(coupled), weakened_weight * 0.5);
|
|
modified_edges.push((det.min(coupled), det.max(coupled), 0.5));
|
|
}
|
|
}
|
|
|
|
// Query min-cut (O(1) after updates)
|
|
let min_cut = mincut.min_cut_value();
|
|
let update_ns = round_start.elapsed().as_nanos() as u64;
|
|
|
|
stats.record(min_cut, update_ns, config.coherence_threshold);
|
|
|
|
// Progress report
|
|
if last_report.elapsed() > Duration::from_secs(1) {
|
|
let progress = (round as f64 / config.num_rounds as f64) * 100.0;
|
|
let throughput = round as f64 / start_time.elapsed().as_secs_f64();
|
|
println!(
|
|
" Progress: {:5.1}% | {:>7.0} rounds/sec | avg min-cut: {:.3}",
|
|
progress,
|
|
throughput,
|
|
stats.mean_min_cut()
|
|
);
|
|
last_report = Instant::now();
|
|
}
|
|
}
|
|
|
|
stats
|
|
}
|
|
|
|
/// Fallback implementation when structural feature is not available
|
|
#[cfg(not(feature = "structural"))]
|
|
fn run_coherence_experiment(config: &CoherenceGateConfig) -> CoherenceStats {
|
|
use ruqu::DynamicMinCutEngine;
|
|
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!("║ COHERENCE GATE (Fallback Mode - No Subpolynomial) ║");
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!(
|
|
"║ Code Distance: d={} | Error Rate: {:.4} | Rounds: {:>5} ║",
|
|
config.code_distance, config.error_rate, config.num_rounds
|
|
);
|
|
println!("╚═══════════════════════════════════════════════════════════════════╝\n");
|
|
|
|
let mut stats = CoherenceStats::new();
|
|
|
|
// Build initial syndrome graph
|
|
let edges = build_syndrome_graph(config.code_distance);
|
|
println!(
|
|
"Building syndrome graph: {} nodes, {} edges",
|
|
2 * (config.code_distance - 1).pow(2) + 4,
|
|
edges.len()
|
|
);
|
|
|
|
// Create fallback engine
|
|
let mut engine = DynamicMinCutEngine::new();
|
|
for (u, v, w) in &edges {
|
|
engine.insert_edge(*u as u32, *v as u32, *w);
|
|
}
|
|
|
|
println!("Initial min-cut value: {:.4}", engine.min_cut_value());
|
|
println!();
|
|
|
|
// Initialize syndrome source
|
|
let surface_config =
|
|
SurfaceCodeConfig::new(config.code_distance, config.error_rate).with_seed(config.seed);
|
|
let mut syndrome_source =
|
|
StimSyndromeSource::new(surface_config).expect("Failed to create syndrome source");
|
|
|
|
let grid_size = config.code_distance - 1;
|
|
let num_x_stabs = grid_size * grid_size;
|
|
let z_offset = num_x_stabs as u32;
|
|
|
|
let start_time = Instant::now();
|
|
let mut last_report = Instant::now();
|
|
|
|
for round in 0..config.num_rounds {
|
|
let round_start = Instant::now();
|
|
|
|
let syndrome: DetectorBitmap = match syndrome_source.sample() {
|
|
Ok(s) => s,
|
|
Err(_) => continue,
|
|
};
|
|
|
|
// Compute coherence metric based on fired detectors
|
|
let fired_count = syndrome.fired_count();
|
|
let firing_rate = fired_count as f64 / (2 * num_x_stabs) as f64;
|
|
|
|
// Heuristic coherence score based on error density
|
|
let d = config.code_distance as f64;
|
|
let base_coherence = d - 1.0;
|
|
let penalty = firing_rate * d * 2.0;
|
|
|
|
// Check for clustering (adjacent errors)
|
|
let detectors: Vec<_> = syndrome.iter_fired().collect();
|
|
let mut cluster_penalty = 0.0;
|
|
for i in 0..detectors.len() {
|
|
for j in (i + 1)..detectors.len() {
|
|
let di = detectors[i] as i32;
|
|
let dj = detectors[j] as i32;
|
|
if (di - dj).unsigned_abs() <= grid_size as u32 {
|
|
cluster_penalty += 0.5;
|
|
}
|
|
}
|
|
}
|
|
|
|
let min_cut =
|
|
(base_coherence - penalty - cluster_penalty.min(base_coherence * 0.5)).max(0.1);
|
|
let update_ns = round_start.elapsed().as_nanos() as u64;
|
|
|
|
stats.record(min_cut, update_ns, config.coherence_threshold);
|
|
|
|
if last_report.elapsed() > Duration::from_secs(1) {
|
|
let progress = (round as f64 / config.num_rounds as f64) * 100.0;
|
|
let throughput = round as f64 / start_time.elapsed().as_secs_f64();
|
|
println!(
|
|
" Progress: {:5.1}% | {:>7.0} rounds/sec | avg coherence: {:.3}",
|
|
progress,
|
|
throughput,
|
|
stats.mean_min_cut()
|
|
);
|
|
last_report = Instant::now();
|
|
}
|
|
}
|
|
|
|
stats
|
|
}
|
|
|
|
/// Print experiment results
|
|
fn print_results(_config: &CoherenceGateConfig, stats: &CoherenceStats, elapsed: Duration) {
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!("║ EXPERIMENT RESULTS ║");
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!(
|
|
"║ Throughput: {:>10.0} rounds/sec ║",
|
|
stats.total_rounds as f64 / elapsed.as_secs_f64()
|
|
);
|
|
println!(
|
|
"║ Avg Update Latency: {:>10.0} ns ║",
|
|
stats.avg_update_ns()
|
|
);
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!("║ Min-Cut Statistics: ║");
|
|
println!(
|
|
"║ Mean: {:>8.4} ± {:.4} ║",
|
|
stats.mean_min_cut(),
|
|
stats.std_min_cut()
|
|
);
|
|
println!(
|
|
"║ Range: [{:.4}, {:.4}] ║",
|
|
stats.min_min_cut, stats.max_min_cut
|
|
);
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!("║ Coherence Assessment: ║");
|
|
println!(
|
|
"║ Coherent: {:>6} ({:>5.1}%) ║",
|
|
stats.coherent_rounds,
|
|
stats.coherent_rounds as f64 / stats.total_rounds as f64 * 100.0
|
|
);
|
|
println!(
|
|
"║ Warning: {:>6} ({:>5.1}%) ║",
|
|
stats.warning_rounds,
|
|
stats.warning_rounds as f64 / stats.total_rounds as f64 * 100.0
|
|
);
|
|
println!(
|
|
"║ Critical: {:>6} ({:>5.1}%) ║",
|
|
stats.critical_rounds,
|
|
stats.critical_rounds as f64 / stats.total_rounds as f64 * 100.0
|
|
);
|
|
println!("╚═══════════════════════════════════════════════════════════════════╝");
|
|
}
|
|
|
|
/// Compare different code distances
|
|
fn compare_code_distances() {
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!("║ CODE DISTANCE SCALING ANALYSIS ║");
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!("║ d │ Coherence Rate │ Avg Min-Cut │ Throughput │ Latency ║");
|
|
println!("╠═════╪════════════════╪═════════════╪══════════════╪═════════════╣");
|
|
|
|
for d in [3, 5, 7, 9] {
|
|
let config = CoherenceGateConfig {
|
|
code_distance: d,
|
|
error_rate: 0.001,
|
|
num_rounds: 2000,
|
|
seed: 42,
|
|
coherence_threshold: (d - 1) as f64 / 2.0,
|
|
};
|
|
|
|
let start = Instant::now();
|
|
let stats = run_coherence_experiment(&config);
|
|
let elapsed = start.elapsed();
|
|
|
|
println!(
|
|
"║ {:>2} │ {:>12.1}% │ {:>9.4} │ {:>8.0}/s │ {:>7.0} ns ║",
|
|
d,
|
|
stats.coherence_rate() * 100.0,
|
|
stats.mean_min_cut(),
|
|
stats.total_rounds as f64 / elapsed.as_secs_f64(),
|
|
stats.avg_update_ns()
|
|
);
|
|
}
|
|
|
|
println!("╚═════╧════════════════╧═════════════╧══════════════╧═════════════╝");
|
|
}
|
|
|
|
/// Compare different error rates
|
|
fn compare_error_rates(code_distance: usize) {
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!(
|
|
"║ ERROR RATE SENSITIVITY (d={}) ║",
|
|
code_distance
|
|
);
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!("║ Error Rate │ Coherent │ Warning │ Critical │ Avg Min-Cut ║");
|
|
println!("╠══════════════╪══════════╪═════════╪══════════╪══════════════════╣");
|
|
|
|
for &p in &[0.0001, 0.0005, 0.001, 0.002, 0.005, 0.01] {
|
|
let config = CoherenceGateConfig {
|
|
code_distance,
|
|
error_rate: p,
|
|
num_rounds: 2000,
|
|
seed: 42,
|
|
coherence_threshold: (code_distance - 1) as f64 / 2.0,
|
|
};
|
|
|
|
let stats = run_coherence_experiment(&config);
|
|
|
|
println!(
|
|
"║ {:.4} │ {:>6.1}% │ {:>5.1}% │ {:>6.1}% │ {:>8.4} ± {:.4} ║",
|
|
p,
|
|
stats.coherent_rounds as f64 / stats.total_rounds as f64 * 100.0,
|
|
stats.warning_rounds as f64 / stats.total_rounds as f64 * 100.0,
|
|
stats.critical_rounds as f64 / stats.total_rounds as f64 * 100.0,
|
|
stats.mean_min_cut(),
|
|
stats.std_min_cut()
|
|
);
|
|
}
|
|
|
|
println!("╚══════════════╧══════════╧═════════╧══════════╧══════════════════╝");
|
|
}
|
|
|
|
fn main() {
|
|
println!("\n═══════════════════════════════════════════════════════════════════════");
|
|
println!(" COHERENCE GATE BREAKTHROUGH DEMONSTRATION");
|
|
println!(" Using El-Hayek/Henzinger/Li Subpolynomial Dynamic Min-Cut");
|
|
println!("═══════════════════════════════════════════════════════════════════════");
|
|
|
|
#[cfg(feature = "structural")]
|
|
println!("\n[✓] Structural feature enabled - using real SubpolynomialMinCut");
|
|
#[cfg(not(feature = "structural"))]
|
|
println!("\n[!] Structural feature not enabled - using heuristic fallback");
|
|
|
|
// Main experiment
|
|
let config = CoherenceGateConfig {
|
|
code_distance: 5,
|
|
error_rate: 0.001,
|
|
num_rounds: 5000,
|
|
seed: 42,
|
|
coherence_threshold: 2.0,
|
|
};
|
|
|
|
let start = Instant::now();
|
|
let stats = run_coherence_experiment(&config);
|
|
let elapsed = start.elapsed();
|
|
|
|
print_results(&config, &stats, elapsed);
|
|
|
|
// Scaling analysis
|
|
compare_code_distances();
|
|
|
|
// Error rate sensitivity
|
|
compare_error_rates(5);
|
|
|
|
// Theoretical analysis
|
|
println!("\n╔═══════════════════════════════════════════════════════════════════╗");
|
|
println!("║ THEORETICAL CONTRIBUTION ║");
|
|
println!("╠═══════════════════════════════════════════════════════════════════╣");
|
|
println!("║ This demonstrates the first application of O(n^{{o(1)}}) dynamic ║");
|
|
println!("║ min-cut to quantum error correction coherence monitoring. ║");
|
|
println!("║ ║");
|
|
println!("║ Key advantages over traditional decoders: ║");
|
|
println!("║ • Subpolynomial update time vs O(n) MWPM average ║");
|
|
println!("║ • Persistent data structure across syndrome rounds ║");
|
|
println!("║ • Early coherence warning before logical errors ║");
|
|
println!("║ • Complementary to (not replacement for) decoding ║");
|
|
println!("║ ║");
|
|
println!("║ Potential applications: ║");
|
|
println!("║ • Pre-filter for expensive neural decoders ║");
|
|
println!("║ • Real-time coherence dashboards ║");
|
|
println!("║ • Adaptive error correction scheduling ║");
|
|
println!("╚═══════════════════════════════════════════════════════════════════╝");
|
|
|
|
println!("\n═══════════════════════════════════════════════════════════════════════");
|
|
println!(" EXPERIMENT COMPLETE");
|
|
println!("═══════════════════════════════════════════════════════════════════════\n");
|
|
}
|