# Release Notes¶

## Version History¶

This table tracks the meta-package versions and the version of each Qiskit element installed:

Table 1 Version History

Qiskit Metapackage Version

qiskit-terra

qiskit-aer

qiskit-ignis

qiskit-ibmq-provider

qiskit-aqua

Release Date

0.38.0

0.21.2

0.11.0

0.19.2

2022-09-14

0.37.2

0.21.2

0.10.4

0.19.2

2022-08-23

0.37.1

0.21.1

0.10.4

0.19.2

2022-07-28

0.37.0

0.21.0

0.10.4

0.19.2

2022-06-30

0.36.2

0.20.2

0.10.4

0.7.1

0.19.1

2022-05-18

0.36.1

0.20.1

0.10.4

0.7.0

0.19.1

2022-04-21

0.36.0

0.20.0

0.10.4

0.7.0

0.19.0

2022-04-06

0.35.0

0.20.0

0.10.3

0.7.0

0.18.3

2022-03-31

0.34.2

0.19.2

0.10.3

0.7.0

0.18.3

2022-02-09

0.34.1

0.19.1

0.10.2

0.7.0

0.18.3

2022-01-05

0.34.0

0.19.1

0.10.1

0.7.0

0.18.3

2021-12-20

0.33.1

0.19.1

0.9.1

0.7.0

0.18.2

2021-12-10

0.33.0

0.19.0

0.9.1

0.7.0

0.18.1

2021-12-06

0.32.1

0.18.3

0.9.1

0.6.0

0.18.1

0.9.5

2021-11-22

0.32.0

0.18.3

0.9.1

0.6.0

0.18.0

0.9.5

2021-11-10

0.31.0

0.18.3

0.9.1

0.6.0

0.17.0

0.9.5

2021-10-12

0.30.1

0.18.3

0.9.0

0.6.0

0.16.0

0.9.5

2021-09-29

0.30.0

0.18.2

0.9.0

0.6.0

0.16.0

0.9.5

2021-09-16

0.29.1

0.18.2

0.8.2

0.6.0

0.16.0

0.9.5

2021-09-10

0.29.0

0.18.1

0.8.2

0.6.0

0.16.0

0.9.4

2021-08-02

0.28.0

0.18.0

0.8.2

0.6.0

0.15.0

0.9.4

2021-07-13

0.27.0

0.17.4

0.8.2

0.6.0

0.14.0

0.9.2

2021-06-15

0.26.2

0.17.4

0.8.2

0.6.0

0.13.1

0.9.1

2021-05-19

0.26.1

0.17.4

0.8.2

0.6.0

0.13.1

0.9.1

2021-05-18

0.26.0

0.17.3

0.8.2

0.6.0

0.13.1

0.9.1

2021-05-11

0.25.4

0.17.2

0.8.2

0.6.0

0.12.3

0.9.1

2021-05-05

0.25.3

0.17.1

0.8.2

0.6.0

0.12.3

0.9.1

2021-04-29

0.25.2

0.17.1

0.8.1

0.6.0

0.12.3

0.9.1

2021-04-21

0.25.1

0.17.1

0.8.1

0.6.0

0.12.2

0.9.1

2021-04-15

0.25.0

0.17.0

0.8.0

0.6.0

0.12.2

0.9.0

2021-04-02

0.24.1

0.16.4

0.7.6

0.5.2

0.12.2

0.8.2

2021-03-24

0.24.0

0.16.4

0.7.6

0.5.2

0.12.1

0.8.2

2021-03-04

0.23.6

0.16.4

0.7.5

0.5.2

0.11.1

0.8.2

2021-02-18

0.23.5

0.16.4

0.7.4

0.5.2

0.11.1

0.8.2

2021-02-08

0.23.4

0.16.3

0.7.3

0.5.1

0.11.1

0.8.1

2021-01-28

0.23.3

0.16.2

0.7.3

0.5.1

0.11.1

0.8.1

2021-01-26

0.23.2

0.16.1

0.7.2

0.5.1

0.11.1

0.8.1

2020-12-15

0.23.1

0.16.1

0.7.1

0.5.1

0.11.1

0.8.1

2020-11-12

0.23.0

0.16.0

0.7.0

0.5.0

0.11.0

0.8.0

2020-10-16

0.22.0

0.15.2

0.6.1

0.4.0

0.10.0

0.7.5

2020-10-05

0.21.0

0.15.2

0.6.1

0.4.0

0.9.0

0.7.5

2020-09-16

0.20.1

0.15.2

0.6.1

0.4.0

0.8.0

0.7.5

2020-09-08

0.20.0

0.15.1

0.6.1

0.4.0

0.8.0

0.7.5

2020-08-10

0.19.6

0.14.2

0.5.2

0.3.3

0.7.2

0.7.3

2020-06-25

0.19.5

0.14.2

0.5.2

0.3.2

0.7.2

0.7.3

2020-06-19

0.19.4

0.14.2

0.5.2

0.3.0

0.7.2

0.7.2

2020-06-16

0.19.3

0.14.1

0.5.2

0.3.0

0.7.2

0.7.1

2020-06-02

0.19.2

0.14.1

0.5.1

0.3.0

0.7.1

0.7.1

2020-05-14

0.19.1

0.14.1

0.5.1

0.3.0

0.7.0

0.7.0

2020-05-01

0.19.0

0.14.0

0.5.1

0.3.0

0.7.0

0.7.0

2020-04-30

0.18.3

0.13.0

0.5.1

0.3.0

0.6.1

0.6.6

2020-04-24

0.18.2

0.13.0

0.5.0

0.3.0

0.6.1

0.6.6

2020-04-23

0.18.1

0.13.0

0.5.0

0.3.0

0.6.0

0.6.6

2020-04-20

0.18.0

0.13.0

0.5.0

0.3.0

0.6.0

0.6.5

2020-04-09

0.17.0

0.12.0

0.4.1

0.2.0

0.6.0

0.6.5

2020-04-01

0.16.2

0.12.0

0.4.1

0.2.0

0.5.0

0.6.5

2020-03-20

0.16.1

0.12.0

0.4.1

0.2.0

0.5.0

0.6.4

2020-03-05

0.16.0

0.12.0

0.4.0

0.2.0

0.5.0

0.6.4

2020-02-27

0.15.0

0.12.0

0.4.0

0.2.0

0.4.6

0.6.4

2020-02-06

0.14.1

0.11.1

0.3.4

0.2.0

0.4.5

0.6.2

2020-01-07

0.14.0

0.11.0

0.3.4

0.2.0

0.4.4

0.6.1

2019-12-10

0.13.0

0.10.0

0.3.2

0.2.0

0.3.3

0.6.1

2019-10-17

0.12.2

0.9.1

0.3.0

0.2.0

0.3.3

0.6.0

2019-10-11

0.12.1

0.9.0

0.3.0

0.2.0

0.3.3

0.6.0

2019-09-30

0.12.0

0.9.0

0.3.0

0.2.0

0.3.2

0.6.0

2019-08-22

0.11.2

0.8.2

0.2.3

0.1.1

0.3.2

0.5.5

2019-08-20

0.11.1

0.8.2

0.2.3

0.1.1

0.3.1

0.5.3

2019-07-24

0.11.0

0.8.2

0.2.3

0.1.1

0.3.0

0.5.2

2019-07-15

0.10.5

0.8.2

0.2.1

0.1.1

0.2.2

0.5.2

2019-06-27

0.10.4

0.8.2

0.2.1

0.1.1

0.2.2

0.5.1

2019-06-17

0.10.3

0.8.1

0.2.1

0.1.1

0.2.2

0.5.1

2019-05-29

0.10.2

0.8.0

0.2.1

0.1.1

0.2.2

0.5.1

2019-05-24

0.10.1

0.8.0

0.2.0

0.1.1

0.2.2

0.5.0

2019-05-07

0.10.0

0.8.0

0.2.0

0.1.1

0.2.1

0.5.0

2019-05-06

0.9.0

0.8.0

0.2.0

0.1.1

0.1.1

0.5.0

2019-05-02

0.8.1

0.7.2

0.1.1

0.1.0

2019-05-01

0.8.0

0.7.1

0.1.1

0.1.0

2019-03-05

0.7.3

>=0.7,<0.8

>=0.1,<0.2

2019-02-19

0.7.2

>=0.7,<0.8

>=0.1,<0.2

2019-01-22

0.7.1

>=0.7,<0.8

>=0.1,<0.2

2019-01-17

0.7.0

>=0.7,<0.8

>=0.1,<0.2

2018-12-14

Nota

For the 0.7.0, 0.7.1, and 0.7.2 meta-package releases the Control de Versiones de Qiskit policy was not formalized yet.

## Notable Changes¶

### Qiskit 0.38.0¶

No change

#### Aer 0.11.0¶

##### Prelude¶

The Qiskit Aer 0.11.0 release highlights are:

##### New Features¶
• 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)
qc.initialize('+-rl')
qc.save_statevector()

AerSimulator(method="statevector").run(qc)

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

• 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 22.5.0.41 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)
qc.cx(0, 1)

AerSimulator(method="statevector").run(qc)

• 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 https://github.com/Qiskit/qiskit-aer/issues/1511, 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 <https://github.com/Qiskit/qiskit-aer/issues/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.

• Fixes an issue when while_loop is the tail of QuantumCircuit. while_loop is translated to jump and mark instructions. However, if a while_loop is at the end of a circuit, its mark instruction is truncated wrongly. This fix corrects the truncation algorithm to always remain mark instructions.

No change

### Qiskit 0.37.2¶

#### Terra 0.21.2¶

##### Prelude¶

Qiskit Terra 0.21.2 is a primarily a bugfix release, and also comes with several improved documentation pages.

##### Bug Fixes¶
• aer_simulator_statevector_gpu will now be recognized correctly as statevector method in some function when using Qiskit Aer’s GPU simulators in QuantumInstance and other algorithm runners.

• Fixed the UCGate.inverse() method which previously did not invert the global phase.

• QuantumCircuit.compose() will now function correctly when used with the inplace=True argument within control-flow builder contexts. Previously the instructions would be added outside the control-flow scope. Fixed #8433.

• Fixed a bug where a bound ParameterExpression was not identified as real if symengine was installed and the bound expression was not a plain 1j. For example:

from qiskit.circuit import Parameter

x = Parameter("x")
expr = 1j * x
bound = expr.bind({x: 2})
print(bound.is_real())  # used to be True, but is now False

• Fixed QPY serialisation and deserialisation of ControlledGate with open controls (i.e. those whose ctrl_state is not all ones). Fixed #8549.

• All fake backends in qiskit.providers.fake_provider.backends have been updated to return the corresponding pulse channel objects with the method call of drive_channel(), measure_channel(), acquire_channel(), control_channel().

• Fixed support for running Z2Symmetries.taper() on larger problems. Previously, the method would require a large amount of memory which would typically cause failures for larger problem. As a side effect of this fix the performance has significantly improved.

No change

No change

### Qiskit 0.37.1¶

#### Terra 0.21.1¶

##### Bug Fixes¶
• Fixed an issue in QuantumCircuit.decompose() method when passing in a list of Gate classes for the gates_to_decompose argument. If any gates in the circuit had a label set this argument wouldn’t be handled correctly and caused the output decomposition to incorrectly skip gates explicitly in the gates_to_decompose list.

• Fix to_instruction() which previously tried to create a UnitaryGate without exponentiating the operator to evolve. Since this operator is generally not unitary, this raised an error (and if the operator would have been unitary by chance, it would not have been the expected result).

Now calling to_instruction() correctly produces a gate that implements the time evolution of the operator it holds:

>>> from qiskit.opflow import EvolvedOp, X
>>> op = EvolvedOp(0.5 * X)
>>> op.to_instruction()
Instruction(
name='unitary', num_qubits=1, num_clbits=0,
params=[array([[0.87758256+0.j, 0.-0.47942554j], [0.-0.47942554j, 0.87758256+0.j]])]
)

• Previously it was not possible to adjoint a CircuitStateFn that has been constructed from a VectorStateFn. That’s because the statevector has been converted to a circuit with the Initialize instruction, which is not unitary. This problem is now fixed by instead using the StatePreparation instruction, which can be used since the state is assumed to start out in the all 0 state.

For example we can now do:

from qiskit import QuantumCircuit
from qiskit.opflow import StateFn

left = StateFn([0, 1])
left_circuit = left.to_circuit_op().primitive

right_circuit = QuantumCircuit(1)
right_circuit.x(0)

overlap = left_circuit.inverse().compose(right_circuit)  # this line raised an error before!

• Fix a bug in the Optimizer classes where re-constructing a new optimizer instance from a previously exisiting settings reset both the new and previous optimizer settings to the defaults. This notably led to a bug if Optimizer objects were send as input to Qiskit Runtime programs.

Now optimizer objects are correctly reconstructed:

>>> from qiskit.algorithms.optimizers import COBYLA
>>> original = COBYLA(maxiter=1)
>>> reconstructed = COBYLA(**original.settings)
>>> reconstructed._options["maxiter"]
1  # used to be 1000!

• Fixed an issue where the limit_amplitude argument on an individual SymbolicPulse or Waveform instance was not properly reflected by parameter validation. In addition, QPY schedule dump() has been fixed to correctly store the limit_amplitude value tied to the instance, rather than saving the global class variable.

• Fix the pairwise entanglement structure for NLocal circuits. This led to a bug in the ZZFeatureMap, where using entanglement="pairwise" raised an error. Now it correctly produces the desired feature map:

from qiskit.circuit.library import ZZFeatureMap
encoding = ZZFeatureMap(4, entanglement="pairwise", reps=1)
print(encoding.decompose().draw())


The above prints:

     ┌───┐┌─────────────┐
q_0: ┤ H ├┤ P(2.0*x[0]) ├──■────────────────────────────────────■────────────────────────────────────────────
├───┤├─────────────┤┌─┴─┐┌──────────────────────────────┐┌─┴─┐
q_1: ┤ H ├┤ P(2.0*x[1]) ├┤ X ├┤ P(2.0*(π - x[0])*(π - x[1])) ├┤ X ├──■────────────────────────────────────■──
├───┤├─────────────┤└───┘└──────────────────────────────┘└───┘┌─┴─┐┌──────────────────────────────┐┌─┴─┐
q_2: ┤ H ├┤ P(2.0*x[2]) ├──■────────────────────────────────────■──┤ X ├┤ P(2.0*(π - x[1])*(π - x[2])) ├┤ X ├
├───┤├─────────────┤┌─┴─┐┌──────────────────────────────┐┌─┴─┐└───┘└──────────────────────────────┘└───┘
q_3: ┤ H ├┤ P(2.0*x[3]) ├┤ X ├┤ P(2.0*(π - x[2])*(π - x[3])) ├┤ X ├──────────────────────────────────────────
└───┘└─────────────┘└───┘└──────────────────────────────┘└───┘

• Fixed an issue in handling the global phase of the UCGate class.

No change

No change

### Qiskit 0.37.0¶

This release officially marks the end of support for the Qiskit Ignis project from Qiskit. It was originally deprecated in the 0.33.0 release and as was documented in that release the qiskit-ignis package has been removed from the Qiskit metapackage, which means in that future release pip install qiskit will no longer include qiskit-ignis. However, note because of limitations in python packaging we cannot automatically remove a pre-existing install of qiskit-ignis. If you are upgrading from a previous version it’s recommended that you manually uninstall Qiskit Ignis with pip uninstall qiskit-ignis or install the metapackage in a fresh python environment.

Qiskit Ignis has been supersceded by the Qiskit Experiments project. You can refer to the migration guide for details on how to switch from Qiskit Ignis to Qiskit Experiments.

#### Terra 0.21.0¶

##### Prelude¶

The Qiskit 0.21.0 release highlights are:

Additionally, the transpiler has been improved to enable better quality outputs. This includes the introduction of new passes such as VF2PostLayout and ToqmSwap.

##### New Features¶
• Added a new class, qiskit.transpiler.StagedPassManager, which is a PassManager subclass that has a pipeline with defined phases to perform circuit compilation. Each phase is a PassManager object that will get executed in a fixed order. For example:

from qiskit.transpiler.passes import *
from qiskit.transpiler import PassManager, StagedPassManager

basis_gates = ['rx', 'ry', 'rxx']
init = PassManager([UnitarySynthesis(basis_gates, min_qubits=3), Unroll3qOrMore()])
translate = PassManager([Collect2qBlocks(),
ConsolidateBlocks(basis_gates=basis_gates),
UnitarySynthesis(basis_gates)])

staged_pm = StagedPassManager(stages=['init', 'translation'], init=init, translation=translate)

• Added the methods PauliList.group_commuting() and SparsePauliOp.group_commuting(), which partition these operators into sublists where each element commutes with all the others. For example:

from qiskit.quantum_info import PauliList, SparsePauliOp

groups = PauliList(["XX", "YY", "IZ", "ZZ"]).group_commuting()
# 'groups' is [PauliList(['IZ', 'ZZ']), PauliList(['XX', 'YY'])]

op = SparsePauliOp.from_list([("XX", 2), ("YY", 1), ("IZ", 2j), ("ZZ", 1j)])
groups = op.group_commuting()
# 'groups' is [
#     SparsePauliOp(['IZ', 'ZZ'], coeffs=[0.+2.j, 0.+1.j]),
#     SparsePauliOp(['XX', 'YY'], coeffs=[2.+0.j, 1.+0.j]),
# ]

• Added the @ (__matmul__) binary operator to BaseOperator subclasses in the qiskit.quantum_info module. This is shorthand to call the classes” dot method (A @ B == A.dot(B)).

• Added a new optional argument, reps, to QuantumCircuit.decompose(), which allows repeated decomposition of the circuit. For example:

from qiskit import QuantumCircuit

circuit = QuantumCircuit(1)
circuit.ry(0.5, 0)

# Equivalent to circuit.decompose().decompose()
circuit.decompose(reps=2)

# decompose 2 times, but only RY gate 2 times and R gate 1 times
circuit.decompose(gates_to_decompose=['ry','r'], reps=2)

• Added a new pulse base class SymbolicPulse. This is a replacement of the conventional ParametricPulse, which will be deprecated. In the new base class, pulse-envelope and parameter-validation functions are represented by symbolic-expression objects. The new class provides self-contained and portable pulse data since these symbolic equations can be easily serialized through symbolic computation libraries.

• Added support for non-Hermitian operators in AerPauliExpectation. This allows the use of Aer’s fast snapshot expectation computations in algorithms such as QEOM.

• Added a new circuit drawing style, textbook, which uses the color scheme of the Qiskit Textbook.

• A new attribute QuantumCircuit.op_start_times is populated when one of scheduling analysis passes is run on the circuit. It can be used to obtain circuit instruction with instruction time, for example:

from qiskit import QuantumCircuit, transpile
from qiskit.providers.fake_provider import FakeMontreal

backend = FakeMontreal()

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

qct = transpile(
qc, backend, initial_layout=[0, 1], coupling_map=[[0, 1]], scheduling_method="alap"
)
scheduled_insts = list(zip(qct.op_start_times, qct.data))

• Added a new method QuantumCircuit.copy_empty_like() which is used to get a cleared copy of a QuantumCircuit instance. This is logically equivalent to qc.copy().clear(), but significantly faster and more memory-efficient. This is useful when one needs a new empty circuit with all the same resources (qubits, classical bits, metadata, and so on) already added.

• The Target.instruction_supported() method now supports two new keyword arguments, operation_class and parameters. Using these arguments the instruction_supported() method can now be used for checking that a specific operation with parameter values are supported by a Target object. For example, if you want to check if a Target named target supports running a RXGate with $$\theta = \frac{\pi}{2}$$ you would do something like:

from math import pi
from qiskit.circuit.library import RXGate

target.instruction_supported(operation_class=RXGate, parameters=[pi/2])


which will return True if target supports running RXGate with $$\theta = \frac{\pi}{2}$$ and False if it does not.

• Added a Trotterization-based quantum real-time evolution algorithm qiskit.algorithms.TrotterQRTE. It is compliant with the new quantum time evolution framework and makes use of the ProductFormula and PauliEvolutionGate implementations.

from qiskit.algorithms import EvolutionProblem
from qiskit.algorithms.evolvers.trotterization import TrotterQRTE
from qiskit.opflow import X, Z, StateFn, SummedOp

operator = SummedOp([X, Z])
initial_state = StateFn([1, 0])
time = 1
evolution_problem = EvolutionProblem(operator, time, initial_state)

trotter_qrte = TrotterQRTE()
evolution_result = trotter_qrte.evolve(evolution_problem)
evolved_state_circuit = evolution_result.evolved_state

• Added a new function marginal_memory() which is used to marginalize shot memory arrays. Provided with the shot memory array and the indices of interest, the function will return a maginized shot memory array. This function differs from the memory support in the marginal_counts() method which only works on the memory field in a Results object.

• The primitives interface has been extended to accept objects in addition to indices as arguments to the __call__ method. The parameter_values argument can now be optional.

• Added a new layout and routing method to transpile() based on the paper «Time-optimal qubit mapping». To use it, the optional package Qiskit TOQM must be installed. The routing_method kwarg of transpile() supports an additional value, 'toqm' which is used to enable layout and routing via TOQM.

To install qiskit-toqm along with Terra, run:

