Release Notes#



Aer release 0.14 supports Qiskit 1.0 and based on BackendV2. These are summary of features included in this release: - Optimization of MPS method by using BLAS/LAPACK - Implementing V2 primitives EstimatorV2/SamplerV2 - Deprecation of standalone/qobj (will be removed in the next release)

New Features#

  • Added support for running qiskit-aer with Python 3.12.

  • bit_not is defined for Uint values. However, in other language, depending hardware, Bool values can be applied as logical_not (False is 0 and True is 1). This PR supports such implicit operations for only “bit_not”.

  • Adding build test for qiskit-aer-cuda. Because GPU build takes long time, it only tests building on Python 3.12 environment.

  • Replace Qiskit SVD function with OpenBLAS/LAPACK SVD functions zgesvd and zgesdd. By default zgesvd is used. Performance of zgesdd is better than that of zgesvd on large matrices, whereas zgesvd performs better on small matrices. User can use zgesdd function setting the environment variable QISKIT_LAPACK_SVD=DC.

  • Added BitVector class to store classical bits instead of using reg_t to save memory usage and memory bandwidth.

  • Adding SamplerV2 implementation based on BaseSamplerV2 using AerSimulator. This is implemented based on qiskit.primitives.StatevectorSampler, but this can simulate using any simulation methods other than statevector by passing AerSimulator object with any methods.

  • Adding native support for ccz gate for statevector, unitary and tensornet methods. ccz gate is implemented by using mcz gate

  • Added CMake option USE_BUNDLED_BLAS_WIN which allows CMake to search for a BLAS library against which to link instead of using the OpenBLAS library bundled into the repo.

Upgrade Notes#

  • Add option to ignore checking system memory availability against required memory if max_memory_mb=-1 is set

  • Improve performance in MPS measurement method matrix_product_state::sample_measure_all by parallelizing the shots.

  • Parallelize un-parallelized loops in sampling measure to speed up for simulation with large number of shots.

  • Added psutil as a dependency for Qiskit Aer. This is used to determine the amount of physical resources available. psutil is currently a dependency of Qiskit, which is a requirement for Qiskit Aer, so psutil was effectively already required for any qiskit-aer installation. But, as qiskit-aer is now using it directly is now a direct dependency for qiskit-aer.

Deprecation Notes#

  • Removed importing qiskit.test from test and include some classes in Aer

Bug Fixes#

  • Fixed backend name in backend.configuration when method and device is specified from AerProvider, this issue is caused by upgrading AerBackend to V2 backend.

    Also fixed issue AerProvider did not enumerate tensor_network method when GPU device is available

  • Fixes AerBackend issues caused by upgading to BackendV2 in 0.13.0 release and fix test failures for Qiskit 0.45 release.

    For issue #1987, added description if backend given by from_backend does not have description.

    For issue #1988, added building coupling map from option.

    For issue #1982, added custome pass maneger to rebuild basis gates from input circuits to prevent unnecessary gate changes

  • Fixed stabilizer was selected with method=”automatic” ` when simulating circuits with rotational gates with noise models for small number of qubits even it is faster to calculate with `density_matrix method. This fix checks if density_matrix method with noise model is faster or not at first and then check using stabilizer method. This is side effect of implementing rotational gates in stabilizer PR #1938

  • Fixed basis gates sets of Aer backend, moved reset and switch_case to custom instructions.

  • Fixed GPU batched shots optimization and GPU runtime parameter binding failures caused by wrong checking of return condition

  • Extended stabilizer simulation was sharing a single copy of RngEngine amongst parallelized states in ExtendedStabilizer::State::apply_ops_parallel, leading to thread safety issue. Now, a new RngEngine is seeded for each parallel state.

  • Removed deprecate function test in test.terra.states.test_aer_statevector.TestAerStatevector.test_number_to_latex_terms

    Sorted the output properties in test.terra.noise.test_device_models.test_basic_device_gate_errors_from_target_and_properties to compare correctly.

  • When applying initialize, global phase was not multiplied to state. This fix multiplies global phase to initialize operation. Also this fix applies global phase to matrix_product_state method, which did not use global phase.

  • Fixed required memory size for MPS method. Required memory was wrongly estimated because all the 2-qubits gates increased required memory, but only rxx, ryy and rzx gates (when theta is not multiple of pi/2) and unitary increase memory.

  • Fixes order of applying read out error in sampling measure in circuit executors. Ordering is reversed to fit to the older verison of Aer. Also fixed check of bacth execution.

  • This fix changes device query method from running simple circuit to search devices from C++ binary to prevent initializing GPUs at initialization phase and simulation methods are listed in Python code. Aer built with GPU support will not initialize when device=CPU is used. And only initialize and access GPUs defined in target_gpus option.

  • fixed ry gate for stabilizer method, PI/2 and PI3/2 was inverted

  • Fixes test cases failed due to upgrade of Qiskit.

    Removed importing Aer from qiskit.

    QuantumCircuit.diagonal was deprecated, using circuit.library.Diagonal instead

  • For dynamic circuits, aer_compiler calls transpiler without optimizaiton level. Because id gates are removed by transpiler, noise applied id gates did not work correctly. This fix adds optimization_level=0 not to remove id gates of dynamic circuits



Here are highlights of the Aer 0.13.0 release: Aer’s backend is now backendV2. Introducing shot-branching optimization that accelerates dynamic circuits simulations. By using shot_branching_enable=True, multi-shots simulation starts with single state and state will be branched with attached shots dynamically. This option is available for statevector, density_matrix and tensor_network methods. Adding support for classical expressions used for branch operations. Introducing runtime parameter binding that accelerates parameterized circuits simulations on GPU. With runtime_parameter_bind_enable=True and batched_shots_gpu=True, this optimization will be enabled on GPU. This optimization can be used with Aer primitives. Fix dynamic link library path for GPU binary distributions. Now Aer supports AMD’s GPUs based on ROCm (building from source code only)

Build environment variable was added to enable building Qiskit-Aer without the CUDA requirements. The new variable is QISKIT_ADD_CUDA_REQUIREMENTS and can be set to False/No/Off or True/Yes/On. By default, it is assumed True.

