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}