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,925 @@
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
+ Aer qasm simulator backend.
14
+ """
15
+
16
+ import copy
17
+ import logging
18
+ from warnings import warn
19
+ from qiskit.providers.options import Options
20
+ from qiskit.providers.backend import BackendV2
21
+
22
+ from ..version import __version__
23
+ from ..aererror import AerError
24
+ from .aerbackend import AerBackend
25
+ from .backendconfiguration import AerBackendConfiguration
26
+ from .backendproperties import target_to_backend_properties
27
+ from .backend_utils import (
28
+ cpp_execute_circuits,
29
+ available_methods,
30
+ MAX_QUBITS_STATEVECTOR,
31
+ LEGACY_METHOD_MAP,
32
+ map_legacy_method_config,
33
+ )
34
+
35
+ # pylint: disable=import-error, no-name-in-module, abstract-method
36
+ from .controller_wrappers import aer_controller_execute
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
+ class QasmSimulator(AerBackend):
42
+ """
43
+ Noisy quantum circuit simulator backend.
44
+
45
+ **Configurable Options**
46
+
47
+ The `QasmSimulator` supports multiple simulation methods and
48
+ configurable options for each simulation method. These may be set using the
49
+ appropriate kwargs during initialization. They can also be set of updated
50
+ using the :meth:`set_options` method.
51
+
52
+ Run-time options may also be specified as kwargs using the :meth:`run` method.
53
+ These will not be stored in the backend and will only apply to that execution.
54
+ They will also override any previously set options.
55
+
56
+ For example, to configure a density matrix simulator with a custom noise
57
+ model to use for every execution
58
+
59
+ .. code-block:: python
60
+
61
+ noise_model = NoiseModel.from_backend(backend)
62
+ backend = QasmSimulator(method='density_matrix',
63
+ noise_model=noise_model)
64
+
65
+ **Simulating an IBM Quantum Backend**
66
+
67
+ The simulator can be automatically configured to mimic an IBM Quantum backend using
68
+ the :meth:`from_backend` method. This will configure the simulator to use the
69
+ basic device :class:`NoiseModel` for that backend, and the same basis gates
70
+ and coupling map.
71
+
72
+ .. code-block:: python
73
+
74
+ backend = QasmSimulator.from_backend(backend)
75
+
76
+ **Simulation Method Option**
77
+
78
+ The simulation method is set using the ``method`` kwarg.
79
+ Supported simulation methods are
80
+
81
+ * ``"statevector"``: A dense statevector simulation that can sample
82
+ measurement outcomes from *ideal* circuits with all measurements at
83
+ end of the circuit. For noisy simulations each shot samples a
84
+ randomly sampled noisy circuit from the noise model.
85
+ ``"statevector_cpu"`` is an alias of ``"statevector"``.
86
+
87
+ * ``"statevector_gpu"``: A dense statevector simulation that provides
88
+ the same functionalities with ``"statevector"``. GPU performs the computation
89
+ to calculate probability amplitudes as CPU does. If no GPU is available,
90
+ a runtime error is raised.
91
+
92
+ * ``"density_matrix"``: A dense density matrix simulation that may
93
+ sample measurement outcomes from *noisy* circuits with all
94
+ measurements at end of the circuit. It can only simulate half the
95
+ number of qubits as the statevector method.
96
+
97
+ * ``"density_matrix_gpu"``: A dense density matrix simulation that provides
98
+ the same functionalities with ``"density_matrix"``. GPU performs the computation
99
+ to calculate probability amplitudes as CPU does. If no GPU is available,
100
+ a runtime error is raised.
101
+
102
+ * ``"stabilizer"``: An efficient Clifford stabilizer state simulator
103
+ that can simulate noisy Clifford circuits if all errors in the noise model are also
104
+ Clifford errors.
105
+
106
+ * ``"extended_stabilizer"``: An approximate simulated based on a
107
+ ranked-stabilizer decomposition that decomposes circuits into stabilizer
108
+ state terms. The number of terms grows with the number of
109
+ non-Clifford gates.
110
+
111
+ * ``"matrix_product_state"``: A tensor-network statevector simulator that
112
+ uses a Matrix Product State (MPS) representation for the state.
113
+
114
+ * ``"automatic"``: The default behavior where the method is chosen
115
+ automatically for each circuit based on the circuit instructions,
116
+ number of qubits, and noise model.
117
+
118
+ **Additional Backend Options**
119
+
120
+ The following simulator specific backend options are supported
121
+
122
+ * ``method`` (str): Set the simulation method (Default: ``"automatic"``).
123
+ Use :meth:`available_methods` to return a list of all availabe methods.
124
+
125
+ * ``device`` (str): Set the simulation device (Default: ``"CPU"``).
126
+ Use :meth:`available_devices` to return a list of devices supported
127
+ on the current system.
128
+
129
+ * ``precision`` (str): Set the floating point precision for
130
+ certain simulation methods to either ``"single"`` or ``"double"``
131
+ precision (default: ``"double"``).
132
+
133
+ * ``executor`` (futures.Executor): Set a custom executor for
134
+ asynchronous running of simulation jobs (Default: None).
135
+
136
+ * ``max_job_size`` (int or None): If the number of run circuits
137
+ exceeds this value simulation will be run as a set of of sub-jobs
138
+ on the executor. If ``None`` simulation of all circuits are submitted
139
+ to the executor as a single job (Default: None).
140
+
141
+ * ``max_shot_size`` (int or None): If the number of shots of a noisy
142
+ circuit exceeds this value simulation will be split into multi
143
+ circuits for execution and the results accumulated. If ``None``
144
+ circuits will not be split based on shots. When splitting circuits
145
+ use the ``max_job_size`` option to control how these split circuits
146
+ should be submitted to the executor (Default: None).
147
+
148
+ * ``enable_truncation`` (bool): If set to True this removes unnecessary
149
+ qubits which do not affect the simulation outcome from the simulated
150
+ circuits (Default: True).
151
+
152
+ * ``zero_threshold`` (double): Sets the threshold for truncating
153
+ small values to zero in the result data (Default: 1e-10).
154
+
155
+ * ``validation_threshold`` (double): Sets the threshold for checking
156
+ if initial states are valid (Default: 1e-8).
157
+
158
+ * ``max_parallel_threads`` (int): Sets the maximum number of CPU
159
+ cores used by OpenMP for parallelization. If set to 0 the
160
+ maximum will be set to the number of CPU cores (Default: 0).
161
+
162
+ * ``max_parallel_experiments`` (int): Sets the maximum number of
163
+ experiments that may be executed in parallel up to the
164
+ max_parallel_threads value. If set to 1 parallel circuit
165
+ execution will be disabled. If set to 0 the maximum will be
166
+ automatically set to max_parallel_threads (Default: 1).
167
+
168
+ * ``max_parallel_shots`` (int): Sets the maximum number of
169
+ shots that may be executed in parallel during each experiment
170
+ execution, up to the max_parallel_threads value. If set to 1
171
+ parallel shot execution will be disabled. If set to 0 the
172
+ maximum will be automatically set to max_parallel_threads.
173
+ Note that this cannot be enabled at the same time as parallel
174
+ experiment execution (Default: 0).
175
+
176
+ * ``max_memory_mb`` (int): Sets the maximum size of memory
177
+ to store a state vector. If a state vector needs more, an error
178
+ is thrown. In general, a state vector of n-qubits uses 2^n complex
179
+ values (16 Bytes). If set to 0, the maximum will be automatically
180
+ set to the system memory size (Default: 0).
181
+
182
+ These backend options only apply when using the ``"statevector"``
183
+ simulation method:
184
+
185
+ * ``statevector_parallel_threshold`` (int): Sets the threshold that
186
+ the number of qubits must be greater than to enable OpenMP
187
+ parallelization for matrix multiplication during execution of
188
+ an experiment. If parallel circuit or shot execution is enabled
189
+ this will only use unallocated CPU cores up to
190
+ max_parallel_threads. Note that setting this too low can reduce
191
+ performance (Default: 14).
192
+
193
+ * ``statevector_sample_measure_opt`` (int): Sets the threshold that
194
+ the number of qubits must be greater than to enable a large
195
+ qubit optimized implementation of measurement sampling. Note
196
+ that setting this two low can reduce performance (Default: 10)
197
+
198
+ These backend options only apply when using the ``"stabilizer"``
199
+ simulation method:
200
+
201
+ * ``stabilizer_max_snapshot_probabilities`` (int): set the maximum
202
+ qubit number for the :class:`~qiskit_aer.library.SaveProbabilities` instruction (Default: 32).
203
+
204
+ These backend options only apply when using the ``"extended_stabilizer"``
205
+ simulation method:
206
+
207
+ * ``extended_stabilizer_sampling_method`` (string): Choose how to simulate
208
+ measurements on qubits. The performance of the simulator depends
209
+ significantly on this choice. In the following, let n be the number of
210
+ qubits in the circuit, m the number of qubits measured, and S be the
211
+ number of shots (Default: resampled_metropolis).
212
+
213
+ - ``"metropolis"``: Use a Monte-Carlo method to sample many output
214
+ strings from the simulator at once. To be accurate, this method
215
+ requires that all the possible output strings have a non-zero
216
+ probability. It will give inaccurate results on cases where
217
+ the circuit has many zero-probability outcomes.
218
+ This method has an overall runtime that scales as n^{2} + (S-1)n.
219
+
220
+ - ``"resampled_metropolis"``: A variant of the metropolis method,
221
+ where the Monte-Carlo method is reinitialised for every shot. This
222
+ gives better results for circuits where some outcomes have zero
223
+ probability, but will still fail if the output distribution
224
+ is sparse. The overall runtime scales as Sn^{2}.
225
+
226
+ - ``"norm_estimation"``: An alternative sampling method using
227
+ random state inner products to estimate outcome probabilities. This
228
+ method requires twice as much memory, and significantly longer
229
+ runtimes, but gives accurate results on circuits with sparse
230
+ output distributions. The overall runtime scales as Sn^{3}m^{3}.
231
+
232
+ * ``extended_stabilizer_metropolis_mixing_time`` (int): Set how long the
233
+ monte-carlo method runs before performing measurements. If the
234
+ output distribution is strongly peaked, this can be decreased
235
+ alongside setting extended_stabilizer_disable_measurement_opt
236
+ to True (Default: 5000).
237
+
238
+ * ``"extended_stabilizer_approximation_error"`` (double): Set the error
239
+ in the approximation for the extended_stabilizer method. A
240
+ smaller error needs more memory and computational time
241
+ (Default: 0.05).
242
+
243
+ * ``extended_stabilizer_norm_estimation_samples`` (int): The default number
244
+ of samples for the norm estimation sampler. The method will use the
245
+ default, or 4m^{2} samples where m is the number of qubits to be
246
+ measured, whichever is larger (Default: 100).
247
+
248
+ * ``extended_stabilizer_norm_estimation_repetitions`` (int): The number
249
+ of times to repeat the norm estimation. The median of these reptitions
250
+ is used to estimate and sample output strings (Default: 3).
251
+
252
+ * ``extended_stabilizer_parallel_threshold`` (int): Set the minimum
253
+ size of the extended stabilizer decomposition before we enable
254
+ OpenMP parallelization. If parallel circuit or shot execution
255
+ is enabled this will only use unallocated CPU cores up to
256
+ max_parallel_threads (Default: 100).
257
+
258
+ * ``extended_stabilizer_probabilities_snapshot_samples`` (int): If using
259
+ the metropolis or resampled_metropolis sampling method, set the number of
260
+ samples used to estimate probabilities in a probabilities snapshot
261
+ (Default: 3000).
262
+
263
+ These backend options only apply when using the ``"matrix_product_state"``
264
+ simulation method:
265
+
266
+ * ``matrix_product_state_max_bond_dimension`` (int): Sets a limit
267
+ on the number of Schmidt coefficients retained at the end of
268
+ the svd algorithm. Coefficients beyond this limit will be discarded.
269
+ (Default: None, i.e., no limit on the bond dimension).
270
+
271
+ * ``matrix_product_state_truncation_threshold`` (double):
272
+ Discard the smallest coefficients for which the sum of
273
+ their squares is smaller than this threshold.
274
+ (Default: 1e-16).
275
+
276
+ * ``mps_sample_measure_algorithm`` (str): Choose which algorithm to use for
277
+ ``"sample_measure"`` (Default: "mps_apply_measure").
278
+
279
+ - ``"mps_probabilities"``: This method first constructs the probability
280
+ vector and then generates a sample per shot. It is more efficient for
281
+ a large number of shots and a small number of qubits, with complexity
282
+ O(2^n * n * D^2) to create the vector and O(1) per shot, where n is
283
+ the number of qubits and D is the bond dimension.
284
+
285
+ - ``"mps_apply_measure"``: This method creates a copy of the mps structure
286
+ and measures directly on it. It is more efficient for a small number of
287
+ shots, and a large number of qubits, with complexity around
288
+ O(n * D^2) per shot.
289
+
290
+ * ``mps_log_data`` (str): if True, output logging data of the MPS
291
+ structure: bond dimensions and values discarded during approximation.
292
+ (Default: False)
293
+
294
+ These backend options apply in circuit optimization passes:
295
+
296
+ * ``fusion_enable`` (bool): Enable fusion optimization in circuit
297
+ optimization passes [Default: True]
298
+ * ``fusion_verbose`` (bool): Output gates generated in fusion optimization
299
+ into metadata [Default: False]
300
+ * ``fusion_max_qubit`` (int): Maximum number of qubits for a operation generated
301
+ in a fusion optimization [Default: 5]
302
+ * ``fusion_threshold`` (int): Threshold that number of qubits must be greater
303
+ than or equal to enable fusion optimization [Default: 14]
304
+ """
305
+
306
+ _DEFAULT_BASIS_GATES = sorted(
307
+ [
308
+ "u1",
309
+ "u2",
310
+ "u3",
311
+ "u",
312
+ "p",
313
+ "r",
314
+ "rx",
315
+ "ry",
316
+ "rz",
317
+ "id",
318
+ "x",
319
+ "y",
320
+ "z",
321
+ "h",
322
+ "s",
323
+ "sdg",
324
+ "sx",
325
+ "sxdg",
326
+ "t",
327
+ "tdg",
328
+ "swap",
329
+ "cx",
330
+ "cy",
331
+ "cz",
332
+ "csx",
333
+ "cp",
334
+ "cu",
335
+ "cu1",
336
+ "cu2",
337
+ "cu3",
338
+ "rxx",
339
+ "ryy",
340
+ "rzz",
341
+ "rzx",
342
+ "ccx",
343
+ "cswap",
344
+ "mcx",
345
+ "mcy",
346
+ "mcz",
347
+ "mcsx",
348
+ "mcp",
349
+ "mcphase",
350
+ "mcu",
351
+ "mcu1",
352
+ "mcu2",
353
+ "mcu3",
354
+ "mcrx",
355
+ "mcry",
356
+ "mcrz",
357
+ "mcr",
358
+ "mcswap",
359
+ "unitary",
360
+ "diagonal",
361
+ "multiplexer",
362
+ "initialize",
363
+ "delay",
364
+ "pauli",
365
+ "mcx_gray",
366
+ "ecr",
367
+ ]
368
+ )
369
+
370
+ _DEFAULT_CUSTOM_INSTR = sorted(
371
+ [
372
+ "quantum_channel",
373
+ "qerror_loc",
374
+ "roerror",
375
+ "kraus",
376
+ "save_expval",
377
+ "save_expval_var",
378
+ "save_probabilities",
379
+ "save_probabilities_dict",
380
+ "save_amplitudes",
381
+ "save_amplitudes_sq",
382
+ "save_state",
383
+ "save_density_matrix",
384
+ "save_statevector",
385
+ "save_statevector_dict",
386
+ "save_stabilizer",
387
+ "set_statevector",
388
+ "set_density_matrix",
389
+ "set_stabilizer",
390
+ "reset",
391
+ ]
392
+ )
393
+
394
+ _DEFAULT_CONFIGURATION = {
395
+ "backend_name": "qasm_simulator",
396
+ "backend_version": __version__,
397
+ "n_qubits": MAX_QUBITS_STATEVECTOR,
398
+ "url": "https://github.com/Qiskit/qiskit-aer",
399
+ "simulator": True,
400
+ "local": True,
401
+ "conditional": True,
402
+ "memory": True,
403
+ "max_shots": int(1e6),
404
+ "description": "A C++ Qasm simulator with noise",
405
+ "coupling_map": None,
406
+ "basis_gates": _DEFAULT_BASIS_GATES,
407
+ "custom_instructions": _DEFAULT_CUSTOM_INSTR,
408
+ "gates": [],
409
+ }
410
+
411
+ _SIMULATION_METHODS = [
412
+ "automatic",
413
+ "statevector",
414
+ "statevector_gpu",
415
+ "statevector_custatevec",
416
+ "statevector_thrust",
417
+ "density_matrix",
418
+ "density_matrix_gpu",
419
+ "density_matrix_custatevec",
420
+ "density_matrix_thrust",
421
+ "stabilizer",
422
+ "matrix_product_state",
423
+ "extended_stabilizer",
424
+ ]
425
+
426
+ _AVAILABLE_METHODS = None
427
+
428
+ _SIMULATION_DEVICES = ("CPU", "GPU", "Thrust")
429
+
430
+ _AVAILABLE_DEVICES = None
431
+
432
+ def __init__(self, configuration=None, properties=None, provider=None, **backend_options):
433
+ warn(
434
+ "The `QasmSimulator` backend will be deprecated in the"
435
+ " future. It has been superseded by the `AerSimulator`"
436
+ " backend.",
437
+ PendingDeprecationWarning,
438
+ )
439
+
440
+ self._controller = aer_controller_execute()
441
+
442
+ # Update available methods for class
443
+ if QasmSimulator._AVAILABLE_METHODS is None:
444
+ QasmSimulator._AVAILABLE_METHODS = available_methods(
445
+ QasmSimulator._SIMULATION_METHODS,
446
+ QasmSimulator._SIMULATION_DEVICES,
447
+ )
448
+
449
+ # Default configuration
450
+ if configuration is None:
451
+ configuration = AerBackendConfiguration.from_dict(QasmSimulator._DEFAULT_CONFIGURATION)
452
+ else:
453
+ configuration.open_pulse = False
454
+
455
+ # Cache basis gates since computing the intersection
456
+ # of noise model, method, and config gates is expensive.
457
+ self._cached_basis_gates = self._DEFAULT_BASIS_GATES
458
+
459
+ super().__init__(
460
+ configuration, properties, provider=provider, backend_options=backend_options
461
+ )
462
+
463
+ def __repr__(self):
464
+ """String representation of an AerBackend."""
465
+ display = super().__repr__()[:-1]
466
+ pad = " " * (len(self.__class__.__name__) + 1)
467
+
468
+ method = getattr(self.options, "method", None)
469
+ if method not in [None, "automatic"]:
470
+ display += f",\n{pad}method='{method}'"
471
+
472
+ noise_model = getattr(self.options, "noise_model", None)
473
+ if noise_model is not None and not noise_model.is_ideal():
474
+ display += f",\n{pad}noise_model={repr(noise_model)})"
475
+
476
+ display += ")"
477
+ return display
478
+
479
+ @classmethod
480
+ def _default_options(cls):
481
+ return Options(
482
+ # Global options
483
+ shots=1024,
484
+ method=None,
485
+ device="CPU",
486
+ precision="double",
487
+ executor=None,
488
+ max_job_size=None,
489
+ max_shot_size=None,
490
+ enable_truncation=True,
491
+ zero_threshold=1e-10,
492
+ validation_threshold=None,
493
+ max_parallel_threads=None,
494
+ max_parallel_experiments=None,
495
+ max_parallel_shots=None,
496
+ max_memory_mb=None,
497
+ fusion_enable=True,
498
+ fusion_verbose=False,
499
+ fusion_max_qubit=5,
500
+ fusion_threshold=14,
501
+ accept_distributed_results=None,
502
+ blocking_qubits=None,
503
+ blocking_enable=False,
504
+ memory=None,
505
+ noise_model=None,
506
+ seed_simulator=None,
507
+ # statevector options
508
+ statevector_parallel_threshold=14,
509
+ statevector_sample_measure_opt=10,
510
+ # stabilizer options
511
+ stabilizer_max_snapshot_probabilities=32,
512
+ # extended stabilizer options
513
+ extended_stabilizer_sampling_method="resampled_metropolis",
514
+ extended_stabilizer_metropolis_mixing_time=5000,
515
+ extended_stabilizer_approximation_error=0.05,
516
+ extended_stabilizer_norm_estimation_samples=100,
517
+ extended_stabilizer_norm_estimation_repetitions=3,
518
+ extended_stabilizer_parallel_threshold=100,
519
+ extended_stabilizer_probabilities_snapshot_samples=3000,
520
+ # MPS options
521
+ matrix_product_state_truncation_threshold=1e-16,
522
+ matrix_product_state_max_bond_dimension=None,
523
+ mps_sample_measure_algorithm="mps_heuristic",
524
+ mps_log_data=False,
525
+ chop_threshold=1e-8,
526
+ mps_parallel_threshold=14,
527
+ mps_omp_threads=1,
528
+ mps_lapack=False,
529
+ )
530
+
531
+ @classmethod
532
+ def from_backend(cls, backend, **options):
533
+ """Initialize simulator from backend."""
534
+ if isinstance(backend, BackendV2):
535
+ if backend.description is None:
536
+ description = "created by AerSimulator.from_backend"
537
+ else:
538
+ description = backend.description
539
+
540
+ configuration = AerBackendConfiguration(
541
+ backend_name=f"aer_simulator_from({backend.name})",
542
+ backend_version=backend.backend_version,
543
+ n_qubits=backend.num_qubits,
544
+ basis_gates=backend.operation_names,
545
+ gates=[],
546
+ max_shots=int(1e6),
547
+ coupling_map=list(backend.coupling_map.get_edges()),
548
+ max_experiments=backend.max_circuits,
549
+ description=description,
550
+ )
551
+ properties = target_to_backend_properties(backend.target)
552
+ target = backend.target
553
+ else:
554
+ raise TypeError(
555
+ "The backend argument requires a BackendV2 object, " f"not a {type(backend)} object"
556
+ )
557
+ # Use automatic noise model if none is provided
558
+ if "noise_model" not in options:
559
+ # pylint: disable=import-outside-toplevel
560
+ # Avoid cyclic import
561
+ from ..noise.noise_model import NoiseModel
562
+
563
+ noise_model = NoiseModel.from_backend(backend)
564
+ if not noise_model.is_ideal():
565
+ options["noise_model"] = noise_model
566
+
567
+ # Initialize simulator
568
+ sim = cls(configuration=configuration, properties=properties, target=target, **options)
569
+ return sim
570
+
571
+ def configuration(self):
572
+ """Return the simulator backend configuration.
573
+
574
+ Returns:
575
+ BackendConfiguration: the configuration for the backend.
576
+ """
577
+ config = copy.copy(self._configuration)
578
+ for key, val in self._options_configuration.items():
579
+ setattr(config, key, val)
580
+ # Update basis gates based on custom options, config, method,
581
+ # and noise model
582
+ config.custom_instructions = self._custom_instructions()
583
+ config.basis_gates = self._cached_basis_gates + config.custom_instructions
584
+ return config
585
+
586
+ def available_methods(self):
587
+ """Return the available simulation methods."""
588
+ return copy.copy(self._AVAILABLE_METHODS)
589
+
590
+ def available_devices(self):
591
+ """Return the available simulation methods."""
592
+ return copy.copy(self._AVAILABLE_DEVICES)
593
+
594
+ def _execute_circuits(self, aer_circuits, noise_model, config):
595
+ """Execute circuits on the backend."""
596
+ config = map_legacy_method_config(config)
597
+ return cpp_execute_circuits(self._controller, aer_circuits, noise_model, config)
598
+
599
+ def set_option(self, key, value):
600
+ if key == "custom_instructions":
601
+ self._set_configuration_option(key, value)
602
+ return
603
+ if key == "method":
604
+ if value in LEGACY_METHOD_MAP:
605
+ value, device = LEGACY_METHOD_MAP[value]
606
+ self.set_option("device", device)
607
+ if value is not None and value not in self.available_methods():
608
+ raise AerError(
609
+ f"Invalid simulation method {value}. Available methods"
610
+ f" are: {self.available_methods()}"
611
+ )
612
+ self._set_method_config(value)
613
+ super().set_option(key, value)
614
+ if key in ["method", "noise_model", "basis_gates"]:
615
+ self._cached_basis_gates = self._basis_gates()
616
+
617
+ def _basis_gates(self):
618
+ """Return simulator basis gates.
619
+
620
+ This will be the option value of basis gates if it was set,
621
+ otherwise it will be the intersection of the configuration, noise model
622
+ and method supported basis gates.
623
+ """
624
+ # Use option value for basis gates if set
625
+ if "basis_gates" in self._options_configuration:
626
+ return self._options_configuration["basis_gates"]
627
+
628
+ # Compute intersection with method basis gates
629
+ method_gates = self._method_basis_gates()
630
+ config_gates = self._configuration.basis_gates
631
+ if config_gates:
632
+ basis_gates = set(config_gates).intersection(method_gates)
633
+ else:
634
+ basis_gates = method_gates
635
+
636
+ # Compute intersection with noise model basis gates
637
+ noise_model = getattr(self.options, "noise_model", None)
638
+ if noise_model:
639
+ noise_gates = noise_model.basis_gates
640
+ basis_gates = basis_gates.intersection(noise_gates)
641
+ else:
642
+ noise_gates = None
643
+
644
+ if not basis_gates:
645
+ logger.warning(
646
+ "The intersection of configuration basis gates (%s), "
647
+ "simulation method basis gates (%s), and "
648
+ "noise model basis gates (%s) is empty",
649
+ config_gates,
650
+ method_gates,
651
+ noise_gates,
652
+ )
653
+ return sorted(basis_gates)
654
+
655
+ def _method_basis_gates(self):
656
+ """Return method basis gates and custom instructions"""
657
+ method = self._options.get("method", None)
658
+ if method in [
659
+ "density_matrix",
660
+ "density_matrix_gpu",
661
+ "density_matrix_custatevec",
662
+ "density_matrix_thrust",
663
+ ]:
664
+ return sorted(
665
+ [
666
+ "u1",
667
+ "u2",
668
+ "u3",
669
+ "u",
670
+ "p",
671
+ "r",
672
+ "rx",
673
+ "ry",
674
+ "rz",
675
+ "id",
676
+ "x",
677
+ "y",
678
+ "z",
679
+ "h",
680
+ "s",
681
+ "sdg",
682
+ "sx",
683
+ "sxdg",
684
+ "t",
685
+ "tdg",
686
+ "swap",
687
+ "cx",
688
+ "cy",
689
+ "cz",
690
+ "cp",
691
+ "cu1",
692
+ "rxx",
693
+ "ryy",
694
+ "rzz",
695
+ "rzx",
696
+ "ccx",
697
+ "unitary",
698
+ "diagonal",
699
+ "delay",
700
+ "pauli",
701
+ "ecr",
702
+ ]
703
+ )
704
+ if method == "matrix_product_state":
705
+ return sorted(
706
+ [
707
+ "u1",
708
+ "u2",
709
+ "u3",
710
+ "u",
711
+ "p",
712
+ "cp",
713
+ "cx",
714
+ "cy",
715
+ "cz",
716
+ "id",
717
+ "x",
718
+ "y",
719
+ "z",
720
+ "h",
721
+ "s",
722
+ "sdg",
723
+ "sx",
724
+ "sxdg",
725
+ "t",
726
+ "tdg",
727
+ "swap",
728
+ "ccx",
729
+ "unitary",
730
+ "roerror",
731
+ "delay",
732
+ "pauli",
733
+ "r",
734
+ "rx",
735
+ "ry",
736
+ "rz",
737
+ "rxx",
738
+ "ryy",
739
+ "rzz",
740
+ "rzx",
741
+ "csx",
742
+ "cswap",
743
+ "diagonal",
744
+ "initialize",
745
+ ]
746
+ )
747
+ if method == "stabilizer":
748
+ return sorted(
749
+ [
750
+ "id",
751
+ "x",
752
+ "y",
753
+ "z",
754
+ "h",
755
+ "s",
756
+ "sdg",
757
+ "sx",
758
+ "sxdg",
759
+ "cx",
760
+ "cy",
761
+ "cz",
762
+ "swap",
763
+ "delay",
764
+ "pauli",
765
+ "ecr",
766
+ ]
767
+ )
768
+ if method == "extended_stabilizer":
769
+ return sorted(
770
+ [
771
+ "cx",
772
+ "cz",
773
+ "id",
774
+ "x",
775
+ "y",
776
+ "z",
777
+ "h",
778
+ "s",
779
+ "sdg",
780
+ "sx",
781
+ "sxdg",
782
+ "swap",
783
+ "u0",
784
+ "t",
785
+ "tdg",
786
+ "u1",
787
+ "p",
788
+ "ccx",
789
+ "ccz",
790
+ "delay",
791
+ "pauli",
792
+ ]
793
+ )
794
+ return QasmSimulator._DEFAULT_BASIS_GATES
795
+
796
+ def _custom_instructions(self):
797
+ """Return method basis gates and custom instructions"""
798
+ # pylint: disable = too-many-return-statements
799
+ if "custom_instructions" in self._options_configuration:
800
+ return self._options_configuration["custom_instructions"]
801
+
802
+ method = self._options.get("method", None)
803
+ if method in [
804
+ "statevector",
805
+ "statevector_gpu",
806
+ "statevector_custatevec",
807
+ "statevector_thrust",
808
+ ]:
809
+ return sorted(
810
+ [
811
+ "quantum_channel",
812
+ "qerror_loc",
813
+ "roerror",
814
+ "kraus",
815
+ "save_expval",
816
+ "save_expval_var",
817
+ "save_probabilities",
818
+ "save_probabilities_dict",
819
+ "save_amplitudes",
820
+ "save_amplitudes_sq",
821
+ "save_state",
822
+ "save_density_matrix",
823
+ "save_statevector",
824
+ "save_statevector_dict",
825
+ "set_statevector",
826
+ ]
827
+ )
828
+ if method in [
829
+ "density_matrix",
830
+ "density_matrix_gpu",
831
+ "density_matrix_custatevec",
832
+ "density_matrix_thrust",
833
+ ]:
834
+ return sorted(
835
+ [
836
+ "quantum_channel",
837
+ "qerror_loc",
838
+ "roerror",
839
+ "kraus",
840
+ "superop",
841
+ "save_expval",
842
+ "save_expval_var",
843
+ "save_probabilities",
844
+ "save_probabilities_dict",
845
+ "save_state",
846
+ "save_density_matrix",
847
+ "save_amplitudes_sq",
848
+ "set_statevector",
849
+ "set_density_matrix",
850
+ ]
851
+ )
852
+ if method == "matrix_product_state":
853
+ return sorted(
854
+ [
855
+ "quantum_channel",
856
+ "qerror_loc",
857
+ "roerror",
858
+ "kraus",
859
+ "save_expval",
860
+ "save_expval_var",
861
+ "save_probabilities",
862
+ "save_probabilities_dict",
863
+ "save_density_matrix",
864
+ "save_state",
865
+ "save_statevector",
866
+ "save_amplitudes",
867
+ "save_amplitudes_sq",
868
+ "save_matrix_product_state",
869
+ "set_matrix_product_state",
870
+ ]
871
+ )
872
+ if method == "stabilizer":
873
+ return sorted(
874
+ [
875
+ "quantum_channel",
876
+ "qerror_loc",
877
+ "roerror",
878
+ "save_expval",
879
+ "save_expval_var",
880
+ "save_probabilities",
881
+ "save_probabilities_dict",
882
+ "save_amplitudes_sq",
883
+ "save_state",
884
+ "save_stabilizer",
885
+ "set_stabilizer",
886
+ ]
887
+ )
888
+ if method == "extended_stabilizer":
889
+ return sorted(["quantum_channel", "qerror_loc", "roerror", "save_statevector"])
890
+ return QasmSimulator._DEFAULT_CUSTOM_INSTR
891
+
892
+ def _set_method_config(self, method=None):
893
+ """Set non-basis gate options when setting method"""
894
+ # Update configuration description and number of qubits
895
+ if method in [
896
+ "statevector",
897
+ "statevector_gpu",
898
+ "statevector_custatevec",
899
+ "statevector_thrust",
900
+ ]:
901
+ description = "A C++ statevector simulator with noise"
902
+ n_qubits = MAX_QUBITS_STATEVECTOR
903
+ elif method in [
904
+ "density_matrix",
905
+ "density_matrix_gpu",
906
+ "density_matrix_custatevec",
907
+ "density_matrix_thrust",
908
+ ]:
909
+ description = "A C++ density matrix simulator with noise"
910
+ n_qubits = MAX_QUBITS_STATEVECTOR // 2
911
+ elif method == "matrix_product_state":
912
+ description = "A C++ matrix product state simulator with noise"
913
+ n_qubits = 63 # TODO: not sure what to put here?
914
+ elif method == "stabilizer":
915
+ description = "A C++ Clifford stabilizer simulator with noise"
916
+ n_qubits = 10000 # TODO: estimate from memory
917
+ elif method == "extended_stabilizer":
918
+ description = "A C++ Clifford+T extended stabilizer simulator with noise"
919
+ n_qubits = 63 # TODO: estimate from memory
920
+ else:
921
+ # Clear options to default
922
+ description = None
923
+ n_qubits = None
924
+ self._set_configuration_option("description", description)
925
+ self._set_configuration_option("n_qubits", n_qubits)