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.
Files changed (83) hide show
  1. qiskit_aer/VERSION.txt +1 -0
  2. qiskit_aer/__init__.py +89 -0
  3. qiskit_aer/aererror.py +30 -0
  4. qiskit_aer/aerprovider.py +119 -0
  5. qiskit_aer/backends/__init__.py +20 -0
  6. qiskit_aer/backends/aer_compiler.py +1085 -0
  7. qiskit_aer/backends/aer_simulator.py +1025 -0
  8. qiskit_aer/backends/aerbackend.py +679 -0
  9. qiskit_aer/backends/backend_utils.py +567 -0
  10. qiskit_aer/backends/backendconfiguration.py +395 -0
  11. qiskit_aer/backends/backendproperties.py +590 -0
  12. qiskit_aer/backends/compatibility.py +287 -0
  13. qiskit_aer/backends/controller_wrappers.cp314-win_amd64.pyd +0 -0
  14. qiskit_aer/backends/libopenblas.dll +0 -0
  15. qiskit_aer/backends/name_mapping.py +306 -0
  16. qiskit_aer/backends/qasm_simulator.py +925 -0
  17. qiskit_aer/backends/statevector_simulator.py +330 -0
  18. qiskit_aer/backends/unitary_simulator.py +316 -0
  19. qiskit_aer/jobs/__init__.py +35 -0
  20. qiskit_aer/jobs/aerjob.py +143 -0
  21. qiskit_aer/jobs/utils.py +66 -0
  22. qiskit_aer/library/__init__.py +204 -0
  23. qiskit_aer/library/control_flow_instructions/__init__.py +16 -0
  24. qiskit_aer/library/control_flow_instructions/jump.py +47 -0
  25. qiskit_aer/library/control_flow_instructions/mark.py +30 -0
  26. qiskit_aer/library/control_flow_instructions/store.py +29 -0
  27. qiskit_aer/library/default_qubits.py +44 -0
  28. qiskit_aer/library/instructions_table.csv +21 -0
  29. qiskit_aer/library/save_instructions/__init__.py +44 -0
  30. qiskit_aer/library/save_instructions/save_amplitudes.py +168 -0
  31. qiskit_aer/library/save_instructions/save_clifford.py +63 -0
  32. qiskit_aer/library/save_instructions/save_data.py +129 -0
  33. qiskit_aer/library/save_instructions/save_density_matrix.py +91 -0
  34. qiskit_aer/library/save_instructions/save_expectation_value.py +257 -0
  35. qiskit_aer/library/save_instructions/save_matrix_product_state.py +71 -0
  36. qiskit_aer/library/save_instructions/save_probabilities.py +156 -0
  37. qiskit_aer/library/save_instructions/save_stabilizer.py +70 -0
  38. qiskit_aer/library/save_instructions/save_state.py +79 -0
  39. qiskit_aer/library/save_instructions/save_statevector.py +120 -0
  40. qiskit_aer/library/save_instructions/save_superop.py +62 -0
  41. qiskit_aer/library/save_instructions/save_unitary.py +63 -0
  42. qiskit_aer/library/set_instructions/__init__.py +19 -0
  43. qiskit_aer/library/set_instructions/set_density_matrix.py +78 -0
  44. qiskit_aer/library/set_instructions/set_matrix_product_state.py +83 -0
  45. qiskit_aer/library/set_instructions/set_stabilizer.py +77 -0
  46. qiskit_aer/library/set_instructions/set_statevector.py +78 -0
  47. qiskit_aer/library/set_instructions/set_superop.py +78 -0
  48. qiskit_aer/library/set_instructions/set_unitary.py +78 -0
  49. qiskit_aer/noise/__init__.py +265 -0
  50. qiskit_aer/noise/device/__init__.py +25 -0
  51. qiskit_aer/noise/device/models.py +397 -0
  52. qiskit_aer/noise/device/parameters.py +202 -0
  53. qiskit_aer/noise/errors/__init__.py +30 -0
  54. qiskit_aer/noise/errors/base_quantum_error.py +119 -0
  55. qiskit_aer/noise/errors/pauli_error.py +283 -0
  56. qiskit_aer/noise/errors/pauli_lindblad_error.py +363 -0
  57. qiskit_aer/noise/errors/quantum_error.py +451 -0
  58. qiskit_aer/noise/errors/readout_error.py +355 -0
  59. qiskit_aer/noise/errors/standard_errors.py +498 -0
  60. qiskit_aer/noise/noise_model.py +1231 -0
  61. qiskit_aer/noise/noiseerror.py +30 -0
  62. qiskit_aer/noise/passes/__init__.py +18 -0
  63. qiskit_aer/noise/passes/local_noise_pass.py +160 -0
  64. qiskit_aer/noise/passes/relaxation_noise_pass.py +137 -0
  65. qiskit_aer/primitives/__init__.py +44 -0
  66. qiskit_aer/primitives/estimator.py +751 -0
  67. qiskit_aer/primitives/estimator_v2.py +159 -0
  68. qiskit_aer/primitives/sampler.py +361 -0
  69. qiskit_aer/primitives/sampler_v2.py +256 -0
  70. qiskit_aer/quantum_info/__init__.py +32 -0
  71. qiskit_aer/quantum_info/states/__init__.py +16 -0
  72. qiskit_aer/quantum_info/states/aer_densitymatrix.py +313 -0
  73. qiskit_aer/quantum_info/states/aer_state.py +525 -0
  74. qiskit_aer/quantum_info/states/aer_statevector.py +302 -0
  75. qiskit_aer/utils/__init__.py +44 -0
  76. qiskit_aer/utils/noise_model_inserter.py +66 -0
  77. qiskit_aer/utils/noise_transformation.py +431 -0
  78. qiskit_aer/version.py +86 -0
  79. qiskit_aer-0.17.2.dist-info/METADATA +209 -0
  80. qiskit_aer-0.17.2.dist-info/RECORD +83 -0
  81. qiskit_aer-0.17.2.dist-info/WHEEL +5 -0
  82. qiskit_aer-0.17.2.dist-info/licenses/LICENSE.txt +203 -0
  83. 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
+ )