pip install qiskit-terra[toqm]

• Added a new module qiskit.quantum_info.synthesis.qsd to apply Quantum Shannon Decomposition of arbitrary unitaries. This functionality replaces the previous isometry-based approach in the default unitary synthesis transpiler pass as well as when adding unitaries to a circuit using a UnitaryGate.

The Quantum Shannon Decomposition uses about half the cnot gates as the isometry implementation when decomposing unitary matrices of greater than two qubits.

• Classes in the quantum_info module that support scalar multiplication can now be multiplied by a scalar from either the left or the right. Previously, they would only accept scalar multipliers from the left.

• The transpiler pass LookaheadSwap (used by transpile() when routing_method="lookahead") has seen some performance improvements and will now be approximately three times as fast. This is purely being more efficient in its calculations, and does not change the complexity of the algorithm. In most cases, a more modern routing algorithm like SabreSwap (routing_method="sabre") will be vastly more performant.

• New transpiler passes have been added. The transpiler pass Commuting2qGateRouter uses swap strategies to route a block of commuting gates to the coupling map. Indeed, routing is a hard problem but is significantly easier when the gates commute as in CZ networks. Blocks of commuting gates are also typically found in QAOA. Such cases can be dealt with using swap strategies that apply a predefined set of layers of SWAP gates. Furthermore, the new transpiler pass FindCommutingPauliEvolutions identifies blocks of Pauli evolutions made of commuting two-qubit terms. Here, a swap strategy is specified by the class SwapStrategy. Swap strategies need to be tailored to the coupling map and, ideally, the circuit for the best results.

• Introduced a new optimizer to Qiskit library, which adds support to the optimization of parameters of variational quantum algorithms. This is the Univariate Marginal Distribution Algorithm (UMDA), which is a specific type of the Estimation of Distribution Algorithms. For example:

from qiskit.opflow import X, Z, I
from qiskit import Aer
from qiskit.algorithms.optimizers import UMDA
from qiskit.algorithms import QAOA
from qiskit.utils import QuantumInstance

H2_op = (-1.052373245772859 * I ^ I) + \
(0.39793742484318045 * I ^ Z) + \
(-0.39793742484318045 * Z ^ I) + \
(-0.01128010425623538 * Z ^ Z) + \
(0.18093119978423156 * X ^ X)

p = 2  # Toy example: 2 layers with 2 parameters in each layer: 4 variables

opt = UMDA(maxiter=100, size_gen=20)
backend = Aer.get_backend('statevector_simulator')
vqe = QAOA(opt,
quantum_instance=QuantumInstance(backend=backend),
reps=p)

result = vqe.compute_minimum_eigenvalue(operator=H2_op)

• The constructor for the Unroll3qOrMore transpiler pass has two new optional keyword arguments, target and basis_gates. These options enable you to specify the Target or supported basis gates respectively to describe the target backend. If any of the operations in the circuit are in the target or basis_gates those will not be unrolled by the pass as the target device has native support for the operation.

• QPY serialization has been upgraded to support ScheduleBlock. Now you can save pulse program in binary and load it at later time:

from qiskit import pulse, qpy

with pulse.build() as schedule:
pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0))

with open('schedule.qpy', 'wb') as fd:
qpy.dump(schedule, fd)

with open('schedule.qpy', 'rb') as fd:


This uses the QPY interface common to QuantumCircuit. See SCHEDULE_BLOCK for details of data structure.

• Added a new transpiler pass, VF2PostLayout. This pass is of a new type to perform a new phase/function in the compilation pipeline, post-layout or post optimization qubit selection. The idea behind this pass is after we finish the optimization loop in transpiler we know what the final gate counts will be on each qubit in the circuit so we can potentially find a better-performing subset of qubits on a backend to execute the circuit. The pass will search for an isomorphic subgraph in the connectivity graph of the target backend and look at the full error rate of the complete circuit on any subgraph found and return the layout found with the lowest error rate for the circuit.

This pass is similar to the VF2Layout pass and both internally use the same VF2 implementation from retworkx. However, VF2PostLayout is deisgned to run after initial layout, routing, basis translation, and any optimization passes run and will only work if a layout has already been applied, the circuit has been routed, and all gates are in the target basis. This is required so that when a new layout is applied the circuit can still be run on the target device. VF2Layout on the other hand is designed to find a perfect initial layout and can work with any circuit.

• The ApplyLayout transpiler pass now has support for updating a layout on a circuit after a layout has been applied once before. If the post_layout field is present (in addition to the required layout field) the property_set when the ApplyLayout pass is run the pass will update the layout to apply the new layout. This will return a DAGCircuit with the qubits in the new physical order and the layout property set will be updated so that it maps the virtual qubits from the original layout to the physical qubits in the new post_layout field.

• The algorithm iteratively computes each eigenstate by starting from the ground state (which is computed as in VQE) and then optimising a modified cost function that tries to compute eigen states that are orthogonal to the states computed in the previous iterations and have the lowest energy when computed over the ansatz. The interface implemented is very similar to that of VQE and is of the form:

from qiskit.algorithms import VQD
from qiskit.utils import QuantumInstance
from qiskit.circuit.library import TwoLocal
from qiskit.algorithms.optimizers import COBYLA
from qiskit import BasicAer
from qiskit.opflow import I,Z,X

h2_op = (
-1.052373245772859 * (I ^ I)
+ 0.39793742484318045 * (I ^ Z)
- 0.39793742484318045 * (Z ^ I)
- 0.01128010425623538 * (Z ^ Z)
+ 0.18093119978423156 * (X ^ X)
)

vqd = VQD(k =2, ansatz = TwoLocal(rotation_blocks="ry", entanglement_blocks="cz"),optimizer = COBYLA(maxiter = 0), quantum_instance = QuantumInstance(
BasicAer.get_backend("qasm_simulator"), shots = 2048)
)
vqd_res = vqd.compute_eigenvalues(op)


This particular code snippet generates 2 eigenvalues (ground and 1st excited state) Tests have also been implemented.

• The python-constraint dependency, which is used solely by the CSPLayout transpiler pass, is no longer in the requirements list for the Qiskit Terra package. This is because the CSPLayout pass is no longer used by default in any of the preset pass managers for transpile(). While the pass is still available, if you’re using it you will need to manually install python-contraint or when you install qiskit-terra you can use the csp-layout extra, for example:

pip install "qiskit-terra[csp-layout]"

• The QPY version format version emitted by qpy.dump() has been increased to version 5. This new format version is incompatible with the previous versions and will result in an error when trying to load it with a deserializer that isn’t able to handle QPY version 5. This change was necessary to fix support for representing controlled gates properly and representing non-default control states.

• Qiskit Terra’s compiled Rust extensions now have a minimum supported Rust version (MSRV) of 1.56.1. This means when building Qiskit Terra from source the oldest version of the Rust compiler supported is 1.56.1. If you are using an older version of the Rust compiler you will need to update to a newer version to continue to build Qiskit from source. This change was necessary as a number of upstream dependencies have updated their minimum supported versions too.

• Circuit scheduling now executes in parallel when more than one circuit is provided to schedule(). Refer to #2695 for more details.

• The previously deprecated BaseBackend, BaseJob, and BaseProvider classes have all been removed. They were originally deprecated in the 0.18.0 release. Instead of these classes you should be using the versioned providers interface classes, the latest being BackendV2, JobV1, and ProviderV1.

• The previously deprecated backend argument for the constructor of the RZXCalibrationBuilder transpiler pass has been removed. It was originally deprecated in the 0.19.0 release. Instead you should query the Backend object for the instruction_schedule_map and qubit_channel_mapping and pass that directly to the constructor. For example, with a BackendV1 backend:

from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit.providers.fake_provider import FakeMumbai

backend = FakeMumbai()
inst_map = backend.defaults().instruction_schedule_map
channel_map = backend.configuration().qubit_channel_mapping
cal_pass = RZXCalibrationBuilder(
instruction_schedule_map=inst_map,
qubit_channel_mapping=channel_map,
)


or with a BackendV2 backend:

from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit.providers.fake_provider import FakeMumbaiV2

backend = FakeMumbaiV2()
inst_map = backend.instruction_schedule_map
channel_map = {bit: backend.drive_channel(bit) for bit in range(backend.num_qubits)}
cal_pass = RZXCalibrationBuilder(
instruction_schedule_map=inst_map,
qubit_channel_mapping=channel_map,
)

• The measurement shot limit for the BasicAer backend has been removed.

• For the DAGNode, the previously deprecated type, op, qargs, cargs, and wire kwargs and attributes have been removed. These were originally deprecated in the 0.19.0 release. The op, qargs, and cargs kwargs and attributes can be accessed only on instances of DAGOpNode, and the wire kwarg and attribute are only on instances of DAGInNode or DAGOutNode.

• The deprecated function pauli_group() has been removed. It was originally deprecated in Qiskit Terra 0.17.

• Several deprecated methods on Pauli have been removed, which were originally deprecated in Qiskit Terra 0.17. These were:

sgn_prod

Use Pauli.compose() or Pauli.dot() instead.

to_spmatrix

Use Pauli.to_matrix() with argument sparse=True instead.

kron

Use Pauli.expand(), but beware that this returns a new object, rather than mutating the existing one.

update_z and update_x

Set the z and x attributes of the object directly.

insert_paulis
append_paulis
delete_qubits
pauli_single

Construct the label manually and pass directly to the initializer, such as:

Pauli("I" * index + pauli_label + "I" * (num_qubits - index - len(pauli_label)))

random

Use quantum_info.random_pauli() instead.

• Result was modified so that it always contains date, status, and header attributes (set to None if not specified).

• For Python 3.7 shared-memory38 is now a dependency. This was added as a dependency for Python 3.7 to enable leveraging the shared memory constructs in the standard library of newer versions of Python. If you’re running on Python >= 3.8 there is no extra dependency required.

• The preset pass managers generated by level_1_pass_manager(), level_2_pass_manager(), and level_3_pass_manager() and used by the transpile() function’s optimization_level argument at 1, 2, and 3 respectively no longer set a hard time limit on the VF2Layout transpiler pass. This means that the pass will no longer stop trying to find a better alternative perfect layout up until a fixed time limit (100ms for level 1, 10 sec for level 2, and 60 sec for level 3) as doing this limited the reproducibility of compilation when a perfect layout was available. This means that the output when using the pass might be different than before, although in all cases it would only change if a lower noise set of qubits can be found over the previous output. If you wish to retain the previous behavior you can create a custom PassManager that sets the time_limit argument on the constructor for the VF2Layout pass.

##### Deprecation Notes¶
• The NetworkX converter functions for the DAGCircuit.to_networkx() and from_networkx(), along with the DAGDependency.to_networkx() method have been deprecated and will be removed in a future release. Qiskit has been using retworkx as its graph library since the qiskit-terra 0.12.0 release, and since then the networkx converter functions have been lossy. They were originally added so that users could leverage functionality in NetworkX’s algorithms library not present in retworkx. Since that time, retworkx has matured and offers more functionality, and the DAGCircuit is tightly coupled to retworkx for its operation. Having these converter methods provides limited value moving forward and are therefore going to be removed in a future release.

• Accessing several old toggles (HAS_MATPLOTLIB, HAS_PDFTOCAIRO, HAS_PYLATEX and HAS_PIL) from the qiskit.visualization module is now deprecated, and these import paths will be removed in a future version of Qiskit Terra. The same objects should instead be accessed through qiskit.utils.optionals, which contains testers for almost all of Terra’s optional dependencies.

• The qiskit.test.mock module is now deprecated. The fake backend and fake provider classes which were previously available in qiskit.test.mock have been accessible in qiskit.providers.fake_provider since Terra 0.20.0. This change represents a proper commitment to support the fake backend classes as part of Qiskit, whereas previously they were just part of the internal testing suite, and were exposed to users as a side effect.

• The arguments” names when calling an Estimator or Sampler object as a function are renamed from circuit_indices and observable_indices to circuits and observables.

• The qobj_id and qobj_header keyword arguments for the execute() function have been deprecated and will be removed in a future release. Since the removal of the BaseBackend class these arguments don’t have any effect as no backend supports execution with a Qobj object directly and instead only work with QuantumCircuit objects directly.

• The arguments x, z and label to the initializer of Pauli were documented as deprecated in Qiskit Terra 0.17, but a bug prevented the expected warning from being shown at runtime. The warning will now correctly show, and the arguments will be removed in Qiskit Terra 0.23 or later. A pair of x and z should be passed positionally as a single tuple (Pauli((z, x))). A string label should be passed positionally in the first argument (Pauli("XYZ")).

• The circuits argument of qpy.dump() has been deprecated and replaced with programs since now QPY supports multiple data types other than circuits.

• AlignmentKind.to_dict() method has been deprecated and will be removed.

##### Bug Fixes¶
• Extra validation was added to DiagonalGate to check the argument has modulus one.

• Duplicate qubit indices given to SparsePauliOp.from_sparse_list() will now correctly raise an error, instead of silently overwriting previous values. The old behavior can be accessed by passing the new keyword argument do_checks=False.

• Fixed a bug in which the LaTeX statevector drawer ignored the max_size parameter.

• Fixed the ConfigurableFakeBackend.t2 attribute, which was previously incorrectly set based on the provided t1 value.

• Fixed a bug in plot_histogram() when the number_to_keep argument was smaller that the number of keys. The following code will no longer throw errors and will be properly aligned:

from qiskit.visualization import plot_histogram
data = {'00': 3, '01': 5, '11': 8, '10': 11}
plot_histogram(data, number_to_keep=2)

• Improved the performance of building and working with parameterized QuantumCircuit instances with many gates that share a relatively small number of parameters.

• The OpenQASM 3 exporter (qiskit.qasm3) will no longer attempt to produce definitions for non-standard gates in the basis_gates option.

• Fixed a bug in the string representation of Result objects that caused the attributes to be specified incorrectly.

• Fixed an issue with transpile() where in some cases providing a list of basis gate strings with the basis_gates keyword argument or implicitly via a Target input via the target keyword argument would not be interpreted correctly and result in a subset of the listed gates being used for each circuit.

• Fixed an issue in the UnitarySynthesis transpiler pass which would result in an error when a Target that didn’t have any qubit restrictions on the operations (e.g. in the case of an ideal simulator target) was specified with the target keyword argument for the constructor.

• The method qiskit.result.marginal_counts(), when passed a Result from a pulse backend, would fail, because it contains an array of ExperimentResult objects, each of which have an QobjExperimentHeader, and those ExperimentHeaders lack creg_sizes instance-variables. If the Result came from a simulator backend (e.g. Aer), that instance-variable would be there. We fix marginal_counts so that it skips logic that needs creg_sizes if the field is not present, or non-None.

• Fixed an issue with reproducibility of the transpile() function when running with optimization_level 1, 2, and 3. Previously, under some conditions when there were multiple perfect layouts (a layout that doesn’t require any SWAP gates) available the selected layout and output circuit could vary regardless of whether the seed_transpiler argument was set.

No change

#### IBM Q Provider 0.19.2¶

##### Bug Fixes¶
• In the upcoming terra release there will be a release candidate tagged prior to the final release. However changing the version string for the package is blocked on the qiskit-ibmq-provider right now because it is trying to parse the version and is assuming there will be no prelease suffix on the version string (see #8200 for the details). PR #1135 fixes this version parsing to use the regex from the pypa/packaging project which handles all the PEP440 package versioning include pre-release suffixes. This will enable terra to release an 0.21.0rc1 tag without breaking the qiskit-ibmq-provider.

• threading.currentThread and notifyAll were deprecated in Python 3.10 (October 2021) and will be removed in Python 3.12 (October 2023). PR #1133 replaces them with threading.current_thread, notify_all added in Python 2.6 (October 2008).

### Qiskit 0.36.2¶

#### Terra 0.20.2¶

##### Prelude¶

Qiskit Terra 0.20.2 is a bugfix release, addressing some minor issues identified since the last patch release.

##### Bug Fixes¶
• Fixed an issue with BackendV2-based fake backend classes from the qiskit.providers.fake_provider module such as FakeMontrealV2, where the values for the dtm and dt attributes and the associated attribute Target.dt would not be properly converted to seconds. This would cause issues when using these fake backends with scheduling. See #8018.

• marginal_counts() will now succeed when asked to marginalize memory with an indices parameter containing non-zero elements. Previously, shots whose hexadecimal result representation was sufficiently small could raise a ValueError. See #8044.

• The OpenQASM 3 exporter (qiskit.qasm3) will now output input or output declarations before gate declarations. This is more consistent with the current reference ANTLR grammar from the OpenQASM 3 team. See #7964.

• Fixed a bug in the RZXCalibrationBuilder transpiler pass where the scaled cross-resonance pulse amplitude could appear to be parametrized even after assignment. This could cause the pulse visualization tools to use the parametrized format instead of the expected numeric one. See #8031.

• Fixed an issue with the transpile() function when run with a BackendV2-based backend and setting the scheduling_method keyword argument. Previously, the function would not correctly process the default durations of the instructions supported by the backend which would lead to an error.

• The SabreSwap transpiler pass, used in transpile() when routing_method="sabre" is set, will no longer sporadically drop classically conditioned gates and their successors from circuits during the routing phase of transpilation. See #8040.

• Statevector will now allow direct iteration through its values (such as for coefficient in statevector) and correctly report its length under len. Previously it would try and and access out-of-bounds data and raise a QiskitError. See #8039.

No change

#### Ignis 0.7.1¶

##### Prelude¶

This is a bugfix release that primarily fixes a packaging issue that was causing the docs/ directory, which contains the source files used to build the qiskit-ignis documentation, to get included in the Python package.

No change

### Qiskit 0.36.1¶

#### Terra 0.20.1¶

##### Prelude¶

Qiskit Terra 0.20.1 is a bugfix release resolving issues identified in release 0.20.0.

##### Known Issues¶
• Since its original introduction in Qiskit Terra 0.20, XXPlusYYGate has used a negative angle convention compared to all other rotation gates. In Qiskit Terra 0.21, this will be corrected to be consistent with the other rotation gates. This does not affect any other rotation gates, nor XXMinusYYGate.

##### Bug Fixes¶
• Fixed an issue where the eval_observables() function would raise an error if its quantum_state argument was of type StateFn. eval_observables now correctly supports all input types denoted by its type hints.

• Fixed parameter validation for class Drag. Previously, it was not sensitive to large beta values with negative signs, which may have resulted in waveform samples with a maximum value exceeding the amplitude limit of 1.0.

• Fixed a bug that could result in exponential runtime and nontermination when a Pauli instance is given to method init_observables().

• Fixed SabreSwap, and by extension transpile() with optimization_level=3, occasionally re-ordering measurements invalidly. Previously, if two measurements wrote to the same classical bit, SabreSwap could (depending on the coupling map) re-order them to produce a non-equivalent circuit. This behaviour was stochastic, so may not have appeared reliably. Fixed #7950

• The SabreSwap transpiler pass, and by extension SabreLayout and transpile() at optimization_level=3, now has an escape mechanism to guarantee that it can never get stuck in an infinite loop. Certain inputs previously could, with a great amount of bad luck, get stuck in a stable local minimum of the search space and the pass would never make further progress. It will now force a series of swaps that allow the routing to continue if it detects it has not made progress recently. Fixed #7707.

No change

No change

#### 0.19.1¶

##### Bug Fixes¶
• PR #1129 updates least_busy() method to no longer support BaseBackend as a valid input or output type since it has been long deprecated in qiskit-terra and has recently been removed.

### Qiskit 0.36.0¶

No change

#### Aer 0.10.4¶

• Qiskit Aer is no longer compiled with unsafe floating-point optimisations. While most of the effects should have been localised to Qiskit Aer, some aspects of subnormal handling may previously have been leaked into user code by the library incorrectly setting the «flush to zero» mode. This will not happen any more.

##### Bug Fixes¶
• Fix cache blocking transpiler to recognize superop to be cache blocked. This is fix for issue 1479 <https://github.com/Qiskit/qiskit-aer/issues/1479> now density_matrix with noise models can be parallelized. New test, test_noise.TestNoise.test_kraus_gate_noise_on_QFT_cache_blocking is added to verify this issue. Also this fix include fix for issue 1483 <https://github.com/Qiskit/qiskit-aer/issues/1483> discovered by adding new test case. This fixes measure over chunks for statevector.

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

• device=Thrust was very slow for small number of qubits because OpenMP threading was always applied. This fix applies OpenMP threads as same as device=CPU by using statevector_parallel_threshold.

• Qiskit Aer will no longer set the floating-point mode to «flush to zero» when loaded. Downstream users may previously have seen warnings from Numpy such as:

The value of the smallest subnormal for <class “numpy.float64”> type is zero.

These will now no longer be emitted, and the floating-point handling will be correct.

• Fixed a potential issue with running simulations on circuits that have the QuantumCircuit.metadata attribute set. The metadata attribute can be any python dictionary and previously qiskit-aer would attempt to JSON serialize the contents of the attribute to process it with the rest of the rest of the circuit input, even if the contents were not JSON serializable. This no longer occurs as the QuantumCircuit.metadata attribute is not used to run the simulation so now the contents are no serialized and instead are directly attached to the qiskit.result.Result object without attempting to JSON serialize the contents. Fixed #1435

No change

#### IBM Q Provider 0.19.0¶

##### New Features¶
• The qiskit-ibmq-provider package now supports IBM Quantum LiveData features. These features allow users to observe the real-time behavior of IBM Quantum backends while executing jobs. Specifically, the provider now includes a new tab in the backend Jupyter-related widget and supports the execution of jobs (via qiskit.providers.ibmq.IBMQBackend.run() method) with the live_data_enabled=True parameter in allowed IBM Quantum backends.

• You can now specify a different logging level in the options keyword when submitting a Qiskit Runtime job with the qiskit.providers.ibmq.runtime.IBMRuntimeService.run() method.

• Python 3.6 support has been dropped since it has reached end of life in Dec 2021.

• qiskit.providers.ibmq.random, the random number service which was used to access the CQC randomness extractor is no longer supported and has been removed.

### Qiskit 0.35.0¶

#### Terra 0.20.0¶

##### Prelude¶

The Qiskit Terra 0.20.0 release highlights are:

• The introduction of multithreaded modules written in Rust to accelerate the performance of certain portions of Qiskit Terra and improve scaling with larger numbers of qubits. However, when building Qiskit from source a Rust compiler is now required.

• More native support for working with a Target in the transpiler. Several passes now support working directly with a Target object which makes the transpiler robust in the types of backends it can target.

• The introduction of the qiskit.primitives module. These APIs provide different abstraction levels for computing outputs of interest from QuantumCircuit and using backends. For example, the BaseEstimator defines an abstract interface for estimating an expectation value of an observable. This can then be used to construct higher level algorithms and applications that are built using the estimation of expectation values without having to worry about the implementation of computing the expectation value. This decoupling allows the implementation to improve in speed and quality while adhering to the defined abstract interface. Likewise, the BaseSampler computes quasi-probability distributions from circuit measurements. Other primitives will be introduced in the future.

This release no longer has support for Python 3.6. With this release, Python 3.7 through Python 3.10 are required.

##### New Features¶
• Added a new constructor method for the Operator class, Operator.from_circuit() for creating a new Operator object from a QuantumCircuit. While this was possible normally using the default constructor, the Operator.from_circuit() method provides additional options to adjust how the operator is created. Primarily this lets you permute the qubit order based on a set Layout. For, example:

from qiskit.circuit import QuantumCircuit
from qiskit import transpile
from qiskit.transpiler import CouplingMap
from qiskit.quantum_info import Operator

circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)

