qiskit-aer 0.17.2__cp314-cp314-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit_aer/VERSION.txt +1 -0
- qiskit_aer/__init__.py +89 -0
- qiskit_aer/aererror.py +30 -0
- qiskit_aer/aerprovider.py +119 -0
- qiskit_aer/backends/__init__.py +20 -0
- qiskit_aer/backends/aer_compiler.py +1085 -0
- qiskit_aer/backends/aer_simulator.py +1025 -0
- qiskit_aer/backends/aerbackend.py +679 -0
- qiskit_aer/backends/backend_utils.py +567 -0
- qiskit_aer/backends/backendconfiguration.py +395 -0
- qiskit_aer/backends/backendproperties.py +590 -0
- qiskit_aer/backends/compatibility.py +287 -0
- qiskit_aer/backends/controller_wrappers.cp314-win_amd64.pyd +0 -0
- qiskit_aer/backends/libopenblas.dll +0 -0
- qiskit_aer/backends/name_mapping.py +306 -0
- qiskit_aer/backends/qasm_simulator.py +925 -0
- qiskit_aer/backends/statevector_simulator.py +330 -0
- qiskit_aer/backends/unitary_simulator.py +316 -0
- qiskit_aer/jobs/__init__.py +35 -0
- qiskit_aer/jobs/aerjob.py +143 -0
- qiskit_aer/jobs/utils.py +66 -0
- qiskit_aer/library/__init__.py +204 -0
- qiskit_aer/library/control_flow_instructions/__init__.py +16 -0
- qiskit_aer/library/control_flow_instructions/jump.py +47 -0
- qiskit_aer/library/control_flow_instructions/mark.py +30 -0
- qiskit_aer/library/control_flow_instructions/store.py +29 -0
- qiskit_aer/library/default_qubits.py +44 -0
- qiskit_aer/library/instructions_table.csv +21 -0
- qiskit_aer/library/save_instructions/__init__.py +44 -0
- qiskit_aer/library/save_instructions/save_amplitudes.py +168 -0
- qiskit_aer/library/save_instructions/save_clifford.py +63 -0
- qiskit_aer/library/save_instructions/save_data.py +129 -0
- qiskit_aer/library/save_instructions/save_density_matrix.py +91 -0
- qiskit_aer/library/save_instructions/save_expectation_value.py +257 -0
- qiskit_aer/library/save_instructions/save_matrix_product_state.py +71 -0
- qiskit_aer/library/save_instructions/save_probabilities.py +156 -0
- qiskit_aer/library/save_instructions/save_stabilizer.py +70 -0
- qiskit_aer/library/save_instructions/save_state.py +79 -0
- qiskit_aer/library/save_instructions/save_statevector.py +120 -0
- qiskit_aer/library/save_instructions/save_superop.py +62 -0
- qiskit_aer/library/save_instructions/save_unitary.py +63 -0
- qiskit_aer/library/set_instructions/__init__.py +19 -0
- qiskit_aer/library/set_instructions/set_density_matrix.py +78 -0
- qiskit_aer/library/set_instructions/set_matrix_product_state.py +83 -0
- qiskit_aer/library/set_instructions/set_stabilizer.py +77 -0
- qiskit_aer/library/set_instructions/set_statevector.py +78 -0
- qiskit_aer/library/set_instructions/set_superop.py +78 -0
- qiskit_aer/library/set_instructions/set_unitary.py +78 -0
- qiskit_aer/noise/__init__.py +265 -0
- qiskit_aer/noise/device/__init__.py +25 -0
- qiskit_aer/noise/device/models.py +397 -0
- qiskit_aer/noise/device/parameters.py +202 -0
- qiskit_aer/noise/errors/__init__.py +30 -0
- qiskit_aer/noise/errors/base_quantum_error.py +119 -0
- qiskit_aer/noise/errors/pauli_error.py +283 -0
- qiskit_aer/noise/errors/pauli_lindblad_error.py +363 -0
- qiskit_aer/noise/errors/quantum_error.py +451 -0
- qiskit_aer/noise/errors/readout_error.py +355 -0
- qiskit_aer/noise/errors/standard_errors.py +498 -0
- qiskit_aer/noise/noise_model.py +1231 -0
- qiskit_aer/noise/noiseerror.py +30 -0
- qiskit_aer/noise/passes/__init__.py +18 -0
- qiskit_aer/noise/passes/local_noise_pass.py +160 -0
- qiskit_aer/noise/passes/relaxation_noise_pass.py +137 -0
- qiskit_aer/primitives/__init__.py +44 -0
- qiskit_aer/primitives/estimator.py +751 -0
- qiskit_aer/primitives/estimator_v2.py +159 -0
- qiskit_aer/primitives/sampler.py +361 -0
- qiskit_aer/primitives/sampler_v2.py +256 -0
- qiskit_aer/quantum_info/__init__.py +32 -0
- qiskit_aer/quantum_info/states/__init__.py +16 -0
- qiskit_aer/quantum_info/states/aer_densitymatrix.py +313 -0
- qiskit_aer/quantum_info/states/aer_state.py +525 -0
- qiskit_aer/quantum_info/states/aer_statevector.py +302 -0
- qiskit_aer/utils/__init__.py +44 -0
- qiskit_aer/utils/noise_model_inserter.py +66 -0
- qiskit_aer/utils/noise_transformation.py +431 -0
- qiskit_aer/version.py +86 -0
- qiskit_aer-0.17.2.dist-info/METADATA +209 -0
- qiskit_aer-0.17.2.dist-info/RECORD +83 -0
- qiskit_aer-0.17.2.dist-info/WHEEL +5 -0
- qiskit_aer-0.17.2.dist-info/licenses/LICENSE.txt +203 -0
- qiskit_aer-0.17.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
# This code is part of Qiskit.
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright IBM 2018-2023.
|
|
4
|
+
#
|
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
8
|
+
#
|
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
|
11
|
+
# that they have been altered from the originals.
|
|
12
|
+
"""
|
|
13
|
+
Standard quantum computing error channels for Aer.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import itertools as it
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
from qiskit.circuit import Reset
|
|
21
|
+
from qiskit.circuit.library.standard_gates import IGate, XGate, ZGate
|
|
22
|
+
from qiskit.circuit.library.generalized_gates import UnitaryGate
|
|
23
|
+
from qiskit.exceptions import QiskitError
|
|
24
|
+
from qiskit.quantum_info.operators import Pauli
|
|
25
|
+
from qiskit.quantum_info.operators.channel import Choi, Kraus
|
|
26
|
+
from qiskit.quantum_info.operators.predicates import is_identity_matrix
|
|
27
|
+
from qiskit.quantum_info.operators.predicates import is_unitary_matrix
|
|
28
|
+
from .quantum_error import QuantumError
|
|
29
|
+
from ..noiseerror import NoiseError
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def kraus_error(noise_ops, canonical_kraus=False):
|
|
33
|
+
"""
|
|
34
|
+
Return a Kraus quantum error channel.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
noise_ops (list[matrix]): Kraus matrices.
|
|
38
|
+
canonical_kraus (bool): Convert input Kraus matrices into the
|
|
39
|
+
canonical Kraus representation (default: False)
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
QuantumError: The quantum error object.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
NoiseError: if error parameters are invalid.
|
|
46
|
+
"""
|
|
47
|
+
if not isinstance(noise_ops, (list, tuple)):
|
|
48
|
+
raise NoiseError("Invalid Kraus error input.")
|
|
49
|
+
if not noise_ops:
|
|
50
|
+
raise NoiseError("Kraus error noise_ops must not be empty.")
|
|
51
|
+
|
|
52
|
+
kraus = Kraus(noise_ops)
|
|
53
|
+
if canonical_kraus:
|
|
54
|
+
# Convert to Choi and back to get canonical Kraus
|
|
55
|
+
kraus = Kraus(Choi(kraus))
|
|
56
|
+
return QuantumError(kraus)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def mixed_unitary_error(noise_ops):
|
|
60
|
+
"""
|
|
61
|
+
Return a mixed unitary quantum error channel.
|
|
62
|
+
|
|
63
|
+
The input should be a list of pairs ``(U[j], p[j])``, where
|
|
64
|
+
``U[j]`` is a unitary matrix and ``p[j]`` is a probability. All
|
|
65
|
+
probabilities must sum to 1 for the input ops to be valid.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
noise_ops (list[pair[matrix, double]]): unitary error matrices.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
QuantumError: The quantum error object.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
NoiseError: if error parameters are invalid.
|
|
75
|
+
"""
|
|
76
|
+
# Error checking
|
|
77
|
+
if not isinstance(noise_ops, (list, tuple, zip)):
|
|
78
|
+
raise NoiseError("Input noise ops is not a list.")
|
|
79
|
+
|
|
80
|
+
# Convert to numpy arrays
|
|
81
|
+
noise_ops = [(np.array(op, dtype=complex), p) for op, p in noise_ops]
|
|
82
|
+
if not noise_ops:
|
|
83
|
+
raise NoiseError("Input noise list is empty.")
|
|
84
|
+
|
|
85
|
+
# Check for identity unitaries
|
|
86
|
+
prob_identity = 0.0
|
|
87
|
+
instructions = []
|
|
88
|
+
instructions_probs = []
|
|
89
|
+
num_qubits = int(np.log2(noise_ops[0][0].shape[0]))
|
|
90
|
+
if noise_ops[0][0].shape != (2**num_qubits, 2**num_qubits):
|
|
91
|
+
raise NoiseError("A unitary matrix in input noise_ops is not a multi-qubit matrix.")
|
|
92
|
+
for unitary, prob in noise_ops:
|
|
93
|
+
# Check unitary
|
|
94
|
+
if unitary.shape != noise_ops[0][0].shape:
|
|
95
|
+
raise NoiseError("Input matrices different size.")
|
|
96
|
+
if not is_unitary_matrix(unitary):
|
|
97
|
+
raise NoiseError("Input matrix is not unitary.")
|
|
98
|
+
if is_identity_matrix(unitary):
|
|
99
|
+
prob_identity += prob
|
|
100
|
+
else:
|
|
101
|
+
instr = UnitaryGate(unitary)
|
|
102
|
+
instructions.append(instr)
|
|
103
|
+
instructions_probs.append(prob)
|
|
104
|
+
if prob_identity > 0:
|
|
105
|
+
instructions.append(IGate())
|
|
106
|
+
instructions_probs.append(prob_identity)
|
|
107
|
+
return QuantumError(zip(instructions, instructions_probs))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def coherent_unitary_error(unitary):
|
|
111
|
+
"""
|
|
112
|
+
Return a coherent unitary quantum error channel.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
unitary (matrix like): unitary error matrix.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
QuantumError: The quantum error object.
|
|
119
|
+
"""
|
|
120
|
+
return mixed_unitary_error([(unitary, 1)])
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def pauli_error(noise_ops):
|
|
124
|
+
"""
|
|
125
|
+
Return a mixed Pauli quantum error channel.
|
|
126
|
+
|
|
127
|
+
The input should be a list of pairs ``(P[j], p[j])``, where
|
|
128
|
+
``P[j]`` is a ``Pauli`` object or string label, and ``p[j]`` is a
|
|
129
|
+
probability. All probabilities must sum to 1 for the input ops to
|
|
130
|
+
be valid.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
noise_ops (list[pair[Pauli, double]]): Pauli error terms.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
QuantumError: The quantum error object.
|
|
137
|
+
|
|
138
|
+
Raises:
|
|
139
|
+
NoiseError: If depolarizing probability is less than 0 or greater than 1.
|
|
140
|
+
"""
|
|
141
|
+
# Error checking
|
|
142
|
+
if not isinstance(noise_ops, (list, tuple, zip)):
|
|
143
|
+
raise NoiseError("Input noise ops is not a list.")
|
|
144
|
+
noise_ops = list(noise_ops)
|
|
145
|
+
if not noise_ops:
|
|
146
|
+
raise NoiseError("Input noise list is empty.")
|
|
147
|
+
|
|
148
|
+
ops, probs = zip(*noise_ops) # unzip
|
|
149
|
+
|
|
150
|
+
def to_pauli(op):
|
|
151
|
+
if isinstance(op, Pauli):
|
|
152
|
+
return op
|
|
153
|
+
elif isinstance(op, str):
|
|
154
|
+
try:
|
|
155
|
+
return Pauli(op)
|
|
156
|
+
except QiskitError:
|
|
157
|
+
pass
|
|
158
|
+
raise NoiseError("Invalid Pauli input operator: {}".format(op))
|
|
159
|
+
|
|
160
|
+
paulis = [to_pauli(op) for op in ops]
|
|
161
|
+
|
|
162
|
+
num_qubits = paulis[0].num_qubits
|
|
163
|
+
for pauli in paulis:
|
|
164
|
+
if num_qubits != pauli.num_qubits:
|
|
165
|
+
raise NoiseError("Pauli's are not all of the same length.")
|
|
166
|
+
|
|
167
|
+
return QuantumError(zip(paulis, probs))
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def depolarizing_error(param, num_qubits):
|
|
171
|
+
r"""
|
|
172
|
+
Return a depolarizing quantum error channel.
|
|
173
|
+
|
|
174
|
+
The depolarizing channel is defined as:
|
|
175
|
+
|
|
176
|
+
.. math::
|
|
177
|
+
|
|
178
|
+
E(ρ) = (1 - λ) ρ + λ \text{Tr}[ρ] \frac{I}{2^n}
|
|
179
|
+
|
|
180
|
+
with :math:`0 \le λ \le 4^n / (4^n - 1)`
|
|
181
|
+
|
|
182
|
+
where :math:`λ` is the depolarizing error param and :math:`n` is the
|
|
183
|
+
number of qubits.
|
|
184
|
+
|
|
185
|
+
* If :math:`λ = 0` this is the identity channel :math:`E(ρ) = ρ`
|
|
186
|
+
* If :math:`λ = 1` this is a completely depolarizing channel
|
|
187
|
+
:math:`E(ρ) = I / 2^n`
|
|
188
|
+
* If :math:`λ = 4^n / (4^n - 1)` this is a uniform Pauli
|
|
189
|
+
error channel: :math:`E(ρ) = \sum_j P_j ρ P_j / (4^n - 1)` for
|
|
190
|
+
all :math:`P_j != I`.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
param (double): depolarizing error parameter.
|
|
194
|
+
num_qubits (int): the number of qubits for the error channel.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
QuantumError: The quantum error object.
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
NoiseError: If noise parameters are invalid.
|
|
201
|
+
"""
|
|
202
|
+
if not isinstance(num_qubits, int) or num_qubits < 1:
|
|
203
|
+
raise NoiseError("num_qubits must be a positive integer.")
|
|
204
|
+
# Check that the depolarizing parameter gives a valid CPTP
|
|
205
|
+
num_terms = 4**num_qubits
|
|
206
|
+
max_param = num_terms / (num_terms - 1)
|
|
207
|
+
if param < 0 or param > max_param:
|
|
208
|
+
raise NoiseError("Depolarizing parameter must be in between 0 " "and {}.".format(max_param))
|
|
209
|
+
|
|
210
|
+
# Rescale completely depolarizing channel error probs
|
|
211
|
+
# with the identity component removed
|
|
212
|
+
prob_iden = 1 - param / max_param
|
|
213
|
+
prob_pauli = param / num_terms
|
|
214
|
+
probs = [prob_iden] + (num_terms - 1) * [prob_pauli]
|
|
215
|
+
|
|
216
|
+
# Generate pauli strings. The order doesn't matter as long
|
|
217
|
+
# as the all identity string is first.
|
|
218
|
+
paulis = [Pauli("".join(tup)) for tup in it.product(["I", "X", "Y", "Z"], repeat=num_qubits)]
|
|
219
|
+
return QuantumError(zip(paulis, probs))
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def reset_error(prob0, prob1=0):
|
|
223
|
+
r"""
|
|
224
|
+
Return a single qubit reset quantum error channel.
|
|
225
|
+
|
|
226
|
+
The error channel returned is given by the map
|
|
227
|
+
|
|
228
|
+
.. math::
|
|
229
|
+
|
|
230
|
+
E(ρ) = (1 - p_0 - p_1) ρ + \text{Tr}[ρ] \left(
|
|
231
|
+
p_0 |0 \rangle\langle 0|
|
|
232
|
+
+ p_1 |1 \rangle\langle 1| \right)
|
|
233
|
+
|
|
234
|
+
where the probability of no reset is given by :math:`1 - p_0 - p_1`.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
prob0 (double): reset probability to :math:`|0\rangle`.
|
|
238
|
+
prob1 (double): reset probability to :math:`|1\rangle`.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
QuantumError: the quantum error object.
|
|
242
|
+
|
|
243
|
+
Raises:
|
|
244
|
+
NoiseError: If noise parameters are invalid.
|
|
245
|
+
"""
|
|
246
|
+
if prob0 < 0 or prob1 < 0 or prob0 > 1 or prob1 > 1 or (prob0 + prob1) > 1:
|
|
247
|
+
raise NoiseError("Invalid reset probabilities.")
|
|
248
|
+
noise_ops = [
|
|
249
|
+
([(IGate(), [0])], 1 - prob0 - prob1),
|
|
250
|
+
([(Reset(), [0])], prob0),
|
|
251
|
+
([(Reset(), [0]), (XGate(), [0])], prob1),
|
|
252
|
+
]
|
|
253
|
+
return QuantumError(noise_ops)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
# pylint: disable=invalid-name
|
|
257
|
+
def thermal_relaxation_error(t1, t2, time, excited_state_population=0):
|
|
258
|
+
r"""
|
|
259
|
+
Return a single-qubit thermal relaxation quantum error channel.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
t1 (double): the :math:`T_1` relaxation time constant.
|
|
263
|
+
t2 (double): the :math:`T_2` relaxation time constant.
|
|
264
|
+
time (double): the gate time for relaxation error.
|
|
265
|
+
excited_state_population (double): the population of :math:`|1\rangle`
|
|
266
|
+
state at equilibrium (default: 0).
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
QuantumError: a quantum error object for a noise model.
|
|
270
|
+
|
|
271
|
+
Raises:
|
|
272
|
+
NoiseError: If noise parameters are invalid.
|
|
273
|
+
|
|
274
|
+
Additional information:
|
|
275
|
+
* For parameters to be valid :math:`T_1` and :math:`T_2` must
|
|
276
|
+
satisfy :math:`T_2 \le 2 T_1`.
|
|
277
|
+
|
|
278
|
+
* If :math:`T_2 \le T_1` the error can be expressed as a mixed
|
|
279
|
+
reset and unitary error channel.
|
|
280
|
+
|
|
281
|
+
* If :math:`T_1 < T_2 \le 2 T_1` the error must be expressed as a
|
|
282
|
+
general non-unitary Kraus error channel.
|
|
283
|
+
"""
|
|
284
|
+
if excited_state_population < 0:
|
|
285
|
+
raise NoiseError(
|
|
286
|
+
"Invalid excited state population " "({} < 0).".format(excited_state_population)
|
|
287
|
+
)
|
|
288
|
+
if excited_state_population > 1:
|
|
289
|
+
raise NoiseError(
|
|
290
|
+
"Invalid excited state population " "({} > 1).".format(excited_state_population)
|
|
291
|
+
)
|
|
292
|
+
if time < 0:
|
|
293
|
+
raise NoiseError("Invalid gate_time ({} < 0)".format(time))
|
|
294
|
+
if t1 <= 0:
|
|
295
|
+
raise NoiseError("Invalid T_1 relaxation time parameter: T_1 <= 0.")
|
|
296
|
+
if t2 <= 0:
|
|
297
|
+
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 <= 0.")
|
|
298
|
+
if t2 - 2 * t1 > 0:
|
|
299
|
+
raise NoiseError("Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.")
|
|
300
|
+
|
|
301
|
+
# T1 relaxation rate
|
|
302
|
+
if t1 == np.inf:
|
|
303
|
+
rate1 = 0
|
|
304
|
+
p_reset = 0
|
|
305
|
+
else:
|
|
306
|
+
rate1 = 1 / t1
|
|
307
|
+
p_reset = 1 - np.exp(-time * rate1)
|
|
308
|
+
# T2 dephasing rate
|
|
309
|
+
if t2 == np.inf:
|
|
310
|
+
rate2 = 0
|
|
311
|
+
exp_t2 = 1
|
|
312
|
+
else:
|
|
313
|
+
rate2 = 1 / t2
|
|
314
|
+
exp_t2 = np.exp(-time * rate2)
|
|
315
|
+
# Qubit state equilibrium probabilities
|
|
316
|
+
p0 = 1 - excited_state_population
|
|
317
|
+
p1 = excited_state_population
|
|
318
|
+
|
|
319
|
+
if t2 > t1:
|
|
320
|
+
# If T_2 > T_1 we must express this as a Kraus channel
|
|
321
|
+
# We start with the Choi-matrix representation:
|
|
322
|
+
chan = Choi(
|
|
323
|
+
np.array(
|
|
324
|
+
[
|
|
325
|
+
[1 - p1 * p_reset, 0, 0, exp_t2],
|
|
326
|
+
[0, p1 * p_reset, 0, 0],
|
|
327
|
+
[0, 0, p0 * p_reset, 0],
|
|
328
|
+
[exp_t2, 0, 0, 1 - p0 * p_reset],
|
|
329
|
+
]
|
|
330
|
+
)
|
|
331
|
+
)
|
|
332
|
+
return QuantumError(Kraus(chan))
|
|
333
|
+
else:
|
|
334
|
+
# If T_2 < T_1 we can express this channel as a probabilistic
|
|
335
|
+
# mixture of reset operations and unitary errors:
|
|
336
|
+
circuits = [
|
|
337
|
+
[(IGate(), [0])],
|
|
338
|
+
[(ZGate(), [0])],
|
|
339
|
+
[(Reset(), [0])],
|
|
340
|
+
[(Reset(), [0]), (XGate(), [0])],
|
|
341
|
+
]
|
|
342
|
+
# Probability
|
|
343
|
+
p_reset0 = p_reset * p0
|
|
344
|
+
p_reset1 = p_reset * p1
|
|
345
|
+
p_z = (1 - p_reset) * (1 - np.exp(-time * (rate2 - rate1))) / 2
|
|
346
|
+
p_identity = 1 - p_z - p_reset0 - p_reset1
|
|
347
|
+
probabilities = [p_identity, p_z, p_reset0, p_reset1]
|
|
348
|
+
return QuantumError(zip(circuits, probabilities))
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def phase_amplitude_damping_error(
|
|
352
|
+
param_amp, param_phase, excited_state_population=0, canonical_kraus=True
|
|
353
|
+
):
|
|
354
|
+
r"""
|
|
355
|
+
Return a single-qubit combined phase and amplitude damping quantum error channel.
|
|
356
|
+
|
|
357
|
+
The single-qubit combined phase and amplitude damping channel is
|
|
358
|
+
described by the following Kraus matrices:
|
|
359
|
+
|
|
360
|
+
.. code-block:: python
|
|
361
|
+
|
|
362
|
+
A0 = sqrt(1 - p1) * [[1, 0], [0, sqrt(1 - a - b)]]
|
|
363
|
+
A1 = sqrt(1 - p1) * [[0, sqrt(a)], [0, 0]]
|
|
364
|
+
A2 = sqrt(1 - p1) * [[0, 0], [0, sqrt(b)]]
|
|
365
|
+
B0 = sqrt(p1) * [[sqrt(1 - a - b), 0], [0, 1]]
|
|
366
|
+
B1 = sqrt(p1) * [[0, 0], [sqrt(a), 0]]
|
|
367
|
+
B2 = sqrt(p1) * [[sqrt(b), 0], [0, 0]]
|
|
368
|
+
|
|
369
|
+
where ``a = param_amp``, ``b = param_phase``, and
|
|
370
|
+
``p1 = excited_state_population``. The equilibrium state after infinitely
|
|
371
|
+
many applications of the channel is:
|
|
372
|
+
|
|
373
|
+
.. code-block:: python
|
|
374
|
+
|
|
375
|
+
rho_eq = [[1 - p1, 0]], [0, p1]]
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
param_amp (double): the amplitude damping error parameter.
|
|
379
|
+
param_phase (double): the phase damping error parameter.
|
|
380
|
+
excited_state_population (double): the population of :math:`|1\rangle`
|
|
381
|
+
state at equilibrium (default: 0).
|
|
382
|
+
canonical_kraus (bool): Convert input Kraus matrices into the
|
|
383
|
+
canonical Kraus representation (default: True)
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
QuantumError: a quantum error object for a noise model.
|
|
387
|
+
|
|
388
|
+
Raises:
|
|
389
|
+
NoiseError: If noise parameters are invalid.
|
|
390
|
+
"""
|
|
391
|
+
|
|
392
|
+
if param_amp < 0:
|
|
393
|
+
raise NoiseError("Invalid amplitude damping to |0> parameter " "({} < 0)".format(param_amp))
|
|
394
|
+
if param_phase < 0:
|
|
395
|
+
raise NoiseError("Invalid phase damping parameter " "({} < 0)".format(param_phase))
|
|
396
|
+
if param_phase + param_amp > 1:
|
|
397
|
+
raise NoiseError(
|
|
398
|
+
"Invalid amplitude and phase damping parameters "
|
|
399
|
+
"({} + {} > 1)".format(param_phase, param_amp)
|
|
400
|
+
)
|
|
401
|
+
if excited_state_population < 0:
|
|
402
|
+
raise NoiseError(
|
|
403
|
+
"Invalid excited state population " "({} < 0).".format(excited_state_population)
|
|
404
|
+
)
|
|
405
|
+
if excited_state_population > 1:
|
|
406
|
+
raise NoiseError(
|
|
407
|
+
"Invalid excited state population " "({} > 1).".format(excited_state_population)
|
|
408
|
+
)
|
|
409
|
+
c0 = np.sqrt(1 - excited_state_population)
|
|
410
|
+
c1 = np.sqrt(excited_state_population)
|
|
411
|
+
param = 1 - param_amp - param_phase
|
|
412
|
+
# Damping ops to 0 state
|
|
413
|
+
A0 = c0 * np.array([[1, 0], [0, np.sqrt(param)]], dtype=complex)
|
|
414
|
+
A1 = c0 * np.array([[0, np.sqrt(param_amp)], [0, 0]], dtype=complex)
|
|
415
|
+
A2 = c0 * np.array([[0, 0], [0, np.sqrt(param_phase)]], dtype=complex)
|
|
416
|
+
# Damping ops to 1 state
|
|
417
|
+
B0 = c1 * np.array([[np.sqrt(param), 0], [0, 1]], dtype=complex)
|
|
418
|
+
B1 = c1 * np.array([[0, 0], [np.sqrt(param_amp), 0]], dtype=complex)
|
|
419
|
+
B2 = c1 * np.array([[np.sqrt(param_phase), 0], [0, 0]], dtype=complex)
|
|
420
|
+
# Select non-zero ops
|
|
421
|
+
noise_ops = [a for a in [A0, A1, A2, B0, B1, B2] if np.linalg.norm(a) > 1e-10]
|
|
422
|
+
return kraus_error(noise_ops, canonical_kraus=canonical_kraus)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def amplitude_damping_error(param_amp, excited_state_population=0, canonical_kraus=True):
|
|
426
|
+
r"""
|
|
427
|
+
Return a single-qubit generalized amplitude damping quantum error channel.
|
|
428
|
+
|
|
429
|
+
The single-qubit amplitude damping channel is described by the
|
|
430
|
+
following Kraus matrices:
|
|
431
|
+
|
|
432
|
+
.. code-block:: python
|
|
433
|
+
|
|
434
|
+
A0 = sqrt(1 - p1) * [[1, 0], [0, sqrt(1 - a)]]
|
|
435
|
+
A1 = sqrt(1 - p1) * [[0, sqrt(a)], [0, 0]]
|
|
436
|
+
B0 = sqrt(p1) * [[sqrt(1 - a), 0], [0, 1]]
|
|
437
|
+
B1 = sqrt(p1) * [[0, 0], [sqrt(a), 0]]
|
|
438
|
+
|
|
439
|
+
where ``a = param_amp``, ``p1 = excited_state_population``.
|
|
440
|
+
The equilibrium state after infinitely many applications of the
|
|
441
|
+
channel is:
|
|
442
|
+
|
|
443
|
+
.. code-block:: python
|
|
444
|
+
|
|
445
|
+
rho_eq = [[1 - p1, 0]], [0, p1]]
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
param_amp (double): the amplitude damping parameter.
|
|
449
|
+
excited_state_population (double): the population of :math:`|0\rangle`
|
|
450
|
+
state at equilibrium (default: 0).
|
|
451
|
+
canonical_kraus (bool): Convert input Kraus matrices into the
|
|
452
|
+
canonical Kraus representation (default: True)
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
QuantumError: a quantum error object for a noise model.
|
|
456
|
+
"""
|
|
457
|
+
return phase_amplitude_damping_error(
|
|
458
|
+
param_amp,
|
|
459
|
+
0,
|
|
460
|
+
excited_state_population=excited_state_population,
|
|
461
|
+
canonical_kraus=canonical_kraus,
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def phase_damping_error(param_phase, canonical_kraus=True):
|
|
466
|
+
r"""
|
|
467
|
+
Return a single-qubit generalized phase damping quantum error channel.
|
|
468
|
+
|
|
469
|
+
The single-qubit phase damping channel is described by the
|
|
470
|
+
following Kraus matrices:
|
|
471
|
+
|
|
472
|
+
.. code-block:: python
|
|
473
|
+
|
|
474
|
+
A0 = [[1, 0], [0, sqrt(1 - b)]]
|
|
475
|
+
A2 = [[0, 0], [0, sqrt(b)]]
|
|
476
|
+
|
|
477
|
+
where ``b = param_phase``.
|
|
478
|
+
The equilibrium state after infinitely many applications of the
|
|
479
|
+
channel is:
|
|
480
|
+
|
|
481
|
+
.. code-block:: python
|
|
482
|
+
|
|
483
|
+
rho_eq = [[rho_init[0, 0], 0]], [0, rho_init[1, 1]]]
|
|
484
|
+
|
|
485
|
+
where ``rho_init`` is the input state ρ.
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
param_phase (double): the phase damping parameter.
|
|
489
|
+
canonical_kraus (bool): Convert input Kraus matrices into the
|
|
490
|
+
canonical Kraus representation (default: True)
|
|
491
|
+
|
|
492
|
+
Returns:
|
|
493
|
+
QuantumError: a quantum error object for a noise model.
|
|
494
|
+
"""
|
|
495
|
+
|
|
496
|
+
return phase_amplitude_damping_error(
|
|
497
|
+
0, param_phase, excited_state_population=0, canonical_kraus=canonical_kraus
|
|
498
|
+
)
|