Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
19f9ead
Expose the Rust stabilizer-code distance search and verification work…
ciaranra Aug 3, 2026
94174a8
Add shortest_logicals, result reprs, and typed parity-check/symplecti…
ciaranra Aug 3, 2026
d857f92
Add stabilizer-code verification user guide with executable examples
ciaranra Aug 3, 2026
73046eb
Merge branch 'dev' into code-distance-rust
ciaranra Aug 4, 2026
70a698d
Apply blackdoc formatting to the verification guide
ciaranra Aug 5, 2026
beac013
Merge remote-tracking branch 'origin/code-distance-rust' into code-di…
ciaranra Aug 5, 2026
6c070c8
Consolidate duplicate distance searches and parallelize the search en…
ciaranra Aug 5, 2026
c44d211
Add detector-error-model fault distance with graphlike and exhaustive…
ciaranra Aug 5, 2026
36c9f25
Merge branch 'dem-fault-distance' into code-distance-rust
ciaranra Aug 5, 2026
551e97f
Inject each fault at its own tick and before/after position when prop…
ciaranra Aug 5, 2026
a8685f8
Merge branch 'fix-multifault-prop' into code-distance-rust
ciaranra Aug 5, 2026
341f110
Enumerate single-leg Pauli faults at multi-qubit gate locations
ciaranra Aug 6, 2026
125e6c9
Add hook-error diagnosis naming the gate responsible for fault amplif…
ciaranra Aug 6, 2026
1abd836
Report circuit fault distance as a number, per logical operator
ciaranra Aug 6, 2026
7f793ba
Prune the DEM fault-distance search with connected clusters and uniqu…
ciaranra Aug 6, 2026
70ec6ec
Verify the propagated-fault half of the Chao-Reichardt t-flag condition
ciaranra Aug 6, 2026
a50915b
Add SAT/MaxSAT distance encoding with native witness certification
ciaranra Aug 6, 2026
d7f848c
Certify exact distance in-process with a batsat backend
ciaranra Aug 6, 2026
48908e3
Expose fault-tolerance analysis and distance certification to Python
ciaranra Aug 6, 2026
375193b
Apply black formatting to the qec type stubs
ciaranra Aug 6, 2026
5d16fe2
Extract fault locations per gate instance instead of per batch
ciaranra Aug 6, 2026
646c251
Retain learned clauses across the certification weight loop via assum…
ciaranra Aug 6, 2026
d211e5b
Revert "Retain learned clauses across the certification weight loop v…
ciaranra Aug 6, 2026
c1bfb99
Document the fault-tolerance analysis and distance certification tooling
ciaranra Aug 6, 2026
ac9e73e
Add per-observable DEM fault distances and non-CSS symplectic distanc…
ciaranra Aug 6, 2026
3a50101
Deprecate VerifyStabilizers in favor of the StabilizerCodeSpec workflow
ciaranra Aug 6, 2026
74bcf8b
Range observable ids as u32 instead of casting
ciaranra Aug 7, 2026
41e7ec9
Document the panic condition and remove the remaining test-helper cast
ciaranra Aug 7, 2026
d345ea0
Keep the neo stub signature under the new clippy release
ciaranra Aug 7, 2026
f1142e2
Add code-level connected-cluster distance as a third independent exac…
ciaranra Aug 7, 2026
fa05b24
Build the bivariate-bicycle depth-8 syndrome cycle with native X-basi…
ciaranra Aug 7, 2026
45c4404
Contain solver panics at the certification boundary
ciaranra Aug 7, 2026
d842c16
Restore QASM-engine PZ support, disambiguate BB order getters, run ba…
ciaranra Aug 7, 2026
1719982
Drive the connected-cluster search by unsatisfied detectors
ciaranra Aug 7, 2026
3f5a732
Add a generic edge-coloration syndrome-extraction builder and measure…
ciaranra Aug 7, 2026
3d079ed
Add self-certifying bounded-enumeration distance for the dense-code r…
ciaranra Aug 7, 2026
78e5e4a
Add a wgpu backend for bounded-enumeration levels behind a packed CPU…
ciaranra Aug 7, 2026
f6194b7
Add certified coset weights, logical weight profiles, and classical d…
ciaranra Aug 8, 2026
2d9e186
Add hypergraph-product code construction with a GF(2) Kronecker primi…
ciaranra Aug 8, 2026
03a377a
Add subsystem-code dressed distance over the stabilizer-only reduction
ciaranra Aug 8, 2026
672c9ad
Rename the ambiguous logical-matrix variable in the certification tests
ciaranra Aug 8, 2026
057b934
Add randomized decoder-based upper bounds on DEM fault distance
ciaranra Aug 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ bitflags = "2"
bitvec = { version = "1", features = ["serde"] }
bytemuck = { version = "1", features = ["derive"] }
dyn-clone = "1"
batsat = "0.5"
smallvec = "1"

