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