Skip to main contentIBM Quantum Documentation

Qiskit 0.34 release notes


Terra 0.19.2


Qiskit Terra 0.19.2 is predominantly a bugfix release, but also now comes with wheels built for Python 3.10 on all major platforms.

New Features

  • Added support for running with Python 3.10. This includes publishing precompiled binaries to PyPI for Python 3.10 on supported platforms.

Upgrade Notes

  • Starting from Python 3.10, Qiskit Terra will have reduced support for 32-bit platforms. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: in a new tab)) This is because the upstream dependencies Numpy and Scipy have dropped support for them. Qiskit will still publish precompiled binaries for these platforms, but we’re unable to test the packages prior to publishing, and you will need a C/C++ compiler so that pip can build their dependencies from source. If you’re using one of these platforms, we recommended that you use Python 3.7, 3.8, or 3.9.

Bug Fixes

  • Fixed a bug where the CVaRMeasurement attempted to convert a PauliSumOp to a dense matrix to check whether it were diagonal. For large operators (> 16 qubits) this computation was extremely expensive and raised an error if not explicitly enabled using qiskit.utils.algorithm_globals.massive = True. The check is now efficient even for large numbers of qubits.

  • DAGCircuit.draw() and the associated function dag_drawer() will now show a more useful error message when the provided filename is not valid.

  • QuantumCircuit.add_register() will no longer cause duplicate AncillaQubit references in a circuit when given an AncillaRegister whose bits are already present.

  • Fixed conversion of QuantumCircuits with classical conditions on single, registerless Clbit s to Instructions when using the circuit_to_instruction() function or the QuantumCircuit.to_instruction() method. For example, the following will now work:

    from qiskit.circuit import QuantumCircuit, Qubit, Clbit
    qc = QuantumCircuit([Qubit(), Clbit()])
    qc.h(0).c_if(qc.clbits[0], 0)
  • Registers will now correctly reject duplicate bits. Fixed #7446(opens in a new tab).

  • The FakeOpenPulse2Q mock backend now has T2 times and readout errors stored for its qubits. These are arbitrary values, approximately consistent with real backends at the time of its creation.

  • Fix the qubit order of 2-qubit evolutions in the PauliEvolutionGate, if used with a product formula synthesis. For instance, before, the evolution of IIZ + IZI + IZZ

    from qiskit.circuit.library import PauliEvolutionGate
    from qiskit.opflow import I, Z
    operator = (I ^ I ^ Z) + (I ^ Z ^ I) + (I ^ Z ^ Z)


    q_0:Rz(2) ├────────
    q_1:Rz(2) ├─■──────
         └───────┘ │ZZ(2)
    q_2: ──────────■──────

    whereas now it correctly yields

    q_0:Rz(2) ├─■──────
         ├───────┤ │ZZ(2)
    q_1:Rz(2) ├─■──────
    q_2: ─────────────────
  • Fixed a problem in the latex and mpl circuit drawers when register names with multiple underscores in the name did not display correctly.

  • Negative numbers in array outputs from the drawers will now appear as decimal numbers instead of fractions with huge numerators and denominators. Like positive numbers, they will still be fractions if the ratio is between small numbers.

  • Fixed an issue with the Target.get_non_global_operation_names() method when running on a target incorrectly raising an exception on targets with ideal global operations. Previously, if this method was called on a target that contained any ideal globally defined operations, where the instruction properties are set to None, this method would raise an exception instead of treating that instruction as global.

  • Fixed an issue with the transpile() function where it could fail when being passed a Target object directly with the target kwarg.

  • Fixed an issue with the transpile() function where it could fail when the backend argument was a BackendV2 or a Target via the target kwarg that contained ideal globally defined operations.

  • Fixed an issue where plotting Bloch spheres could cause an AttributeError to be raised in Jupyter or when trying to crop figures down to size with Matplotlib 3.3 or 3.4 (but not 3.5). For example, the following code would previously crash with a message:

    AttributeError: 'Arrow3D' object has no attribute '_path2d'

    but will now succeed with all current supported versions of Matplotlib:

    from qiskit.visualization import plot_bloch_vector
    plot_bloch_vector([0, 1, 0]).savefig("tmp.png", bbox_inches='tight')
  • Fixed a bug in PauliSumOp.permute() where the object on which the method is called was permuted in-place, instead of returning a permuted copy. This bug only occured for permutations that left the number of qubits in the operator unchanged.

  • Fixed the PauliEvolutionGate.inverse() method, which previously computed the inverse by inverting the evolution time. This was only the correct inverse if the operator was evolved exactly. In particular, this led to the inverse of Trotterization-based time evolutions being incorrect.

  • The QuantumInstance.execute() method will no longer mutate its input if it is given a list of circuits.

  • Fixed QPY serialisation of custom instructions which had an explicit no-op definition. Previously these would be written and subsequently read the same way as if they were opaque gates (with no given definition). They will now correctly round-trip an empty definition. For example, the following will now be correct:

    import io
    from qiskit.circuit import Instruction, QuantumCircuit, qpy_serialization
    # This instruction is explicitly defined as a one-qubit gate with no
    # operations.
    empty = QuantumCircuit(1, name="empty").to_instruction()
    # This instruction will perform some operations that are only known
    # by the hardware backend.
    opaque = Instruction("opaque", 1, 0, [])
    circuit = QuantumCircuit(2)
    circuit.append(empty, [0], [])
    circuit.append(opaque, [1], [])
    qpy_file = io.BytesIO()
    qpy_serialization.dump(circuit, qpy_file)
    new_circuit = qpy_serialization.load(qpy_file)[0]
    # Previously both instructions in `new_circuit` would now be opaque, but
    # there is now a correct distinction.
    circuit == new_circuit
  • Added a missing BackendV2.provider attribute to implementations of the BackendV2 abstract class. Previously, BackendV2 backends could be initialized with a provider but that was not accessible to users.

  • Fixed support for the QuantumInstance class when running with a BackendV2 backend. Previously, attempting to use a QuantumInstance with a BackendV2 would have resulted in an error.

  • Fixed a bug in VQE where the parameters of the ansatz were still explicitly ASCII-sorted by their name if the ansatz was resized. This led to a mismatched order of the optimized values in the optimal_point attribute of the result object.

    In particular, this bug occurred if no ansatz was set by the user and the VQE chose a default with 11 or more free parameters.

  • Stopped the parser in QuantumCircuit.from_qasm_str() and from_qasm_file() from accepting OpenQASM programs that identified themselves as being from a language version other than 2.0. This parser is only for OpenQASM 2.0; support for imported circuits from OpenQASM 3.0 will be added in an upcoming release.

  • Fixed QPY serialization of QuantumCircuit objects that contained control flow instructions. Previously if you attempted to serialize a circuit containing IfElseOp, WhileLoopOp, or ForLoopOp the serialization would fail. Fixed #7583(opens in a new tab).

  • Fixed QPY serialization of QuantumCircuit containing subsets of bits from a QuantumRegister or ClassicalRegister. Previously if you tried to serialize a circuit like this it would incorrectly treat these bits as standalone Qubit or Clbit without having a register set. For example, if you try to serialize a circuit like:

    import io
    from qiskit import QuantumCircuit, QuantumRegister
    from qiskit.circuit.qpy_serialization import load, dump
    qr = QuantumRegister(2)
    qc = QuantumCircuit([qr[0]])
    with open('file.qpy', 'wb') as fd:
        dump(qc, fd)

    when that circuit is loaded now the registers will be correctly populated fully even though the circuit only contains a subset of the bits from the register.

  • QFT will now warn if it is instantiated or built with settings that will cause it to lose precision, rather than raising an OverflowError. This can happen if the number of qubits is very large (slightly over 1000) without the approximation degree being similarly large. The circuit will now build successfully, but some angles might be indistinguishable from zero, due to limitations in double-precision floating-point numbers.