cmap = CouplingMap.from_line(3)
out_circuit = transpile(circuit, initial_layout=[2, 1, 0], coupling_map=cmap)
operator = Operator.from_circuit(out_circuit)


the operator variable will have the qubits permuted based on the layout so that it is identical to what is returned by Operator(circuit) before transpilation.

• The fake backend and fake provider classes which were previously available in qiskit.test.mock are now also accessible in a new module: qiskit.providers.fake_provider. This new module supersedes the previous module qiskit.test.mock which will be deprecated in Qiskit 0.21.0.

• FlowController classes (such as ConditionalController) can now be nested inside a PassManager instance when using the PassManager.append() method. This enables the use of nested logic to control the execution of passes in the PassManager. For example:

from qiskit.transpiler import ConditionalController, PassManager
from qiskit.transpiler.passes import (
BasisTranslator, GatesInBasis, Optimize1qGatesDecomposition, FixedPoint, Depth
)
from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel

pm = PassManager()

def opt_control(property_set):
return not property_set["depth_fixed_point"]

def unroll_condition(property_set):
return not property_set["all_gates_in_basis"]

depth_check = [Depth(), FixedPoint("depth")]
opt = [Optimize1qGatesDecomposition(['rx', 'ry', 'rz', 'rxx'])]
unroll = [BasisTranslator(sel, ['rx', 'ry', 'rz', 'rxx'])]
unroll_check = [GatesInBasis(['rx', 'ry', 'rz', 'rxx'])]
flow_unroll = [ConditionalController(unroll, condition=unroll_condition)]

pm.append(depth_check + opt + unroll_check + flow_unroll, do_while=opt_control)


The pm PassManager object will only execute the BasisTranslator pass (in the unroll step) in each loop iteration if the unroll_condition is met.

• The constructors for the ZFeatureMap and ZZFeatureMap classes have a new keyword argument parameter_prefix. This new argument is used to set the prefix of parameters of the data encoding circuit. For example:

from qiskit.circuit.library import ZFeatureMap

feature_map = ZFeatureMap(feature_dimension=4, parameter_prefix="my_prefix")
feature_map.decompose().draw('mpl')


the generated ZFeatureMap circuit has prefixed all its internal parameters with the prefix "my_prefix".

• The TemplateOptimization transpiler pass can now work with Gate objects that have ParameterExpression parameters. An illustrative example of using Parameters with TemplateOptimization is the following:

from qiskit import QuantumCircuit, transpile, schedule
from qiskit.circuit import Parameter

from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import TemplateOptimization

# New contributions to the template optimization
from qiskit.transpiler.passes.calibration import RZXCalibrationBuilder, rzx_templates

from qiskit.test.mock import FakeCasablanca
backend = FakeCasablanca()

phi = Parameter('φ')

qc = QuantumCircuit(2)
qc.cx(0,1)
qc.p(2*phi, 1)
qc.cx(0,1)
print('Original circuit:')
print(qc)

pass_ = TemplateOptimization(**rzx_templates.rzx_templates(['zz2']))
qc_cz = PassManager(pass_).run(qc)
print('ZX based circuit:')
print(qc_cz)

pass_ = RZXCalibrationBuilder(backend)
cal_qc = PassManager(pass_).run(qc_cz.bind_parameters({phi: 0.12}))

# Transpile to the backend basis gates
cal_qct = transpile(cal_qc, backend)
qct = transpile(qc.bind_parameters({phi: 0.12}), backend)

# Compare the schedule durations
print('Duration of schedule with the calibration:')
print(schedule(cal_qct, backend).duration)
print('Duration of standard with two CNOT gates:')
print(schedule(qct, backend).duration)


outputs

Original circuit:

q_0: ──■──────────────■──
┌─┴─┐┌────────┐┌─┴─┐
q_1: ┤ X ├┤ P(2*φ) ├┤ X ├
└───┘└────────┘└───┘
ZX based circuit:
┌─────────────┐            »
q_0: ────────────────────────────────────┤0            ├────────────»
┌──────────┐┌──────────┐┌──────────┐│  Rzx(2.0*φ) │┌──────────┐»
q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤1            ├┤ Rx(-2*φ) ├»
└──────────┘└──────────┘└──────────┘└─────────────┘└──────────┘»
«
«q_0: ────────────────────────────────────────────────
«     ┌──────────┐┌──────────┐┌──────────┐┌──────────┐
«q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤ P(2.0*φ) ├
«     └──────────┘└──────────┘└──────────┘└──────────┘
Duration of schedule with the calibration:
1600
Duration of standard with two CNOT gates:
6848

• The performance of the SparsePauliOp.simplify() method has greatly improved by replacing the use of numpy.unique to compute unique elements of an array by a new similar function implemented in Rust that doesn’t pre-sort the array.

• Added a new method equiv() to the SparsePauliOp class for testing the equivalence of a SparsePauliOp with another SparsePauliOp object. Unlike the == operator which compares operators element-wise, equiv() compares whether two operators are equivalent or not. For example:

op = SparsePauliOp.from_list([("X", 1), ("Y", 1)])
op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)])
op3 = SparsePauliOp.from_list([("Y", 1), ("X", 1)])

print(op == op2)  # False
print(op == op3)  # False
print(op.equiv(op2))  # True
print(op.equiv(op3))  # True

• Added new fake backend classes from snapshots of the IBM Quantum systems based on the BackendV2 interface and provided a Target for each backend. BackendV2 based versions of all the existing backends are added except for three old backends FakeRueschlikon, FakeTenerife and FakeTokyo as they do not have snapshots files available which are required for creating a new fake backend class based on BackendV2.

These new V2 fake backends will enable testing and development of new features introduced by BackendV2 and Target such as improving the transpiler.

• The FakeBogota, FakeManila, FakeRome, and FakeSantiago fake backends which can be found in the qiskit.providers.fake_provider module can now be used as backends in Pulse experiments as they now include a PulseDefaults created from a snapshot of the equivalent IBM Quantum machine’s properties.

• The ConsolidateBlocks pass has a new keyword argument on its constructor, target. This argument is used to specify a Target object representing the compilation target for the pass. If it is specified it supersedes the basis_gates kwarg. If a target is specified, the pass will respect the gates and qubits for the instructions defined in the Target when deciding which gates to consolidate into a unitary.

• Added a new kwarg, metadata_serializer, to the qpy.dump() function for specifying a custom JSONEncoder subclass for use when serializing the QuantumCircuit.metadata attribute and a dual kwarg metadata_deserializer to the qpy.load() function for specifying a JSONDecoder subclass. By default the dump() and load() functions will attempt to JSON serialize and deserialize with the stdlib default json encoder and decoder. Since QuantumCircuit.metadata can contain any Python dictionary, even those with contents not JSON serializable by the default encoder, will lead to circuits that can’t be serialized. The new metadata_serializer argument for dump() enables users to specify a custom JSONEncoder that will be used with the internal json.dump() call for serializing the QuantumCircuit.metadata dictionary. This can then be paired with the new metadata_deserializer argument of the qpy.load() function to decode those custom JSON encodings. If metadata_serializer is specified on dump() but metadata_deserializer is not specified on load() calls the QPY will be loaded, but the circuit metadata may not be reconstructed fully.

For example if you wanted to define a custom serialization for metadata and then load it you can do something like:

from qiskit.qpy import dump, load
from qiskit.circuit import QuantumCircuit, Parameter
import json
import io

class CustomObject:
"""Custom string container object."""

def __init__(self, string):
self.string = string

def __eq__(self, other):
return self.string == other.string

class CustomSerializer(json.JSONEncoder):
"""Custom json encoder to handle CustomObject."""

def default(self, o):
if isinstance(o, CustomObject):
return {"__type__": "Custom", "value": o.string}
return json.JSONEncoder.default(self, o)

class CustomDeserializer(json.JSONDecoder):
"""Custom json decoder to handle CustomObject."""

def __init__(self, *args, **kwargs):
super().__init__(*args, object_hook=self.object_hook, **kwargs)

def object_hook(self, o):
"""Hook to override default decoder."""
if "__type__" in o:
obj_type = o["__type__"]
if obj_type == "Custom":
return CustomObject(o["value"])
return o

theta = Parameter("theta")
qc = QuantumCircuit(2, global_phase=theta)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
circuits = [qc, qc.copy()]
with io.BytesIO() as qpy_buf:
qpy_buf.seek(0)

• The DenseLayout pass has a new keyword argument on its constructor, target. This argument is used to specify a Target object representing the compilation target for the pass. If it is specified it supersedes the other arguments on the constructor, coupling_map and backend_prop.

• A new pass DynamicalDecouplingPadding has been added to the qiskit.transpiler.passes module. This new pass supersedes the existing DynamicalDecoupling pass to work with the new scheduling workflow in the transpiler. It is a subclass of the BasePadding pass and depends on having scheduling and alignment analysis passes run prior to it in a PassManager. This new pass can take a pulse_alignment argument which represents a hardware constraint for waveform start timing. The spacing between gates comprising a dynamical decoupling sequence is now adjusted to satisfy this constraint so that the circuit can be executed on hardware with the constraint. This value is usually found in BackendConfiguration.timing_constraints. Additionally the pass also has an extra_slack_distribution option has been to control how to distribute the extra slack when the duration of the created dynamical decoupling sequence is shorter than the idle time of your circuit that you want to fill with the sequence. This defaults to middle which is identical to conventional behavior. The new strategy split_edges evenly divide the extra slack into the beginning and end of the sequence, rather than adding it to the interval in the middle of the sequence. This might result in better noise cancellation especially when pulse_alignment > 1.

• The Z2Symmetries class now exposes the threshold tolerances used to chop small real and imaginary parts of coefficients. With this one can control how the coefficients of the tapered operator are simplified. For example:

from qiskit.opflow import Z2Symmetries
from qiskit.quantum_info import Pauli

z2_symmetries = Z2Symmetries(
symmetries=[Pauli("IIZI"), Pauli("IZIZ"), Pauli("ZIII")],
sq_paulis=[Pauli("IIXI"), Pauli("IIIX"), Pauli("XIII")],
sq_list=[1, 0, 3],
tapering_values=[1, -1, -1],
tol=1e-10,
)


By default, coefficients are chopped with a tolerance of tol=1e-14.

• Added a chop() method to the SparsePauliOp class that truncates real and imaginary parts of coefficients individually. This is different from the SparsePauliOp.simplify() method which removes a coefficient only if the absolute value is close to 0. For example:

>>> from qiskit.quantum_info import SparsePauliOp
>>> op = SparsePauliOp(["X", "Y", "Z"], coeffs=[1+1e-17j, 1e-17+1j, 1e-17])
>>> op.simplify()
SparsePauliOp(['X', 'Y'],
coeffs=[1.e+00+1.e-17j, 1.e-17+1.e+00j])
>>> op.chop()
SparsePauliOp(['X', 'Y'],
coeffs=[1.+0.j, 0.+1.j])


Note that the chop method does not accumulate the coefficents of the same Paulis, e.g.

>>> op = SparsePauliOp(["X", "X"], coeffs=[1+1e-17j, 1e-17+1j)
>>> op.chop()
SparsePauliOp(['X', 'X'],
coeffs=[1.+0.j, 0.+1.j])

• 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-terra with just a working Python environment will not be sufficient to install Qiskit. 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 here.

• The Gradient and QFI classes can now calculate the imaginary part of expectation value gradients. When using a different measurement basis, i.e. -Y instead of Z, we can measure the imaginary part of gradients The measurement basis can be set with the aux_meas_op argument.

For the gradients, aux_meas_op = Z computes 0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉] and aux_meas_op = -Y computes 0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. For the QFIs, aux_meas_op = Z computes 4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)] and aux_meas_op = -Y computes 4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]. For example:

from qiskit import QuantumRegister, QuantumCircuit
from qiskit.opflow import CircuitStateFn, Y
from qiskit.circuit import Parameter

a = Parameter("a")
b = Parameter("b")
params = [a, b]

q = QuantumRegister(1)
qc = QuantumCircuit(q)
qc.h(q)
qc.rz(params[0], q[0])
qc.rx(params[1], q[0])
op = CircuitStateFn(primitive=qc, coeff=1.0)

aux_meas_op = -Y


• Added a new value for the style keyword argument on the circuit drawer function circuit_drawer() and QuantumCircuit.draw() method, iqx_dark. When style is set to iqx_dark with the mpl drawer backend, the output visualization will use a color scheme similar to the the dark mode color scheme used by the IBM Quantum composer. For example:

from qiskit.circuit import QuantumCircuit
from matplotlib.pyplot import show

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.p(0.2, 1)

circuit.draw("mpl", style="iqx-dark")

• Several lazy dependency checkers have been added to the new module qiskit.utils.optionals, which can be used to query if certain Qiskit functionality is available. For example, you can ask if Qiskit has detected the presence of matplotlib by asking if qiskit.utils.optionals.HAS_MATPLOTLIB. These objects only attempt to import their dependencies when they are queried, so you can use them in runtime code without affecting import time.

• Import time for qiskit has been significantly improved, especially for those with many of Qiskit Terra’s optional dependencies installed.

• The marginal_counts() function now supports marginalizing the memory field of an input Result object. For example, if the input result argument is a qiskit Result object obtained from a 4-qubit measurement we can marginalize onto the first qubit with:

print(result.results[0].data.memory)
marginal_result = marginal_counts(result, [0])
print(marginal_result.results[0].data.memory)


The output is:

['0x0', '0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7']
['0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1']

• The internals of the StochasticSwap algorithm have been reimplemented to be multithreaded and are now written in the Rust programming language instead of Cython. This significantly increases the run time performance of the compiler pass and by extension transpile() when run with optimization_level 0, 1, and 2. By default the pass will use up to the number of logical CPUs on your local system but you can control the number of threads used by the pass by setting the RAYON_NUM_THREADS environment variable to an integer value. For example, setting RAYON_NUM_THREADS=4 will run the StochasticSwap with 4 threads.

• A new environment variable QISKIT_FORCE_THREADS is available for users to directly control whether potentially multithreaded portions of Qiskit’s code will run in multiple threads. Currently this is only used by the StochasticSwap transpiler pass but it likely will be used other parts of Qiskit in the future. When this env variable is set to TRUE any multithreaded code in Qiskit Terra will always use multiple threads regardless of any other runtime conditions that might have otherwise caused the function to use a single threaded variant. For example, in StochasticSwap if the pass is being run as part of a transpile() call with > 1 circuit that is being executed in parallel with multiprocessing via parallel_map() the StochasticSwap will not use multiple threads to avoid potentially oversubscribing CPU resources. However, if you’d like to use multiple threads in the pass along with multiple processes you can set QISKIT_FORCE_THREADS=TRUE.

• New fake backend classes are available under qiskit.providers.fake_provider. These include mocked versions of ibm_cairo, ibm_hanoi, ibmq_kolkata, ibm_nairobi, and ibm_washington. As with the other fake backends, these include snapshots of calibration and error data taken from the real system, and can be used for local testing, compilation and simulation.

• Introduced a new class StatePreparation. This class allows users to prepare a desired state in the same fashion as Initialize without the reset being automatically applied.

For example, to prepare a qubit in the state $$(|0\rangle - |1\rangle) / \sqrt{2}$$:

import numpy as np
from qiskit import QuantumCircuit

circuit = QuantumCircuit(1)
circuit.prepare_state([1/np.sqrt(2), -1/np.sqrt(2)], 0)
circuit.draw()


The output is as:

     ┌─────────────────────────────────────┐
q_0: ┤ State Preparation(0.70711,-0.70711) ├
└─────────────────────────────────────┘

• The Optimize1qGates transpiler pass now has support for optimizing U1Gate, U2Gate, and PhaseGate gates with unbound parameters in a circuit. Previously, if these gates had unbound parameters the pass would not use them. For example:

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import Optimize1qGates, Unroller

phi = Parameter('φ')
alpha = Parameter('α')

qc = QuantumCircuit(1)
qc.u1(2*phi, 0)
qc.u1(alpha, 0)
qc.u1(0.1, 0)
qc.u1(0.2, 0)

pm = PassManager([Unroller(['u1', 'cx']), Optimize1qGates()])
nqc = pm.run(qc)


will be combined to the circuit with only one single-qubit gate:

qc = QuantumCircuit(1)
qc.u1(2*phi + alpha + 0.3, 0)

• The methods Pauli.evolve() and PauliList.evolve() now have a new keyword argument, frame, which is used to perform an evolution of a Pauli by a Clifford. If frame='h' (default) then it does the Heisenberg picture evolution of a Pauli by a Clifford ($$P' = C^\dagger P C$$), and if frame='s' then it does the Schrödinger picture evolution of a Pauli by a Clifford ($$P' = C P C^\dagger$$). The latter option yields a faster calculation, and is also useful in certain cases. This new option makes the calculation of the greedy Clifford decomposition method in decompose_clifford significantly faster.

• Added a new module to Qiskit: qiskit.primitives. The primitives module is where APIs are defined which provide different abstractions around computing certain common functions from QuantumCircuit which abstracts away the details of the underlying execution on a Backend. This enables higher level algorithms and applications to concentrate on performing the computation and not need to worry about the execution and processing of results and have a standardized interface for common computations. For example, estimating an expectation value of a quantum circuit and observable can be performed by any class implementing the BaseEstimator class and consumed in a standardized manner regardless of the underlying implementation. Applications can then be written using the primitive interface directly.

To start the module contains two types of primitives, the Sampler (see BaseSampler for the abstract class definition) and Estimator (see BaseEstimator for the abstract class definition). Reference implementations are included in the qiskit.primitives module and are built using the qiskit.quantum_info module which perform ideal simulation of primitive operation. The expectation is that provider packages will offer their own implementations of these interfaces for providers which can efficiently implement the protocol natively (typically using a classical runtime). Additionally, in the future for providers which do not offer a native implementation of the primitives a method will be provided which will enable constructing primitive objects from a Backend.

• The basis search strategy in BasisTranslator transpiler pass has been modified into a variant of Dijkstra search which greatly improves the runtime performance of the pass when attempting to target an unreachable basis.

• The DenseLayout transpiler pass is now multithreaded, which greatly improves the runtime performance of the pass. By default, it will use the number of logical CPUs on your local system, but you can control the number of threads used by the pass by setting the RAYON_NUM_THREADS environment variable to an integer value. For example, setting RAYON_NUM_THREADS=4 will run the DenseLayout pass with 4 threads.

• Added a new SparsePauliOp.from_sparse_list() constructor that takes an iterable, where the elements represent Pauli terms that are themselves sparse, so that "XIIIIIIIIIIIIIIIX" can now be written as ("XX", [0, 16]). For example, the operator

$H = X_0 Z_3 + 2 Y_1 Y_4$

can now be constructed as