# --- Concurrency ---
Expand Down Expand Up @@ -301,3 +302,10 @@ opt-level = 2
opt-level = 2
[profile.dev.package.fusion-blossom]
opt-level = 2

# batsat's solver core is tested and shipped by upstream with release arithmetic;
# under this workspace's debug profile its internal activity/restart arithmetic
# overflows on instances with thousands of variables. Run the dependency at its
# supported semantics; PECOS code keeps full debug overflow checks.
[profile.dev.package.batsat]
overflow-checks = false
6 changes: 4 additions & 2 deletions crates/benchmarks/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use criterion::{Criterion, criterion_group, criterion_main};

mod modules {
pub mod allocation_overhead;
pub mod code_distance;
pub mod cpu_stabilizer_comparison;
pub mod dem_builder;
pub mod dem_sampler;
Expand Down Expand Up @@ -58,14 +59,15 @@ use modules::sparse_stab_vs_cpp;
#[cfg(feature = "stab-tn")]
use modules::stab_mps_vs_stab_vec;
use modules::{
allocation_overhead, cpu_stabilizer_comparison, dem_builder, dem_sampler, dod_statevec,
fault_catalog, measurement_sampling, native_statevec_comparison, noise_models,
allocation_overhead, code_distance, cpu_stabilizer_comparison, dem_builder, dem_sampler,
dod_statevec, fault_catalog, measurement_sampling, native_statevec_comparison, noise_models,
pecos_neo_comparison, quizx_eval, rng, set_ops, sparse_stab_w_vs_y, sparse_state_vec, stab_vec,
stabilizer_sims, state_vec_sims, surface_code, tick_circuit_layout, trig,
};

fn all_benchmarks(c: &mut Criterion) {
allocation_overhead::benchmarks(c);
code_distance::benchmarks(c);
stab_vec::benchmarks(c);
cpu_stabilizer_comparison::benchmarks(c);
quizx_eval::benchmarks(c);
Expand Down
89 changes: 89 additions & 0 deletions crates/benchmarks/benches/modules/code_distance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2026 The PECOS Developers
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under
// the License.

//! Exhaustive code-distance search benchmarks.

use criterion::{Criterion, measurement::Measurement};
use pecos_core::{Xs, Zs};
use pecos_qec::{
DistanceSearchConfig, StabilizerCode, StabilizerCodeSpec, calculate_distance,
find_shortest_logicals,
};
use std::hint::black_box;

pub fn benchmarks<M: Measurement>(c: &mut Criterion<M>) {
eprintln!(
"code-distance benchmark available parallelism: {}",
std::thread::available_parallelism().map_or(1, std::num::NonZero::get)
);

let five_qubit = standard_code_spec(&StabilizerCode::five_qubit());
let steane = standard_code_spec(&StabilizerCode::steane());
let toric_3 = standard_code_spec(&StabilizerCode::toric(3));
let color_17 = color_code_17();
let config = DistanceSearchConfig::default();

let mut group = c.benchmark_group("code_distance/calculate_distance");
group.sample_size(10);
group.bench_function("five_qubit_5_1_3", |b| {
b.iter(|| calculate_distance(black_box(&five_qubit), black_box(&config)));
});
group.bench_function("steane_7_1_3", |b| {
b.iter(|| calculate_distance(black_box(&steane), black_box(&config)));
});
group.bench_function("toric_3_18_2_3", |b| {
b.iter(|| calculate_distance(black_box(&toric_3), black_box(&config)));
});
group.bench_function("color_17_1_5", |b| {
b.iter(|| calculate_distance(black_box(&color_17), black_box(&config)));
});
group.finish();

let mut group = c.benchmark_group("code_distance/find_shortest_logicals");
group.sample_size(10);
group.bench_function("color_17_1_5_delta_1", |b| {
b.iter(|| find_shortest_logicals(black_box(&color_17), black_box(&config), 1));
});
group.finish();
}

fn standard_code_spec(code: &StabilizerCode) -> StabilizerCodeSpec {
StabilizerCodeSpec::from_stabilizer_code(code)
.expect("standard stabilizer code should have discoverable logicals")
}

fn color_code_17() -> StabilizerCodeSpec {
const SUPPORTS: [&[usize]; 8] = [
&[0, 9, 12, 15],
&[1, 9, 12, 16],
&[2, 11, 13, 14],
&[3, 8, 9, 12],
&[4, 8, 10, 12, 13, 14, 15, 16],
&[5, 10, 11, 13],
&[6, 8, 9, 10, 13, 14, 15, 16],
&[7, 10, 11, 14],
];

let mut builder = StabilizerCodeSpec::builder(17);
for support in SUPPORTS {
builder = builder.check(Xs(support));
}
for support in SUPPORTS {
builder = builder.check(Zs(support));
}

builder
.logical_x(Xs(0..17))
.logical_z(Zs(0..17))
.build()
.expect("[[17,1,5]] color code should be valid")
}
24 changes: 20 additions & 4 deletions crates/pecos-core/src/gate_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ pub enum GateType {
/// Toffoli gate (CCX, 3 qubits)
CCX = 90,

// MX = 100
/// Measure in the X basis.
MX = 100,
// MnX = 101
// MY = 102
// MnY = 103
Expand All @@ -97,8 +98,8 @@ pub enum GateType {
/// Measure +Z, then prepare |0> (measure-and-prepare; the MP* family)
MPZ = 107,
// TODO: MPauli instead of the other variants?

// PX = 130
/// Prepare the +1 eigenstate of X.
PX = 130,
// PNX = 131
// PY = 132
// PNY = 133
Expand Down Expand Up @@ -173,10 +174,12 @@ impl From<u8> for GateType {
83 => GateType::RXXRYYRZZ,
84 => GateType::U2q,
90 => GateType::CCX,
100 => GateType::MX,
104 => GateType::MZ,
105 => GateType::MeasureLeaked,
106 => GateType::MeasureFree,
107 => GateType::MPZ,
130 => GateType::PX,
134 => GateType::PZ,
135 => GateType::QAlloc,
136 => GateType::QFree,
Expand Down Expand Up @@ -220,7 +223,10 @@ impl GateType {
/// Deciding otherwise means changing this function and nothing else.
#[must_use]
pub const fn consumes_measurement_record(self) -> bool {
matches!(self, GateType::MZ | GateType::MeasureFree | GateType::MPZ)
matches!(
self,
GateType::MX | GateType::MZ | GateType::MeasureFree | GateType::MPZ
)
}

/// Returns the number of angle parameters this gate type requires
Expand Down Expand Up @@ -259,13 +265,15 @@ impl GateType {
| GateType::SZZdg
| GateType::SWAP
| GateType::CCX
| GateType::MX
| GateType::MZ
| GateType::MeasureLeaked
| GateType::MeasureFree
| GateType::MPZ
| GateType::MeasCrosstalkGlobalPayload
| GateType::MeasCrosstalkLocalPayload
| GateType::Channel
| GateType::PX
| GateType::PZ
| GateType::QAlloc
| GateType::QFree
Expand Down Expand Up @@ -324,10 +332,12 @@ impl GateType {
| GateType::Tdg
| GateType::R1XY
| GateType::U
| GateType::MX
| GateType::MZ
| GateType::MeasureLeaked
| GateType::MeasureFree
| GateType::MPZ
| GateType::PX
| GateType::PZ
| GateType::QAlloc
| GateType::QFree
Expand Down Expand Up @@ -480,10 +490,12 @@ impl fmt::Display for GateType {
GateType::RXXRYYRZZ => write!(f, "RXXRYYRZZ"),
GateType::U2q => write!(f, "U2q"),
GateType::CCX => write!(f, "CCX"),
GateType::MX => write!(f, "MX"),
GateType::MZ => write!(f, "MZ"),
GateType::MeasureLeaked => write!(f, "MeasureLeaked"),
GateType::MeasureFree => write!(f, "MeasureFree"),
GateType::MPZ => write!(f, "MPZ"),
GateType::PX => write!(f, "PX"),
GateType::PZ => write!(f, "PZ"),
GateType::QAlloc => write!(f, "QAlloc"),
GateType::QFree => write!(f, "QFree"),
Expand All @@ -503,7 +515,9 @@ impl std::str::FromStr for GateType {
fn from_str(s: &str) -> Result<Self, Self::Err> {
// Try exact match first for multi-word aliases with specific casing
match s {
"init |+>" | "Init |+>" => return Ok(GateType::PX),
"init |0>" | "Init |0>" => return Ok(GateType::PZ),
"measure X" => return Ok(GateType::MX),
"measure Z" => return Ok(GateType::MZ),
_ => {}
}
Expand Down Expand Up @@ -549,10 +563,12 @@ impl std::str::FromStr for GateType {
"CRZ" => Ok(GateType::CRZ),
"CCX" | "TOFFOLI" => Ok(GateType::CCX),
"SWAP" => Ok(GateType::SWAP),
"MX" | "MEASURE X" => Ok(GateType::MX),
"MEASURE" | "MZ" | "MEASURE Z" => Ok(GateType::MZ),
"MEASUREFREE" | "MZFREE" => Ok(GateType::MeasureFree),
"MEASURELEAKED" => Ok(GateType::MeasureLeaked),
"MPZ" => Ok(GateType::MPZ),
"PX" | "INIT |+>" => Ok(GateType::PX),
"PREP" | "PZ" | "INIT" | "INIT |0>" | "RESET" => Ok(GateType::PZ),
"QALLOC" => Ok(GateType::QAlloc),
"QFREE" => Ok(GateType::QFree),
Expand Down
Loading
Loading