New Features#

  • ROCm support has been added matching the existing CUDA implementation based on the thrust library. This enables Qiskit-Aer to run on AMD GPUs, including the AMD Instinct GPU line based on the CDNA architecture. To build the standalone version, the following should be sufficient:

    cmake <Qiskit-Aer source folder> -G Ninja \
      -DCMAKE_INSTALL_PREFIX=<Qiskit-Aer target instalation folder> \
      -DAER_MPI=<set to ON or OFF depending on whether to activate MPI support> \
      -DAER_ROCM_ARCH=<target AMD GPU list, white-space separated, e.g. 'gfx90a gfx908'> \
      -DCMAKE_BUILD_TYPE=Release \
    ninja install

    Alternatively, and possibly preferred for most use cases, you can create a Python wheel file that you can install as part of your Python environemnt:

    cd <Qiskit-Aer source folder>
    QISKIT_AER_PACKAGE_NAME='qiskit-aer-gpu-rocm' \
       python3 bdist_wheel -- \
          -DAER_MPI=<set to ON or OFF depending on whether to activate MPI support> \
          -DAER_ROCM_ARCH=<target AMD GPU list, white-space separated, e.g. 'gfx90a gfx908'>
    pip install --force-reinstall dist/qiskit_aer_gpu_rocm-*.whl

    In both cases, the host system needs to have a functional ROCm instalation and the environment variable ROCM_PATH set pointing to the ROCm instalation folder if that is not the default /opt/rocm. Depending on how your Python environment is set, you might need to install Qiskit-Aer’s required development modules:

    cd <Qiskit-Aer source folder>
    pip install -r requirements-dev.txt
  • This release restructures State classes. Adding circuit executor classes that runs a circuit and manages multiple states for multi-shots simulations or multi-chunk simulations for large number of qubits. Previously StateChunk class manages multiple chunks for multi-shots or multi-chunk simulations but now State class only has one state and all the parallelization codes are moved to Executor classes. Now all State classes are independent from parallelization. Also some of the functions in Aer::Controller class are moved to CircuitExecutor::Executor class.

  • Shot-branching technique that accelerates dynamic circuits simulations is implemented with restructured Executor classes. Shot-branching is currently applicable to statevector density_matrix and tensor_network methods. Shot-branching provides dynamic distribution of multi-shots by branching states when applying dynamic operations (measure, reset, initialize, noises) By default shot_branching_enable is disabled. And by setting shot_branching_sampling_enable, final measures will be done by sampling measure that will speed up to get counts for multiple shots sharing the same state.

  • A new option target_gpus is added to select GPUs used for the simulation. A list of target GPU’s ID is passed for example target_gpus=[0, 2] select 2 GPUs to be used. Without this option, all the available GPUs are used.

  • This release restructures State classes. Adding circuit executor classes that runs a circuit and manages multiple states for multi-shots simulations or multi-chunk simulations for large number of qubits. Previously StateChunk class manages multiple chunks for multi-shots or multi-chunk simulations but now State class only has one state and all the parallelization codes are moved to Executor classes. Now all State classes are independent from parallelization. Also some of the functions in Aer::Controller class are moved to CircuitExecutor::Executor class.

  • Shot-branching technique that accelerates dynamic circuits simulations is implemented with restructured Executor classes. Shot-branching is currently applicable to statevector, density_matrix and tensor_network methods. Shot-branching provides dynamic distribution of multi-shots by branching states when applying dynamic operations (measure, reset, initialize, noises) By default shot_branching_enable is disabled. And by setting shot_branching_sampling_enable, final measures will be done by sampling measure that will speed up to get counts for multiple shots sharing the same state.

  • New option for GPU simulation target_gpus is added. A list of GPUs used for the simulation can be set by this option. Without this option, all the available GPUs are used. For example, if there is 4 GPUs, target_gpus=[0, 2] will use 2 GPUs.

  • Enable 2-qubit gate ECR for aer_stabilizer_simulator. Refer to #1883 < for more details.

  • Implements from_dict() method for QuantumError. This takes a dictionary and checks if style is the one from to_dict() method. If any mismatches are determined then NoiseError is raised. Else dict is parsed and a new QuantumError with noise_ops created.

  • A runtime parameter binding option is implemented to bind paramters at runtime to a single circuit instead running multiple circuits as input. An option runtime_parameter_bind_enable=True enables this feature and for GPU, batched_shots_gpu=True should be also set to speed up simulating parameterized circuit.

  • A new environment variable QISKIT_ADD_CUDA_REQUIREMENTS can be sed to control whether or not build the Python package for Qiskit-Aer with CUDA requirements. This flag can be set to False/No/Off or True/Yes/On. By default it is assumed True. This is useful in case a CUDA instalation is already available on the system where Qiskit-Aer will run. Not including the requirements results in a smaller footprint and facilitates leveraging different CUDA installs for development purposes. The new flag can used like:

    cd <Qiskit-Aer source folder>
    QISKIT_AER_PACKAGE_NAME='qiskit-aer-gpu' \
       python3 bdist_wheel -- \
  • c_if is supportted of reset instruction and an exception is thrown if c_if is called for an instruction that does not support c_if.

  • Support qiskit.circuit.classical.expr.Expr introduced in Qiskit 0.44. If a circuit includes unsupported expression which will be introduced in Qiskit 0.45 or later, AerError is thrown. Objects of sub-classes of Expr are converted to corresponding sub-classes of AER::Operations::CExpr in C++ and evaluated. In addition, AER::Operations::RegComparison in bfunc operation is replaced with corresponding binary operations.

  • Add support of qiskit.circuit.controlflow.SwitchCaseOp that was introduced in qiskit-terra 0.24.0. The instruction is converted to multiple instructions of AerMark and AerJump with c_if conditions.

  • aer_apply_u3 is added to aer_runtime_api.h

  • Update Aer Backend to BackendV2. Refer to #1681<>. BackendV2 is differs from BackendV1 in the following points: changes to string attribute, the configuration attribute no longer exists, and the options attribute is added. For more information about BackendV2 is here<>.

Known Issues#

  • Fix a bug that returns wrong expectation values in Estimator when abelian_grouping=True.

  • Though Aer supports switch for several methods, transpilation of circuits with switch has been failed. This commit enables such transpilation by adding switch_case operations into basis gates.