op = SparsePauliOp.from_sparse_list([("XZ", [0, 3], 1), ("YY", [1, 4], 2)], num_qubits=5)
# or equivalently, as previously
op = SparsePauliOp.from_list([("IZIIX", 1), ("YIIYI", 2)])


This facilitates the construction of very sparse operators on many qubits, as is often the case for Ising Hamiltonians.

• The UnitarySynthesis transpiler pass has a new keyword argument on its constructor, target. This can be used to optionally specify a Target object which represents the compilation target for the pass. When it’s specified it will supersede the values set for basis_gates, coupling_map, and backend_props.

• Introduced a new transpiler pass workflow for building PassManager objects for scheduling QuantumCircuit objects in the transpiler. In the new workflow scheduling and alignment passes are all AnalysisPass objects that only update the property set of the pass manager, specifically new property set item node_start_time, which holds the absolute start time of each opnode. A separate TransformationPass such as PadDelay is subsequently used to apply scheduling to the DAG. This new workflow is both more efficient and can correct for additional timing constraints exposed by a backend.

Previously, the pass chain would have been implemented as scheduling -> alignment which were both transform passes thus there were multiple DAGCircuit instances recreated during each pass. In addition, scheduling occured in each pass to obtain instruction start time. Now the required pass chain becomes scheduling -> alignment -> padding where the DAGCircuit update only occurs at the end with the padding pass.

For those who are creating custom PassManager objects that involve circuit scheduling you will need to adjust your PassManager to insert one of the BasePadding passes (currently either PadDelay or PadDynamicalDecoupling can be used) at the end of the scheduling pass chain. Without the padding pass the scheduling passes will not be reflected in the output circuit of the run() method of your custom PassManager.

For example, if you were previously building your PassManager with something like:

from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import TimeUnitConversion, ALAPSchedule, ValidatePulseGates, AlignMeasures

pm = PassManager()
scheduling = [
ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
AlignMeasures(alignment=timing_constraints.acquire_alignment),
]
pm.append(scheduling)


from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay

pm = PassManager()
scheduling = [
ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment),
ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
]
pm.append(scheduling)


which will both be more efficient and also align instructions based on any hardware constraints.

• Added two new transpiler passes ALAPScheduleAnalysis and ASAPScheduleAnalysis which superscede the ALAPSchedule and ASAPSchedule as part of the reworked transpiler workflow for schedling. The new passes perform the same scheduling but in the property set and relying on a BasePadding pass to adjust the circuit based on all the scheduling alignment analysis.

The standard behavior of these passes also aligns timing ordering with the topological ordering of the DAG nodes. This change may affect the scheduling outcome if it includes conditional operations, or simultaneously measuring two qubits with the same classical register (edge-case). To reproduce conventional behavior, set clbit_write_latency identical to the measurement instruction length.

For example, consider scheduling an input circuit like:

     ┌───┐┌─┐
q_0: ┤ X ├┤M├──────────────
└───┘└╥┘   ┌───┐
q_1: ──────╫────┤ X ├──────
║    └─╥─┘   ┌─┐
q_2: ──────╫──────╫─────┤M├
║ ┌────╨────┐└╥┘
c: 1/══════╩═╡ c_0=0x1 ╞═╩═
0 └─────────┘ 0

from qiskit import QuantumCircuit
from qiskit.transpiler import InstructionDurations, PassManager
from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay, SetIOLatency
from qiskit.visualization.timeline import draw

circuit = QuantumCircuit(3, 1)
circuit.x(0)
circuit.measure(0, 0)
circuit.x(1).c_if(0, 1)
circuit.measure(2, 0)

durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])

pm = PassManager(
[
SetIOLatency(clbit_write_latency=800, conditional_latency=0),
ALAPScheduleAnalysis(durations),
]
)
draw(pm.run(circuit))


As you can see in the timeline view, the measurement on q_2 starts before the conditional X gate on the q_1, which seems to be opposite to the topological ordering of the node. This is also expected behavior because clbit write-access happens at the end edge of the measure instruction, and the read-access of the conditional gate happens the begin edge of the instruction. Thus topological ordering is preserved on the timeslot of the classical register, which is not captured by the timeline view. However, this assumes a paticular microarchitecture design, and the circuit is not necessary scheduled like this.

By using the default configuration of passes, the circuit is schedule like below.

from qiskit import QuantumCircuit
from qiskit.transpiler import InstructionDurations, PassManager
from qiskit.visualization.timeline import draw

circuit = QuantumCircuit(3, 1)
circuit.x(0)
circuit.measure(0, 0)
circuit.x(1).c_if(0, 1)
circuit.measure(2, 0)

durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])

draw(pm.run(circuit))


Note that clbit is locked throughout the measurement instruction interval. This behavior is designed based on the Qiskit Pulse, in which the acquire instruction takes AcquireChannel and MemorySlot which are not allowed to overlap with other instructions, i.e. simultaneous memory access from the different instructions is prohibited. This also always aligns the timing ordering with the topological node ordering.

• The plot_gate_map() visualization function and the functions built on top of it, plot_error_map() and plot_circuit_layout(), have a new keyword argument, qubit_coordinates. This argument takes a sequence of 2D coordinates to use for plotting each qubit in the backend being visualized. If specified this sequence must have a length equal to the number of qubits on the backend and it will be used instead of the default behavior.

• The plot_gate_map() visualization function and the functions built on top of it, plot_error_map() and plot_circuit_layout(), now are able to plot any backend not just those with the number of qubits equal to one of the IBM backends. This relies on the retworkx spring_layout() function to generate the layout for the visualization. If the default layout doesn’t work with a backend’s particular coupling graph you can use the qubit_coordinates function to set a custom layout.

• Added a new transpiler pass, SetIOLatency. This pass takes two arguments clbit_write_latency and conditional_latency to define the I/O latency for classical bits and classical conditions on a backend. This pass will then define these values on the pass manager’s property set to enable subsequent scheduling and alignment passes to correct for these latencies and provide a more presice scheduling output of a dynamic circuit.

• The VF2Layout transpiler pass has a new keyword argument, target which is used to provide a Target object for the pass. When specified, the Target will be used by the pass for all information about the target device. If it is specified, the target option will take priority over the coupling_map and properties arguments.

• Allow callables as optimizers in VQE and QAOA. Now, the optimizer can either be one of Qiskit’s optimizers, such as SPSA or a callable with the following signature:

from qiskit.algorithms.optimizers import OptimizerResult

def my_optimizer(fun, x0, jac=None, bounds=None) -> OptimizerResult:
# Args:
#     fun (callable): the function to minimize
#     x0 (np.ndarray): the initial point for the optimization
#     jac (callable, optional): the gradient of the objective function
#     bounds (list, optional): a list of tuples specifying the parameter bounds

result = OptimizerResult()
result.x = # optimal parameters
result.fun = # optimal function value
return result


The above signature also allows to directly pass any SciPy minimizer, for instance as

from functools import partial
from scipy.optimize import minimize

optimizer = partial(minimize, method="L-BFGS-B")

##### Known Issues¶
• When running parallel_map() (which is done internally by performance sensitive functions such as transpile() and assemble()) in a subprocess launched outside of parallel_map(), it is possible that the parallel dispatch performed inside parallel_map() will hang and never return. This is due to upstream issues in CPython around the default method to launch subprocesses on Linux and macOS with Python 3.7 (see https://bugs.python.org/issue40379 for more details). If you encounter this, you have two options: you can either remove the nested parallel processes, as calling parallel_map() from a main process should work fine; or you can manually call the CPython standard library multiprocessing module to perform similar parallel dispatch from a subprocess, but use the "spawn" or "forkserver" launch methods to avoid the potential to have things get stuck and never return.

• The classes Qubit, Clbit and AncillaQubit now have the __slots__ attribute. This is to reduce their memory usage. As a side effect, they can no longer have arbitrary data attached as attributes to them. This is very unlikely to have any effect on downstream code other than performance benefits.

• The core dependency retworkx had its version requirement bumped to 0.11.0, up from 0.10.1. This improves the performance of transpilation pass ConsolidateBlocks.

• The minimum supported version of symengine is now 0.9.0. This was necessary to improve compatibility with Python’s pickle module which is used internally as part of parallel dispatch with parallel_map().

• The default value of QISKIT_PARALLEL when running with Python 3.9 on Linux is now set to TRUE. This means when running parallel_map() or functions that call it internally, such as transpile() and assemble(), the function will be executed in multiple processes and should have better run time performance. This change was made because the issues with reliability of parallel dispatch appear to have been resolved (see #6188 for more details). If you still encounter issues because of this you can disable multiprocessing and revert to the previous default behavior by setting the QISKIT_PARALLEL environment variable to FALSE, or setting the parallel option to False in your user config file (also please file an issue so we can track any issues related to multiprocessing).

• The previously deprecated MSGate gate class previously found in qiskit.circuit.library has been removed. It was originally deprecated in the 0.16.0 release. Instead the GMS class should be used, as this allows you to create an equivalent 2 qubit MS gate in addition to an MSGate for any number of qubits.

• The previously deprecated angle argument on the constructors for the C3SXGate and C3XGate gate classes has been removed. It was originally deprecated in the 0.17.0 release. Instead for fractional 3-controlled X gates you can use the C3XGate.power() method.

• A new extra csp-layout-pass has been added to the install target for pip install qiskit-terra, and is also included in the all extra. This has no effect in Qiskit Terra 0.20, but starting from Qiskit Terra 0.21, the dependencies needed only for the CSPLayout transpiler pass will be downgraded from requirements to optionals, and installed by this extra. You can prepare a package that depends on this pass by setting its requirements (or pip install command) to target qiskit-terra[csp-layout-pass].

• Support for running with Python 3.6 has been removed. To run Qiskit you need a minimum Python version of 3.7.

• The error raised by HoareOptimizer if the optional dependency z3 is not available has changed from TranspilerError to MissingOptionalLibraryError (which is both a QiskitError and an ImportError). This was done to be consistent with the other optional dependencies.

• On Linux, the minimum library support has been raised from the manylinux2010 VM to manylinux2014. This mirrors similar changes in Numpy and Scipy. There should be no meaningful effect for most users, unless your system still contains a very old version of glibc.

• The marginal_counts() function when called with a Result object input, will now marginalize the memory field of experiment data if it’s set in the input Result. Previously, the memory field in the the input was not marginalized. This change was made because the previous behavior would result in the counts field not matching the memory field after marginal_counts() was called. If the previous behavior is desired it can be restored by setting marginalize_memory=None as an argument to marginal_counts() which will not marginalize the memory field.

• The StochasticSwap transpiler pass may return different results with the same seed value set. This is due to the internal rewrite of the transpiler pass to improve runtime performance. However, this means that if you ran transpile() with optimization_level 0, 1 (the default), or 2 with a value set for seed_transpiler you may get an output with different swap mapping present after upgrading to Qiskit Terra 0.20.0.

• To build Qiskit Terra from source a Rust compiler is now needed. This is due to the internal rewrite of the StochasticSwap transpiler pass which greatly improves the runtime performance of the transpiler. The rust compiler can easily be installed using rustup, which can be found here: https://rustup.rs/

• The previously deprecated methods:

• qiskit.algorithms.VQE.get_optimal_cost

• qiskit.algorithms.VQE.get_optimal_circuit

• qiskit.algorithms.VQE.get_optimal_vector

• qiskit.algorithms.VQE.optimal_params

• qiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phase

• qiskit.algorithms.PhaseEstimationResult.most_likely_phase

which were originally deprecated in the Qiskit Terra 0.18.0 release have been removed and will no longer work.

• The qiskit.algorithms.VariationalAlgorithm class is now defined as an abstract base class (ABC) which will require classes that inherit from it to define both a VariationalAlgorithm.initial_point getter and setter method.

• The previously deprecated ParametrizedSchedule class has been removed and no longer exists. This class was deprecated as a part of the 0.17.0 release. Instead of using this class you can directly parametrize Schedule or ScheduleBlock objects by specifying a Parameter object to the parametric pulse argument.

• The module qiskit.circuit.library.probability_distributions has been removed and no longer exists as per the deprecation notice from qiskit-terra 0.17.0 (released Apr 1, 2021). The affected classes are UniformDistribution, NormalDistribution, and LogNormalDistribution. They are all moved to the qiskit-finance library, into its circuit library module: qiskit_finance.circuit.library.probability_distributions.

• The previous qiskit.test.mock.fake_mumbai_v2.FakeMumbaiV2 class has been renamed to FakeMumbaiFractionalCX to differentiate it from the BackendV2 based fake backend for the IBM Mumbai device, qiskit.test.mock.backends.FakeMumbaiV2. If you were previously relying on the FakeMumbaiV2 class to get a fake backend that had fractional applications of CXGate defined in its target you need to use FakeMumbaiFractionalCX class as the FakeMumbaiV2 will no longer have those extra gate definitions in its Target.

• The resolver used by QuantumCircuit.append() (and consequently all methods that add an instruction onto a QuantumCircuit) to convert bit specifiers has changed to make it faster and more reliable. Certain constructs like:

import numpy as np
from qiskit import QuantumCircuit

qc = QuantumCircuit(1, 1)
qc.measure(np.array([0]), np.array([0]))


will now work where they previously would incorrectly raise an error, but certain pathological inputs such as:

from sympy import E, I, pi
qc.x(E ** (I * pi))


will now raise errors where they may have occasionally (erroneously) succeeded before. For almost all correct uses, there should be no noticeable change except for a general speed-up.

• The semi-public internal method QuantumCircuit._append() no longer checks the types of its inputs, and assumes that there are no invalid duplicates in its argument lists. This function is used by certain internal parts of Qiskit and other libraries to build up QuantumCircuit instances as quickly as possible by skipping the error checking when the data is already known to be correct. In general, users or functions taking in user data should use the public QuantumCircuit.append() method, which resolves integer bit specifiers, broadcasts its arguments and checks the inputs for correctness.

• Cython is no longer a build dependency of Qiskit Terra and is no longer required to be installed when building Qiskit Terra from source.

##### Deprecation Notes¶
• The max_credits argument to execute(), and all of the Qobj configurations (e.g. QasmQobjConfig and PulseQobjConfig), is deprecated and will be removed in a future release. The credit system has not been in use on IBM Quantum backends for two years, and the option has no effect. No alternative is necessary. For example, if you were calling execute() as:

job = execute(qc, backend, shots=4321, max_credits=10)


you can simply omit the max_credits argument:

job = execute(qc, backend, shots=4321)

• Using an odd integer for the order argument on the constructor of the SuzukiTrotter class is deprecated and will no longer work in a future release. The product formulae used by the SuzukiTrotter are only defined when the order is even as the Suzuki product formulae is symmetric.

• The qregs, cregs, layout, and global_phase kwargs to the MatplotlibDrawer, TextDrawing, and QCircuitImage classes, and the calibrations kwarg to the MatplotlibDrawer class, are now deprecated and will be removed in a subsequent release.

##### Bug Fixes¶
• Fixed an issue where calling QuantumCircuit.copy() on the «body» circuits of a control-flow operation created with the builder interface would raise an error. For example, this was previously an error, but will now return successfully:

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qreg = QuantumRegister(4)
creg = ClassicalRegister(1)
circ = QuantumCircuit(qreg, creg)

with circ.if_test((creg, 0)):
circ.h(0)

if_else_instruction, _, _ = circ.data[0]
true_body = if_else_instruction.params[0]
true_body.copy()

• Fixed an issue where running the == operator between two SparsePauliOp objects would raise an error when the two operators had different numbers of coefficients. For example:

op = SparsePauliOp.from_list([("X", 1), ("Y", 1)])
op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)])
print(op == op2)


This would previously raise a ValueError instead of returning False.

• Fixed an issue in the LocalReadoutMitigator.assignment_matrix() method where it would previously reject an input value for the qubits argument that wasn’t a trivial sequence of qubits in the form: [0, 1, 2, ..., n-1]. This has been corrected so that now any list of qubit indices to be measured are accepted by the method.

• An opflow expression containing the Pauli identity opflow.I no longer produces an IGate when converted to a circuit. This change fixes a difference in expectation; the identity gate in the circuit indicates a delay however in opflow we expect a mathematical identity – meaning no operation at all.

• PauliSumOp equality tests now handle the case when one of the compared items is a single PauliOp. For example, 0 * X + I == I now evaluates to True, whereas it was False prior to this release.

• Fixed an issue with the ALAPSchedule and ASAPSchedule transpiler passes when working with instructions that had custom pulse calibrations (i.e. pulse gates) set. Previously, the scheduling passes would not use the duration from the custom pulse calibration for thse instructions which would result in the an incorrect scheduling being generated for the circuit. This has been fixed so that now the scheduling passes will use the duration of the custom pulse calibration for any instruction in the circuit which has a custom calibration.

• The OpenQASM 3 exporter, qasm3.Exporter, will now escape register and parameter names that clash with reserved OpenQASM 3 keywords by generating a new unique name. Registers and parameters with the same name will no longer have naming clashes in the code output from the OpenQASM 3 exporter. Fixed #7742.

No change

No change

No change

### Qiskit 0.34.2¶

#### Terra 0.19.2¶

##### Prelude¶

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.

• 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: https://qiskit.org/documentation/getting_started.html#platform-support) 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.

• Registers will now correctly reject duplicate bits. Fixed #7446.

• 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)
print(PauliEvolutionGate(operator).definition.decompose())


produced

     ┌───────┐
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 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.

• 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)
qpy_file.seek(0)

# Previously both instructions in new_circuit would now be opaque, but
# there is now a correct distinction.
circuit == new_circuit

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

• 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

qr = QuantumRegister(2)
qc = QuantumCircuit([qr[0]])
qc.x(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¶

##### Prelude¶

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.

• 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: https://qiskit.org/documentation/getting_started.html#platform-support) 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 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 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 for details.

No change

No change

### Qiskit 0.34.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)
qc.cx(0, 1)

AerSimulator(method="statevector").run(qc)

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

No change

No change

### Qiskit 0.34.0¶

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.

No change

#### Aer 0.10.1¶

##### Prelude¶

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 for details.

#### Aer 0.10.0¶

##### Prelude¶

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 = backend.run(circuits)


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 = backend.run(scheduled_circuit).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)
])
print(QuantumError(kraus))

# Construction from a QuantumCircuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(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.

Example:

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.h(0)
qc.append(error_h, [0])
qc.cx(0, 1)
qc.append(error_cx, [0, 1])
qc.cx(0, 2)
qc.append(error_cx, [0, 2])
qc.measure_all()

backend = AerSimulator(method='stabilizer')
result = backend.run(qc).result()
result.get_counts(0)


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

• 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¶
• Deprecated the number_of_qubits option of the QuantumError constructor in favor of automatic determination of the dimension.

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

No change

#### IBM Q Provider 0.18.3¶

##### Bug Fixes¶
• Fix delivered in #1100 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.

### Qiskit 0.33.1¶

#### Terra 0.19.1¶

##### Prelude¶

Qiskit Terra 0.19.1 is a bugfix release, solving some issues in 0.19.0 concerning circuits constructed by the control-flow builder interface, conditional gates and QPY serialisation of newer Terra objects.

##### Deprecation Notes¶
• The loose functions qiskit.circuit.measure.measure() and qiskit.circuit.reset.reset() are deprecated, and will be removed in a future release. Instead, you should access these as methods on QuantumCircuit:

from qiskit import QuantumCircuit
circuit = QuantumCircuit(1, 1)

# Replace this deprecated form ...
from qiskit.circuit.measure import measure
measure(circuit, 0, 0)

# ... with either of the next two lines:
circuit.measure(0, 0)
QuantumCircuit.measure(circuit, 0, 0)

##### Bug Fixes¶
• Fixed an issue where calling QuantumCircuit.copy() on the «body» circuits of a control-flow operation created with the builder interface would raise an error. For example, this was previously an error, but will now return successfully:

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qreg = QuantumRegister(4)
creg = ClassicalRegister(1)
circ = QuantumCircuit(qreg, creg)

with circ.if_test((creg, 0)):
circ.h(0)

if_else_instruction, _, _ = circ.data[0]
true_body = if_else_instruction.params[0]
true_body.copy()

• The control-flow builder interface now supports using ClassicalRegisters as conditions in nested control-flow scopes. Previously, doing this would not raise an error immediately, but the internal circuit blocks would not have the correct registers defined, and so later logic that worked with the inner blocks would fail.

For example, previously the drawers would fail when trying to draw an inner block conditioned on a classical register, whereas now it will succeed, such as in this example:

from qiskit import QuantumCircuit
from qiskit.circuit import QuantumRegister, ClassicalRegister

qreg = QuantumRegister(4)
creg = ClassicalRegister(1)
circ = QuantumCircuit(qreg, creg)

with circ.for_loop(range(10)) as a:
circ.ry(a, 0)
with circ.if_test((creg, 1)):
circ.break_loop()

print(circ.draw(cregbundle=False))
print(circ.data[0][0].blocks[0].draw(cregbundle=False))

• Fixed qpy_serialization support for serializing QuantumCircuit objects that are using ParameterVector or ParameterVectorElement as parameters. Previously, a ParameterVectorElement parameter was just treated as a Parameter for QPY serialization which meant the ParameterVector context was lost in QPY and the output order of parameters could be incorrect.

