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,397 @@
|
|
|
1
|
+
# This code is part of Qiskit.
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright IBM 2018, 2019.
|
|
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
|
+
# pylint: disable=invalid-name
|
|
14
|
+
"""
|
|
15
|
+
Simplified noise models for devices backends.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from warnings import warn
|
|
20
|
+
|
|
21
|
+
from numpy import inf, exp, allclose
|
|
22
|
+
|
|
23
|
+
import qiskit.quantum_info as qi
|
|
24
|
+
from qiskit.circuit import Gate, Measure
|
|
25
|
+
from .parameters import _NANOSECOND_UNITS
|
|
26
|
+
from .parameters import gate_param_values
|
|
27
|
+
from .parameters import readout_error_values
|
|
28
|
+
from .parameters import thermal_relaxation_values
|
|
29
|
+
from ..errors.readout_error import ReadoutError
|
|
30
|
+
from ..errors.standard_errors import depolarizing_error
|
|
31
|
+
from ..errors.standard_errors import thermal_relaxation_error
|
|
32
|
+
from ..noiseerror import NoiseError
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def basic_device_readout_errors(properties=None, target=None):
|
|
38
|
+
"""
|
|
39
|
+
Return readout error parameters from either of device Target or BackendProperties.
|
|
40
|
+
|
|
41
|
+
If ``target`` is supplied, ``properties`` will be ignored.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
properties (BackendProperties): device backend properties
|
|
45
|
+
target (Target): device backend target
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
list: A list of pairs ``(qubits, ReadoutError)`` for qubits with
|
|
49
|
+
non-zero readout error values.
|
|
50
|
+
|
|
51
|
+
Raises:
|
|
52
|
+
NoiseError: if neither properties nor target is supplied.
|
|
53
|
+
"""
|
|
54
|
+
errors = []
|
|
55
|
+
if target is None:
|
|
56
|
+
if properties is None:
|
|
57
|
+
raise NoiseError("Either properties or target must be supplied.")
|
|
58
|
+
# create from BackendProperties
|
|
59
|
+
for qubit, value in enumerate(readout_error_values(properties)):
|
|
60
|
+
if value is not None and not allclose(value, [0, 0]):
|
|
61
|
+
probabilities = [[1 - value[0], value[0]], [value[1], 1 - value[1]]]
|
|
62
|
+
errors.append(([qubit], ReadoutError(probabilities)))
|
|
63
|
+
else:
|
|
64
|
+
# create from Target
|
|
65
|
+
for q in range(target.num_qubits):
|
|
66
|
+
meas_props = target.get("measure", None)
|
|
67
|
+
if meas_props is None:
|
|
68
|
+
continue
|
|
69
|
+
prop = meas_props.get((q,), None)
|
|
70
|
+
if prop is None:
|
|
71
|
+
continue
|
|
72
|
+
if hasattr(prop, "prob_meas1_prep0") and hasattr(prop, "prob_meas0_prep1"):
|
|
73
|
+
p0m1, p1m0 = prop.prob_meas1_prep0, prop.prob_meas0_prep1
|
|
74
|
+
else:
|
|
75
|
+
p0m1, p1m0 = prop.error, prop.error
|
|
76
|
+
probabilities = [[1 - p0m1, p0m1], [p1m0, 1 - p1m0]]
|
|
77
|
+
errors.append(([q], ReadoutError(probabilities)))
|
|
78
|
+
|
|
79
|
+
return errors
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def basic_device_gate_errors(
|
|
83
|
+
properties=None,
|
|
84
|
+
gate_error=True,
|
|
85
|
+
thermal_relaxation=True,
|
|
86
|
+
gate_lengths=None,
|
|
87
|
+
gate_length_units="ns",
|
|
88
|
+
temperature=0,
|
|
89
|
+
warnings=None,
|
|
90
|
+
target=None,
|
|
91
|
+
):
|
|
92
|
+
"""
|
|
93
|
+
Return QuantumErrors derived from either of a devices BackendProperties or Target.
|
|
94
|
+
|
|
95
|
+
If non-default values are used gate_lengths should be a list
|
|
96
|
+
of tuples ``(name, qubits, value)`` where ``name`` is the gate
|
|
97
|
+
name string, ``qubits`` is either a list of qubits or ``None``
|
|
98
|
+
to apply gate time to this gate one any set of qubits,
|
|
99
|
+
and ``value`` is the gate time in nanoseconds.
|
|
100
|
+
|
|
101
|
+
The resulting errors may contains two types of errors: gate errors and relaxation errors.
|
|
102
|
+
The gate errors are generated only for ``Gate`` objects while the relaxation errors are
|
|
103
|
+
generated for all ``Instruction`` objects. Exceptionally, no ``QuantumError`` s are
|
|
104
|
+
generated for ``Measure`` since ``ReadoutError`` s are generated separately instead.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
properties (BackendProperties): device backend properties.
|
|
108
|
+
gate_error (bool): Include depolarizing gate errors (Default: True).
|
|
109
|
+
thermal_relaxation (Bool): Include thermal relaxation errors (Default: True).
|
|
110
|
+
If no ``t1`` and ``t2`` values are provided (i.e. None) in ``target`` for a qubit,
|
|
111
|
+
an identity ``QuantumError` (i.e. effectively no thermal relaxation error)
|
|
112
|
+
will be added to the qubit even if this flag is set to True.
|
|
113
|
+
If no ``frequency`` is not defined (i.e. None) in ``target`` for a qubit,
|
|
114
|
+
no excitation is considered in the thermal relaxation error on the qubit
|
|
115
|
+
even with non-zero ``temperature``.
|
|
116
|
+
gate_lengths (list): Override device gate times with custom
|
|
117
|
+
values. If None use gate times from
|
|
118
|
+
backend properties. (Default: None).
|
|
119
|
+
gate_length_units (str): Time units for gate length values in ``gate_lengths``.
|
|
120
|
+
Can be 'ns', 'ms', 'us', or 's' (Default: 'ns').
|
|
121
|
+
temperature (double): qubit temperature in milli-Kelvin (mK)
|
|
122
|
+
(Default: 0).
|
|
123
|
+
warnings (bool): DEPRECATED, Display warnings (Default: None).
|
|
124
|
+
target (Target): device backend target (Default: None). When this is supplied,
|
|
125
|
+
several options are disabled:
|
|
126
|
+
``properties``, ``gate_lengths`` and ``gate_length_units`` are not used
|
|
127
|
+
during the construction of gate errors.
|
|
128
|
+
Default values are always used for ``warnings``.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
list: A list of tuples ``(label, qubits, QuantumError)``, for gates
|
|
132
|
+
with non-zero quantum error terms, where `label` is the label of the
|
|
133
|
+
noisy gate, `qubits` is the list of qubits for the gate.
|
|
134
|
+
|
|
135
|
+
Raises:
|
|
136
|
+
NoiseError: If invalid arguments are supplied.
|
|
137
|
+
"""
|
|
138
|
+
if properties is None and target is None:
|
|
139
|
+
raise NoiseError("Either properties or target must be supplied.")
|
|
140
|
+
|
|
141
|
+
if warnings is not None:
|
|
142
|
+
warn(
|
|
143
|
+
'"warnings" argument has been deprecated as of qiskit-aer 0.12.0 '
|
|
144
|
+
"and will be removed no earlier than 3 months from that release date. "
|
|
145
|
+
"Use the warnings filter in Python standard library instead.",
|
|
146
|
+
DeprecationWarning,
|
|
147
|
+
stacklevel=2,
|
|
148
|
+
)
|
|
149
|
+
else:
|
|
150
|
+
warnings = True
|
|
151
|
+
|
|
152
|
+
if target is not None:
|
|
153
|
+
if not warnings:
|
|
154
|
+
warn(
|
|
155
|
+
"When `target` is supplied, `warnings` are ignored,"
|
|
156
|
+
" and they are always set to true.",
|
|
157
|
+
UserWarning,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if gate_lengths:
|
|
161
|
+
raise NoiseError(
|
|
162
|
+
"When `target` is supplied, `gate_lengths` option is not allowed."
|
|
163
|
+
"Use `duration` property in target's InstructionProperties instead."
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return _basic_device_target_gate_errors(
|
|
167
|
+
target=target,
|
|
168
|
+
gate_error=gate_error,
|
|
169
|
+
thermal_relaxation=thermal_relaxation,
|
|
170
|
+
temperature=temperature,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Generate custom gate time dict
|
|
174
|
+
# Units used in the following computation: ns (time), Hz (frequency), mK (temperature).
|
|
175
|
+
custom_times = {}
|
|
176
|
+
relax_params = []
|
|
177
|
+
if thermal_relaxation:
|
|
178
|
+
# If including thermal relaxation errors load
|
|
179
|
+
# T1 [ns], T2 [ns], and frequency [GHz] values from properties
|
|
180
|
+
relax_params = thermal_relaxation_values(properties)
|
|
181
|
+
# Unit conversion: GHz -> Hz
|
|
182
|
+
relax_params = [(t1, t2, freq * 1e9) for t1, t2, freq in relax_params]
|
|
183
|
+
# If we are specifying custom gate times include
|
|
184
|
+
# them in the custom times dict
|
|
185
|
+
if gate_lengths:
|
|
186
|
+
for name, qubits, value in gate_lengths:
|
|
187
|
+
# Convert all gate lengths to nanosecond units
|
|
188
|
+
time = value * _NANOSECOND_UNITS[gate_length_units]
|
|
189
|
+
if name in custom_times:
|
|
190
|
+
custom_times[name].append((qubits, time))
|
|
191
|
+
else:
|
|
192
|
+
custom_times[name] = [(qubits, time)]
|
|
193
|
+
# Get the device gate parameters from properties
|
|
194
|
+
device_gate_params = gate_param_values(properties)
|
|
195
|
+
|
|
196
|
+
# Construct quantum errors
|
|
197
|
+
errors = []
|
|
198
|
+
for name, qubits, gate_length, error_param in device_gate_params:
|
|
199
|
+
# Initilize empty errors
|
|
200
|
+
depol_error = None
|
|
201
|
+
relax_error = None
|
|
202
|
+
# Check for custom gate time
|
|
203
|
+
relax_time = gate_length
|
|
204
|
+
# Override with custom value
|
|
205
|
+
if name in custom_times:
|
|
206
|
+
filtered = [val for q, val in custom_times[name] if q is None or q == qubits]
|
|
207
|
+
if filtered:
|
|
208
|
+
# get first value
|
|
209
|
+
relax_time = filtered[0]
|
|
210
|
+
# Get relaxation error
|
|
211
|
+
if thermal_relaxation:
|
|
212
|
+
relax_error = _device_thermal_relaxation_error(
|
|
213
|
+
qubits, relax_time, relax_params, temperature
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Get depolarizing error channel
|
|
217
|
+
if gate_error:
|
|
218
|
+
depol_error = _device_depolarizing_error(qubits, error_param, relax_error)
|
|
219
|
+
|
|
220
|
+
# Combine errors
|
|
221
|
+
combined_error = _combine_depol_and_relax_error(depol_error, relax_error)
|
|
222
|
+
if combined_error:
|
|
223
|
+
errors.append((name, qubits, combined_error))
|
|
224
|
+
|
|
225
|
+
return errors
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _combine_depol_and_relax_error(depol_error, relax_error):
|
|
229
|
+
if depol_error and relax_error:
|
|
230
|
+
return depol_error.compose(relax_error)
|
|
231
|
+
if depol_error:
|
|
232
|
+
return depol_error
|
|
233
|
+
if relax_error:
|
|
234
|
+
return relax_error
|
|
235
|
+
return None
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _basic_device_target_gate_errors(
|
|
239
|
+
target, gate_error=True, thermal_relaxation=True, temperature=0
|
|
240
|
+
):
|
|
241
|
+
"""Return QuantumErrors derived from a devices Target.
|
|
242
|
+
Note that, in the resulting error list, non-Gate instructions (e.g. Reset) will have
|
|
243
|
+
no gate errors while they may have thermal relaxation errors. Exceptionally,
|
|
244
|
+
Measure instruction will have no errors, neither gate errors nor relaxation errors.
|
|
245
|
+
|
|
246
|
+
Note: Units in use: Time [s], Frequency [Hz], Temperature [mK]
|
|
247
|
+
"""
|
|
248
|
+
errors = []
|
|
249
|
+
for op_name, inst_prop_dic in target.items():
|
|
250
|
+
operation = target.operation_from_name(op_name)
|
|
251
|
+
if isinstance(operation, Measure):
|
|
252
|
+
continue
|
|
253
|
+
if inst_prop_dic is None: # ideal simulator
|
|
254
|
+
continue
|
|
255
|
+
for qubits, inst_prop in inst_prop_dic.items():
|
|
256
|
+
if inst_prop is None:
|
|
257
|
+
continue
|
|
258
|
+
depol_error = None
|
|
259
|
+
relax_error = None
|
|
260
|
+
# Get relaxation error
|
|
261
|
+
if thermal_relaxation and inst_prop.duration:
|
|
262
|
+
relax_params = {
|
|
263
|
+
q: (
|
|
264
|
+
target.qubit_properties[q].t1,
|
|
265
|
+
target.qubit_properties[q].t2,
|
|
266
|
+
target.qubit_properties[q].frequency,
|
|
267
|
+
)
|
|
268
|
+
for q in qubits
|
|
269
|
+
}
|
|
270
|
+
relax_error = _device_thermal_relaxation_error(
|
|
271
|
+
qubits=qubits,
|
|
272
|
+
gate_time=inst_prop.duration,
|
|
273
|
+
relax_params=relax_params,
|
|
274
|
+
temperature=temperature,
|
|
275
|
+
)
|
|
276
|
+
# Get depolarizing error
|
|
277
|
+
if gate_error and inst_prop.error and isinstance(operation, Gate):
|
|
278
|
+
depol_error = _device_depolarizing_error(
|
|
279
|
+
qubits=qubits,
|
|
280
|
+
error_param=inst_prop.error,
|
|
281
|
+
relax_error=relax_error,
|
|
282
|
+
)
|
|
283
|
+
# Combine errors
|
|
284
|
+
combined_error = _combine_depol_and_relax_error(depol_error, relax_error)
|
|
285
|
+
if combined_error:
|
|
286
|
+
errors.append((op_name, qubits, combined_error))
|
|
287
|
+
|
|
288
|
+
return errors
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _device_depolarizing_error(qubits, error_param, relax_error=None):
|
|
292
|
+
"""Construct a depolarizing_error for device.
|
|
293
|
+
If un-physical parameters are supplied, they are truncated to the theoretical bound values."""
|
|
294
|
+
|
|
295
|
+
# We now deduce the depolarizing channel error parameter in the
|
|
296
|
+
# presence of T1/T2 thermal relaxation. We assume the gate error
|
|
297
|
+
# parameter is given by e = 1 - F where F is the average gate fidelity,
|
|
298
|
+
# and that this average gate fidelity is for the composition
|
|
299
|
+
# of a T1/T2 thermal relaxation channel and a depolarizing channel.
|
|
300
|
+
|
|
301
|
+
# For the n-qubit depolarizing channel E_dep = (1-p) * I + p * D, where
|
|
302
|
+
# I is the identity channel and D is the completely depolarizing
|
|
303
|
+
# channel. To compose the errors we solve for the equation
|
|
304
|
+
# F = F(E_dep * E_relax)
|
|
305
|
+
# = (1 - p) * F(I * E_relax) + p * F(D * E_relax)
|
|
306
|
+
# = (1 - p) * F(E_relax) + p * F(D)
|
|
307
|
+
# = F(E_relax) - p * (dim * F(E_relax) - 1) / dim
|
|
308
|
+
|
|
309
|
+
# Hence we have that the depolarizing error probability
|
|
310
|
+
# for the composed depolarization channel is
|
|
311
|
+
# p = dim * (F(E_relax) - F) / (dim * F(E_relax) - 1)
|
|
312
|
+
if relax_error is not None:
|
|
313
|
+
relax_fid = qi.average_gate_fidelity(relax_error)
|
|
314
|
+
relax_infid = 1 - relax_fid
|
|
315
|
+
else:
|
|
316
|
+
relax_fid = 1
|
|
317
|
+
relax_infid = 0
|
|
318
|
+
if error_param is not None and error_param > relax_infid:
|
|
319
|
+
num_qubits = len(qubits)
|
|
320
|
+
dim = 2**num_qubits
|
|
321
|
+
error_max = dim / (dim + 1)
|
|
322
|
+
# Check if reported error param is un-physical
|
|
323
|
+
# The minimum average gate fidelity is F_min = 1 / (dim + 1)
|
|
324
|
+
# So the maximum gate error is 1 - F_min = dim / (dim + 1)
|
|
325
|
+
error_param = min(error_param, error_max)
|
|
326
|
+
# Model gate error entirely as depolarizing error
|
|
327
|
+
num_qubits = len(qubits)
|
|
328
|
+
dim = 2**num_qubits
|
|
329
|
+
depol_param = dim * (error_param - relax_infid) / (dim * relax_fid - 1)
|
|
330
|
+
max_param = 4**num_qubits / (4**num_qubits - 1)
|
|
331
|
+
if depol_param > max_param:
|
|
332
|
+
depol_param = min(depol_param, max_param)
|
|
333
|
+
return depolarizing_error(depol_param, num_qubits)
|
|
334
|
+
return None
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _device_thermal_relaxation_error(qubits, gate_time, relax_params, temperature):
|
|
338
|
+
"""Construct a thermal_relaxation_error for device.
|
|
339
|
+
|
|
340
|
+
Expected units: frequency in relax_params [Hz], temperature [mK].
|
|
341
|
+
Note that gate_time and T1/T2 in relax_params must be in the same time unit.
|
|
342
|
+
"""
|
|
343
|
+
# Check trivial case
|
|
344
|
+
if gate_time is None or gate_time == 0:
|
|
345
|
+
return None
|
|
346
|
+
|
|
347
|
+
# Construct a tensor product of single qubit relaxation errors
|
|
348
|
+
# for any multi qubit gates
|
|
349
|
+
first = True
|
|
350
|
+
error = None
|
|
351
|
+
for qubit in qubits:
|
|
352
|
+
t1, t2, freq = relax_params[qubit]
|
|
353
|
+
t2 = _truncate_t2_value(t1, t2)
|
|
354
|
+
if t1 is None:
|
|
355
|
+
t1 = inf
|
|
356
|
+
if t2 is None:
|
|
357
|
+
t2 = inf
|
|
358
|
+
population = _excited_population(freq, temperature)
|
|
359
|
+
if first:
|
|
360
|
+
error = thermal_relaxation_error(t1, t2, gate_time, population)
|
|
361
|
+
first = False
|
|
362
|
+
else:
|
|
363
|
+
single = thermal_relaxation_error(t1, t2, gate_time, population)
|
|
364
|
+
error = error.expand(single)
|
|
365
|
+
return error
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _truncate_t2_value(t1, t2):
|
|
369
|
+
"""Return t2 value truncated to 2 * t1 (for t2 > 2 * t1)"""
|
|
370
|
+
if t1 is None:
|
|
371
|
+
return t2
|
|
372
|
+
elif t2 is None:
|
|
373
|
+
return 2 * t1
|
|
374
|
+
return min(t2, 2 * t1)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _excited_population(freq, temperature):
|
|
378
|
+
"""Return excited state population from freq [Hz] and temperature [mK]."""
|
|
379
|
+
if freq is None or temperature is None:
|
|
380
|
+
return 0
|
|
381
|
+
population = 0
|
|
382
|
+
if freq != inf and temperature != 0:
|
|
383
|
+
# Compute the excited state population from qubit frequency and temperature
|
|
384
|
+
# based on Maxwell-Boltzmann distribution
|
|
385
|
+
# considering only qubit states (|0> and |1>), i.e. truncating higher energy states.
|
|
386
|
+
# Boltzman constant kB = 8.617333262e-5 (eV/K)
|
|
387
|
+
# Planck constant h = 4.135667696e-15 (eV.s)
|
|
388
|
+
# qubit temperature temperatue = T (mK)
|
|
389
|
+
# qubit frequency frequency = f (Hz)
|
|
390
|
+
# excited state population = 1/(1+exp((h*f)/(kb*T*1e-3)))
|
|
391
|
+
# See e.g. Phys. Rev. Lett. 114, 240501 (2015).
|
|
392
|
+
exp_param = exp((47.99243 * 1e-9 * freq) / abs(temperature))
|
|
393
|
+
population = 1 / (1 + exp_param)
|
|
394
|
+
if temperature < 0:
|
|
395
|
+
# negative temperate implies |1> is thermal ground
|
|
396
|
+
population = 1 - population
|
|
397
|
+
return population
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# This code is part of Qiskit.
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright IBM 2018, 2019.
|
|
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
|
+
"""
|
|
14
|
+
Functions to extract device error parameters from backend properties.
|
|
15
|
+
|
|
16
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from numpy import inf
|
|
20
|
+
|
|
21
|
+
# Time and frequency unit conversions
|
|
22
|
+
_NANOSECOND_UNITS = {"s": 1e9, "ms": 1e6, "µs": 1e3, "us": 1e3, "ns": 1}
|
|
23
|
+
_GHZ_UNITS = {"Hz": 1e-9, "KHz": 1e-6, "MHz": 1e-3, "GHz": 1, "THz": 1e3}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def gate_param_values(properties):
|
|
27
|
+
"""
|
|
28
|
+
Return parameter error values from a devices BackendProperties.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
properties (BackendProperties): device backend properties
|
|
32
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
list: A list of tuples ``(name, qubits, time, error)``. If gate
|
|
36
|
+
error or gate_length information is not available ``None``
|
|
37
|
+
will be returned for value.
|
|
38
|
+
"""
|
|
39
|
+
values = []
|
|
40
|
+
for gate in properties.gates:
|
|
41
|
+
name = gate.gate
|
|
42
|
+
qubits = gate.qubits
|
|
43
|
+
# Check for gate time information
|
|
44
|
+
gate_length = None # default value
|
|
45
|
+
time_param = _check_for_item(gate.parameters, "gate_length")
|
|
46
|
+
if hasattr(time_param, "value"):
|
|
47
|
+
gate_length = time_param.value
|
|
48
|
+
if hasattr(time_param, "unit"):
|
|
49
|
+
# Convert gate time to ns
|
|
50
|
+
gate_length *= _NANOSECOND_UNITS.get(time_param.unit, 1)
|
|
51
|
+
# Check for gate error information
|
|
52
|
+
gate_error = None # default value
|
|
53
|
+
error_param = _check_for_item(gate.parameters, "gate_error")
|
|
54
|
+
if hasattr(error_param, "value"):
|
|
55
|
+
gate_error = error_param.value
|
|
56
|
+
values.append((name, qubits, gate_length, gate_error))
|
|
57
|
+
|
|
58
|
+
return values
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def gate_error_values(properties):
|
|
62
|
+
"""
|
|
63
|
+
Return gate error values from a devices BackendProperties.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
properties (BackendProperties): device backend properties
|
|
67
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
list: A list of tuples ``(name, qubits, value)``. If gate
|
|
71
|
+
error information is not available ``None`` will be returned
|
|
72
|
+
for value.
|
|
73
|
+
"""
|
|
74
|
+
values = []
|
|
75
|
+
for gate in properties.gates:
|
|
76
|
+
name = gate.gate
|
|
77
|
+
qubits = gate.qubits
|
|
78
|
+
value = None # default value
|
|
79
|
+
params = _check_for_item(gate.parameters, "gate_error")
|
|
80
|
+
if hasattr(params, "value"):
|
|
81
|
+
value = params.value
|
|
82
|
+
values.append((name, qubits, value))
|
|
83
|
+
return values
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def gate_length_values(properties):
|
|
87
|
+
"""
|
|
88
|
+
Return gate length values from a devices BackendProperties.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
properties (BackendProperties): device backend properties
|
|
92
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
list: A list of tuples ``(name, qubits, value)``. If gate length
|
|
96
|
+
information is not available ``None`` will be returned for value.
|
|
97
|
+
|
|
98
|
+
Additional Information:
|
|
99
|
+
Gate length values are returned in nanosecond (ns) units.
|
|
100
|
+
"""
|
|
101
|
+
values = []
|
|
102
|
+
for gate in properties.gates:
|
|
103
|
+
name = gate.gate
|
|
104
|
+
qubits = gate.qubits
|
|
105
|
+
value = None # default value
|
|
106
|
+
params = _check_for_item(gate.parameters, "gate_length")
|
|
107
|
+
if hasattr(params, "value"):
|
|
108
|
+
value = params.value
|
|
109
|
+
if hasattr(params, "unit"):
|
|
110
|
+
# Convert gate time to ns
|
|
111
|
+
value *= _NANOSECOND_UNITS.get(params.unit, 1)
|
|
112
|
+
values.append((name, qubits, value))
|
|
113
|
+
return values
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def readout_error_values(properties):
|
|
117
|
+
"""
|
|
118
|
+
Return readout error values from a devices BackendProperties.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
properties (BackendProperties): device backend properties
|
|
122
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
list: A list of readout error values for qubits. If readout
|
|
126
|
+
error information is not available None will be returned
|
|
127
|
+
for value.
|
|
128
|
+
"""
|
|
129
|
+
values = []
|
|
130
|
+
for qubit_props in properties.qubits:
|
|
131
|
+
value = None # default value
|
|
132
|
+
|
|
133
|
+
params_roerror = _check_for_item(qubit_props, "readout_error")
|
|
134
|
+
params_m1p0 = _check_for_item(qubit_props, "prob_meas1_prep0")
|
|
135
|
+
params_m0p1 = _check_for_item(qubit_props, "prob_meas0_prep1")
|
|
136
|
+
|
|
137
|
+
if hasattr(params_m1p0, "value") and hasattr(params_m0p1, "value"):
|
|
138
|
+
value = [params_m1p0.value, params_m0p1.value]
|
|
139
|
+
elif hasattr(params_roerror, "value"):
|
|
140
|
+
value = [params_roerror.value, params_roerror.value]
|
|
141
|
+
values.append(value)
|
|
142
|
+
return values
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def thermal_relaxation_values(properties):
|
|
146
|
+
"""
|
|
147
|
+
Return T1, T2 and frequency values from a devices BackendProperties.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
properties (BackendProperties): device backend properties
|
|
151
|
+
We assume the structure of the class `BackendProperties` in `qiskit-ibm-runtime`
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
list: A list of tuples ``(T1, T2, freq)`` for each qubit in the device.
|
|
155
|
+
If :math:`T_1`, :math:`T_2`, or frequency cannot be found for qubit a
|
|
156
|
+
value of ``Numpy.inf`` will be used.
|
|
157
|
+
|
|
158
|
+
Additional Information:
|
|
159
|
+
:math:`T_1` and :math:`T_2` values are returned in nanosecond
|
|
160
|
+
(ns) units and frequency is returned in gigahertz (GHz) units
|
|
161
|
+
if ``unit`` for each ``value`` is provided in ``properties``.
|
|
162
|
+
Otherwise, the raw values (in unknown original units) are returned.
|
|
163
|
+
"""
|
|
164
|
+
values = []
|
|
165
|
+
for qubit_props in properties.qubits:
|
|
166
|
+
# pylint: disable=invalid-name
|
|
167
|
+
# Default values
|
|
168
|
+
t1, t2, freq = inf, inf, inf
|
|
169
|
+
|
|
170
|
+
# Get the readout error value
|
|
171
|
+
t1_params = _check_for_item(qubit_props, "T1")
|
|
172
|
+
t2_params = _check_for_item(qubit_props, "T2")
|
|
173
|
+
freq_params = _check_for_item(qubit_props, "frequency")
|
|
174
|
+
|
|
175
|
+
# Load values from parameters
|
|
176
|
+
if hasattr(t1_params, "value"):
|
|
177
|
+
t1 = t1_params.value
|
|
178
|
+
if hasattr(t1_params, "unit"):
|
|
179
|
+
# Convert to nanoseconds
|
|
180
|
+
t1 *= _NANOSECOND_UNITS.get(t1_params.unit, 1)
|
|
181
|
+
if hasattr(t2_params, "value"):
|
|
182
|
+
t2 = t2_params.value
|
|
183
|
+
if hasattr(t2_params, "unit"):
|
|
184
|
+
# Convert to nanoseconds
|
|
185
|
+
t2 *= _NANOSECOND_UNITS.get(t2_params.unit, 1)
|
|
186
|
+
if hasattr(freq_params, "value"):
|
|
187
|
+
freq = freq_params.value
|
|
188
|
+
if hasattr(freq_params, "unit"):
|
|
189
|
+
# Convert to Gigahertz
|
|
190
|
+
freq *= _GHZ_UNITS.get(freq_params.unit, 1)
|
|
191
|
+
|
|
192
|
+
values.append((t1, t2, freq))
|
|
193
|
+
return values
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _check_for_item(lst, name):
|
|
197
|
+
"""Search list for item with given name."""
|
|
198
|
+
filtered = [item for item in lst if item.name == name]
|
|
199
|
+
if not filtered:
|
|
200
|
+
return None
|
|
201
|
+
else:
|
|
202
|
+
return filtered[0]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# This code is part of Qiskit.
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright IBM 2018, 2019.
|
|
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
|
+
"""
|
|
14
|
+
Errors for qiskit-aer noise models.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from .readout_error import ReadoutError
|
|
18
|
+
from .quantum_error import QuantumError
|
|
19
|
+
from .pauli_error import PauliError
|
|
20
|
+
from .pauli_lindblad_error import PauliLindbladError
|
|
21
|
+
from .standard_errors import kraus_error
|
|
22
|
+
from .standard_errors import mixed_unitary_error
|
|
23
|
+
from .standard_errors import coherent_unitary_error
|
|
24
|
+
from .standard_errors import pauli_error
|
|
25
|
+
from .standard_errors import depolarizing_error
|
|
26
|
+
from .standard_errors import reset_error
|
|
27
|
+
from .standard_errors import thermal_relaxation_error
|
|
28
|
+
from .standard_errors import phase_amplitude_damping_error
|
|
29
|
+
from .standard_errors import amplitude_damping_error
|
|
30
|
+
from .standard_errors import phase_damping_error
|