Upgrade Notes#

  • Fixed a bug that caused results to be incorrectly ordered or errors in Estimator with approximation=True.

  • Improved performance when the same circuits and multiple parameters are passed to Estimator with approximation=True.

  • Qiskit Aer now requires CUDA version for GPU simulator to 11.2 or higher. Previously, CUDA 10.1 was the minimum supported version. This change was necessary because of changes in the upstream CUDA ecosystem, including cuQuantum support. To support users running with different versions of CUDA there is now a separate package available for running with CUDA 11: qiskit-aer-gpu-cu11 and using the qiskit-aer-gpu package now requires CUDA 12. If you’re an existing user of the qiskit-aer-gpu package and want to use CUDA 11 you will need to run:

    pip uninstall qiskit-aer-gpu && pip install -U qiskit-aer-gpu-cu11

    to go from the previously CUDA 10.x compatible qiskit-aer-gpu package’s releases to upgrade to the new CUDA 11 compatible package. If you’re running CUDA 12 locally already you can upgrade the qiskit-aer-gpu package as normal.

  • Improved performance when the same circuits and multiple parameters are passed to Sampler.

  • Adding support of rotation gates (rx, ry and rz gates) to stabilizer method when input theta is multiple of pi/2. If method=automatic is specified (this is default), if all the input theta of rotation gates are multiple of pi/2 method=stabilizer is selected. Of when user sets method=stabilizer and any of theta is not multiple of pi/2, Aer raises an exception.

Deprecation Notes#

  • Options of need to use correct types.

Bug Fixes#

  • Aer runtime api (from contrib) exposed the wrong sx operation, implemented with a rx. The implementation is changed now by adding AerState::apply_mcsx and calling it from aer_apply_sx. This way the api has the same behavior as the documentation states and also how the sx gate behaves in python. Fix for:

  • Performance regression due to introduction of AER::Config is fixed. This class has many fields but is frequently copied in AER::Transpile::CircuitOptimization. Originally json_t (former class for configuration) was also frequently copied but it does have entries in most cases and then this copy overhead is not a problem. With this fix, AER::Transpile::CircuitOptimization does not copy AER::Config.

  • When BLAS calls are failed, because omp threads do not handle exceptions, Aer crashes without any error messages. This fix is for omp threads to catch exceptions correctly and then rethrow them outside of omp loops.

  • Previously, parameters for gates are not validate in C++. If parameters are shorter than expected (due to custom gate), segmentaion faults are thrown. This commit adds checks whether parameter lenght is expceted. This commit will fix issues reported in #1612.

  • Since 0.12.0, parameter values in circuits are temporarily replaced with constant values and parameter values are assigned in C++ library. Therefore, if parameter_binds is specified, simulator returns results with the constnat values as paramter values. With this commit, Aer raises an error if parameter_binds is not specified though circuits have parameters.

  • measure in wrongly read classical memory by assuming opposite ordering of its indices. This fix corrects the assumed ordering. This change affects only and not python applications.

  • Available devices and methods are no longer queried when importing Aer.

  • Previously AerSimulator modifies circuit metadata to maintain consistency between input and output of simulation with side effect of unexpected view of metadata from applicatiln in simiulation. This fix avoids using circuit metadata to maintain consistency internaly and then always provides consistent view of metadata to application.

  • Fixed a bug where the variance in metadata in EstimatorResult was complex and now returns float.

  • Change AER::Vector object alignement to 64-byte. In some cases, it is used to initialize AER:QV::QubitVector objects by moving storage ownership to these objects. As the code assumes that AER:QV::QubitVector storage is at least 32-byte aligned for AVX2 load instructions, this change enforces the same alignement requirements for both AER::Vector and AER:QV::QubitVector objects so that one doesn’t get into segmentation faults.

  • Fixed a build break to compile Qiskit Aer with cuQuautum support (AER_ENABLE_CUQUANTUM=true). This change does not affect build for CPU and normal GPU binaries.

  • Fixed a bug where from_backend() with BackendV2 and non-zero temperature produces relaxation noises with incorrect excitation population. Fixed #1937.

  • Fixed a bug in from_backend() that raised an error when the backend has no T1 and T2 values (i.e. None) for a qubit in its qubit properties. This commit updates NoiseModel.from_backend() and basic_device_gate_errors() so that they add an identity QuantumError (i.e. effectively no thermal relaxation error) to a qubit with no T1 and T2 values for all gates acting on qubits including the qubit. Fixed #1779 and #1815.

  • Fixed a bug where from_backend() raises an error when a backend reports no T2 value (while it reports T1 value) for a qubit, which was an oversight in the previous fix on None handling: #1818. Fixed #1896.

  • Fix an issue even if the number of qubits is set by a coupling map or device’s configuration, when the simulation method is configured, the number of qubits is overwritten in accordance with the method. Fixed #1769

  • A function aer_state_initialize() in C API wrongly takes no argument though it initializes a state created by aer_state(). Example codes pass handler and rouboustness of C compiler allows its compilation. This commit corrects for aer_state_initialize() to take an argument handler to be initialized.

  • This is fix for library path setting in CMakeLists.txt for cuQuantum SDK. Because the latest cuQuantum includes libraries for CUDA 11.x and 12.x, this fix uses CUDA version returned from FindCUDA to the path of libraries of cuQuantum and cuTENSOR.

  • This is fix for static link libraries of cuQuantum when building with CUQUANTUM_STATIC=true.

  • Fixing binary distribution package for GPU support, adding some missing dynamic link pathes for CUDA and cuQuantum libraries. By this fix, Qiskit Aer can be executed without setting LD_LIBRARY_PATH.

  • Fix the version of matplotlib required by seaborn

  • MPI parallelization was not enabled since we have not used qobj. This fix sets the number of processes and MPI rank correctly.

  • OpenMP parallel nested was not correctly set when number of input circuits is less than number of threads. Also parallel state update was not correctly set if number of input circuits is more than 1. This release fixes these settings to get more speed up with OpenMP. For single circuit with multiple-shots run, when nested parallel is used omp_nested=True is set in the metadata of result for a circuit.

  • OpenMP nested parallel simulation for parallel experiments + parallel state update was very slow because gate fusion uses unitary simulator inside and it used omp parallel region. This fix remove parallel region in gate fusion and improve performance of nested parallel simulations

  • AerCircuit is created from a circuit by iterating its operations while skipping barrier instructions. However, skipping barrier instructions make wrong positionings of parameter bindings. This fix adds barrier() and keeps parametr bindings correct.

  • If a circuit has conditional and parameters, the circuit was not be correctly simulated because parameter bindings of Aer used wrong positions to apply parameters. This is from a lack of consideration of bfunc operations injected by conditional. With this commit, parameters are set to correct positions with consideration of injected bfun operations.

  • Parameters for global phases were not correctly set in #1814. Parameter values for global phases were copied to a template circuit and not to actual circuits to be simulated. This commit correctly copies parameter values to circuits to be simulated.

  • Aer still supports Qobj as an argument of run() though it was deprecated. However, since 0.12.0, it always fails if no run_options is specified. This fix enables simulation of Qobj without run_options.

  • This release fixes an issue in measurement function of stabilizer simulator

  • Since 0.12.0, AerConfig is used for simulation configuration while performing strict type checking for arguments of This commit adds casting if argument types are not expected.

  • Adresses two opened issues, one about replacing a char* parameter to a const char*, another one for adding support for the latest vc++ in conan.cmake Changes: Passing const char* to a char* parameter in CacheBlocking::insert_sim_op call: #1905 Add support for the latest VC++ in conan.cmake #1906:

  • Results of were not serializable because they include AerCircuits. This commit makes the results serializable by removing AerCircuits from metadata.

  • :meth:QuantumCircuit.save_statevector() does not work if the circuit is generated from OpenQASM3 text because its quantum registers have duplicated qubit instances. With this commit, :meth:QuantumCircuit.save_statevector() uses :data:QuantumCircuit.qubits to get qubits to be saved.

  • :meth:QuantumCircuit.initialize() with int value was not processed correctly as reported in #1821 <>. This commit enables such initialization by decomposing initialize instructions.

  • Aer will now use omp_set_max_active_levels() instead of the deprecated omp_set_nested() when compiled against recent versions of OpenMP.

  • State::set_config was not called before calling State::required_memory_mb. Extended stabilizer uses parameter from config to calculate required memory so size was not correct before this fix. Now Config is passed to required_memory_mb function.

    State::required_memory_mb for MPS method returned wrong memory size. This fix adds memory size estimation by calculating max bond dimension.

  • requried_memory_mb function for statevector returns wrong value when number of qubits is very large because of overflow of 64 bits integer. Now it returns SIZE_MAX value when number of qubits is too large so that Qiskit Aer can know memory is not sufficient for statvector/unitary/density matrix methods.