To fix this issue a new QPY format version, version_3, was required. This new format version includes a representation of the ParameterVectorElement class which is described in the qpy_serialization documentation at param_vector.

• Two loose functions qiskit.circuit.measure.measure() and qiskit.circuit.reset.reset() were accidentally removed without a deprecation period. They have been reinstated, but are marked as deprecated in favour of the methods QuantumCircuit.measure() and QuantumCircuit.reset(), respectively, and will be removed in a future release.

##### Other Notes¶
• The new control-flow builder interface uses various context managers and helper objects to do its work. These should not be considered part of the public API, and are liable to be changed and removed without warning. The usage of the builder interface has stability guarantees, in the sense that the behaviour described by QuantumCircuit.for_loop(), while_loop() and if_test() for the builder interface are subject to the standard deprecation policies, but the actual objects used to effect this are not. You should not rely on the objects (such as IfContext or ControlFlowBuilderBlock) existing in their current locations, or having any methods or attributes attached to them.

This was not previously clear in the 0.19.0 release. All such objects now have a warning in their documentation strings making this explicit. It is likely in the future that their locations and backing implementations will become quite different.

No change

No change

### Qiskit 0.33.0¶

This release officially marks the end of support for the Qiskit Aqua project in Qiskit. It was originally deprecated in the 0.25.0 release and as was documented in that release the qiskit-aqua package has been removed from the Qiskit metapackage, which means pip install qiskit will no longer include qiskit-aqua. However, because of limitations in python packaging we cannot automatically remove a pre-existing install of qiskit-aqua when upgrading a previous version of Qiskit to this release (or a future release) with pip install -U qiskit. If you are upgrading from a previous version it’s recommended that you manually uninstall Qiskit Aqua with pip uninstall qiskit-aqua or install in a fresh python environment.

The application modules that were provided by qiskit-aqua have been split into several new packages: qiskit-optimization, qiskit-nature, qiskit-machine-learning, and qiskit-finance. These packages can be installed by themselves (via the standard pip install command, e.g. pip install qiskit-nature) or with the rest of the Qiskit metapackage as optional extras (e.g. pip install 'qiskit[finance,optimization]' or pip install 'qiskit[all]'). The core algorithms and the operator flow now exist as part of Qiskit Terra at qiskit.algorithms and qiskit.opflow. Depending on your existing usage of Aqua you should either use the application packages or the new modules in Qiskit Terra. For more details on how to migrate from Qiskit Aqua you can refer to the Aqua Migration Guide.

This release also officially deprecates the Qiskit Ignis project. Accordingly, in a future release the qiskit-ignis package will be removed from the Qiskit metapackage, which means in that future release pip install qiskit will no longer include qiskit-ignis. Qiskit Ignis has been supersceded by the Qiskit Experiments project and active development has ceased. While deprecated, critical bug fixes and compatibility fixes will continue to be made to provide users a sufficient opportunity to migrate off of Ignis. After the deprecation period (which will be no shorter than 3 months from this release) the project will be retired and archived. You can refer to the migration guide for details on how to switch from Qiskit Ignis to Qiskit Experiments.

#### Terra 0.19.0¶

##### Prelude¶

The Qiskit Terra 0.19 release highlights are:

This release marks the end of support for Python 3.6 in Qiskit. This release of Qiskit Terra, and any subsequent bugfix releases in the 0.19.x series, will be the last to work with Python 3.6. Starting from the next minor release (0.20.0) of Qiskit Terra, the minimum required Python version will be 3.7.

As always, there are many more features and fixes in this release as well, which you can read about below.

##### New Features¶
• QuantumCircuit.decompose() and its corresponding transpiler pass Decompose now optionally accept a parameter containing a collection of gate names. If this parameter is given, then only gates with matching names will be decomposed. This supports Unix-shell-style wildcard matches. For example:

qc.decompose(["h", "r[xz]"])


will decompose any h, rx or rz gates, but leave (for example) x gates untouched.

• Added the termination_checker argument to the SPSA optimizer. This allows the user to implement a custom termination criterion.

import numpy as np
from qiskit.algorithms.optimizers import SPSA

def objective(x):
return np.linalg.norm(x) + .04*np.random.rand(1)

class TerminationChecker:

def __init__(self, N : int):
"""
Callback to terminate optimization when the average decrease over
the last N data points is smaller than the specified tolerance.
"""
self.N = N
self.values = []

def __call__(self, nfev, parameters, value, stepsize, accepted) -> bool:
"""
Returns:
True if the optimization loop should be terminated.
"""
self.values.append(value)

if len(self.values) > self.N:
last_values = self.values[-self.N:]
pp = np.polyfit(range(self.N), last_values, 1)
slope = pp[0] / self.N

if slope > 0:
return True
return False

maxiter = 400
spsa = SPSA(maxiter=maxiter, termination_checker=TerminationChecker(10))
parameters, value, niter = spsa.optimize(2, objective, initial_point=np.array([0.5, 0.5]))

• Added a new Target class to the transpiler module. The Target class is designed to represent the constraints of backend to the compiler. The Target class is intended to be used with a BackendV2 backend and is how backends will model their constraints for the transpiler moving forward. It combines the previously distinct fields used for controlling the transpile() target device (e.g. basis_gates, coupling_map, instruction_durations, etc) into a single data structure. It also adds additional functionality on top of what was available previously such as representing heterogeneous gate sets, multi-qubit gate connectivity, and tuned variants of the same gates. Currently the transpiler doesn’t factor in all these constraints, but over time it will grow to leverage the extra functionality.

• The Options class now has optional support for specifying validators. This enables Backend authors to optionally specify basic validation on the user supplied values for fields in the Options object. For example, if you had an Options object defined with:

from qiskit.providers.Options
options = Options(shots=1024)


you can set a validator on shots for it to be between 1 and 4096 with:

options.set_validator('shots', (1, 4096))


With the validator set any call to the update_options() method will check that if shots is being updated the proposed new value is within the valid range.

• Added a new transpiler analysis pass, ContainsInstruction, to the qiskit.transpiler.passes module. This pass is used to determine if a circuit contains a specific instruction. It takes in a single parameter at initialization, the name of the instruction to check for and set a boolean in the property set whether the circuit contains that instruction or not. For example:

from qiskit.transpiler.passes import ContainsInstruction
from qiskit.circuit import QuantumCircuit

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

property_set = {}
contains_h = ContainsInstruction("h")
contains_h(circuit, property_set)
assert property_set["contains_h"] == True
# Not contains SX
contains_sx = ContainsInstruction("sx")
contains_sx(circuit, property_set)
assert property_set["contains_sx"] == False

• Added a utility function qiskit.utils.detach_prefix() that is a counterpart of apply_prefix(). The new function returns a tuple of scaled value and prefix from a given float value. For example, a value 1.3e8 will be converted into (130, "M") that can be used to display a value in the user friendly format, such as 130 MHz.

• The values "gate_error" and "balanced" are now available for the objective option in the construction of the BIPMapping object, and "balanced" is now the default.

The "gate_error" objective requires passing a BackendProperties instance in the backend_prop kwarg, which contains the 2q-gate gate errors used in the computation of the objectives. The "balanced" objective will use the BackendProperties instance if it is given, but otherwise will assume a CX error rate as given in the new parameter default_cx_error_rate. The relative weights of the gate-error and depth components of the balanced objective can be controlled with the new depth_obj_weight parameter.

• Every attribute of the VQE class that is set at the initialization is now accessible with getters and setters. Further, the default values of the VQE attributes ansatz and optimizer can be reset by assigning None to them:

vqe = VQE(my_ansatz, my_optimizer)
vqe.ansatz = None   # reset to default: RealAmplitudes ansatz
vqe.optimizer = None  # reset to default: SLSQP optimizer

• Added a new coupling-map constructor method CouplingMap.from_hexagonal_lattice() for constructing a hexagonal lattice coupling map. For example, to construct a 2x2 hexagonal lattice coupling map:

from qiskit.transpiler import CouplingMap
cmap = CouplingMap.from_hexagonal_lattice(2, 2)
cmap.draw()

• New fake backend classes are available under qiskit.test.mock. These include mocked versions of ibmq_brooklyn, ibmq_manila, ibmq_jakarta, and ibmq_lagos. As with the other fake backends, these include snapshots of calibration data (i.e. backend.defaults()) and error data (i.e. backend.properties()) taken from the real system, and can be used for local testing, compilation and simulation.

• Added a new constructor method PassManagerConfig.from_backend(). It constructs a PassManagerConfig object with user options and the configuration of a backend. With this feature, a preset passmanager can be built easier. For example:

from qiskit.transpiler.passmanager_config import PassManagerConfig
from qiskit.transpiler.preset_passmanagers import level_1_pass_manager
from qiskit.test.mock import FakeMelbourne

pass_manager = level_1_pass_manager(
PassManagerConfig.from_backend(FakeMelbourne(), seed_transpiler=42)
)

• A new transpiler pass, PulseGates, was added, which automatically extracts user-provided calibrations from the instruction schedule map and attaches the gate schedule to the given (transpiled) quantum circuit as a pulse gate.

The PulseGates transpiler pass is applied to all optimization levels from 0 to 3. No gate implementation is updated unless the end-user explicitly overrides the backend.defaults().instruction_schedule_map. This pass saves users from individually calling QuantumCircuit.add_calibration() for every circuit run on the hardware.

To supplement this new pass, a schedule was added to InstructionScheduleMap and is implicitly updated with a metadata field "publisher". Backend-calibrated gate schedules have a special publisher kind to avoid overriding circuits with calibrations of already known schedules. Usually, end-users don’t need to take care of this metadata as it is applied automatically. You can call InstructionScheduleMap.has_custom_gate() to check if the map has custom gate calibration.

See the below code example to learn how to apply custom gate implementation for all circuits under execution.

from qiskit.test.mock import FakeGuadalupe
from qiskit import pulse, circuit, transpile

with pulse.build(backend, name="x") as x_q0:
pulse.play(pulse.Constant(160, 0.1), pulse.drive_channel(0))

circs = []
for _ in range(100):
circ = circuit.QuantumCircuit(1)
circ.sx(0)
circ.rz(1.57, 0)
circ.x(0)
circ.measure_active()
circs.append(circ)

circs = transpile(circs, backend)
circs[0].calibrations  # This returns calibration only for x gate


Note that the instruction schedule map is a mutable object. If you override one of the entries and use that backend for other experiments, you may accidentally update the gate definition.

backend = FakeGuadalupe()

instmap = backend.defaults().instruction_schedule_map

qc = QuantumCircuit(1, 1)
qc.x(0)
qc.measure(0, 0)

qc = transpile(qc, backend)  # This backend uses custom X gate


If you want to update the gate definitions of a specific experiment, you need to first deepcopy the instruction schedule map and directly pass it to the transpiler.

• Introduced a new option qubit_subset to the constructor of BIPMapping. The option enables us to specify physical qubits to be used (in coupling_map of the device) during the mapping in one line:

mapped_circ = BIPMapping(
coupling_map=CouplingMap([[0, 1], [1, 2], [1, 3], [3, 4]]),
qubit_subset=[1, 3, 4]
)(circ)


Previously, to do the same thing, we had to supply a reduced coupling_map which contains only the qubits to be used, embed the resulting circuit onto the original coupling_map and update the QuantumCircuit._layout accordingly:

reduced_coupling = coupling_map.reduce(qubit_to_use)
mapped = BIPMapping(reduced_coupling)(circ)
# skip the definition of fill_with_ancilla()
# recover circuit on original coupling map
layout = Layout({q: qubit_to_use[i] for i, q in enumerate(mapped.qubits)})
for reg in mapped.qregs:
property_set = {"layout": fill_with_ancilla(layout)}
recovered = ApplyLayout()(mapped, property_set)
# recover layout
overall_layout = Layout({v: qubit_to_use[q] for v, q in mapped._layout.get_virtual_bits().items()})
for reg in mapped.qregs:
recovered._layout = fill_with_ancilla(overall_layout)

• Added the ignore_pauli_phase and copy arguments to the constructor of SparsePauliOp. ignore_pauli_phase prevents the phase attribute of an input PauliList from being read, which is more performant if the PauliList is already known to have all phases as zero in the internal ZX convention. copy allows users to avoid the copy of the input data when they explicitly set copy=False.

• Added the SparsePauliOp.sum() method to add together many SparsePauliOps. This method has significantly better performance than adding the instances together in a loop. For example, the previous way to add several SparsePauliOps together would be to do:

from qiskit.quantum_info import SparsePauliOp, random_pauli_list
sparse_ops = [SparsePauliOp(random_pauli_list(10, 10)) for _ in [None]*1000]

total = sparse_ops[0]
for op in sparse_ops[1:]:
total += op


This can now be done far more efficiently (in both speed and typing!) as:

SparsePauliOp.sum(sparse_ops)

• Using QuantumCircuit.draw() or circuit_drawer() with the latex drawer will now generate a file in an image format inferred from the filename extension, for example:

import qiskit

circuit = qiskit.QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.draw('latex', filename='./file.jpg')


This will save the circuit drawing in the JPEG format. Previously, the image always be in PNG format. Refer to #6448 for more details.

Now, if it encounters a filename extension which is not supported, for example:

circuit.draw('latex', filename='./file.spooky')


it will raise a ValueError to change the filename extension to a supported image format.

• Introduced an approximate quantum compiler and a corresponding unitary synthesis plugin implementation. The main AQC class is AQC for a standalone version that compiles a unitary matrix into an approximate circuit. The plugin may be invoked by transpile() when the unitary_synthesis_method argument is set to 'aqc'. See qiskit.transpiler.synthesis.aqc for full details.

• Added a filter_function argument to QuantumCircuit.depth() and QuantumCircuit.size() in order to analyze circuit operations according to some criteria.

For example, to get the number of two-qubit gates, you can do:

circuit.size(lambda x: x[0].num_qubits == 2)


Or to get the depth of T gates acting on the zeroth qubit:

circuit.depth(lambda x: x[0].name == 't' and circuit.qubits[0] in x[1])

• Introduced a new transpiler pass InverseCancellation that generalizes the CXCancellation pass to cancel any self-inverse gates or gate-inverse pairs. It can be used by initializing InverseCancellation and passing a gate to cancel, for example:

from qiskit.transpiler.passes import InverseCancellation
from qiskit import QuantumCircuit
from qiskit.circuit.library import HGate
from qiskit.transpiler import PassManager

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.h(0)
pass_ = InverseCancellation([HGate()])
pm = PassManager(pass_)
new_circ = pm.run(qc)

• The constructor of RZXCalibrationBuilder has two new kwargs instruction_schedule_map and qubit_channel_mapping which take a InstructionScheduleMap and list of channel name lists for each qubit respectively. These new arguments are used to directly specify the information needed from a backend target. They should be used instead of passing a BaseBackend or BackendV1 object directly to the pass with the backend argument.

• The Statevectors of states comprised only of qubits can now be drawn in LaTeX in ket notation. In ket notation the entries of the statevector are processed such that exact factors like fractions or square roots of two are drawn as such. The particular convention can be chosen by passing the convention keyword argument as either "ket" or "vector" as appropriate:

import math
from qiskit.quantum_info import Statevector

sv = Statevector([math.sqrt(0.5), 0, 0, -math.sqrt(0.5)])
sv.draw("latex", convention="ket")
sv.draw("latex", convention="vector")

• Added a new transpiler pass EchoRZXWeylDecomposition that allows users to decompose an arbitrary two-qubit gate in terms of echoed RZX-gates by leveraging Cartan’s decomposition. In combination with other transpiler passes, this can be used to transpile arbitrary circuits to RZX-gate-based and pulse-efficient circuits that implement the same unitary.

• The SPSA and QNSPSA optimizer classes are now capable of batching as many circuit evaluations as possible for both the iterations and the initial calibrations. This can be leveraged by setting the max_evals_grouped kwarg on the constructor for VQE when using either SPSA or QNSPSA as the optimizer parameter. For example:

from qiskit.circuit.library import TwoLocal
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import QNSPSA
from qiskit.test.mock import FakeMontreal

backend = FakeMontreal()
ansatz = TwoLocal(2, rotation_blocks=["ry", "rz"], entanglement_blocks="cz")
qnspsa = QNSPSA(fidelity, maxiter=5)
vqe = VQE(
ansatz=ansatz,
optimizer=qnspsa,
max_evals_grouped=100,
quantum_instance=backend,
)

• This release introduces a decomposition method for two-qubit gates which targets user-defined sets of RZX gates. Transpiler users can enable decomposition for {RZX(pi/2), RZX(pi/4), and RZX(pi/6)} specifically by including 'rzx' in their basis_gates list when calling transpile(). Quantum information package users can find the method itself under the XXDecomposer class.

• Added a max_job_tries parameter to QuantumInstance, to limit the number of times a job will attempt to be executed on a backend. Previously the submission and fetching of results would be attempted infinitely, even if the job was cancelled or errored on the backend. The default is now 50, and the previous behaviour can be achieved by setting max_job_tries=-1. Fixes #6872 and #6821.

• The latex output method for the circuit_drawer() function and the QuantumCircuit.draw() method can now draw circuits that contain gates with single bit condition. This was added for compatibility of latex drawer with the new feature of supporting classical conditioning of gates on single classical bits.

• The "mpl" output method for the circuit_drawer() function and the QuantumCircuit.draw() method can now draw circuits that contain gates with single bit condition. This was added for compatibility of the "mpl" drawer with the new feature of supporting classical conditioning of gates on single classical bits.

• The text output method for the circuit_drawer() function and the QuantumCircuit.draw() method can now draw circuits that contain gates with single bit condition. This was added for compatibility of text drawer with the new feature of supporting classical conditioning of gates on single classical bits.

• A new analysis transpiler pass, GatesInBasis, was added to qiskit.transpiler.passes. This pass is used to check if the DAGCircuit being transpiled has all the gates in the configured basis set or not. It will set the attribute "all_gates_in_basis" in the property set to True if all the gates in the DAGCircuit are in the configured basis set or False if they are not. For example:

from qiskit.circuit import QuantumCircuit
from qiskit.transpiler.passes import GatesInBasis

# Instatiate Pass
basis_gates = ["cx", "h"]
basis_check_pass = GatesInBasis(basis_gates)
# Build circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# Run pass on circuit
property_set = {}
basis_check_pass(circuit, property_set=property_set)
assert property_set["all_gates_in_basis"]

• The HHL algorithm can now find solutions when its matrix has negative eigenvalues. To enable this, the algorithm now adds an extra qubit to represent the sign of the value, and the helper algorithm ExactReciprocal was updated to process this new information. See #6971 for more details.

• Added a new parameter, add_bits, to QuantumCircuit.measure_all(). By default it is set to True to maintain the previous behaviour of adding a new ClassicalRegister of the same size as the number of qubits to store the measurements. If set to False, the measurements will be stored in the already existing classical bits. For example, if you created a circuit with existing classical bits like:

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qr = QuantumRegister(2)
cr = ClassicalRegister(2, "meas")
circuit = QuantumCircuit(qr, cr)


calling circuit.measure_all(add_bits=False) will use the existing classical register cr as the output target of the Measurement objects added to the circuit.

• ParameterExpression now delegates its numeric conversions to the underlying symbolic library, even if there are potentially unbound parameters. This allows conversions of expressions such as:

>>> from qiskit.circuit import Parameter
>>> x = Parameter('x')
>>> float(x - x + 2.3)
2.3


where the underlying expression has a fixed value, but the parameter x is not yet bound.

• Added an Optimizer.minimize() method to all optimizers: Optimizer and derived classes. This method mimics the signature of SciPy’s minimize() function and returns an OptimizerResult.

For example

import numpy as np
from qiskit.algorithms.optimizers import COBYLA

def loss(x):
return -(x[0] - 1) ** 2 - (x[1] + 1) ** 3

initial_point = np.array([0, 0])
optimizer = COBYLA()
result = optimizer.minimize(loss, initial_point)

optimal_parameters = result.x
minimum_value = result.fun
num_function_evals = result.nfev

• Added a PauliEvolutionGate to the circuit library (qiskit.circuit.library) which defines a gate performing time evolution of (sums or sums-of-sums of) Paulis. The synthesis of this gate is performed by EvolutionSynthesis and is decoupled from the gate itself. Currently available synthesis methods are:

For example:

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.quantum_info import SparsePauliOp
from qiskit.synthesis import SuzukiTrotter

operator = SparsePauliOp.from_list([
("XIZ", 0.5), ("ZZX", 0.5), ("IYY", -1)
])
time = 0.12  # evolution time
synth = SuzukiTrotter(order=4, reps=2)

evo = PauliEvolutionGate(operator, time=time, synthesis=synth)

circuit = QuantumCircuit(3)
circuit.append(evo, range(3))

• A new function plot_coupling_map() has been introduced, which extends the functionality of the existing function plot_gate_map(), by accepting three parameters: num_qubit, qubit_coordinates, and coupling_map (instead of backend), to allow an arbitrary qubit coupling map to be plotted.

• Qiskit Terra now has initial support for serializing QuantumCircuits to OpenQASM 3:

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit import qasm3

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

print(qasm3.dumps(qc))

OPENQASM 3;
include "stdgates.inc";
qubit[2] _all_qubits;
let q = _all_qubits[0:1];
h q[0];
cx q[0], q[1];



