1use crate::device::{LogicalQubit, PhysicalQubit};
20use std::fmt;
21use thiserror::Error;
22
23#[derive(Error, Debug, Clone, PartialEq, Eq)]
24pub enum DeviceError {
25 InvalidOnlineQubit(PhysicalQubit),
26 QubitNotInDevice(PhysicalQubit),
27 QubitNotInTopology(PhysicalQubit),
28 EdgeNotInTopology(PhysicalQubit, PhysicalQubit),
29 InvalidTopology(TopologyError),
30 NonStandardNativeInstruction {
32 instruction: String,
34 },
35 InvalidNativeInstructionArity {
37 instruction: String,
39 expected: std::ops::RangeInclusive<usize>,
41 actual: usize,
43 },
44 InvalidNativeInstructionErrorRate {
46 instruction: String,
48 value: String,
50 },
51 InvalidNativeInstructionDuration {
53 instruction: String,
55 value: String,
57 },
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
62pub enum DeviceValidationError {
63 UnusablePhysicalQubit {
65 device: String,
67 qubit: PhysicalQubit,
69 },
70 MissingDirectedCoupling {
72 device: String,
74 instruction: String,
76 control: PhysicalQubit,
78 target: PhysicalQubit,
80 },
81 UnsupportedInstruction {
83 device: String,
85 instruction: String,
87 qargs: Vec<PhysicalQubit>,
89 },
90 UndecomposedInstruction {
92 device: String,
94 instruction: String,
96 qargs: Vec<PhysicalQubit>,
98 },
99}
100
101impl fmt::Display for DeviceValidationError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 Self::UnusablePhysicalQubit { device, qubit } => write!(
105 f,
106 "device '{device}' cannot execute an operation on unusable physical qubit {qubit}"
107 ),
108 Self::UnsupportedInstruction {
109 device,
110 instruction,
111 qargs,
112 } => {
113 let qargs = qargs
114 .iter()
115 .map(ToString::to_string)
116 .collect::<Vec<_>>()
117 .join(", ");
118 write!(
119 f,
120 "device '{device}' does not support instruction {instruction} on ordered physical qargs [{qargs}]"
121 )
122 }
123 Self::MissingDirectedCoupling {
124 device,
125 instruction,
126 control,
127 target,
128 } => write!(
129 f,
130 "device '{device}' has no directed coupling {control} -> {target} required by instruction {instruction}"
131 ),
132 Self::UndecomposedInstruction {
133 device,
134 instruction,
135 qargs,
136 } => {
137 let qargs = qargs
138 .iter()
139 .map(ToString::to_string)
140 .collect::<Vec<_>>()
141 .join(", ");
142 write!(
143 f,
144 "device '{device}' cannot validate undecomposed instruction {instruction} on ordered physical qargs [{qargs}]"
145 )
146 }
147 }
148 }
149}
150
151impl std::error::Error for DeviceValidationError {}
152
153impl fmt::Display for DeviceError {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 match self {
156 Self::InvalidOnlineQubit(q) => {
157 write!(
158 f,
159 "Specified online qubit {} does not exist in the device topology",
160 q
161 )
162 }
163 Self::QubitNotInDevice(q) => {
164 write!(f, "Qubit {} is not registered with the device", q)
165 }
166 Self::QubitNotInTopology(q) => {
167 write!(f, "Qubit {} is not in the device topology", q)
168 }
169 Self::EdgeNotInTopology(control, target) => {
170 write!(
171 f,
172 "Edge ({}, {}) is not in the device topology",
173 control, target
174 )
175 }
176 Self::InvalidTopology(error) => {
177 write!(f, "Invalid device topology: {error}")
178 }
179 Self::NonStandardNativeInstruction { instruction } => write!(
180 f,
181 "instruction {instruction} cannot be stored as a native capability: native instructions must be standard gates"
182 ),
183 Self::InvalidNativeInstructionArity {
184 instruction,
185 expected,
186 actual,
187 } => {
188 let expected = if expected.start() == expected.end() {
189 expected.start().to_string()
190 } else {
191 format!("{}..={}", expected.start(), expected.end())
192 };
193 write!(
194 f,
195 "instruction {instruction} cannot be stored as a native capability: expected {expected} qubits, got {actual}"
196 )
197 }
198 Self::InvalidNativeInstructionErrorRate { instruction, value } => write!(
199 f,
200 "instruction {instruction} has invalid native error rate {value}: expected a finite value in [0, 1]"
201 ),
202 Self::InvalidNativeInstructionDuration { instruction, value } => write!(
203 f,
204 "instruction {instruction} has invalid native duration {value}: expected a finite non-negative value"
205 ),
206 }
207 }
208}
209
210#[derive(Error, Debug, Clone, PartialEq, Eq)]
212pub enum LayoutError {
213 TooManyLogicalQubits { logical: usize, physical: usize },
215 DuplicateLogicalQubit(LogicalQubit),
217 DuplicatePhysicalQubit(PhysicalQubit),
219 InvalidLogicalQubit(LogicalQubit),
221 InvalidPhysicalQubit(PhysicalQubit),
223 LogicalQubitAlreadyBound(LogicalQubit),
225 PhysicalQubitAlreadyOccupied(PhysicalQubit),
227 LogicalQubitNotBound(LogicalQubit),
229}
230
231impl fmt::Display for LayoutError {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 match self {
234 Self::TooManyLogicalQubits { logical, physical } => {
235 write!(
236 f,
237 "Logical qubits ({}) exceed physical qubits ({})",
238 logical, physical
239 )
240 }
241 Self::DuplicateLogicalQubit(q) => {
242 write!(f, "Logical qubit {} appears more than once", q)
243 }
244 Self::DuplicatePhysicalQubit(q) => {
245 write!(f, "Physical qubit {} appears more than once", q)
246 }
247 Self::InvalidLogicalQubit(q) => {
248 write!(f, "Logical qubit {} not in logical qubit list", q)
249 }
250 Self::InvalidPhysicalQubit(q) => {
251 write!(f, "Physical qubit {} not in physical qubit list", q)
252 }
253 Self::LogicalQubitAlreadyBound(q) => {
254 write!(f, "Logical qubit {} is already bound", q)
255 }
256 Self::PhysicalQubitAlreadyOccupied(q) => {
257 write!(f, "Physical qubit {} is already occupied", q)
258 }
259 Self::LogicalQubitNotBound(q) => write!(f, "Logical qubit {} is not bound", q),
260 }
261 }
262}
263
264#[derive(Error, Debug, Clone, PartialEq, Eq)]
266pub enum TopologyError {
267 QubitNotFound(PhysicalQubit),
269 CouplingNotFound {
271 control: PhysicalQubit,
272 target: PhysicalQubit,
273 },
274 QubitAlreadyExists(PhysicalQubit),
276 CouplingAlreadyExists {
278 control: PhysicalQubit,
279 target: PhysicalQubit,
280 },
281 SelfCoupling { qubit: PhysicalQubit },
283 DuplicateQubitRemoval(PhysicalQubit),
285 DuplicateCouplingRemoval {
287 control: PhysicalQubit,
288 target: PhysicalQubit,
289 },
290}
291
292impl fmt::Display for TopologyError {
293 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294 match self {
295 TopologyError::QubitNotFound(q) => write!(f, "Qubit {:?} not found", q),
296 TopologyError::CouplingNotFound { control, target } => {
297 write!(f, "Coupling ({:?} -> {:?}) not found", control, target)
298 }
299 TopologyError::QubitAlreadyExists(q) => write!(f, "Qubit {:?} already exists", q),
300 TopologyError::CouplingAlreadyExists { control, target } => {
301 write!(f, "Coupling ({:?} -> {:?}) already exists", control, target)
302 }
303 TopologyError::SelfCoupling { qubit } => {
304 write!(
305 f,
306 "Self coupling ({:?} -> {:?}) is not allowed",
307 qubit, qubit
308 )
309 }
310 TopologyError::DuplicateQubitRemoval(q) => {
311 write!(f, "Qubit {:?} appears more than once in removal request", q)
312 }
313 TopologyError::DuplicateCouplingRemoval { control, target } => {
314 write!(
315 f,
316 "Coupling ({:?} -> {:?}) appears more than once in removal request",
317 control, target
318 )
319 }
320 }
321 }
322}