The Qiskit Aer 0.12.0 release highlights are:

  • Added a new GPU tensor network simulator based on cuTensorNet

  • Added a new AerDensityMatrix class to the qiskit_aer.quantum_info module

  • Greatly improving the runtime performance of the AerSimulator and the legacy QasmSimulator, StatevectorSimulator, and UnitarySimulator classes by directly converting the input QuantumCircuit objects to an internal C++ representation instead of first serializing the circuit to a QasmQobj. This improvement will be most noticeable for circuits with a small number of qubits or parameterized circuits using the parameter_binds keyword argument.

New Features#

  • Added a new class method from_backend_properties() to the NoiseModel. This enables constructing a new NoiseModel from a BackendProperties object. Similar functionality used to be present in the NoiseModel.from_backend() constructor, however it was removed since a BackendProperties object alone doesn’t contain sufficient information to create a NoiseModel object.

  • Added a new keyword argument, abelian_grouping, to the Estimator. This argument is used to control whether the Estimator will group the input observables into qubit-wise commutable observables which reduces the number of circuit executions required to compute the expectation value and improves the runtime performance of the Estimator. By default this is set to True.

  • AerState has a new method initialize_density_matrix() that sets a density matrix to AER::QV::DensityMatrix. This method will be called in q.i.states.DensityMatrix to initialize its data with ndarray. initialize_density_matrix() has a boolean argument that specifies copy or share of ndarray data. If the data is shared with C++ and python, the data must not be collected in python while C++ accesses it.

  • The overhead for running simulations with run() (for all simulator backend classess) has been greatly reduced. This was accomplished by no longer internally serializing QuantumCircuit objects into QasmQobj and instead the QuantumCircuit object directly to an internal C++ circuit structure used for simulation. This improvement is most noticeable for simulations of circuts with a small number of qubits or parameterized circuits using the parameter_binds keyword argument of run(). Note that pulse simualation (via the now deprecated PulseSimulator) and DASK-based simulation still use the internal serialization and will not see this performance improvement.

  • Added a new method to the AerJob, circuits(), which returns a list of QuantumCircuit objects. This method returns None if Qobj is used for simulation.

  • AerState and AerStatevector now support applying Kraus operators. In AerStatevector, one of the Kraus operators is applied randomly to the quantum state based on the error probabilities.

  • Added a new simulation method based on NVIDIA’s cuTensorNet APIs of cuQuantum SDK. This provides a GPU accelerated general tensor network simulator that can simulate any quantum circuit, by internally translating the circuit into a tensor network to perform the simulation. To use this simulation method, set method="tensor_network" and device="GPU" when initializing an AerSimulator object. For example:

    from qiskit_aer import AerSimulator
    tensor_net_sim = AerSimulator(method="tensor_network", device="GPU")

    This method supports both statevector and density matrix simulations. Noise simulation can also be done with a density matrix single shot simulation if there are not any SaveStatevector operations in the circuit.

    This new simulation method also supports parallelization with multiple GPUs and MPI processes by using tensor network slicing technique. However, this type of simulation will likely take a very long time if the input circuits are complicated.

  • The BLA_VENDOR environment variable can now be specified to use a different BLAS library when building Qiskit Aer from source. By default if this is not specified OpenBLAS will be used by default. If the BLAS library specified in BLA_VENDOR` can not be found then the Cmake build process will stop.

Known Issues#

  • This release of Qiskit Aer is not compatible with the Conan 2.X release series. If you are building Qiskit Aer from source manually ensure that you are using a Conan 1.x release. Compatibility with newer versions of Conan will be fixed in a future release. You can refer to issue #1730 for more details.

Upgrade Notes#

  • The default behavior of the Estimator primitive will now group the input observable into qubit-wise commutable observables. The grouping reduces the number of circuits to be executed and improves the performance. If you desire the previous behavior you can initialize your Estimator instance with the keyword argument abelian_grouping=False.

  • Removed the usage of primitives with the context manager and the initialization with circuits, (observables only for Estimator), and parameters which has been deprecated in the Qiskit Terra 0.22.0 release in October 2022.

  • The behavior of run() method has changed when invalid or otherwise unsimulatable QuantumCircuit objects are passed as an input. Previously, in these cases the run() method would return an AerJob whose result() method would return a Result with the ERROR or PARTIAL COMPLETED (depending on whether all the circuit inputs or only some were invalid or not). Starting in this release instead of returning a result object with these statuses an exception will be raised instead. This change was necessary because of the performance improvements by no longer internally serializing the QuantumCircuit objects to a Qobj before passing it to C++, instead the direct conversion from QuantumCircuit now errors directly when trying to simulate a circuit Qiskit Aer is unable to execute. If you desire the previous behavior you can build Qiskit Aer in standalone mode and manually serialize your QuantumCircuit objects to a JSON representation of the QasmQobj which you then pass to the standalone Aer binary which will retain the previous behavior.

  • A deprecated method add_nonlocal_quantum_error() in NoiseModel has been removed. No alternative method is available. If you want to add non-local quantum errors, you should write a transpiler pass that inserts your own quantum error into a circuit, and run the pass just before running the circuit on Aer simulator.

  • A deprecated standard_gates argument broadly used in several methods and functions (listed below) across noise module has been removed.

    • NoiseModel.from_backend() and noise.device.basic_device_gate_errors()

    • kraus_error(), mixed_unitary_error(), pauli_error() and depolarizing_error() in noise.errors.standard_errors

    • QuantumError.__init__()

    No alternative means are available because the user should be agnostic about how the simulator represents noises (quantum errors) internally.

  • The constructor of QuantumError has now dropped the support of deprecated json-like input for noise_ops argument. Use the new styple input for noise_ops argument instead, for example,

    from qiskit.circuit.library import IGate, XGate
    from qiskit_aer.noise import QuantumError
    error = QuantumError([
        ((IGate(), [1]), 0.9),
        ((XGate(), [1]), 0.1),
    # json-like input is no longer accepted (the following code fails)
    #  error = QuantumError([
    #      ([{"name": "I", "qubits": [1]}], 0.9),
    #      ([{"name": "X", "qubits": [1]}], 0.1),
    #  ])

    Also it has dropped deprecated arguments:

    • number_of_qubits: Use QuantumCircuit to define noise_ops instead.

    • atol: Use QuantumError.atol attribute instead.

    • standard_gates: No alternative is available (users should not too much care about internal representation of quantum errors).

  • The deprecated noise.errors.errorutils module has been entirely removed and no alternatives are available. All functions in the module were helper functions meant to be used only for implementing functions in standard_errors (i.e. they should have been provided as private functions) and no longer used in it.

  • The deprecated utils.noise_remapper have been entirely removed and no alternatives are available since the C++ code now automatically truncates and remaps noise models if it truncates circuits.

  • All deprecated functions (pauli_operators() and reset_operators()) and class (NoiseTransformer) in utils.noise_transformation module have been removed, and no alternatives are available. They were in fact private functions/class used only for implementing approximate_quantum_error() and should not have been public.

  • The previously deprecated qobj argument name of the AerSimulator and PulseSimulator classes’ run() method has now been removed. This argument name was deprecated as part of the Qiskit Aer 0.8.0 release and has been by the circuits and schedules argument name respectively.

  • Aer’s has been updated to no longer attempt to make calls to pip to install build requirements, both manually and via the setup_requires option in setuptools.setup. The preferred way to build Aer is to use a PEP 517-compatible builder such as:

    pip install .

    This change means that a direct call to will no longer work if the build requirements are not installed. This is inline with modern Python packaging guidelines.

Deprecation Notes#

  • Support for running Qiskit Aer with Python 3.7 support has been deprecated and will be removed in a future release. This means starting in a future release you will need to upgrade the Python version you’re using to Python 3.8 or above.

  • The PulseSimulator backend has been deprecated and will be removed in a future release. If you’re using the PulseSimulator backend to perform pulse level simulation, instead you should use the Qiskit Dynamics library instead to perform the simulation. Qiskit Dynamics provides a more flexible and robust pulse level simulation framework than the PulseSimulator backend.

  • The qobj() method of the AerJob class is now deprecated and will be removed in a future release. The use of the qobj format as input to run() has been deprecated since qiskit-aer 0.9.0 and in most cases this method would return None now anyway. If you’d like to get the input to the run() method now you can use the circuits() method instead, which will return the QuantumCircuit objects that were simulated in the job.

  • A warnings argument broadly used in several methods and functions across noise module has been deprecated in favor of the use of filtering functions in Python’s standard warnings library.

Bug Fixes#

  • Fixed an issue when creating a new AerStatevector instance from a numpy.ndarray that had non-contiguous memory. Previously, this would result in unexpected behavior (and a potential error) as the AerStatevector assumed the input array was contiguous. This has been fixed so that memory layout is checked and the numpy.ndarray will be copied internally as a contiguous array before using it.

  • Fixed an issue with the Sampler class where it would previously fail if the input QuantumCircuit contained multiple multiple classical registers. Fixed #1679

  • The bits count of classical register used on the GPU was not set before calculating free available memory for chunks that causes infinite loop. So this fix set bits count before allocating chunks if batch shots execution is enabled.

  • Fix build errors and test errors when enabling GPU but disabling cuQuantum.

  • Fixed an issue in the matrix product state simulation method (i.e. setting the keyword argument method="matrix_product_state" when initializing an AerSimulator object) where the simulator would incorrectly sort the qubits prior to performing measurment potentially resulting in an infinite loop. This has been fixed so the measurement of the qubits occurs in the order of the current MPS structure and then sorting afterwards as a post-processing step. This also will likely improve the performance of the simulation method and enable more accurate representation of entangled states. Fixed #1694

  • The AerSimulator backend with methods:

    • statevector

    • density_matrix

    • matrix_product_state

    • stabilizer

    now report that they support break_loop and continue_loop instructions when used as backends for the Terra transpile() function. The simulators already did support these, but had just not been reporting it.



The Qiskit Aer 0.11.0 release highlights are:

New Features#

  • Added support for BackendV2 to from_backend(). Now it can generate a NoiseModel object from an input BackendV2 instance. When a BackendV2 input is used on from_backend() the two deprecated options, standard_gates and warnings, are gracefully ignored.

  • Added Aer implementation of primitives, Sampler and BaseSampler and BaseEstimator interfaces leverage qiskit aer to efficiently perform the computation of the primitive operations. You can refer to the qiskit.primitives docs for a more detailed description of the primitives API.

  • Added a shared library to Qiskit Aer that allows external programs to use Aer’s simulation methods. This is an experimental feature and its API may be changed without the deprecation period.

  • Added support for M1 macOS systems. Precompiled binaries for supported Python versions >=3.8 on arm64 macOS will now be published on PyPI for this and future releases.

  • Added support for cuQuantum, NVIDIA’s APIs for quantum computing, to accelerate statevector, density matrix and unitary simulators by using GPUs. This is experiemental implementation for cuQuantum Beta 2. (0.1.0) cuStateVec APIs are enabled to accelerate instead of Aer’s implementations by building Aer by setting path of cuQuantum to CUSTATEVEC_ROOT. (binary distribution is not available currently.) cuStateVector is enabled by setting device='GPU' and cuStateVec_threshold options. cuStateVec is enabled when number of qubits of input circuit is equal or greater than cuStateVec_threshold.

  • Added partial support for running on ppc64le and s390x Linux platforms. This release will start publishing pre-compiled binaries for ppc64le and s390x Linux platforms on all Python versions. However, unlike other supported platforms not all of Qiskit’s upstream dependencies support these platforms yet. So a C/C++ compiler may be required to build and install these dependencies and a simple pip install qiskit-aer with just a working Python environment will not be sufficient to install Qiskit Aer. Additionally, these same constraints prevent us from testing the pre-compiled wheels before publishing them, so the same guarantees around platform support that exist for the other platforms don’t apply to these platforms.

  • Allow initialization with a label, that consists of +-rl. Now the following code works:

    import qiskit
    from qiskit_aer import AerSimulator
    qc = qiskit.QuantumCircuit(4)

Known Issues#

  • When running on Linux s390x platforms (or other big endian platforms) running circuits that contain UnitaryGate operations will not work because of an endianess bug. See #1506 for more details.

Upgrade Notes#

  • MPI parallelization for large number of qubits is optimized to apply multiple chunk-swaps as all-to-all communication that can decrease data size exchanged over MPI processes. This upgrade improve scalability of parallelization.

  • Set default fusion_max_qubit and fusion_threshold depending on the configured method for AerSimulator. Previously, the default values of fusion_max_qubit and fusion_threshold were 5 and 14 respectively for all simulation methods. However, their optimal values depend on running methods. If you depended on the previous defaults you can explicitly set fusion_max_qubit=5 or fusion_threshold=14 to retain the previous default behavior. For example:

    from qiskit_aer import AerSimulator
    sim = AerSimulator(method='mps', fusion_max_qubit=5, fusion_threshold=14)
  • This is update to support cuQuantum including bug fix of thread safety in some cuStateVec APIs. Now Qiskit Aer turns on multi-threading for multi-shots and multi-chunk parallelization when enabling cuStateVec.

  • Running qiskit-aer with Python 3.6 is no longer supported. Python >= 3.7 is now required to install and run qiskit-aer.

  • The qiskit-aer Python package has moved to be a self-contained namespace, qiskit_aer. Previously, it shared a namespace with qiskit-terra by being qiskit.providers.aer. This was problematic for several reasons, and this release moves away from it. For the time being import qiskit.providers.aer will continue to work and redirect to qiskit_aer automatically. Imports from the legacy qiskit.provider.aer namespace will emit a DeprecationWarning in the future. To avoid any potential issues starting with this release, updating all imports from qiskit.providers.aer to qiskit_aer and from qiskit.Aer to qiskit_aer.Aer is recommended.

  • Removed snapshot instructions (such as SnapshotStatevector) which were deprecated since 0.9.0. Applications that use these instructions need to be modified to use corresponding save instructions (such as SaveStatevector).

  • Removed the qiskit_aer.extensions module completely. With the removal of the snapshot instructions, this module has become empty and no longer serves a purpose.

  • The required version of Qiskit Terra has been bumped to 0.20.0.

Bug Fixes#

  • Fixes for MPI chunk distribution. Including fix for global indexing for Thrust implementations, fix for cache blocking of non-gate operations. Also savestatevector returns same statevector to all processes (only 1st process received statevector previously.)

  • Handles a multiplexer gate as a unitary gate if it has no control qubits. Previously, if a multiplexer gate does not have control qubits, quantum state was not updated.

  • Fixes a bug in RelaxationNoisePass where instruction durations were always assumed to be in dt time units, regardless of the actual unit of the isntruction. Now unit conversion is correctly handled for all instruction duration units.

    See #1453 for details.

  • Fixed simulation of for loops where the loop parameter was not used in the body of the loop. For example, previously this code would fail, but will now succeed:

    import qiskit
    from qiskit_aer import AerSimulator
    qc = qiskit.QuantumCircuit(2)
    with qc.for_loop(range(4)) as i:
        qc.h(0), 1)
  • Fixes a bug in NoiseModel.from_backend() that raised an error when T2 value greater than 2 * T1 was supplied by the backend. After this fix, it becomes to truncate T2 value up to 2 * T1 and issue a user warning if truncates. The bug was introduced at #1391 and, before that, NoiseModel.from_backend() had truncated the T2 value up to 2 * T1 silently.

    See Issue 1464 for details.

  • Fix performance regression in noisy simulations due to large increase in serialization overhead for loading noise models from Python into C++ resulting from unintended nested Python multiprocessing calls. See issue 1407 for details.

  • This is the fix for Issue #1557. Different seed numbers are generated for each process if seed_simulator option is not set. This fix average seed set in Circuit for all processes to use the same seed number.

  • This is a fix of MPI parallelization for multi-chunk parallelization and multi-shot distribution over parallel processes. There were missing distribution configuration that prevents MPI distribution, is now fixed.

  • This is fix for cache blocking transpiler and chunk parallelization for GPUs or MPI. This fix fixes issue with qubits which has many control or target qubits (> blocking_qubits). From this fix, only target qubits of the multi-controlled gate is cache blocked in blocking_qubits. But it does not support case if number of target qubits is still larger than blocking_qubits (i.e. large unitary matrix multiplication)

  • Fixes a bug in QuantumError.to_dict() where N-qubit circuit instructions where the assembled instruction always applied to qubits [0, ..., N-1] rather than the instruction qubits. This bug also affected device and fake backend noise models.

    See Issue 1415 for details.

  • Because a seed was randomly assigned to each circuit if seed_simulator is not set, multi-circuit simulation was not reproducible with another multi-circuit simulation. Users needed to run multiple single-circuit simulation with the seed_simulator which is randomly assigned in the multi-circuit simulation. This fix allows users to reproduce multi-circuit simulation with another multi-circuit simulation by setting seed_simulator of the first circuit in the first multi-circuit simulation. This fix also resolve an issue reported in, where simulation with parameter-binds returns identical results for each circuit instance.

  • Fix performance issue in multi-shots batched optimization for GPU when using Pauli noise. This fix allows multi-threading to runtime noise sampling, and uses nested OpenMP parallelization when using multiple GPUs. This is fix for issue 1473 <>

  • This is the fix for cuStateVec support, fix for build error because of specification change of some APIs of cuStateVec from cuQuantum version 0.40.



The Qiskit Aer 0.10 release includes several performance and noise model improvements. Some highlights are:

  • Improved performance for parallel shot GPU and HPC simulations

  • Support for simulation of circuits containing QASM 3.0 control-flow instructions

  • Support for relaxation noise on scheduled circuits in backend noise models

  • Support of user-created transpiler passes for defining custom gate errors and noise models, and inserting them into circuits.

New Features#

  • Added a batched-shot simulation optimization for GPU simulations. This optional feature will use available memory on 1 or more GPUs to run multiple simulation shots in parallel for greatly improved performance on multi-shot simulations with noise models and/or intermediate measurements.

    This option is enabled by default when using device="GPU" and a simulation method of either "statevector" or "density_matrix" with the AerSimulator. It can be disabled by setting batched_shots_gpu=False in the simulator options.

    This optimization is most beneficial for small to medium numbers of qubits where there is sufficient GPU memory to run multiple simulations in parallel. The maximum number of active circuit qubits for enabling this optimization can be configured using the batch_shots_gpu_max_qubits simulator option. The default value of this option is 16.

  • Added the new max_shot_size option to a custom executor for running multiple shots of a noisy circuit in parallel.

    For example configuring max_shot_size with a custom executor:

    backend = AerSimulator(
       max_shot_size=1, max_job_size=1, executor=custom_executor)
    job =

    will split the shots of a noisy circuit into multiple circuits. After all individual shots have finished executing, the job results are automatically combined into a single Result object that is returned by job.result().

  • Added the mps_swap_direction simulator option that allows the user to determine the direction of internal swaps, when they are inserted for a 2-qubit gate. Possible values are "mps_swap_right" and "mps_swap_left". The direction of the swaps may affect performance, depending on the circuit.

  • Implemented a new measurement sampling optimization for the "matrix_product_state" simulation method of the AerSimulator. Currently this algorithm is used only when all qubits are measured and when the simulator mps_sample_measure_algorithm simulator option is set to "mps_probabilities".

  • Improved the performance of the measure instruction for the "matrix_product_state" simulation method of the AerSimulator.

  • Added a SaveClifford instruction for saving the state of the stabilizer simulation method as a Clifford object.

    Note that this instruction is essentially equivalent to the SaveStabilizer instruction, however that instruction will return the saved state as a StabilizerState object instead of a Clifford object.

  • Added two transpiler passes for inserting instruction-dependent quantum errors into circuits:

    • qiskit.providers.aer.noise.LocalNoisePass

    • qiskit.providers.aer.noise.RelaxationNoisePass

    The LocalNoisePass pass can be used to implement custom parameterized noise models by defining a noise generating function of the form

    def fn(
        inst: Instruction,
        qubits: Optional[List[int]] = None,
    ) -> InstructionLike

    which returns a noise instruction (eg. a QuantumError or other instruction) that can depend on any properties or parameters of the instruction and qubit arguements.

    This function can be applied to all instructions in a circuit, or a specified subset (See the LocalNoisePass documentation for additional details.)

    The RelaxationNoisePass is a special case of the LocalNoisePass using a predefined noise function that returns a tensor product of thermal_relaxation_error() on each qubit in an instruction, dependent on the instruction’s duration and the supplied relaxation time constant parameters of the pass.

  • The basic device noise model implemented by NoiseModel.from_backend() and AerSimulator.from_backend() has been upgraded to allow adding duration-dependent relaxation errors on circuit delay gates using the RelaxationNoisePass.

    To enable this noise when running noisy simulations you must first schedule your circuit to insert scheduled delay instructions as follows:

    backend = AerSimulator.from_backend(ibmq_backend)
    scheduled_circuit = qiskit.transpile(
        circuit, backend=backend, scheduling_method='asap')
    result =

    If the circuit is transpiled without being scheduled (and also contains no delay instructions) the noisy simulation will not include the effect of delay relaxation errors. In this case the simulation will be equivalent to the previous qiskit-aer 0.9 simulation where relaxation noise is only added to gate instructions based on their duration as obtained from the backend properties.

  • The constructor of QuantumError now accepts several new types of input as noise_ops argument, for example:

    import numpy as np
    from qiskit import QuantumCircuit
    from qiskit.circuit.library import IGate, XGate, Reset
    from qiskit.quantum_info import Kraus
    from qiskit.providers.aer.noise import QuantumError
    # Quantum channels
    kraus = Kraus([
        np.array([[1, 0], [0, np.sqrt(1 - 0.9)]], dtype=complex),
        np.array([[0, 0], [0, np.sqrt(0.9)]], dtype=complex)
    # Construction from a QuantumCircuit
    qc = QuantumCircuit(2)
    qc.h(0), 1)
    error = QuantumError(qc)
    # Construction from a tuple of (Instruction, List[int]), where the list of
    # integers represents the qubits.
    error = QuantumError((Reset(), [0]))
    # Construction from an iterable of objects in the same form as above, but
    # where each also has an associated probability.
    error = QuantumError([
        ((IGate(), [0]), 0.9),
        ((XGate(), [0]), 0.1),
    # A short-hand for the iterable form above, where the qubits are implicit,
    # and each instruction is over all qubits.
    error = QuantumError([(IGate(), 0.9), (XGate(), 0.1)])

    Note that the original JSON-based input format is deperecated.

  • Added a utility function qiskit.providers.aer.utils.transform_noise_model() for constructing a noise model by applying a supplied function to all QuantumErrors in the noise model.

  • Added two utility functions qiskit.providers.aer.utils.transpile_quantum_error() and qiskit.providers.aer.utils.transpile_noise_model() for transpiling the circuits contained in QuantumError, and all errors in a NoiseModel.

  • Added the ability to add QuantumError objects directly to a QuantumCircuit without converting to a Kraus instruction.

    Circuits containing quantum errors can now be run on the AerSimulator and QasmSimulator simulators as an alternative to, or in addition to, building a NoiseModel for defining noisy circuit instructions.


    from qiskit import QuantumCircuit
    from qiskit.providers.aer import AerSimulator
    from qiskit.providers.aer.noise import pauli_error
    error_h = pauli_error([('I', 0.95), ('X', 0.05)])
    error_cx = pauli_error([('II', 0.9), ('XX', 0.1)])
    qc = QuantumCircuit(3)
    qc.append(error_h, [0]), 1)
    qc.append(error_cx, [0, 1]), 2)
    qc.append(error_cx, [0, 2])
    backend = AerSimulator(method='stabilizer')
    result =

    Circuits containing quantum errors can also be evaluated using the quantum_info quantum channel and DensityMatrix classes.

Upgrade Notes#

  • Changed the default value of standard_gates to None for all functions in qiskit.providers.aer.noise.errors.standard_errors as those functions are updated so that they use standard gates by default.

Deprecation Notes#

  • Using NumPy ndarray methods and attributes on the return type of save_statevector(), save_density_matrix(), save_unitary(), and save_superop() has been deprecated, and will stop working in a future release. These instructions now return qiskit.quantum_info classes for their return types. Partial backwards compatability with treating these objects as NumPy arrays is implemented by forwarding methods to the internal array during the deprecation period.

  • Passing in a BackendProperties object for the backend argument of NoiseModel.from_backend() has been deprecated, as it is incompatible with duration dependent delay noises, and will be removed in a future release. Pass in a Qiskit Terra BackendV1 object instead.

  • Deprecated the number_of_qubits option of the QuantumError constructor in favor of automatic determination of the dimension.

  • Deprecated the standard_gates option of the QuantumError constructor in favor of externalizing such basis-change functionality. In many cases, you can transform any error into an error defined only with specific gates using approximate_quantum_error().

  • Deprecated the standard_gates option of all functions in qiskit.providers.aer.noise.errors.standard_errors in favor of returning errors in the form of a mixture of standard gates as much as possible by default.

  • Deprecated all functions in errorutils because they are helper functions meant to be used only for implementing functions in qiskit.providers.aer.noise.errors.standard_errors and they should have been provided as private functions.

  • Deprecated the standard_gates option of NoiseModel.from_backend() in favor of externalizing such basis-change functionality.

  • Deprecated all public variables, functions and classes in qiskit.providers.aer.noise.utils.noise_transformation except for approximate_quantum_error() and approximate_noise_model(), because they are helper functions meant to be used only for implementing the approximate_* functions and they should have been provided as private functions.

  • Deprecated remap_noise_model() since the C++ code now automatically truncates and remaps noise models if it truncates circuits.

Other Notes#

  • Changes in the implementation of the function approximate_quantum_error() may change the resulting approximate error compared to Qiskit Aer 0.9.



The 0.9 release includes new backend options for parallel exeuction of large numbers of circuits on a HPC cluster using a Dask distributed, along with other general performance improvements and bug fixes.

New Features#

  • Add qiskit library SXdgGate and CUGate to the supported basis gates for the Aer simulator backends. Note that the CUGate gate is only natively supported for the statevector and unitary methods. For other simulation methods it must be transpiled to the supported basis gates for that method.

  • Adds support for N-qubit Pauli gate ( qiskit.circuit.library.generalized_gates.PauliGate) to all simulation methods of the AerSimulator and QasmSimulator.

  • Adds the ability to set a custom executor and configure job splitting for executing multiple circuits in parallel on a HPC clustor. A custom executor can be set using the executor option, and job splitting is configured by using the max_job_size option.

    For example configuring a backend and executing using

    backend = AerSimulator(max_job_size=1, executor=custom_executor)
    job =

    will split the exection into multiple jobs each containing a single circuit. If job splitting is enabled the run method will return a AerJobSet object containing all the individual AerJob classes. After all individual jobs finish running the job results are automatically combined into a single Result object that is returned by job.result().

    Supported executors include those in the Python concurrent.futures module (eg. ThreadPoolExecutor, ProcessPoolExecutor), and Dask distributed Client executors if the optional dask library is installed. Using a Dask executor allows configuring parallel execution of multiple circuits on HPC clusters. See the Dask executor API Documentation for additional details on using Dask executors for HPC simulation.

Upgrade Notes#

  • The default basis for the NoiseModel class has been changed from ["id", "u3", "cx"] to ["id", "rz", "sx", "cx"] due to the deprecation of the u3 circuit method in qiskit-terra and change of qiskit-ibmq-provider backend basis gates. To use the old basis gates you can initialize a noise model with custom basis gates as NoiseModel(basis_gates=["id", "u3", "cx"]).

  • Removed the backend_options kwarg from the run methnod of Aer backends that was deprecated in qiskit-aer 0.7. All run options must now be passed as separate kwargs.

  • Removed passing system_model as a positional arg for the run method of the PulseSimulator.

Deprecation Notes#

  • Passing an assembled qobj directly to the run() method of the Aer simulator backends has been deprecated in favor of passing transpiled circuits directly as, **run_options).

  • All snapshot instructions in qiskit.providers.aer.extensions have been deprecated. For replacement use the save instructions from the qiskit.providers.aer.library module.

  • Adding non-local quantum errors to a NoiseModel has been deprecated due to inconsistencies in how this noise is applied to the optimized circuit. Non-local noise should be manually added to a scheduled circuit in Qiskit using a custom transpiler pass before being run on the simulator.

  • Use of the method option of the StatevectorSimulator, and UnitarySimulator to run a GPU simulation has been deprecated. To run a GPU simulation on a compatible system use the option device='GPU' instead.

Bug Fixes#

  • Fixes bug where the if the required memory is smaller than the system memory the multi-chunk simulation method was enabled and simulation was still started. This case will now throw an insufficient memory exception.

  • Fixes issue where setting the shots option for a backend with set_options(shots=k) was always running the default number of shots (1024) rather than the specified value.

  • Fixes a bug in how the AerSimulator handled the option value for max_parallel_experiments=1. Previously this was treated the same as max_parallel_experiments=0.

  • Fixes bug in the extended_stabilizer simulation method where it incorrectly treated qelay gate and multi-qubit Pauli instructions as unsupported.

  • Fixes typo in the AerSimulator and QasmSimulator options for the extended_stabilizer_norm_estimation_repetitions option.