This initial release has limited support for named registers, basic built-in instructions (such as measure, barrier and reset), user-defined gates, user-defined instructions (as subroutines), and the new control-flow constructs also introduced in this release:

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit import qasm3
import math

composite_circ_qreg = QuantumRegister(2)
composite_circ = QuantumCircuit(composite_circ_qreg, name="composite_circ")
composite_circ.h(0)
composite_circ.x(1)
composite_circ.cx(0, 1)
composite_circ_gate = composite_circ.to_gate()

qr = QuantumRegister(2, "qr")
cr = ClassicalRegister(2, "cr")
qc = QuantumCircuit(qr, cr)
with qc.for_loop(range(4)) as i:
qc.rx(i * math.pi / 4, 0)
qc.cx(0, 1)
qc.barrier()
qc.append(composite_circ_gate, [0, 1])
qc.measure([0, 1], [0, 1])

print(qasm3.dumps(qc))

OPENQASM 3;
include "stdgates.inc";
gate composite_circ _gate_q_0, _gate_q_1 {
h _gate_q_0;
x _gate_q_1;
cx _gate_q_0, _gate_q_1;
}
bit[2] cr;
qubit[2] _all_qubits;
let qr = _all_qubits[0:1];
for _loop_i_0 in [0:3] {
rx(pi/4*_loop_i_0) qr[0];
cx qr[0], qr[1];
}
barrier qr[0], qr[1];
composite_circ qr[0], qr[1];
cr[0] = measure qr[0];
cr[1] = measure qr[1];


• The QDrift class was reformulated as a synthesis method for PauliEvolutionGate, deriving from TrotterizationBase.

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import QDrift
from qiskit.opflow import X, Y, Z

qdrift = QDrift(reps=2)
operator = (X ^ 3) + (Y ^ 3) + (Z ^ 3)
time = 2.345  # evolution time

evolution_gate = PauliEvolutionGate(operator, time, synthesis=qdrift)

circuit = QuantumCircuit(3)
circuit.append(evolution_gate, range(3))

• A new find_bit() method has been added to the QuantumCircuit class, which allows lookups of the index and registers of a provided Bit on the given circuit. The method returns a two-element namedtuple containing 0) the index of the Bit in either qubits (for a Qubit) or clbits (for a Clbit) and 1) a list of length-2 tuples containing each circuit Register which contains the Bit, and the index in that Register at which the Bit can be found.

For example:

from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit

reg1 = QuantumRegister(3, 'foo')
qubit = Qubit()
reg2 = QuantumRegister(2, 'bar')

qc = QuantumCircuit(reg1, [qubit], reg2)

print(qc.find_bit(reg1[2]))
print(qc.find_bit(qubit))


would generate:

BitLocations(index=2, registers=[(QuantumRegister(3, 'foo'), 2)])
BitLocations(index=3, registers=[])

• Added the LocalReadoutMitigator class for performing measurement readout error mitigation of local measurement errors. Local measuerment errors are those that are described by a tensor-product of single-qubit measurement errors.

This class can be initialized with a list of $$N$$ single-qubit of measurement error assignment matrices or from a backend using the readout error information in the backend properties.

Mitigation is implemented using local assignment-matrix inversion which has complexity of $$O(2^N)$$ for $$N$$-qubit mitigation of QuasiDistribution and expectation values.

• Added the CorrelatedReadoutMitigator class for performing measurement readout error mitigation of correlated measurement errors. This class can be initialized with a single $$2^N \times 2^N$$ measurement error assignment matrix that descirbes the error probabilities. Mitigation is implemented via inversion of assigment matrix which has mitigation complexity of $$O(4^N)$$ of QuasiDistribution and expectation values.

• When running the Grover algorithm class if the optimal power is known and only a single circuit is run, the AmplificationProblem.is_good_state callback function is no longer required to be set and the Grover search will return the most likely bitstring. Generally, if the optimal power of the Grover operator is not known, the Grover algorithm checks different powers (i.e. iterations) and applies the is_good_state function to check whether a good bitstring has been measured. For example, you are now able to run something like:

from qiskit.algorithms import Grover, AmplificationProblem
from qiskit.providers.aer import AerSimulator
from qiskit.quantum_info import Statevector

# Fixed Grover power: 2.
grover = Grover(iterations=2, quantum_instance=AerSimulator())

# The is_good_state argument not required here since Grover search
# will be run only once, with a power of 2.
problem = AmplificationProblem(Statevector.from_label("111"))

# Run Grover search and print the best measurement
result = grover.amplify(problem)
print(result.top_measurement)  # should print 111

• Various transpilation internals now use new features in retworkx 0.10 when operating on the internal circuit representation. This can often result in speedups in calls to transpile of around 10-40%, with greater effects at higher optimization levels. See #6302 for more details.

• Allow two transpiler stages in the QuantumInstance, one for parameterized circuits and a second one for bound circuits (i.e. no free parameters) only. If a quantum instance with passes for unbound and bound circuits is passed into a CircuitSampler, the sampler will attempt to apply the unbound pass once on the parameterized circuit, cache it, and only apply the bound pass for all future evaluations.

This enables variational algorithms like the VQE to run a custom pass manager for parameterized circuits once and, additionally, another the transpiler again with a different custom pass manager on the bound circuits in each iteration. Being able to run different pass managers is important because not all passes support parameterized circuits (for example Optimize1qGatesDecomposition only works with bound circuit parameters).

For example, this feature allows using the pulse-efficient CX decomposition in the VQE, as

from qiskit.algorithms import VQE
from qiskit.opflow import Z
from qiskit.circuit.library.standard_gates.equivalence_library import StandardEquivalenceLibrary as std_eqlib
from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap
from qiskit.transpiler.preset_passmanagers import level_1_pass_manager
from qiskit.transpiler.passes import (
Collect2qBlocks, ConsolidateBlocks, Optimize1qGatesDecomposition,
RZXCalibrationBuilderNoEcho, UnrollCustomDefinitions, BasisTranslator
)
from qiskit.transpiler.passes.optimization.echo_rzx_weyl_decomposition import EchoRZXWeylDecomposition
from qiskit.test.mock import FakeBelem
from qiskit.utils import QuantumInstance

# Replace by a real backend! If not ensure qiskit-aer is installed to simulate the backend
backend = FakeBelem()

# Build the pass manager for the parameterized circuit
rzx_basis = ['rzx', 'rz', 'x', 'sx']
coupling_map = CouplingMap(backend.configuration().coupling_map)
config = PassManagerConfig(basis_gates=rzx_basis, coupling_map=coupling_map)
pre = level_1_pass_manager(config)

# Build a pass manager for the CX decomposition (works only on bound circuits)
post = PassManager([
# Consolidate consecutive two-qubit operations.
Collect2qBlocks(),
ConsolidateBlocks(basis_gates=['rz', 'sx', 'x', 'rxx']),

# Rewrite circuit in terms of Weyl-decomposed echoed RZX gates.
EchoRZXWeylDecomposition(backend),

# Attach scaled CR pulse schedules to the RZX gates.
RZXCalibrationBuilderNoEcho(backend),

# Simplify single-qubit gates.
UnrollCustomDefinitions(std_eqlib, rzx_basis),
BasisTranslator(std_eqlib, rzx_basis),
Optimize1qGatesDecomposition(rzx_basis),
])

quantum_instance = QuantumInstance(backend, pass_manager=pre, bound_pass_manager=post)

vqe = VQE(quantum_instance=quantum_instance)
result = vqe.compute_minimum_eigenvalue(Z ^ Z)

• Introduced a new unitary synthesis plugin interface which is used to enable using alternative synthesis techniques included in external packages seamlessly with the UnitarySynthesis transpiler pass. Users can select a plugin to use when calling transpile() by setting the unitary_synthesis_method kwarg to the plugin’s name. A full list of installed plugins can be found using the qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names() function. For example, if you installed a package that includes a synthesis plugin named special_synth you could use it with:

from qiskit import transpile

transpile(qc, unitary_synthesis_method='special_synth', optimization_level=3)


This will replace all uses of the UnitarySynthesis with the method included in the external package that exports the special_synth plugin.

The plugin interface is built around setuptools entry points which enable packages external to Qiskit to advertise they include a synthesis plugin. For details on writing a new plugin refer to the qiskit.transpiler.passes.synthesis.plugin module documentation.

##### Known Issues¶
• The "ket" convention in the "latex" drawer of Statevector.draw() is only valid for states comprising purely of qubits. If you are using states with some spaces of dimension greater than two, you should either pass convention="vector", or use a different drawer.

• The OpenQASM 3 export capabilities are in a beta state, and some features of Qiskit Terra’s QuantumCircuit are not yet supported. In particular, you may see errors if you try to export custom subroutines with classical parameters, and there is no provision yet for exporting pulse-calibrated operations into OpenPulse.

• When running the BasisTranslator in isolation with the target argument set to a Target object, where some single-qubit gates can only apply to non-overlapping sets of qubits, the output circuit might incorrectly include operations on a qubit that are not allowed by the Target. For example, if you ran:

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.circuit.library import UGate, RZGate, XGate, SXGate, CXGate
from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel

from qiskit.transpiler import PassManager, Target, InstructionProperties
from qiskit.transpiler.passes import BasisTranslator

gmap = Target()

# U gate in qubit 0.
theta = Parameter('theta')
phi = Parameter('phi')
lam = Parameter('lambda')
u_props = {
(0,): InstructionProperties(duration=5.23e-8, error=0.00038115),
}

# Rz gate in qubit 1.
phi = Parameter("phi")
rz_props = {
(1,): InstructionProperties(duration=0.0, error=0),
}

# X gate in qubit 1.
x_props = {
(1,): InstructionProperties(
duration=3.5555555555555554e-08, error=0.00020056469709026198
),
}

# SX gate in qubit 1.
sx_props = {
(1,): InstructionProperties(
duration=3.5555555555555554e-08, error=0.00020056469709026198
),
}

cx_props = {
(0, 1): InstructionProperties(duration=5.23e-7, error=0.00098115),
(1, 0): InstructionProperties(duration=4.52e-7, error=0.00132115),
}

bt_pass = BasisTranslator(sel, target_basis=None, target=gmap)

qc = QuantumCircuit(2)
qc.iswap(0, 1)
output = bt_pass(qc)


output will have RZGate and SXGate on qubit 0, even though this is forbidden. To correct this you can normally run the basis translator a second time (i.e. output = bt_pass(output) in the above example) to correct this. This should not affect the output of running the transpile() function and is only an issue if you run the pass by itself.

• Starting with this version, from qiskit import * will not import submodules, but only a selected list of objects. This might break existing code using from qiskit import * and referring to objects that are not part of the current namespace. As a reminder, import * is considered bad practice and it should not be used in production code. Qiskit sets __all__ in qiskit/__init__.py as a way to mitigate the effects of said bad practice. If your code raises name '<something>' is not defined, add from qiskit import <something> and try again.

• The default method for BIPMapping is now balanced rather than depth. This new objective generally achieves a better result, as it factors in both the circuit depth and the gate error.

• The sort_parameters_by_name of the VQE class has been removed, following its deprecation in Qiskit Terra 0.18. There is no alternative provided, as the new ordering of parameters is the more natural sort order.

• The circuit drawers QuantumCircuit.draw() and circuit_drawer() with the latex option will now save their images in a format determined the file extension (if a file name is provided). Previously, they would always save in PNG format. They now raise ValueError if the image format is not known. This was done to make it easier to save the image in different formats.

• The core dependency retworkx had its version requirement bumped to 0.10.1, up from 0.9. This enables several performance improvements across different transpilation passes.

• The DAGCircuit.extend_back() method has been removed. It was originally deprecated in the 0.13.0 release. Instead you can use the DAGCircuit.compose() method which is more general and provides the same functionality.

• The DAGCircuit.compose_back() method has been removed. It was originally deprecated in the 0.13.0 release. Instead you can use the DAGCircuit.compose() method which is more general and provides the same functionality.

• The edge_map kwarg of the DAGCircuit method compose() has been removed. It was originally deprecated in the 0.14.0 release. The method takes a qubits and clbits kwargs to specify the positional order of bits to compose onto instead of using a dictionary mapping that edge_map previously provided.

• Named access for the first positional argument for the constructor of the SingleQubitUnitary class with u has been removed. It was originally deprecated in the 0.14.0 release. Instead, the first positional argument can be set using the name unitary_matrix (or just set it positionally instead of by name).

• Named access for the first positional argument for the QuantumCircuit method squ with u has been removed. It was originally deprecated in the 0.14.0 release. Instead the first positional argument can be set using the name unitary_matrix (or just set it positionally instead of by name).

• The unused proc and nested_scope kwargs for the qasm() method of the QASM node classes in the qiskit.qasm.node module have been removed. They were originally deprecated in the 0.15.0 release.

• The unused proc and nested_scope kwargs for the latex() method of the QASM node classes in the qiskit.qasm.node module have been removed. They were originally deprecated in the 0.15.0 release.

• The unused proc and nested_scope kwargs for the real() method of the QASM node classes in the qiskit.qasm.node module have been removed. They were originally deprecated in the 0.15.0 release.

• The output of Statevector.draw() when using "latex" output is now the new "ket" convention if plotting a state comprised purely of qubits. This was changed to make reading the output clearer, especially in educational contexts, because it shows the ket labels, and only displays the nonzero elements.

• When running execute() with a BackendV1 backend the default values for the kwargs shots, max_credits, meas_level, meas_return and memory_slot_size will now be whatever the set default is on the target backend’s options attribute. Previously these defaults were set to match the default values when calling execute() with a legacy BaseBackend backend. For example:

from qiskit.test.mock import FakeMumbai
from qiskit import QuantumCircuit, execute

circuit = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

backend = FakeMumbai()
backend.set_options(shots=4096)
execute(qc, backend)


will now run with 4096 shots. While in previous releases it would run with 1024.

• The minimum supported version of Matplotlib has been raised from 2.1.0 to 3.3.0. You will now need to have Matplotlib 3.3.0 installed if you’re using Matplotlib-based visualization functions such as the 'mpl' backend for the circuit_drawer() function or the plot_bloch_vector() function. This was done for two reasons, the first is because recent versions of Matplotlib have deprecated the use of APIs around 3D visualizations that were compatible with older releases and second installing older versions of Matplotlib was becoming increasingly difficult as matplotlib’s upstream dependencies have caused incompatiblities that made testing moving forward more difficult.

• The internal use of the random number generator in random_circuit() was adjusted, which will change the output from previous versions, even with a fixed seed. This was done to greatly improve the runtime scaling with the number of qubits being used. If you were depending on an identical output from a previous version it is recommended that you use qpy_serialization.dump() to save the random circuit generated with a previous version and instead of re-generating it with the new release, and instead just use qpy_serialization.load() to load that saved circuit.

• The use of * (__mul__) for the dot() method and @ (__matmul__) for the compose() method of BaseOperator (which is the parent of all the operator classes in qiskit.quantum_info including classes like Operator and Pauli) is no longer supported. The use of these operators were previously deprecated in 0.17.0 release. Instead you should use the dot() and compose() methods directly, or the & operator (__and__) can be used for compose(). For example, if you were previously using the operator like:

from qiskit.quantum_info import random_hermitian

op_a = random_hermitian(4)
op_b = random_hermitian(4)

new_op = op_a @ op_b


this should be changed to be:

from qiskit.quantum_info import random_hermitian

op_a = random_hermitian(4)
op_b = random_hermitian(4)
new_op = op_a.compose(op_b)


or:

new_op = op_a & op_b

• Various methods of assigning parameters to operands of pulse program instructions have been removed, having been deprecated in Qiskit Terra 0.17. These include:

These parameters should be assigned from the pulse program (pulse.Schedule and pulse.ScheduleBlock) rather than operands of the pulse program instruction.

• The flatten() method of pulse.Instruction and qiskit.pulse.Schedule has been removed and no longer exists as per the deprecation notice from Qiskit Terra 0.17. This transformation is defined as a standalone function in qiskit.pulse.transforms.canonicalization.flatten().

• qiskit.pulse.interfaces.ScheduleComponent has been removed and no longer exists as per the deprecation notice from Qiskit Terra 0.15. No alternative class will be provided.

• Legacy pulse drawer arguments have been removed from pulse.Waveform.draw(), Schedule.draw() and ScheduleBlock.draw() and no longer exist as per the deprecation notice from Qiskit Terra 0.16. Now these draw methods support only V2 pulse drawer arguments. See method documentations for details.

• The qiskit.pulse.reschedule module has been removed and this import path no longer exist as per the deprecation notice from Qiskit Terra 0.14. Use qiskit.pulse.transforms instead.

• A protected method Schedule._children() has been removed and replaced by a protected instance variable as per the deprecation notice from Qiskit Terra 0.17. This is now provided as a public attribute Schedule.children.

• Timeslot relevant methods and properties have been removed and no longer exist in ScheduleBlock as per the deprecation notice from Qiskit Terra 0.17. Since this representation doesn’t have notion of instruction time t0, the timeslot information will be available after it is transformed to a Schedule. Corresponding attributes have been provided after this conversion, but they are no longer supported. The following attributes are removed:

• timeslots

• start_time

• stop_time

• ch_start_time

• ch_stop_time

• shift

• insert

• Alignment pulse schedule transforms have been removed and no longer exist as per the deprecation notice from Qiskit Terra 0.17. These transforms are integrated and implemented in the AlignmentKind context of the schedule block. The following explicit transform functions are removed:

• qiskit.pulse.transforms.align_equispaced

• qiskit.pulse.transforms.align_func

• qiskit.pulse.transforms.align_left

• qiskit.pulse.transforms.align_right

• qiskit.pulse.transforms.align_sequential

• Redundant pulse builder commands have been removed and no longer exist as per the deprecation notice from Qiskit Terra 0.17. pulse.builder.call_schedule and pulse.builder.call_circuit have been integrated into pulse.builder.call().

• An internal filter override that caused all Qiskit deprecation warnings to be displayed has been removed. This means that the behaviour will now revert to the standard Python behaviour for deprecations; you should only see a DeprecationWarning if it was triggered by code in the main script file, interpreter session or Jupyter notebook. The user will no longer be blamed with a warning if internal Qiskit functions call deprecated behaviour. If you write libraries, you should occasionally run with the default warning filters disabled, or have tests which always run with them disabled. See the Python documentation on warnings, and in particular the section on testing for deprecations for more information on how to do this.

• Certain warnings used to be only issued once, even if triggered from multiple places. This behaviour has been removed, so it is possible that if you call deprecated functions, you may see more warnings than you did before. You should change any deprecated function calls to the suggested versions, because the deprecated forms will be removed in future Qiskit releases.

• The deprecated qiskit.schemas module and the qiskit.validation module which build jsonschema validator from the schemas have been removed. This was deprecated in the 0.17.0 release and has been replaced with a dedicated repository for the IBM Quantum API payload schemas.

If you were relying on the schema files previously packaged in qiskit.schemas or the validators built on them you should use that repository and create validators from the schema files it contains.

• The fastjsonschema and jsonschema packages are no longer in the requirements list for qiskit-terra. The internal use of jsonschema has been removed and they are no longer required to use qiskit-terra.

• The exception raised by the assemble() function when invalid parameters are passed in for constructing a PulseQobj have changed from a SchemaValidationError to a QiskitError. This was necessary because the SchemaValidationError class was removed along with the rest of the deprecated qiskit.schemas and qiskit.validation. This also makes it more consistent with other error conditions from assemble() which were already raising a QiskitError.

• The default routing pass and layout pass for transpiler optimization level 3 has changed to use SabreSwap and SabreLayout respectively. This was done to improve the quality of the output result, as using the sabre passes produces better results than using StochasticSwap and DenseLayout, which were used as the defaults in prior releases. This change will improve the quality of the results when running transpile() or execute() functions with the optimization_level kwarg set to 3. While this is generally an improvement, if you need to retain the previous behavior for any reason you can do this by explicitly setting the routing_method="stochastic" and layout_method="dense" when calling transpile() with optimization_level=3.

• The name attribute of the SingleQubitUnitary gate class has been changed from unitary to squ. This was necessary to avoid a conflict with the UnitaryGate class’s name which was also unitary since the 2 gates are not the same and don’t have the same implementation (and can’t be used interchangeably).

• A new dependency stevedore has been added to the requirements list. This is required by qiskit-terra as it is used to build the unitary synthesis plugin interface.

##### Deprecation Notes¶
• The gate attribute and initialization parameter of qiskit.transpiler.passes.Decompose is deprecated, and will be removed in a future release. Instead of this single gate, you should pass a list of gate names to the new parameter gates_to_decompose. This was done as the new form allows you to select more than one gate as a decomposition target, which is more flexible, and does not need to re-run the pass several times to decompose a set of gates.

• There has been a significant transpiler pass reorganization regarding calibrations. The import paths:

from qiskit.transpiler.passes.scheduling.calibration_creators import RZXCalibrationBuilder
from qiskit.transpiler.passes.scheduling.calibration_creators import RZXCalibrationBuilderNoEcho


are deprecated, and will be removed in a future release. The import path:

from qiskit.transpiler.passes.scheduling.rzx_templates import rzx_templates


is also deprecated, and will be removed in a future release. You should use the new import paths:

