Skip to main content

qec_code/
error.rs

1use thiserror::Error;
2
3#[derive(Debug, Clone, PartialEq, Eq, Error)]
4#[error("{0}")]
5pub struct CssMatrixReadSource(pub String);
6
7#[derive(Debug, Clone, Error, PartialEq, Eq)]
8pub enum QecError {
9    #[error("family verification failed")]
10    FamilyVerificationFailed { report: String },
11    #[error("unsupported CSS construction schema version: {version}")]
12    UnsupportedCssConstructionSchemaVersion { version: u64 },
13    #[error("invalid CSS construction JSON: {0}")]
14    InvalidCssConstructionJson(String),
15    #[error("unknown CSS construction: {construction}")]
16    UnknownCssConstruction { construction: String },
17    #[error("invalid CSS construction {construction}: {reason}")]
18    InvalidCssConstruction {
19        construction: String,
20        reason: String,
21    },
22    #[error("invalid directional route {route}: {reason}")]
23    InvalidDirectionalRoute { route: String, reason: String },
24    #[error("invalid directional CSS specification: {reason}")]
25    InvalidDirectionalCssSpec { reason: String },
26    #[error("row width mismatch: expected {expected}, got {actual}")]
27    RowWidthMismatch { expected: usize, actual: usize },
28    #[error("invalid symplectic row width: expected even width, got {width}")]
29    InvalidSymplecticRowWidth { width: usize },
30    #[error("non-binary matrix entry {value} at row {row}, column {col}")]
31    InvalidBinaryEntry { row: usize, col: usize, value: u8 },
32    #[error("invalid column permutation: {reason}")]
33    InvalidColumnPermutation { reason: String },
34    #[error("invalid sparse-rows width: {num_cols}")]
35    InvalidSparseRowsWidth { num_cols: usize },
36    #[error("duplicate sparse-row support {support} in row {row}")]
37    DuplicateSparseRowSupport { row: usize, support: usize },
38    #[error("out-of-range sparse-row support {support} in row {row} for width {num_cols}")]
39    SparseRowSupportOutOfRange {
40        row: usize,
41        support: usize,
42        num_cols: usize,
43    },
44    #[error("sparse GF(2) row count mismatch: expected {expected}, got {actual}")]
45    SparseGf2RowCountMismatch { expected: usize, actual: usize },
46    #[error("out-of-range sparse GF(2) support {support} in row {row} for width {num_cols}")]
47    SparseGf2SupportOutOfRange {
48        row: usize,
49        support: usize,
50        num_cols: usize,
51    },
52    #[error(
53        "sparse GF(2) horizontal concatenation row mismatch: left has {left_rows}, right has {right_rows}"
54    )]
55    SparseGf2HorizontalRowMismatch { left_rows: usize, right_rows: usize },
56    #[error("sparse GF(2) dimension overflow during {operation}")]
57    SparseGf2DimensionOverflow { operation: &'static str },
58    #[error(
59        "invalid boundary map dimensions: domain dimension {domain_dimension}, codomain dimension {codomain_dimension}"
60    )]
61    InvalidBoundaryMapDimensions {
62        domain_dimension: usize,
63        codomain_dimension: usize,
64    },
65    #[error("duplicate boundary map for domain dimension {domain_dimension}")]
66    DuplicateBoundaryMapDimension { domain_dimension: usize },
67    #[error("missing boundary map for domain dimension {domain_dimension}")]
68    MissingBoundaryMap { domain_dimension: usize },
69    #[error(
70        "boundary composition dimension mismatch between dimensions {lower_dimension} and {upper_dimension}: lower domain has {lower_domain_cells} cells, upper codomain has {upper_codomain_cells} cells"
71    )]
72    BoundaryCompositionDimensionMismatch {
73        lower_dimension: usize,
74        upper_dimension: usize,
75        lower_domain_cells: usize,
76        upper_codomain_cells: usize,
77    },
78    #[error(
79        "nonzero boundary composition between dimensions {lower_dimension} and {upper_dimension}: row {row} has support {support:?}"
80    )]
81    NonzeroBoundaryComposition {
82        lower_dimension: usize,
83        upper_dimension: usize,
84        row: usize,
85        support: Vec<usize>,
86    },
87    #[error("invalid finite group table: {reason}")]
88    InvalidFiniteGroupTable { reason: String },
89    #[error("finite group order {order} exceeds maximum supported order {max_order}")]
90    GroupOrderLimitExceeded { order: usize, max_order: usize },
91    #[error("invalid finite group element {element}: expected < {order}")]
92    InvalidFiniteGroupElement { element: usize, order: usize },
93    #[error("invalid group-algebra support {support}: expected < {order}")]
94    InvalidGroupAlgebraElementSupport { support: usize, order: usize },
95    #[error("group-algebra element order mismatch: expected {expected}, got {actual}")]
96    GroupAlgebraOrderMismatch { expected: usize, actual: usize },
97    #[error("group-algebra matrix row width mismatch: expected {expected}, got {actual}")]
98    GroupAlgebraMatrixRowWidthMismatch { expected: usize, actual: usize },
99    #[error("group-algebra dimension overflow during {operation}")]
100    GroupAlgebraDimensionOverflow { operation: &'static str },
101    #[error("invalid regular classical matrix option {option}: {reason}")]
102    InvalidRegularClassicalMatrixConfig {
103        option: &'static str,
104        reason: String,
105    },
106    #[error("unsupported regular classical matrix algorithm version {algorithm_version}")]
107    UnsupportedRegularClassicalMatrixAlgorithm { algorithm_version: u32 },
108    #[error("invalid random two-block spec option {option}: {reason}")]
109    InvalidRandomTwoBlockSpec {
110        option: &'static str,
111        reason: String,
112    },
113    #[error("invalid random HGP spec option {option}: {reason}")]
114    InvalidRandomHgpSpec {
115        option: &'static str,
116        reason: String,
117    },
118    #[error("unsupported random two-block algorithm version {algorithm_version}")]
119    UnsupportedRandomTwoBlockAlgorithm { algorithm_version: u32 },
120    #[error("regular classical matrix stub-count overflow for {side}")]
121    RegularClassicalMatrixStubCountOverflow { side: &'static str },
122    #[error(
123        "regular classical matrix stub-count mismatch: column stubs {column_stubs}, row stubs {row_stubs}"
124    )]
125    RegularClassicalMatrixStubCountMismatch {
126        column_stubs: usize,
127        row_stubs: usize,
128    },
129    #[error(
130        "regular classical matrix generation exhausted retry limit {retry_limit} after {attempts} attempts for algorithm version {algorithm_version} seed {seed}"
131    )]
132    RegularClassicalMatrixGenerationExhausted {
133        retry_limit: usize,
134        attempts: usize,
135        algorithm_version: u32,
136        seed: u64,
137    },
138    #[error("missing CSS matrix format")]
139    MissingCssMatrixFormat,
140    #[error("unsupported CSS matrix format: {format}")]
141    UnsupportedCssMatrixFormat { format: String },
142    #[error("invalid CSS matrix JSON: {0}")]
143    InvalidCssMatrixJson(String),
144    #[error("invalid quantum Tanner spec JSON: {0}")]
145    InvalidQuantumTannerSpecJson(String),
146    #[error("invalid quantum Tanner group table: {reason}")]
147    InvalidQuantumTannerGroupTable { reason: String },
148    #[error("unsupported quantum Tanner construction mode: {mode}")]
149    UnsupportedQuantumTannerConstructionMode { mode: String },
150    #[error("invalid quantum Tanner local code matrix {matrix}: {reason}")]
151    InvalidQuantumTannerLocalCodeMatrix {
152        matrix: &'static str,
153        reason: String,
154    },
155    #[error(
156        "invalid quantum Tanner generator {set}[{index}]: element {element} is out of range for group order {order}"
157    )]
158    InvalidQuantumTannerGeneratorIndex {
159        set: &'static str,
160        index: usize,
161        element: usize,
162        order: usize,
163    },
164    #[error("invalid quantum Tanner generator set {set}: {reason}")]
165    InvalidQuantumTannerGeneratorSet { set: &'static str, reason: String },
166    #[error(
167        "degenerate quantum Tanner face at root {root} with a={a}, b={b}: vertices {vertices:?}"
168    )]
169    DegenerateQuantumTannerFace {
170        root: usize,
171        a: usize,
172        b: usize,
173        vertices: Vec<usize>,
174    },
175    #[error("invalid quantum Tanner group element {element}: expected < {order}")]
176    InvalidQuantumTannerGroupElement { element: usize, order: usize },
177    #[error("invalid quantum Tanner CSS construction: {reason}")]
178    InvalidQuantumTannerCssConstruction { reason: String },
179    #[error("JSON output is required for {command}")]
180    JsonOutputRequired { command: &'static str },
181    #[error("invalid CSS distance input: {0}")]
182    InvalidCssDistanceInput(String),
183    #[error("failed to read CSS matrix {path}: {source}")]
184    CssMatrixReadFailed {
185        path: String,
186        source: CssMatrixReadSource,
187    },
188    #[error("invalid Pauli width: x has {x_width} bits, z has {z_width}")]
189    InvalidPauliWidth { x_width: usize, z_width: usize },
190    #[error("non-binary Pauli bit {value} in {which} support at index {index}")]
191    InvalidPauliBit {
192        which: &'static str,
193        index: usize,
194        value: u8,
195    },
196    #[error("stabilizers do not mutually commute")]
197    NonCommutingStabilizers,
198    #[error("stabilizers are linearly dependent")]
199    DependentStabilizers,
200    #[error("CSS X/Z checks are not orthogonal")]
201    InvalidCssOrthogonality,
202    #[error("logical basis extraction is unsupported for {k} logical qubits")]
203    UnsupportedLogicalBasis { k: usize },
204    #[error("exhaustive Pauli enumeration is unsupported for {n} qubits on this target")]
205    UnsupportedExhaustiveEnumeration { n: usize },
206    #[error(
207        "distance computation is unsupported for {n} qubits in the current configuration: {reason}"
208    )]
209    DistanceComputationUnsupported { n: usize, reason: String },
210    #[error("logical basis not found")]
211    LogicalBasisNotFound,
212    #[error("distance witness not found")]
213    DistanceWitnessNotFound,
214    #[error("invalid distance bound option {option}: {reason}")]
215    InvalidDistanceBoundOption {
216        option: &'static str,
217        reason: String,
218    },
219    #[error("randomized upper-bound witness not found")]
220    RandomizedUpperBoundWitnessNotFound,
221    #[error("distance bound validation failed: {0}")]
222    DistanceBoundValidationFailed(String),
223    #[error("ILP backend is unavailable: {0}")]
224    IlpBackendUnavailable(String),
225    #[error("ILP solve failed: {0}")]
226    IlpSolveFailed(String),
227    #[error("ILP model is infeasible for a code with logical qubits")]
228    IlpInfeasible,
229    #[error("unknown built-in CSS code: {code_id}")]
230    UnknownBuiltInCssCode { code_id: String },
231    #[error("unknown built-in CSS family: {family}")]
232    UnknownBuiltInCssFamily { family: String },
233    #[error("missing built-in CSS parameter {parameter} for family {family}")]
234    MissingBuiltInCssParameter { family: String, parameter: String },
235    #[error("duplicate built-in CSS parameter {parameter} for family {family}")]
236    DuplicateBuiltInCssParameter { family: String, parameter: String },
237    #[error("invalid built-in CSS integer parameter {parameter} for family {family}: {value}")]
238    InvalidBuiltInCssIntegerParameter {
239        family: String,
240        parameter: String,
241        value: String,
242    },
243    #[error("unexpected built-in CSS parameter {parameter} for family {family}")]
244    UnexpectedBuiltInCssParameter { family: String, parameter: String },
245    #[error("out-of-range built-in CSS integer parameter {parameter} for family {family}: {value}")]
246    OutOfRangeBuiltInCssIntegerParameter {
247        family: String,
248        parameter: String,
249        value: usize,
250    },
251    #[error(
252        "unsupported built-in CSS integer parameter {parameter} for family {family}: {value} (supported: {supported}; {note})"
253    )]
254    UnsupportedBuiltInCssIntegerParameter {
255        family: String,
256        parameter: String,
257        value: usize,
258        supported: String,
259        note: String,
260    },
261}
262
263pub type Result<T> = core::result::Result<T, QecError>;
264
265#[cfg(any(feature = "distance-ilp-highs", feature = "distance-ilp-gurobi"))]
266impl From<qec_ilp_core::BinaryIlpError> for QecError {
267    fn from(value: qec_ilp_core::BinaryIlpError) -> Self {
268        match value {
269            qec_ilp_core::BinaryIlpError::BackendUnavailable { requested } => {
270                Self::IlpBackendUnavailable(format!("{requested:?}"))
271            }
272            other => Self::IlpSolveFailed(other.to_string()),
273        }
274    }
275}