1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Module defining common errors that can occur during quantum simulations.
use std::{backtrace::Backtrace, str::Utf8Error};
use miette::Diagnostic;
use ndarray::ShapeError;
use thiserror::Error;
/// Represents errors that can occur during linear algebra operations.
#[derive(Debug, Diagnostic, Error)]
pub enum QdkSimError {
// NB: As a design note, please consider if a more specific error is better
// suited for your usecase before returning `MiscError`.
/// Raised on miscellaneous errors.
#[error("{msg}")]
#[diagnostic(code(qdk_sim::other))]
MiscError {
/// The message associated with this error.
msg: String,
/// A backtrace from where this error was originally raised.
#[backtrace]
backtrace: std::backtrace::Backtrace,
},
/// Raised when functionality that has not yet been implemented is called.
#[error("Not yet implemented: {0}")]
#[diagnostic(code(qdk_sim::not_yet_implemented))]
NotYetImplemented(String),
/// Raised when the wrong number of qubits is provided for a quantum
/// process.
#[error("Channel acts on {expected} qubits, but was applied to an {actual}-qubit state.")]
#[diagnostic(code(qdk_sim::process::wrong_n_qubits))]
WrongNumberOfQubits {
/// The number of qubits that was expected, as given by the size of the
/// channel to be applied.
expected: usize,
/// The actual number of qubits for the given state.
actual: usize,
},
/// Raised when a channel cannot be applied to a given state due to a
/// mismatch between channel and state kinds.
#[error("Unsupported quantum process variant {channel_variant} for applying to state variant {state_variant}.")]
#[diagnostic(code(qdk_sim::process::unsupported_apply))]
UnsupportedApply {
/// The enum variant of the channel to be applied.
channel_variant: &'static str,
/// The enum variant of the state that the channel is to be applied to.
state_variant: &'static str,
},
/// Raised when a matrix is singular, and thus does not have an inverse.
#[error("expected invertible matrix, but got a singular or very poorly conditioned matrix (det = {det})")]
#[diagnostic(code(qdk_sim::linalg::singular))]
Singular {
/// Actual determinant of the matrix which caused this error.
det: f64,
},
/// Raised when a shape error occurs internally to [`qdk_sim`].
#[error(transparent)]
#[diagnostic(code(qdk_sim::linalg::internal_shape))]
InternalShapeError(
#[from]
#[backtrace]
ShapeError,
),
/// Raised when an algorithm requires a matrix to be square, but a
/// rectangular matrix was passed instead.
#[error("expected square matrix, but got shape `{0}` × `{1}")]
#[diagnostic(code(qdk_sim::linalg::not_square))]
NotSquare(usize, usize),
/// Raised when an algorithm needs to convert an element between two
/// different scalar types, but no such conversion exists for those types.
#[error("could not convert value of type `{0}` into element type `{1}`")]
#[diagnostic(code(qdk_sim::linalg::cannot_convert_element))]
CannotConvertElement(String, String),
/// Raised when no noise model exists for a given name.
#[error("{0} is not the name of any valid noise model")]
#[diagnostic(code(qdk_sim::noise_model::invalid_repr))]
InvalidNoiseModel(String),
/// Raised when an initial state representation is invalid.
#[error("C API error: {0} is not a valid initial state representation")]
#[diagnostic(code(qdk_sim::c_api::invalid_repr))]
InvalidRepresentation(String),
/// Raised when a null pointer is passed through the C API.
#[error("C API error: {0} was null")]
#[diagnostic(code(qdk_sim::c_api::nullptr))]
NullPointer(String),
/// Raised when an invalid simulator ID is passed to the C API.
#[error("C API error: No simulator with ID {invalid_id} exists. Expected: {expected:?}.")]
#[diagnostic(code(qdk_sim::c_api::invalid_sim))]
NoSuchSimulator {
/// The invalid simulator id which caused this error.
invalid_id: usize,
/// A list of valid simulator ids at the point when this error occured.
expected: Vec<usize>,
},
/// Raised when a string passed to the C API contains could not be decoded
/// as a UTF-8 string.
#[error("C API error: UTF-8 error decoding {arg_name} argument: {source}")]
#[diagnostic(code(qdk_sim::c_api::utf8))]
InvalidUtf8InArgument {
/// The name of the argument containing invalid UTF-8 data.
arg_name: String,
/// The underlying UTF-8 error that caused this error.
#[source]
source: Utf8Error,
},
/// Raised when a JSON serialization error occurs during a C API call.
#[error(transparent)]
#[diagnostic(code(qdk_sim::c_api::json_deser))]
JsonDeserializationError(
#[from]
#[backtrace]
serde_json::Error,
),
/// Raised when an unanticipated error occurs during a C API call.
#[error(transparent)]
#[diagnostic(code(qdk_sim::c_api::unanticipated))]
UnanticipatedCApiError(
#[from]
#[backtrace]
anyhow::Error,
),
}
impl QdkSimError {
pub(crate) fn misc<T: Into<String>>(msg: T) -> Self {
let msg: String = msg.into();
QdkSimError::MiscError {
msg,
backtrace: Backtrace::force_capture(),
}
}
}