from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit.transpiler.passes import RZXCalibrationBuilderNoEcho
from qiskit.transpiler.passes.calibration.rzx_templates import rzx_templates

• For the constructor of the RZXCalibrationBuilder passing a backend either as the first positional argument or with the named backend kwarg is deprecated and will no longer work in a future release. Instead a InstructionScheduleMap should be passed directly to the instruction_schedule_map kwarg and a list of channel name lists for each qubit should be passed directly to qubit_channel_mapping. For example, if you were calling the pass like:

from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit.test.mock import FakeMumbai

backend = FakeMumbai()
cal_pass = RZXCalibrationBuilder(backend)


instead you should call it like:

from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit.test.mock import FakeMumbai

backend = FakeMumbai()
inst_map = backend.defaults().instruction_schedule_map
channel_map = self.backend.configuration().qubit_channel_mapping
cal_pass = RZXCalibrationBuilder(
instruction_schedule_map=inst_map,
qubit_channel_mapping=channel_map,
)


This change is necessary because as a general rule backend objects are not pickle serializable and it would break when it was used with multiple processes inside of transpile() when compiling multiple circuits at once.

• The label property of class MCMT and subclass MCMTVChain has been deprecated and will be removed in a future release. Consequently, the label kwarg on the constructor for both classes is also deprecated, along with the label kwarg of method MCMT.control(). Currently, the label property is used to name the controlled target when it is comprised of more than one target qubit, however, this was never intended to be user-specifiable, and can result in an incorrect MCMT gate if the name of a well-known operation is used. After deprecation, the label property will no longer be user-specifiable. However, you can get the generated name of the controlled target via

MCMT.data[0][0].base_gate.name

• Creating an instance of InstructionSet with the circuit_cregs keyword argument is deprecated. In general, these classes never need to be constructed by users (but are used internally), but should you need to, you should pass a callable as the resource_requester keyword argument. For example:

from qiskit.circuit import Clbit, ClassicalRegister, InstructionSet
from qiskit.circuit.exceptions import CircuitError

def my_requester(bits, registers):
bits_set = set(bits)
bits_flat = tuple(bits)
registers_set = set(registers)

def requester(specifier):
if isinstance(specifer, Clbit) and specifier in bits_set:
return specifier
if isinstance(specifer, ClassicalRegster) and specifier in register_set:
return specifier
if isinstance(specifier, int) and 0 <= specifier < len(bits_flat):
return bits_flat[specifier]
raise CircuitError(f"Unknown resource: {specifier}")

return requester

my_bits = [Clbit() for _ in [None]*5]
my_registers = [ClassicalRegister(n) for n in range(3)]

InstructionSet(resource_requester=my_requester(my_bits, my_registers))

• The use of the measurement mitigation classes qiskit.ignis.mitigation.CompleteMeasFitter and qiskit.ignis.mitigation.TensoredMeasFitter from qiskit-ignis as values for the measurement_error_mitigation_cls kwarg of the constructor for the QuantumInstance class is deprecated and will be removed in a future release. Instead the equivalent classes from qiskit.utils.mitigation, CompleteMeasFitter and TensoredMeasFitter should be used. This was necessary as the qiskit-ignis project is now deprecated and will no longer be supported in the near future. It’s worth noting that unlike the equivalent classes from qiskit-ignis the versions from qiskit.utils.mitigation are supported only in their use with QuantumInstance (i.e. as a class not an instance with the measurement_error_mitigation_cls kwarg) and not intended for standalone use.

• The Optimizer.optimize() method for all the optimizers (Optimizer and derived classes) is now deprecated and will be removed in a future release. Instead, the Optimizer.minimize() method should be used which mimics the signature of SciPy’s minimize() function.

To replace the current optimize call with minimize you can replace

xopt, fopt, nfev = optimizer.optimize(
num_vars,
objective_function,
variable_bounds,
initial_point,
)


with

result = optimizer.minimize(
fun=objective_function,
x0=initial_point,
bounds=variable_bounds,
)
xopt, fopt, nfev = result.x, result.fun, result.nfev

• Importing the qiskit.util module will now issue a DeprecationWarning. Users should instead import all the same functionality from qiskit.utils. The util module has been deprecated since Terra 0.17, but previously did not issue a warning. It will be removed in Terra 0.20.

##### Bug Fixes¶
• Fixed a bug where many layout methods would ignore 3-or-more qubit gates, resulting in unexpected layout-allocation decisions. The transpiler pass Unroll3qOrMore is now being executed before the layout pass in all the preset pass managers when transpile() is called. Fixed #7156.

• Fixed setting the ansatz or optimizer attributes of a VQE instance to None resulting in a buggy behavior. See #7093 for details.

• Fixed addition of PauliLists with qargs. The method used to raise a runtime error if the operands had different numbers of qubits.

• Fixed an issue causing an error when trying to compute a gradient with the CircuitGradient class for a gate that was not a supported gate. This bugfix transpiles a given gate to the set of supported gates for a requested gradient method. Fixes #6918.

• Fixed an issue where the ax kwarg and the figwidth option in the style kwarg for the mpl circuit drawer did not scale properly. Users can now pass an ax from a Matplotlib subplot to the mpl circuit drawer and the circuit will be drawn within the boundaries of that subplot. Alternatively, users can set the figwidth in inches in the style dict kwarg and the drawing will scale to the width in inches that was set. Fixed #6367.

• Fixed an issue with the circuit_drawer() function and draw() method of QuantumCircuit. With any of the 3 drawer options, mpl, latex, or text, if a gate with a classical condition was conditioned on the same classical bit as a measure and the bit that the measure targeted did not have a register, the drawer would fail.

• C3SXGate now has a correct decomposition and matrix representation. Previously it was equivalent to SdgXGate().control(3), rather than the intended SXGate().control(3).

• The member name of qiskit.test.mock.utils.ConfigurableFakeBackend has been changed to backend_name. This was done to avoid a conflict with the name() method inherited from the parent abstract BackendV1 class. This makes ConfigurableFakeBackend compatible with anything expecting a BackendV1 object. However, if you were using the name attribute directly before you will now need to either call it as a method or access the backend_name attribute instead.

• Fixed an issue where calling QuantumCircuit.decompose() on a circuit containing an Instruction whose definition attribute was empty would leave the instruction in place, instead of decomposing it into zero operations. For example, with a circuit:

from qiskit.circuit import QuantumCircuit
empty = QuantumCircuit(1, name="decompose me!")
circuit = QuantumCircuit(1)
circuit.append(empty.to_gate(), [0])


Previously, calling circuit.decompose() would not change the circuit. Now, the decomposition will correct decompose empty into zero instructions. See #6997 for more.

• Fixed an issue with the circuit_drawer() function and draw() method of QuantumCircuit. When displaying a measure instruction containing a classical condition using the mpl or latex options, the condition information would sometimes overwrite the measure display.

• Fixed a bug in the Hoare optimizer transpilation pass where it could attempt to remove a gate twice if it could be separately combined with both its predecessor and its successor to form the identity. Refer to #7271 for more details.

• Trying to make an instruction conditional with the standard InstructionSet.c_if() method will now correctly raise an error if the classical resource is not present in the circuit. See #7255 for more detail.

• Fixed a compatibility issue with Matplotlib 3.5, where the Bloch sphere would fail to render if it had any vectors attached, such as by using plot_bloch_vector. See #7272 for more detail.

• Complex valued pulse parameter assignment with symengine has been fixed. For example,

from qiskit import circuit, pulse
import numpy as np

amp = circuit.Parameter("amp")
phase = circuit.Parameter("phase")

with pulse.build() as sched:
pulse.play(pulse.Gaussian(160, amp * np.exp(1j * phase), 40), pulse.DriveChannel(0))
sched.assign_parameters({amp: 0.1, phase: 1.57}, inplace=True)


The assigned amplitude has been shown as ParameterExpression(0.1*exp(1.57*I)) after the use of symengine was introduced in the 0.18.0 release. This is now correctly evaluated and shown as 7.96327e-05 + 0.0999999683j.

• Fixed an issue where QAOAAnsatz had an incorrect number of parameters if identities of PauliSumOp were given, e.g., PauliSumOp.from_list([("III", 1)]). See #7225 for more detail.

• Fixed an issue where trying to display registerless bits would cause a failure of the mpl and the latex circuit drawers. A leading _ has been removed from the display of registerless bits” numbers in the text drawer. Fixed #6732.

• For one-bit registers, all of the circuit drawers now display only the register name and no longer show the 0 subscript. Fixed #5784.

• Fixed naming collisions of implicit registers in QuantumCircuit.qasm when dealing with registerless qubits and clbits. Previously, registerless qubits and clbits were put into corresponding qreg and creg both called regless, despite the collision. They will now have separate, deterministically generated names, which will not clash with any user-defined register names in the circuit.

• Fixed an issue in scheduling of circuits with clbits operations, e.g. measurements, conditional gates, updating ASAPSchedule, ALAPSchedule, and AlignMeasures. The updated schedulers assume all clbits I/O operations take no time, measure writes the measured value to a clbit at the end, and c_if reads the conditional value in clbit(s) at the beginning. Fixed #7006.

• Fixed an issue in PiecewiseChebyshev when the function to be approximated was constant. In these cases, you should now pass the constant directly as the f_x argument, rather than using a function, such as:

from qiskit.circuit.library.arithmetic import PiecewiseChebyshev

PiecewiseChebyshev(1.0, degree=3)


See #6707 for more details.

• If an HHL algorithm instance was constructed without a QuantumInstance (the default), attempts to use the getter and setter properties to read or set an instance later would fail. The getters and setters now work as expected.

• The QuantumCircuit.qasm() method now edits the names of copies of the instructions present in the circuit, not the original instructions that live in circuit.data. Refer to #6952 for more details.

• Fixed a bug in PauliSumOp.permute() causing the error:

QiskitError: 'Pauli string label "" is not valid.'


if the permutation had the same number of Pauli terms. Calling permute([2, 1, 0]) on X ^ Y ^ Z no longer raises an error, and now returns Z ^ Y ^ X.

• Fixed multi-bit classical register removal in pass RemoveFinalMeasurements and in method remove_final_measurements() of class QuantumCircuit where classical registers were not removed even if other bits were idle, unless a final measure was done into each and every bit. Now, classical registers that become idle as a result of removing final measurements and barriers are always removed. Classical bits are removed if they are referenced only by removed registers or are not referenced at all and became idle due to the removal. This fix also adds proper handling of registers with shared underlying bits.

• When tapering an empty zero operator in qiskit.opflow, the code, on detecting it was zero, logged a warning and returned the original operator. Such operators are commonly found in the auxiliary operators, when using Qiskit Nature, and the above behavior caused VQE to throw an exception as tapered non-zero operators were a different number of qubits from the tapered zero operators (since taper has returned the input operator unchanged). The code will now correctly taper a zero operator such that the number of qubits is reduced as expected and matches to tapered non-zero operators e.g 0*"IIII" when we are tapering by 3 qubits will become 0*"I".

• Fixed an issue with the draw() method and circuit_drawer() function, where a custom style set via the user config file (i.e. settings.conf) would ignore the set value of the circuit_mpl_style field if the style kwarg on the function/method was not set.

##### Other Notes¶
• The string cast for qiskit.circuit.ParameterExpression does not have full precision anymore. This removes the trailing 0s when printing parameters that are bound to floats. This has consequences for QASM serialization and the circuit text drawer:

>>> from qiskit.circuit import Parameter
>>> x = Parameter('x')
>>> str(x.bind({x:0.5}))

• The QAOAAnsatz has been updated to use the parameter symbol γ for the cost operator and β for the mixer operator, as is the standard notation in QAOA literature.

No change

#### Ignis 0.7.0¶

##### Prelude¶

This release deprecates the Qiskit Ignis project, it has been supersceded by the Qiskit Experiments project and active development has ceased. While deprecated, critical bug fixes and compatibility fixes will continue to be made to provide users a sufficient opportunity to migrate off of Ignis. After the deprecation period (which will be no shorter than 3 months from this release) the project will be retired and archived.

##### New Features¶
• Updated the accreditation protocol to use fitting routine from https://arxiv.org/abs/2103.06603. AccreditationFitter now has methods FullAccreditation (previous protocol) and MeanAccreditation (new protocol). In addtition data entry has been changed to either use the result object AppendResult or a list of strings AppendStrings. qiskit.ignis.verification.QOTPCorrectString() was also added.

• Added the option for the fast analytical generation of syndrome graphs. The RepetitionCode now has a new bool argument brute, which allows to still use the brute force method. Helper class RepetitionCodeSyndromeGenerator added to facilitate this.

• The RepetitionCode now has keyword arguments resets and delay. The former determines whether reset gates are inserted after measurement. The latter allows a time (in dt) to be specificed for a delay after each measurement (and reset, if applicable).

The syndrome_measurement() method of RepetitionCode now has keyword arguments final and delay. The former determines whether to add reset gates according to the global resets, or to overwrite it with appropriate behavior for the final round of syndrome measurements. The latter allows a time (in dt) to be specificed for a delay after each measurement (and reset, if applicable).

• The RepetitionCode class now supports encoding with x basis states. This can be used by setting the xbasis keyword argument when constructing a RepetitionCode object.

• The keyword argument reset has been removed from the the syndrome_measurement() method of RepetitionCode. This is replaced by the global resets keyword argument for the class as well as the keyword argument final for syndrome_measurement. In cases where one would previously add the final measurement round using reset=False to avoid the final reset gates, one should now use final=True.

• Remove ParametrizedSchedule from update_u_gates().

ParametrizedSchedule was deprecated as a part of Qiskit-terra 0.17.0 and will be removed in next release. The function now updates u gates with Schedule programs involving unassigned Parameter objects.

##### Deprecation Notes¶
• Deprecating methods in AccreditationFitter namely bound_variation_distance and single_protocol_run

• The Qiskit Ignis project as a whole has been deprecated and the project will be retired and archived in the future. While deprecated only compatibility fixes and fixes for critical bugs will be made to the proejct. Instead of using Qiskit Ignis you should migrate to use Qiskit Experiments instead. You can refer to the migration guide:

https://github.com/Qiskit/qiskit-ignis#migration-guide

### Qiskit 0.32.1¶

No change

No change

No change

No change

#### IBM Q Provider 0.18.1¶

##### Bug Fixes¶
• Fixes #209 where the websocket connection kept timing out when streaming results for a runtime job, due to inactivity, when the job is in a pending state for a long time.

### Qiskit 0.32.0¶

No change

No change

No change

No change

#### IBM Q Provider 0.18.0¶

##### Bug Fixes¶
• Fixes the issue wherein a runtime job result cannot be retrieved multiple times if the result contains a numpy array.

### Qiskit 0.31.0¶

No change

#### Aer 0.9.1¶

• optimize_ideal_threshold and optimize_noisy_threshold have been removed from the lists of simulator defaults and the documentation. These have had no effect since Aer 0.5.1, but these references to them had remained accidentally.

##### Bug Fixes¶
• Fixes #1351 where running an empty QuantumCircuit with a noise model set would cause the simulator to crash.

• Fixes #1347 where the behaviour of using the set_options() and set_option() methods of simulator backends could lead to different behavior for some options.

• Fixes an bug where using a Dask Client executor would cause an error at job submission due to the executor Client not being pickleable.

• Fixed an issue with the matrix_product_state simulation method where the accumulation of small rounding errors during measurement of many quits could sometimes cause a segmentation fault.

• Fixes an unintended change between qiskit-aer 0.8.0 and 0.9.0 where when running a list of circuits with an invalid circuit using the automatic simulation method of the AerSimulator or QasmSimulator would raise an exception for an invalid input qobj rather than return partial results for the circuits that were valid.

• Fixes an issue with the standalone simulator where it would return a IBM Quantum API schema invalid response in the case of an error that prevented the simulation from running.

• Fixes #1346 which was a bug in the handling of the parameter_binds kwarg of the backend run() method that would result in an error if the parameterized circuit was transpiled to a different set of basis gates than the original parameterizations.

No change

No change

### Qiskit 0.30.1¶

#### Terra 0.18.3¶

##### Prelude¶

This bugfix release fixes a few minor issues in 0.18, including a performance regression in assemble when dealing with executing QuantumCircuit objects on pulse-enabled backends.

##### Bug Fixes¶
• Fixed #7004 where AttributeError was raised when executing ScheduleBlock on a pulse backend. These blocks are now correctly treated as pulse jobs, like Schedule.

• Fixed an issue causing an error when binding a complex parameter value to an operator’s coefficient. Casts to float in PrimitiveOp were generalized to casts to complex if necessary, but will remain float if there is no imaginary component. Fixes #6976.

• Update the 1-qubit gate errors in plot_error_map to use the sx gate instead of the u2 gate, consistent with IBMQ backends.

No change

No change

No change

No change

### Qiskit 0.30.0¶

No change

#### Aer 0.9.0¶

##### Prelude¶

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 = backend.run(circuits)


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.

• Adds ability to record logging data for the matrix_product_state simulation method to the experiment result metadata by setting the backend option mps_log_data=True. The saved data includes the bond dimensions and the discarded value (the sum of the squares of the Schmidt coeffients that were discarded by approximation) after every relevant circuit instruction.

• The run() method for the AerSimulator, QasmSimulator, StatevectorSimulator, and UnitarySimulator has a new kwarg, parameter_binds which is used to provide a list of values to use for any unbound parameters in the inbound circuit. For example:

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.providers.aer import AerSimulator

shots = 1000
backend = AerSimulator()
circuit = QuantumCircuit(2)
theta = Parameter('theta')
circuit.rx(theta, 0)
circuit.cx(0, 1)
circuit.measure_all()
parameter_binds = [{theta: [0, 3.14, 6.28]}]
backend.run(circuit, shots=shots, parameter_binds=parameter_binds).result()


will run the input circuit 3 times with the values 0, 3.14, and 6.28 for theta. When running with multiple parameters the length of the value lists must all be the same. When running with multiple circuits, the length of parameter_binds must match the number of input circuits (you can use an empty dict, {}, if there are no binds for a circuit).

• The PulseSimulator can now take QuantumCircuit objects on the run(). Previously, it only would except Schedule objects as input to run(). When a circuit or list of circuits is passed to the simulator it will call schedule() to convert the circuits to a schedule before executing the circuit. For example:

from qiskit.circuit import QuantumCircuit
from qiskit.compiler import transpile
from qiskit.test.mock import FakeVigo
from qiskit.providers.aer.backends import PulseSimulator

backend = PulseSimulator.from_backend(FakeVigo())

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

transpiled_circuit = transpile(circuit, backend)
backend.run(circuit)

##### Known Issues¶
• The SaveExpectationValue and SaveExpectationValueVariance have been disabled for the extended_stabilizer method of the QasmSimulator and AerSimulator due to returning the incorrect value for certain Pauli operator components. Refer to #1227 <https://github.com/Qiskit/qiskit-aer/issues/1227> for more information and examples.