Aer 0.10.3


Qiskit Aer 0.10.3 is mainly a bugfix release, fixing several bugs that have been discovered since the 0.10.2 release. Howver, this release also introduces support for running with Python 3.10 including precompiled binary wheels on all major platforms. This release also includes precompiled binary wheels for arm64 on macOS.

New Features

  • Added support for running with Python 3.10. This includes publishing precompiled binaries to PyPI for Python 3.10 on supported platforms.

  • 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.

Upgrade Notes

  • Qiskit Aer no longer fully supports 32 bit platforms on Python >= 3.10. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: in a new tab)) This is because the upstream dependencies Numpy and Scipy have dropped support for them. Qiskit will still publish precompiled binaries for these platforms, but we’re unable to test the packages prior to publishing, and you will need a C/C++ compiler so that pip can build their dependencies from source. If you’re using one of these platforms, we recommended that you use Python 3.7, 3.8, or 3.9.

Bug Fixes

  • 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(opens in a new tab) for details.

  • Fixes an issue with LocalNoisePass for noise functions that return a QuantumCircuit for the noise op. These were appended to the DAG as an opaque circuit instruction that must be unrolled to be simulated. This fix composes them so that the cirucit instructions are added to the new DAG and can be simulated without additional unrolling if all circuit instructions are supported by the simulator.

    See #1447(opens in a new tab) for details.

  • Multi-threaded transpilations to generate diagonal gates will now work correctly if the number of gates of a circuit exceeds fusion_parallelization_threshold. Previously, different threads would occasionally fuse the same element into multiple blocks, causing incorrect results.

  • Fixes a bug with truncation of circuits in parameterized Qobjs. Previously parameters of parameterized QObj could be wrongly resolved if unused qubits of their circuits were truncated, because indices of the parameters were not updated after the instructions on unmeasured qubits were removed.

    See #1427(opens in a new tab) for details.

