qiskit-aer 0.17.2__cp314-cp314-macosx_11_0_arm64.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.cpython-314-darwin.so +0 -0
  14. qiskit_aer/backends/libomp.dylib +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 +6 -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,431 @@
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
+ Noise transformation module
15
+
16
+ The goal of this module is to transform one 1-qubit noise channel
17
+ (given by the QuantumError class) into another, built from specified
18
+ "building blocks" (given as Kraus matrices) such that the new channel is
19
+ as close as possible to the original one in the Hilber-Schmidt metric.
20
+
21
+ For a typical use case, consider a simulator for circuits built from the
22
+ Clifford group. Computations on such circuits can be simulated at
23
+ polynomial time and space, but not all noise channels can be used in such
24
+ a simulation. To enable noisy Clifford simulation one can transform the
25
+ given noise channel into the closest one, Hilbert-Schmidt wise, that can be
26
+ used in a Clifford simulator.
27
+ """
28
+ # pylint: disable=import-outside-toplevel
29
+
30
+ import copy
31
+ import logging
32
+ from typing import Sequence, List, Union, Callable
33
+
34
+ import numpy as np
35
+
36
+ from qiskit.circuit import Reset
37
+ from qiskit.circuit.library.standard_gates import (
38
+ IGate,
39
+ XGate,
40
+ YGate,
41
+ ZGate,
42
+ HGate,
43
+ SGate,
44
+ SdgGate,
45
+ )
46
+ from qiskit.compiler import transpile
47
+ from qiskit.exceptions import MissingOptionalLibraryError
48
+ from qiskit.quantum_info.operators.channel import Kraus, SuperOp, Chi
49
+ from qiskit.quantum_info.operators.channel.quantum_channel import QuantumChannel
50
+ from qiskit.transpiler.exceptions import TranspilerError
51
+ from ..noise.errors import QuantumError
52
+ from ..noise.noise_model import NoiseModel
53
+ from ..noise.noiseerror import NoiseError
54
+
55
+ logger = logging.getLogger(__name__)
56
+
57
+
58
+ def transform_noise_model(noise_model: NoiseModel, func: Callable) -> NoiseModel:
59
+ """Return a new noise model by applyign a function to all quantum errors.
60
+
61
+ This returns a new noise model containing the resulting errors from
62
+ applying the supplied function to all QuantumErrors in the noise model.
63
+ This function should have singature `func(error: QuantumError) -> QuantumError`
64
+ where the returned quantum error is defined on the same number of qubits
65
+ as the original error.
66
+
67
+ Args:
68
+ noise_model: the noise model to be transformed.
69
+ func: function for transforming QuantumErrors.
70
+ Returns:
71
+ The transpiled noise model.
72
+
73
+ Raises:
74
+ NoiseError: if the transformation failed.
75
+ """
76
+ # Make a deep copy of the noise model so we can update its
77
+ # internal dicts without affecting the original model
78
+ new_noise = copy.deepcopy(noise_model)
79
+
80
+ for key, error in new_noise._default_quantum_errors.items():
81
+ new_noise._default_quantum_errors[key] = func(error)
82
+
83
+ for inst_name, noise_dic in new_noise._local_quantum_errors.items():
84
+ for qubits, error in noise_dic.items():
85
+ new_noise._local_quantum_errors[inst_name][qubits] = func(error)
86
+
87
+ return new_noise
88
+
89
+
90
+ def transpile_quantum_error(error: QuantumError, **transpile_kwargs) -> QuantumError:
91
+ """Return a new quantum error containin transpiled circuits.
92
+
93
+ This returns a new QuantumError containing the circuits resulting from
94
+ transpiling all error circuits using :func:`qiskit.transpile` with the
95
+ passed keyword agruments.
96
+
97
+ Args:
98
+ error: the quantum error to be transformed.
99
+ transpile_kwargs: kwargs for passing to qiskit transpile function.
100
+
101
+ Returns:
102
+ The transformed quantum error.
103
+
104
+ Raises:
105
+ NoiseError: if the transformation failed.
106
+ """
107
+ try:
108
+ transpiled_circs = transpile(error.circuits, **transpile_kwargs)
109
+ except TranspilerError as err:
110
+ raise NoiseError(
111
+ f"Failed to transpile circuits in {error} with kwargs {transpile_kwargs}"
112
+ ) from err
113
+ return QuantumError(zip(transpiled_circs, error.probabilities))
114
+
115
+
116
+ def transpile_noise_model(noise_model: NoiseModel, **transpile_kwargs) -> NoiseModel:
117
+ """Return a new noise model with transpiled QuantumErrors.
118
+
119
+ This returns a new noise model containing the resulting errors from
120
+ transpiling all QuantumErrors in the noise model
121
+ using :func:`transpile_quantum_error` function with the passed
122
+ keyword agruments.
123
+
124
+ Args:
125
+ noise_model: the noise model to be transformed.
126
+ transpile_kwargs: kwargs for passing to qiskit transpile function.
127
+
128
+ Returns:
129
+ The transpiled noise model.
130
+
131
+ Raises:
132
+ NoiseError: if the transformation failed.
133
+ """
134
+
135
+ def func(error):
136
+ return transpile_quantum_error(error, **transpile_kwargs)
137
+
138
+ return transform_noise_model(noise_model, func)
139
+
140
+
141
+ def approximate_quantum_error(
142
+ error, *, operator_string=None, operator_dict=None, operator_list=None
143
+ ):
144
+ r"""
145
+ Return a ``QuantumError`` object that approximates an error
146
+ as a mixture of specified operators (channels).
147
+
148
+ The approximation is done by minimizing the Hilbert-Schmidt distance
149
+ between the process matrix of the target error channel (:math:`T`) and
150
+ the process matrix of the output channel (:math:`S = \sum_i{p_i S_i}`),
151
+ i.e. :math:`Tr[(T-S)^\dagger (T-S)]`,
152
+ where
153
+ :math:`[p_1, p_2, ..., p_n]` denote probabilities and
154
+ :math:`[S_1, S_2, ..., S_n]` denote basis operators (channels).
155
+
156
+ See `arXiv:1207.0046 <http://arxiv.org/abs/1207.0046>`_ for the details.
157
+
158
+ Args:
159
+ error (QuantumError or QuantumChannel): the error to be approximated.
160
+ The number of qubits must be 1 or 2.
161
+ operator_string (string): a name for a pre-made set of
162
+ building blocks for the output channel (Default: None).
163
+ Possible values are ``'pauli'``, ``'reset'``, ``'clifford'``.
164
+ operator_dict (dict): a dictionary whose values are the
165
+ building blocks for the output channel (Default: None).
166
+ E.g. {"x": XGate(), "y": YGate()}, keys "x" and "y"
167
+ are not used in transformation.
168
+ operator_list (list): list of building block operators for the
169
+ output channel (Default: None). E.g. [XGate(), YGate()]
170
+
171
+ Returns:
172
+ QuantumError: the approximate quantum error.
173
+
174
+ Raises:
175
+ NoiseError: if any invalid argument is specified or approximation failed.
176
+ MissingOptionalLibraryError: if cvxpy is not installed.
177
+
178
+ Note:
179
+ The operator input precedence is: ``list`` < ``dict`` < ``string``.
180
+ If a ``string`` is given, ``dict`` is overwritten;
181
+ if a ``dict`` is given, ``list`` is overwritten.
182
+ The ``string`` supports only 1- or 2-qubit errors and
183
+ its possible values are ``'pauli'``, ``'reset'``, ``'clifford'``.
184
+ The ``'clifford'`` does not support 2-qubit errors.
185
+ """
186
+ if not isinstance(error, (QuantumError, QuantumChannel)):
187
+ raise NoiseError(f"Invalid input error type: {error.__class__.__name__}")
188
+
189
+ if error.num_qubits > 2:
190
+ raise NoiseError(
191
+ "Only 1-qubit and 2-qubit noises can be converted, "
192
+ f"{error.num_qubits}-qubit noise found in model"
193
+ )
194
+
195
+ if operator_string is not None:
196
+ valid_operator_strings = _PRESET_OPERATOR_TABLE.keys()
197
+ operator_string = operator_string.lower()
198
+ if operator_string not in valid_operator_strings:
199
+ raise NoiseError(
200
+ f"{operator_string} is not a valid operator_string. "
201
+ f"It must be one of {valid_operator_strings}"
202
+ )
203
+ try:
204
+ operator_list = _PRESET_OPERATOR_TABLE[operator_string][error.num_qubits]
205
+ except KeyError as err:
206
+ raise NoiseError(
207
+ f"Preset '{operator_string}' operators do not support the "
208
+ f"approximation of errors with {error.num_qubits} qubits"
209
+ ) from err
210
+ if operator_dict is not None:
211
+ _, operator_list = zip(*operator_dict.items())
212
+ if operator_list is not None:
213
+ if not isinstance(operator_list, Sequence):
214
+ raise NoiseError(f"operator_list is not a sequence: {operator_list}")
215
+ try:
216
+ channel_list = [
217
+ op if isinstance(op, QuantumChannel) else QuantumError([(op, 1)])
218
+ for op in operator_list
219
+ ] # preserve operator_list
220
+ except NoiseError as err:
221
+ raise NoiseError(f"Invalid type found in operator list: {operator_list}") from err
222
+
223
+ probabilities = _transform_by_operator_list(channel_list, error)[1:]
224
+ identity_prob = np.round(1 - sum(probabilities), 9)
225
+ if identity_prob < 0 or identity_prob > 1:
226
+ raise NoiseError(f"Channel probabilities sum to {1 - identity_prob}")
227
+ noise_ops = [((IGate(), [0]), identity_prob)]
228
+ for operator, probability in zip(operator_list, probabilities):
229
+ noise_ops.append((operator, probability))
230
+ return QuantumError(noise_ops)
231
+
232
+ raise NoiseError("Quantum error approximation failed - no approximating operators detected")
233
+
234
+
235
+ def approximate_noise_model(model, *, operator_string=None, operator_dict=None, operator_list=None):
236
+ """
237
+ Replace all noises in a noise model with ones approximated
238
+ by a mixture of operators (channels).
239
+
240
+ Args:
241
+ model (NoiseModel): the noise model to be approximated.
242
+ All noises in the model must be 1- or 2-qubit noises.
243
+ operator_string (string): a name for a pre-made set of
244
+ building blocks for the output channel (Default: None).
245
+ Possible values are ``'pauli'``, ``'reset'``, ``'clifford'``.
246
+ operator_dict (dict): a dictionary whose values are the
247
+ building blocks for the output channel (Default: None).
248
+ E.g. {"x": XGate(), "y": YGate()}, keys "x" and "y"
249
+ are not used in transformation.
250
+ operator_list (list): list of building block operators for the
251
+ output channel (Default: None). E.g. [XGate(), YGate()]
252
+
253
+ Returns:
254
+ NoiseModel: the approximate noise model.
255
+
256
+ Raises:
257
+ NoiseError: if any invalid argument is specified or approximation failed.
258
+ MissingOptionalLibraryError: if cvxpy is not installed.
259
+
260
+ Note:
261
+ The operator input precedence is: ``list`` < ``dict`` < ``string``.
262
+ If a ``string`` is given, ``dict`` is overwritten;
263
+ if a ``dict`` is given, ``list`` is overwritten.
264
+ The ``string`` supports only 1- or 2-qubit errors and
265
+ its possible values are ``'pauli'``, ``'reset'``, ``'clifford'``.
266
+ The ``'clifford'`` does not support 2-qubit errors.
267
+ """
268
+
269
+ def approximate(noise):
270
+ return approximate_quantum_error(
271
+ noise,
272
+ operator_string=operator_string,
273
+ operator_dict=operator_dict,
274
+ operator_list=operator_list,
275
+ )
276
+
277
+ return transform_noise_model(model, approximate)
278
+
279
+
280
+ # pauli operators
281
+ _PAULIS_Q0 = [[(IGate(), [0])], [(XGate(), [0])], [(YGate(), [0])], [(ZGate(), [0])]]
282
+ _PAULIS_Q1 = [[(IGate(), [1])], [(XGate(), [1])], [(YGate(), [1])], [(ZGate(), [1])]]
283
+ _PAULIS_Q0Q1 = [op_q0 + op_q1 for op_q0 in _PAULIS_Q0 for op_q1 in _PAULIS_Q1]
284
+ # reset operators
285
+ _RESET_Q0_TO_0 = [(Reset(), [0])]
286
+ _RESET_Q0_TO_1 = [(Reset(), [0]), (XGate(), [0])]
287
+ _RESET_Q0 = [[(IGate(), [0])], _RESET_Q0_TO_0, _RESET_Q0_TO_1]
288
+ _RESET_Q1_TO_0 = [(Reset(), [1])]
289
+ _RESET_Q1_TO_1 = [(Reset(), [1]), (XGate(), [1])]
290
+ _RESET_Q1 = [[(IGate(), [1])], _RESET_Q1_TO_0, _RESET_Q1_TO_1]
291
+ _RESET_Q0Q1 = [op_q0 + op_q1 for op_q0 in _RESET_Q0 for op_q1 in _RESET_Q1]
292
+ # clifford operators
293
+ _CLIFFORD_GATES = [
294
+ (IGate(),),
295
+ (SGate(),),
296
+ (SdgGate(),),
297
+ (ZGate(),),
298
+ # u2 gates
299
+ (HGate(),),
300
+ (HGate(), ZGate()),
301
+ (ZGate(), HGate()),
302
+ (HGate(), SGate()),
303
+ (SGate(), HGate()),
304
+ (HGate(), SdgGate()),
305
+ (SdgGate(), HGate()),
306
+ (SGate(), HGate(), SGate()),
307
+ (SdgGate(), HGate(), SGate()),
308
+ (ZGate(), HGate(), SGate()),
309
+ (SGate(), HGate(), SdgGate()),
310
+ (SdgGate(), HGate(), SdgGate()),
311
+ (ZGate(), HGate(), SdgGate()),
312
+ (SGate(), HGate(), ZGate()),
313
+ (SdgGate(), HGate(), ZGate()),
314
+ (ZGate(), HGate(), ZGate()),
315
+ # u3 gates
316
+ (XGate(),),
317
+ (YGate(),),
318
+ (SGate(), XGate()),
319
+ (SdgGate(), XGate()),
320
+ ]
321
+ # preset operator table
322
+ _PRESET_OPERATOR_TABLE = {
323
+ "pauli": {
324
+ 1: _PAULIS_Q0[1:],
325
+ 2: _PAULIS_Q0Q1[1:],
326
+ },
327
+ "reset": {
328
+ 1: _RESET_Q0[1:],
329
+ 2: _RESET_Q0Q1[1:],
330
+ },
331
+ "clifford": {
332
+ 1: [[(gate, [0]) for gate in _CLIFFORD_GATES[j]] for j in range(1, 24)],
333
+ },
334
+ }
335
+
336
+
337
+ def _transform_by_operator_list(
338
+ basis_ops: Sequence[Union[QuantumChannel, QuantumError]],
339
+ target: Union[QuantumChannel, QuantumError],
340
+ ) -> List[float]:
341
+ r"""
342
+ Transform (or approximate) the target quantum channel into a mixture of
343
+ basis operators (channels) and return the mixing probabilities.
344
+
345
+ The approximate channel is found by minimizing the Hilbert-Schmidt
346
+ distance between the process matrix of the target channel (:math:`T`) and
347
+ the process matrix of the output channel (:math:`S = \sum_i{p_i S_i}`),
348
+ i.e. :math:`Tr[(T-S)^\dagger (T-S)]`,
349
+ where
350
+ :math:`[p_1, p_2, ..., p_n]` denote probabilities and
351
+ :math:`[S_1, S_2, ..., S_n]` denote basis operators (channels).
352
+
353
+ Such an optimization can represented as a quadratic program:
354
+ Minimize :math:`p^T A p + b^T p`,
355
+ subject to :math:`p \ge 0`, `\sum_i{p_i} = 1`, `\sum_i{p_i} = 1`.
356
+ The last constraint is for making the approximation conservative by
357
+ forcing the output channel have more error than the target channel
358
+ in the sense that a "fidelity" against identity channel should be worse.
359
+
360
+ See `arXiv:1207.0046 <http://arxiv.org/abs/1207.0046>`_ for the details.
361
+
362
+ Args:
363
+ target: Quantum channel to be transformed.
364
+ basis_ops: a list of channel objects constructing the output channel.
365
+
366
+ Returns:
367
+ list: A list of amplitudes (probabilities) of basis that define the output channel.
368
+
369
+ Raises:
370
+ MissingOptionalLibraryError: if cvxpy is not installed.
371
+ """
372
+ # pylint: disable=invalid-name
373
+ N = 2 ** basis_ops[0].num_qubits
374
+ # add identity channel in front
375
+ basis_ops = [Kraus(np.eye(N))] + basis_ops
376
+
377
+ # create objective function coefficients
378
+ basis_ops_mats = [Chi(op).data for op in basis_ops]
379
+ T = Chi(target).data
380
+ n = len(basis_ops_mats)
381
+ A = np.zeros((n, n))
382
+ for i, S_i in enumerate(basis_ops_mats):
383
+ for j, S_j in enumerate(basis_ops_mats):
384
+ # A[i][j] = 1/2 * {Tr(S_i^† S_j) - Tr(S_j^† S_i)} = Re[Tr(S_i^† S_j)]
385
+ if i < j:
386
+ A[i][j] = _hs_inner_prod_real(S_i, S_j)
387
+ elif i > j:
388
+ A[i][j] = A[j][i]
389
+ else: # i==j
390
+ A[i][i] = _hs_norm(S_i)
391
+ b = -2 * np.array([_hs_inner_prod_real(T, S_i) for S_i in basis_ops_mats])
392
+ # c = _hs_norm(T)
393
+
394
+ # create honesty constraint coefficients
395
+ def fidelity(channel): # fidelity w.r.t. identity omitting the N^-2 factor
396
+ return float(np.abs(np.trace(SuperOp(channel))))
397
+
398
+ source_fids = np.array([fidelity(op) for op in basis_ops])
399
+ target_fid = fidelity(target)
400
+
401
+ try:
402
+ import cvxpy
403
+ except ImportError as err:
404
+ logger.error("cvxpy module needs to be installed to use this feature.")
405
+ raise MissingOptionalLibraryError(
406
+ libname="cvxpy",
407
+ name="Transformation/Approximation of noise",
408
+ pip_install="pip install cvxpy",
409
+ msg="CVXPY is required to solve an optimization problem of"
410
+ " approximating a noise channel.",
411
+ ) from err
412
+ # create quadratic program
413
+ x = cvxpy.Variable(n)
414
+ prob = cvxpy.Problem(
415
+ cvxpy.Minimize(cvxpy.quad_form(x, A) + b.T @ x),
416
+ constraints=[cvxpy.sum(x) <= 1, x >= 0, source_fids.T @ x <= target_fid],
417
+ )
418
+ # solve quadratic program
419
+ prob.solve()
420
+ probabilities = x.value
421
+ return probabilities
422
+
423
+
424
+ def _hs_norm(A): # pylint: disable=invalid-name
425
+ # Tr(A^† A)
426
+ return np.trace(np.conj(A).T @ A).real
427
+
428
+
429
+ def _hs_inner_prod_real(A, B): # pylint: disable=invalid-name
430
+ # Re[Tr(A^† B)]
431
+ return np.trace(np.conj(A.T) @ B).real
qiskit_aer/version.py ADDED
@@ -0,0 +1,86 @@
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
+ Helper tools for getting Terra addon version information
15
+ """
16
+
17
+ import os
18
+ import subprocess
19
+
20
+ ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
21
+
22
+
23
+ def _minimal_ext_cmd(cmd):
24
+ # construct minimal environment
25
+ env = {}
26
+ for k in ["SYSTEMROOT", "PATH"]:
27
+ v = os.environ.get(k)
28
+ if v is not None:
29
+ env[k] = v
30
+ # LANGUAGE is used on win32
31
+ env["LANGUAGE"] = "C"
32
+ env["LANG"] = "C"
33
+ env["LC_ALL"] = "C"
34
+ with subprocess.Popen(
35
+ cmd,
36
+ stdout=subprocess.PIPE,
37
+ stderr=subprocess.PIPE,
38
+ env=env,
39
+ cwd=os.path.join(os.path.dirname(ROOT_DIR)),
40
+ encoding="utf-8",
41
+ ) as proc:
42
+ out = proc.communicate()[0]
43
+ if proc.returncode > 0:
44
+ raise OSError
45
+ return out
46
+
47
+
48
+ def git_version():
49
+ """Get the current git head sha1."""
50
+ # Determine if we're at main
51
+ try:
52
+ out = _minimal_ext_cmd(["git", "rev-parse", "HEAD"])
53
+ git_revision = out.strip().decode("ascii")
54
+ except OSError:
55
+ git_revision = "Unknown"
56
+
57
+ return git_revision
58
+
59
+
60
+ with open(os.path.join(ROOT_DIR, "VERSION.txt"), "r", encoding="utf-8") as version_file:
61
+ VERSION = version_file.read().strip()
62
+
63
+
64
+ def get_version_info():
65
+ """Get the full version string."""
66
+ # Adding the git rev number needs to be done inside
67
+ # write_version_py(), otherwise the import of scipy.version messes
68
+ # up the build under Python 3.
69
+ full_version = VERSION
70
+
71
+ if not os.path.exists(
72
+ os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(ROOT_DIR))), ".git")
73
+ ):
74
+ return full_version
75
+ try:
76
+ release = _minimal_ext_cmd(["git", "tag", "-l", "--points-at", "HEAD"])
77
+ except Exception: # pylint: disable=broad-except
78
+ return full_version
79
+ if not release:
80
+ git_revision = git_version()
81
+ full_version += ".dev0+" + git_revision[:7]
82
+
83
+ return full_version
84
+
85
+
86
+ __version__ = get_version_info()