• 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 backend.run(circuits, **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 performance issue with how the basis_gates configuration attribute was set. Previously there were unintended side-effects to the backend class which could cause repeated simulation runtime to incrementally increase. Refer to #1229 <https://github.com/Qiskit/qiskit-aer/issues/1229> for more information and examples.

• Fixed bug in MPS::apply_kraus. After applying the kraus matrix to the relevant qubits, we should propagate the changes to the neighboring qubits.

• Fixes a bug where qiskit-terra assumes that qubits in a multiplexer gate are first the targets and then the controls of the gate while qiskit-aer assumes the opposite order.

• Fixes a bug introduced in 0.8.0 where GPU simulations would allocate unneeded host memory in addition to the GPU memory.

• Fixes bug where the initialize instruction would disable measurement sampling optimization for the statevector and matrix product state simulation methods even when it was the first circuit instruction or applied to all qubits and hence deterministic.

• Fix issue #1196 by using the inner products with the computational basis states to calculate the norm rather than the norm estimation algorithm.

• Fixes a bug in the stabilizer simulator method of the QasmSimulator and AerSimulator where the expectation value for the save_expectation_value and snapshot_expectation_value could have the wrong sign for certain Y Pauli’s.

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

• Fixes bug with applying the unitary gate in using the matrix_product_state simulation method which did not correctly support permutations in the ordering of the qubits on which the gate is applied.

• Fixes an issue where gate fusion could still be enabled for the matrix_product_state simulation method even though it is not supported. Now fusion is always disabled for this method.

• Fixed bug in the matrix_product_state simulation method in computing the normalization following truncation of the Schmidt coefficients after performing the SVD.

##### Other Notes¶
• Improves the performance of the measurement sampling algorithm for the matrix_product_state simulation method. The new default behaviour is to always sample using the improved mps_apply_measure method. The mps_probabilities sampling method be still used by setting the custom option value mps_sample_measure_algorithm="mps_probabilities".

No change

No change

No change

### Qiskit 0.29.1¶

#### Terra 0.18.2¶

##### Bug Fixes¶
• Fixed an issue with the assemble() function when called with the backend kwarg set and the parametric_pulses kwarg was set to an empty list the output qobj would contain the parametric_pulses setting from the given backend’s BackendConfiguration instead of the expected empty list. Fixed #6898

• The Matplotlib circuit drawer will no longer duplicate drawings when using ipykernel>=6.0.0. Fixes #6889.

No change

No change

#### Aqua 0.9.5¶

##### Bug Fixes¶
• Fixed a handling error in the Yahoo provider when only one ticker is entered. Added exception error if no ticker is entered. Limit yfinance to >=0.1.62 as previous versions have a JSON decoder error.

No change

### Qiskit 0.29.0¶

#### Terra 0.18.1¶

##### Prelude¶

This bugfix release fixes a few minor issues and regressions in the 0.18.0 release. There is also a minor change to how pip handles the [all] extra when installing qiskit-terra directly, compared to 0.18.0.

• pip install qiskit-terra[all] will no longer attempt to install the bip-mapper extra. This is because the dependency cplex is not well supported on the range of Python versions and OSes that Terra supports, and a failed extra dependency would fail the entire package resolution. If you are using Python 3.7 or 3.8 and are on Linux-x64 or -ppc64le, macOS-x64 or Windows-x64 you should be able to install qiskit-terra[bip-mapper] explicitly, if desired, while other combinations of OS, platform architectures and Python versions will likely fail.

##### Bug Fixes¶
• Fixed an issue where the QuantumInstance class would potentially try to use the CompleteMeasFitter class before it was imported resulting in an error. Fixed #6774

• Fixed the missing Linux aarch64 wheels which were not published for the 0.18.0 release. They should now continue to be built as expected for all future releases.

• Fixed an issue with the mock backends located in qiskit.test.mock where in some situations (mainly fake backends with stored BackendProperties running a QuantumCircuit with qiskit-aer installed) passing run time options to the run() method of a fake backend object would not actually be passed to the simulator underlying the run() method and not have any effect. Fixed #6741

• Fix a bug in EvolvedOperatorAnsatz when the global phase is 0 (such as for QAOAAnsatz) but was still a ParameterExpression.

• Fixed an issue with the settings attribute of QNSPSA, which was missing the fidelity argument from the output. This is now correctly included in the attribute’s output.

• Fixed an issue with the subgraph() method of the CouplingMap class where it would incorrectly add nodes to the output CouplingMap object when the nodelist argument contained a non-contiguous list of qubit indices. This has been fixed so regardless of the input indices in nodelist the output CouplingMap will only contained the specified nodes reindexed starting at 0. Fixes #6736

• Previously, Optimize1qGatesDecomposition failed to properly optimize one qubit gates that are sufficiently close to the identity matrix. This was fixed so that any gates that differ from the identity by less than 1e-15 are removed.

• Fixed the generation and loading of QPY files with qiskit.circuit.qpy_serialization.dump() and qiskit.circuit.qpy_serialization.load() for QuantumCircuit objects that contain instructions with classical conditions on a single Clbit instead of a ClassicalRegister. While the use of single Clbit conditions is not yet fully supported, if you were using them in a circuit they are now correctly serialized by QPY.

No change

No change

No change

### Qiskit 0.28.0¶

#### Terra 0.18.0¶

##### Prelude¶

This release includes many new features and bug fixes. The highlights of this release are the introduction of two new transpiler passes, BIPMapping and DynamicalDecoupling, which when combined with the new pulse_optimize kwarg on the UnitarySynthesis pass enables recreating the Quantum Volume 64 results using the techniques described in: https://arxiv.org/abs/2008.08571. These new transpiler passes and options and are also generally applicable to optimizing any circuit.

##### New Features¶
• The measurement_error_mitgation kwarg for the QuantumInstance constructor can now be set to the TensoredMeasFitter class from qiskit-ignis in addition to CompleteMeasFitter that was already supported. If you use TensoredMeasFitter you will also be able to set the new mit_pattern kwarg to specify the qubits on which to use TensoredMeasFitter You can refer to the documentation for mit_pattern in the TensoredMeasFitter documentation for the expected format.

• The decomposition methods for single-qubit gates, specified via the basis kwarg, in OneQubitEulerDecomposer has been expanded to now also include the 'ZSXX' basis, for making use of direct $$X$$ gate as well as $$\sqrt{X}$$ gate.

• Added two new passes AlignMeasures and ValidatePulseGates to the qiskit.transpiler.passes module. These passes are a hardware-aware optimization, and a validation routine that are used to manage alignment restrictions on time allocation of instructions for a backend.

If a backend has a restriction on the alignment of Measure instructions (in terms of quantization in time), the AlignMeasures pass is used to adjust delays in a scheduled circuit to ensure that any Measure instructions in the circuit are aligned given the constraints of the backend. The ValidatePulseGates pass is used to check if any custom pulse gates (gates that have a custom pulse definition in the calibrations attribute of a QuantumCircuit object) are valid given an alignment constraint for the target backend.

In the built-in preset_passmangers used by the transpile() function, these passes get automatically triggered if the alignment constraint, either via the dedicated timing_constraints kwarg on transpile() or has an timing_constraints attribute in the BackendConfiguration object of the backend being targetted.

The backends from IBM Quantum Services (accessible via the qiskit-ibmq-provider package) will provide the alignment information in the near future.

For example:

from qiskit import circuit, transpile
from qiskit.test.mock import FakeArmonk

backend = FakeArmonk()

qc = circuit.QuantumCircuit(1, 1)
qc.x(0)
qc.delay(110, 0, unit="dt")
qc.measure(0, 0)
qc.draw('mpl')

qct = transpile(qc, backend, scheduling_method='alap',
timing_constraints={'acquire_alignment': 16})
qct.draw('mpl')

• A new transpiler pass class qiskit.transpiler.passes.BIPMapping that tries to find the best layout and routing at once by solving a BIP (binary integer programming) problem as described in arXiv:2106.06446 has been added.

The BIPMapping pass (named «mapping» to refer to «layout and routing») represents the mapping problem as a BIP (binary integer programming) problem and relies on CPLEX (cplex) to solve the BIP problem. The dependent libraries including CPLEX can be installed along with qiskit-terra:

pip install qiskit-terra[bip-mapper]


Since the free version of CPLEX can solve only small BIP problems, i.e. mapping of circuits with less than about 5 qubits, the paid version of CPLEX may be needed to map larger circuits.

The BIP mapper scales badly with respect to the number of qubits or gates. For example, it would not work with coupling_map beyond 10 qubits because the BIP solver (CPLEX) could not find any solution within the default time limit.

Note that, if you want to fix physical qubits to be used in the mapping (e.g. running Quantum Volume (QV) circuits), you need to specify coupling_map which contains only the qubits to be used.

Here is a minimal example code to build pass manager to transpile a QV circuit:

num_qubits = 4  # QV16
circ = QuantumVolume(num_qubits=num_qubits)

backend = ...
basis_gates = backend.configuration().basis_gates
coupling_map = CouplingMap.from_line(num_qubits)  # supply your own coupling map

def _not_mapped(property_set):
return not property_set["is_swap_mapped"]

def _opt_control(property_set):
return not property_set["depth_fixed_point"]

from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
pm = PassManager()
# preparation
pm.append([
Unroll3qOrMore(),
TrivialLayout(coupling_map),
FullAncillaAllocation(coupling_map),
EnlargeWithAncilla(),
BarrierBeforeFinalMeasurements()
])
# mapping
pm.append(BIPMapping(coupling_map))
pm.append(CheckMap(coupling_map))
pm.append(Error(msg="BIP mapper failed to map", action="raise"),
condition=_not_mapped)
# post optimization
pm.append([
Depth(),
FixedPoint("depth"),
Collect2qBlocks(),
ConsolidateBlocks(basis_gates=basis_gates),
UnitarySynthesis(basis_gates),
Optimize1qGatesDecomposition(basis_gates),
CommutativeCancellation(),
UnrollCustomDefinitions(sel, basis_gates),
BasisTranslator(sel, basis_gates)
], do_while=_opt_control)

transpile_circ = pm.run(circ)

• A new constructor method initialize_from() was added to the Schedule and ScheduleBlock classes. This method initializes a new empty schedule which takes the attributes from other schedule. For example:

sched = Schedule(name='my_sched')
new_sched = Schedule.initialize_from(sched)

assert sched.name == new_sched.name

• A new kwarg, line_discipline, has been added to the job_monitor() function. This kwarg enables changing the carriage return characters used in the job_monitor output. The line_discipline kwarg defaults to '\r', which is what was in use before.

• The abstract Pulse class (which is the parent class for classes such as Waveform, Constant, and Gaussian now has a new kwarg on the constructor, limit_amplitude, which can be set to False to disable the previously hard coded amplitude limit of 1. This can also be set as a class attribute directly to change the global default for a Pulse class. For example:

from qiskit.pulse.library import Waveform

# Change the default value of limit_amplitude to False
Waveform.limit_amplitude = False
wave = Waveform(2.0 * np.exp(1j * 2 * np.pi * np.linspace(0, 1, 1000)))

• A new class, PauliList, has been added to the qiskit.quantum_info module. This class is used to efficiently represent a list of Pauli operators. This new class inherets from the same parent class as the existing PauliTable (and therefore can be mostly used interchangeably), however it differs from the PauliTable because the qiskit.quantum_info.PauliList class can handle Z4 phases.

• Added a new transpiler pass, RemoveBarriers, to qiskit.transpiler.passes. This pass is used to remove all barriers in a circuit.

• Add a new optimizer class, SciPyOptimizer, to the qiskit.algorithms.optimizers module. This class is a simple wrapper class of the scipy.optimize.minimize function (documentation) which enables the use of all optimization solvers and all parameters (e.g. callback) which are supported by scipy.optimize.minimize. For example:

from qiskit.algorithms.optimizers import SciPyOptimizer

values = []

def callback(x):
values.append(x)

optimizer = SciPyOptimizer("BFGS", options={"maxiter": 1000}, callback=callback)

• The HoareOptimizer pass has been improved so that it can now replace a ControlledGate in a circuit with with the base gate if all the control qubits are in the $$|1\rangle$$ state.

• Added two new methods, is_successor() and is_predecessor(), to the DAGCircuit class. These functions are used to check if a node is either a successor or predecessor of another node on the DAGCircuit.

• A new transpiler pass, RZXCalibrationBuilderNoEcho, was added to the qiskit.transpiler.passes module. This pass is similar to the existing RZXCalibrationBuilder in that it creates calibrations for an RZXGate(theta), however RZXCalibrationBuilderNoEcho does this without inserting the echo pulses in the pulse schedule. This enables exposing the echo in the cross-resonance sequence as gates so that the transpiler can simplify them. The RZXCalibrationBuilderNoEcho pass only supports the hardware-native direction of the CXGate.

• A new kwarg, wrap, has been added to the compose() method of QuantumCircuit. This enables choosing whether composed circuits should be wrapped into an instruction or not. By default this is False, i.e. no wrapping. For example:

from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.h([0, 1])
other = QuantumCircuit(2)
other.x([0, 1])
print(circuit.compose(other, wrap=True))  # wrapped
print(circuit.compose(other, wrap=False))  # not wrapped

     ┌───┐┌──────────────┐
q_0: ┤ H ├┤0             ├
├───┤│  circuit-123 │
q_1: ┤ H ├┤1             ├
└───┘└──────────────┘
┌───┐┌───┐
q_0: ┤ H ├┤ X ├
├───┤├───┤
q_1: ┤ H ├┤ X ├
└───┘└───┘

• A new attribute, control_channels, has been added to the PulseBackendConfiguration class. This attribute represents the control channels on a backend as a mapping of qubits to a list of ControlChannel objects.

• A new kwarg, epsilon, has been added to the constructor for the Isometry class and the corresponding QuantumCircuit method isometry(). This kwarg enables optionally setting the epsilon tolerance used by an Isometry gate. For example:

import numpy as np
from qiskit import QuantumRegister, QuantumCircuit

tolerance = 1e-8
iso = np.eye(2,2)
num_q_output = int(np.log2(iso.shape[0]))
num_q_input = int(np.log2(iso.shape[1]))
q = QuantumRegister(num_q_output)
qc = QuantumCircuit(q)

qc.isometry(iso, q[:num_q_input], q[num_q_input:], epsilon=tolerance)

• Added a transpiler pass, DynamicalDecoupling, to qiskit.transpiler.passes for inserting dynamical decoupling sequences in idle periods of a circuit (after mapping to physical qubits and scheduling). The pass allows control over the sequence of DD gates, the spacing between them, and the qubits to apply on. For example:

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import XGate
from qiskit.transpiler import PassManager, InstructionDurations
from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling
from qiskit.visualization import timeline_drawer

circ = QuantumCircuit(4)
circ.h(0)
circ.cx(0, 1)
circ.cx(1, 2)
circ.cx(2, 3)
circ.measure_all()

durations = InstructionDurations(
[("h", 0, 50), ("cx", [0, 1], 700), ("reset", None, 10),
("cx", [1, 2], 200), ("cx", [2, 3], 300),
("x", None, 50), ("measure", None, 1000)]
)

dd_sequence = [XGate(), XGate()]

pm = PassManager([ALAPSchedule(durations),
DynamicalDecoupling(durations, dd_sequence)])
circ_dd = pm.run(circ)
timeline_drawer(circ_dd)

• The QuantumCircuit method qasm() has a new kwarg, encoding, which can be used to optionally set the character encoding of an output QASM file generated by the function. This can be set to any valid codec or alias string from the Python standard library’s codec module.

• Added a new class, EvolvedOperatorAnsatz, to the qiskit.circuit.library module. This library circuit, which had previously been located in Qiskit Nature , can be used to construct ansatz circuits that consist of time-evolved operators, where the evolution time is a variational parameter. Examples of such ansatz circuits include UCCSD class in the chemistry module of Qiskit Nature or the QAOAAnsatz class.

• A new fake backend class is available under qiskit.test.mock for the ibmq_guadalupe backend. As with the other fake backends, this includes a snapshot of calibration data (i.e. backend.defaults()) and error data (i.e. backend.properties()) taken from the real system, and can be used for local testing, compilation and simulation.

• A new method children() for the Schedule class has been added. This method is used to return the child schedule components of the Schedule object as a tuple. It returns nested schedules without flattening. This method is equivalent to the private _children() method but has a public and stable interface.

• A new optimizer class, GradientDescent, has been added to the qiskit.algorithms.optimizers module. This optimizer class implements a standard gradient descent optimization algorithm for use with quantum variational algorithms, such as VQE. For a detailed description and examples on how to use this class, please refer to the GradientDescent class documentation.

• A new optimizer class, QNSPSA, has been added to the qiskit.algorithms.optimizers module. This class implements the Quantum Natural SPSA (QN-SPSA) algorithm, a generalization of the 2-SPSA algorithm, and estimates the Quantum Fisher Information Matrix instead of the Hessian to obtain a stochastic estimate of the Quantum Natural Gradient. For examples on how to use this new optimizer refer to the QNSPSA class documentation.

• A new kwarg, second_order, has been added to the constructor of the SPSA class in the qiskit.algorithms.optimizers module. When set to True this enables using second-order SPSA. Second order SPSA, or 2-SPSA, is an extension of the ordinary SPSA algorithm that enables estimating the Hessian alongside the gradient, which is used to precondition the gradient before the parameter update step. As a second-order method, this tries to improve convergence of SPSA. For examples on how to use this option refer to the SPSA class documentation.

• When using the latex or latex_source output mode of circuit_drawer() or the draw() of QuantumCircuit the style kwarg can now be used just as with the mpl output formatting. However, unlike the mpl output mode only the displaytext field will be used when using the latex or latex_source output modes (because neither supports color).

• When using the mpl or latex output methods for the circuit_drawer() function or the draw() of QuantumCircuit, you can now use math mode formatting for text and set color formatting (mpl only) by setting the style kwarg as a dict with a user-generated name or label. For example, to add subscripts and to change a gate color:

from qiskit import QuantumCircuit
from qiskit.circuit.library import HGate
qc = QuantumCircuit(3)
qc.append(HGate(label='h1'), [0])
qc.append(HGate(label='h2'), [1])
qc.append(HGate(label='h3'), [2])
qc.draw('mpl', style={'displaytext': {'h1': 'H_1', 'h2': 'H_2', 'h3': 'H_3'},
'displaycolor': {'h2': ('#EEDD00', '#FF0000')}})

• Added three new classes, CDKMRippleCarryAdder, ClassicalAdder and DraperQFTAdder, to the qiskit.circuit.library module. These new circuit classes are used to perform classical addition of two equally-sized qubit registers. For two registers $$|a\rangle_n$$ and $$|b\rangle_n$$ on $$n$$ qubits, the three new classes perform the operation:

$|a\rangle_n |b\rangle_n \mapsto |a\rangle_n |a + b\rangle_{n + 1}.$

For example:

from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import Statevector

# a encodes |01> = 1
a = QuantumCircuit(2)
a.x(0)

# b encodes |10> = 2
b = QuantumCircuit(2)
b.x(1)

# add the state preparations to the front of the circuit

# simulate and get the state of all qubits
counts = sv.probabilities_dict()
state = list(counts.keys())[0]  # we only have a single state

# skip the input carry (first bit) and the register |a> (last two bits)
result = state[1:-2]
print(result)  # '011' = 3 = 1 + 2

• Added two new classes, RGQFTMultiplier and HRSCumulativeMultiplier, to the qiskit.circuit.library module. These classes are used to perform classical multiplication of two equally-sized qubit registers. For two registers $$|a\rangle_n$$ and $$|b\rangle_n$$ on $$n$$ qubits, the two new classes perform the operation

$|a\rangle_n |b\rangle_n |0\rangle_{2n} \mapsto |a\rangle_n |b\rangle_n |a \cdot b\rangle_{2n}.$

For example:

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import RGQFTMultiplier
from qiskit.quantum_info import Statevector

num_state_qubits = 2

# a encodes |11> = 3
a = QuantumCircuit(num_state_qubits)
a.x(range(num_state_qubits))

# b encodes |11> = 3
b = QuantumCircuit(num_state_qubits)
b.x(range(num_state_qubits))

# multiplier on 2-bit numbers
multiplier = RGQFTMultiplier(num_state_qubits)

# add the state preparations to the front of the circuit
multiplier.compose(a, [0, 1], inplace=True, front=True)
multiplier.compose(b, [2, 3], inplace=True, front=True)

# simulate and get the state of all qubits
sv = Statevector(multiplier)
counts = sv.probabilities_dict(decimals=10)
state = list(counts.keys())[0]  # we only have a single state

# skip both input registers
result = state[:-2*num_state_qubits]
print(result)  # '1001' = 9 = 3 * 3

• The Delay class now can accept a ParameterExpression or Parameter value for the duration kwarg on its constructor and for its duration attribute.

For example:

idle_dur = Parameter('t')
qc = QuantumCircuit(1, 1)
qc.x(0)
qc.delay(idle_dur, 0, 'us')
qc.measure(0, 0)
print(qc)  # parameterized delay in us (micro seconds)

# assign before transpilation
assigned = qc.assign_parameters({idle_dur: 0.1})
print(assigned)  # delay in us
transpiled = transpile(assigned, some_backend_with_dt)
print(transpiled)  # delay in dt

# assign after transpilation
transpiled = transpile(qc, some_backend_with_dt)
print(transpiled)  # parameterized delay in dt
assigned = transpiled.assign_parameters({idle_dur: 0.1})
print(assigned)  # delay in dt

• A new binary serialization format, QPY, has been introduced. It is designed to be a fast binary serialization format that is backwards compatible (QPY files generated with older versions of Qiskit can be loaded by newer versions of Qiskit) that is native to Qiskit. The QPY serialization tooling is available via the qiskit.circuit.qpy_serialization module. For example, to generate a QPY file:

from datetime import datetime

from qiskit.circuit import QuantumCircuit
from qiskit.circuit import qpy_serialization

qc = QuantumCircuit(
)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

circuits = [qc] * 5

with open('five_bells.qpy', 'wb') as qpy_file:
qpy_serialization.dump(circuits, qpy_file)


Then the five circuits saved in the QPY file can be loaded with:

from qiskit.circuit.qpy_serialization

with open('five_bells.qpy', 'rb') as qpy_file:


The QPY file format specification is available in the module documentation.

• The TwoQubitBasisDecomposer class has been updated to perform pulse optimal decompositions for a basis with CX, √X, and virtual Rz gates as described in https://arxiv.org/pdf/2008.08571. Pulse optimal here means that the duration of gates between the CX gates of the decomposition is reduced in exchange for possibly more local gates before or after all the CX gates such that, when composed into a circuit, there is the possibility of single qubit compression with neighboring gates reducing the overall sequence duration.

A new keyword argument, pulse_optimize, has been added to the constructor for TwoQubitBasisDecomposer to control this:

• None: Attempt pulse optimal decomposition. If a pulse optimal decomposition is unknown for the basis of the decomposer, drop back to the standard decomposition without warning. This is the default setting.

• True: Attempt pulse optimal decomposition. If a pulse optimal decomposition is unknown for the basis of the decomposer, raise QiskitError.

• False: Do not attempt pulse optimal decomposition.

For example:

from qiskit.quantum_info import TwoQubitBasisDecomposer
from qiskit.circuit.library import CXGate
from qiskit.quantum_info import random_unitary

unitary_matrix = random_unitary(4)

decomposer = TwoQubitBasisDecomposer(CXGate(), euler_basis="ZSX", pulse_optimize=True`