Ignis 0.7.0

No change

IBM Q Provider 0.18.3

No change


Terra 0.19.1

No change

Aer 0.10.2

Bug Fixes

  • 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.providers.aer import AerSimulator
    qc = qiskit.QuantumCircuit(2)
    with qc.for_loop(range(4)) as i:
        qc.h(0), 1)
  • 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(opens in a new tab) for details.

Ignis 0.7.0

No change

IBM Q Provider 0.18.3

No change


Qiskit 0.34.0 includes a point release of Qiskit Aer: version 0.10.1, which patches performance regressions in version 0.10.0 that were discovered immediately post-release. See below for the release notes for both Qiskit Aer 0.10.0 and 0.10.1.

Terra 0.19.1

No change

Aer 0.10.1


The Qiskit Aer 0.10.1 patch fixes performance regressions introduced in Qiskit Aer 0.10.0.

Bug Fixes

  • 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(opens in a new tab) for details.

Aer 0.10.0


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 support of QASM 3.0 control-flow instructions introduced in Qiskit-Terra 0.19.0. Supported instructions are ForLoopOp, WhileLoopOp, ContinueLoopOp, BreakLoopOp, IfElseOp.

  • 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

  • The return type of several save instructions have been changed to be the corresponding Qiskit Terra classes rather than raw NumPy arrays or dictionaries. The types that have changed are

  • 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.

  • When an unsupported argument is supplied to approximate_quantum_error(), it will now raise a NoiseError instead of a RuntimeError.

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 NoiseModel.from_dict() to make the noise model independent of Qobj (JSON) format.

  • 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.

Ignis 0.7.0

No change

IBM Q Provider 0.18.3

Bug Fixes

  • Fix delivered in #1100(opens in a new tab) for an issue with JSON encoding and decoding when using ParameterExpressions in conjunction with Qiskit Terra 0.19.1 and above. Previously, the Parameter instances reconstructed from the JSON output would have different unique identifiers, causing them to seem unequal to the input. They will now have the correct backing identities.
Was this page helpful?
Report a bug or request content on GitHub.