Release Notes¶
Version History¶
This table tracks the meta-package versions and the version of each Qiskit element installed:
Qiskit Metapackage Version |
qiskit-terra |
qiskit-aer |
qiskit-ignis |
qiskit-ibmq-provider |
qiskit-aqua |
Release Date |
---|---|---|---|---|---|---|
0.39.5 |
0.22.4 |
0.11.2 |
0.19.2 |
2023-01-17 |
||
0.39.4 |
0.22.3 |
0.11.2 |
0.19.2 |
2022-12-08 |
||
0.39.3 |
0.22.3 |
0.11.1 |
0.19.2 |
2022-11-25 |
||
0.39.2 |
0.22.2 |
0.11.1 |
0.19.2 |
2022-11-03 |
||
0.39.1 |
0.22.1 |
0.11.1 |
0.19.2 |
2022-11-02 |
||
0.39.0 |
0.22.0 |
0.11.0 |
0.19.2 |
2022-10-13 |
||
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 |
Note
For the 0.7.0
, 0.7.1
, and 0.7.2
meta-package releases the
Gestion des versions de Qiskit policy was not formalized yet.
Notable Changes¶
Qiskit 0.39.5¶
Terra 0.22.4¶
Prelude¶
Qiskit Terra 0.22.4 is a minor bugfix release, fixing some bugs identified in the 0.22 series.
Bug Fixes¶
Fixed a bug in
BackendSampler
that raised an error if itsrun()
method was called two times sequentially.
Fixed two bugs in the
ComposedOp
where theComposedOp.to_matrix()
method did not provide the correct results for compositions withStateFn
and for compositions with a global coefficient. Fixed #9283.
Fixed the problem in which primitives,
Sampler
andEstimator
, did not work when passed a circuit withnumpy.ndarray
as a parameter.
Fixed a bug in
SamplingVQE
where theaggregation
argument did not have an effect. Now the aggregation function and, with it, the CVaR expectation value can correctly be specified.
Fixed a performance bug where
SamplingVQE
evaluated the energies of eigenstates in a slow manner.
Fixed the autoevaluation of the beta parameters in
VQD
, added support forSparsePauliOp
inputs, and fixed the energy evaluation function to leverage the asynchronous execution of primitives, by only retrieving the job results after both jobs have been submitted.
Fixed an issue with the
Statevector.probabilities_dict()
andDensityMatrix.probabilities_dict()
methods where they would return incorrect results for non-qubit systems when theqargs
argument was specified. Fixed #9210
Fixed handling of some
classmethod
s bywrap_method()
in Python 3.11. Previously, in Python 3.11,wrap_method
would wrap the unbound function associated with theclassmethod
and then fail when invoked because the class object usually bound to theclassmethod
was not passed to the function. Starting in Python 3.11.1, this issue affectedQiskitTestCase
, preventing it from being imported by other test code. Fixed #9291.
Aer 0.11.2¶
No change
IBM Q Provider 0.19.2¶
No change
Qiskit 0.39.4¶
Terra 0.22.3¶
No change
Aer 0.11.2¶
New Features¶
Added support for running Qiskit Aer with Python 3.11 support.
Known Issues¶
Fix two bugs in AerStatevector. AerStatevector uses mc* instructions, which are not enabled in matrix_product_state method. This commit changes AerStatevector not to use MC* and use H, X, Y, Z, U and CX. AerStatevector also failed if an instruction is decomposed to empty QuantumCircuit. This commit allows such instruction.
Bug Fixes¶
Fixed support in the
AerSimulator.from_backend()
method for instantiating anAerSimulator
instance from an aBackendV2
object. Previously, attempting to useAerSimulator.from_backend()
with aBackendV2
object would have raised anAerError
saying this wasn’t supported.
Fixes a bug where
NoiseModel.from_backend()
with aBackendV2
object may generate a noise model with excessiveQuantumError
s on non-Gate instructions while, for example, onlyReadoutError
s should be sufficient for measures. This commit updatesNoiseModel.from_backend()
with aBackendV2
object so that it returns the same noise model as that called with the correspondingBackendV1
object. That is, the resulting noise model does not contain anyQuantumError
s on measures and it may contain only thermal relaxation errors on other non-gate instructions such as resets. Note that it still containsReadoutError
s on measures.
Fixed a bug in
NoiseModel.from_backend()
where using thetemperature
kwarg with a non-default value would incorrectly compute the excited state population for the specified temperature. Previously, there was an additional factor of 2 in the Boltzman distribution calculation leading to an incorrect smaller value for the excited state population.
Fixed incorrect logic in the control-flow compiler that could allow unrelated instructions to appear « inside » control-flow bodies during execution, causing incorrect results. For example, previously:
from qiskit import QuantumCircuit from qiskit_aer import AerSimulator backend = AerSimulator(method="statevector") circuit = QuantumCircuit(3, 3) circuit.measure(0, 0) circuit.measure(1, 1) with circuit.if_test((0, True)): with circuit.if_test((1, False)): circuit.x(2) with circuit.if_test((0, False)): with circuit.if_test((1, True)): circuit.x(2) circuit.measure(range(3), range(3)) print(backend.run(circuit, method=method, shots=100).result())
would print
{'010': 100}
as the nested control-flow operations would accidentally jump over the first X gate on qubit 2, which should have been executed.
Fixes a bug where
NoiseModel.from_backend()
prints verbose warnings when supplying a backend that reports un-physical device parameters such as T2 > 2 * T1 due to statistical errors in their estimation. This commit removes such warnings because they are not actionable for users in the sense that there are no means other than truncating them to the theoretical bounds as done withinnoise.device
module. See Issue 1631 for details of the fixed bug.
This is fix for GPU statevector simulator. Chunk distribution tried to allocate all free memory on GPU, but this causes memory allocation error. So this fix allocates 80 percent of free memory. Also this fixes size of matrix buffer when noise sampling is applied.
This is a fix of AerState running with cache blocking. AerState wrongly configured transpiler of Aer for cache blocking, and then its algorithm to swap qubits worked wrongly. This fix corrects AerState to use this transpiler. More specifically, After the transpilation, a swapped qubit map is recoverd to the original map when using AerState. This fix is necessary for AerStatevector to use multiple-GPUs.
This is fix for AerStatevector. It was not possible to create an AerStatevector instance directly from terra’s Statevector. This fix allows a Statevector as AerStatevector’s input.
SamplerResult.quasi_dists
contain the data about the number of qubits.QuasiDistribution.binary_probabilities()
returns bitstrings with correct length.
Previously seed is not initialized in AerStatevector and then sampled results are always same. With this commit, a seed is initialized for each sampling and sampled results can be vary.
IBM Q Provider 0.19.2¶
No change
Qiskit 0.39.3¶
Terra 0.22.3¶
Prelude¶
Qiskit Terra 0.22.3 is a minor bugfix release, fixing some further bugs in the 0.22 series.
Bug Fixes¶
AdaptVQE
now correctly indicates that it supports auxiliary operators.
The circuit drawers (
QuantumCircuit.draw()
andcircuit_drawer()
) will no longer emit a warning about thecregbundle
parameter when using the default arguments, if the content of the circuit requires all bits to be drawn individually. This was most likely to appear when trying to draw circuits with new-style control-flow operations.
Fixed a bug causing
QNSPSA
to fail whenmax_evals_grouped
was set to a value larger than 1.
Fixed an issue with the
SabreSwap
pass which would cause the output of multiple runs of the pass without theseed
argument specified to reuse the same random number generator seed between runs instead of using different seeds. This previously caused identical results to be returned between runs even when noseed
was specified.
Fixed an issue with the primitive classes,
BackendSampler
andBackendEstimator
, where instances were not able to be serialized withpickle
. In general these classes are not guaranteed to be serializable asBackendV2
andBackendV1
instances are not required to be serializable (and often are not), but the class definitions ofBackendSampler
andBackendEstimator
no longer prevent the use ofpickle
.
The
pulse.Instruction.draw()
method will now succeed, as before. This method is deprecated with no replacement planned, but it should still work for the period of deprecation.
Aer 0.11.1¶
No change
IBM Q Provider 0.19.2¶
No change
Qiskit 0.39.2¶
Terra 0.22.2¶
Prelude¶
Qiskit Terra 0.22.2 is a minor bugfix release, and marks the first official support for Python 3.11.
Bug Fixes¶
Fixed an issue with the backend primitive classes
BackendSampler
andBackendEstimator
which prevented running with aBackendV1
instance that does not have amax_experiments
field set in itsBackendConfiguration
.
Fixed a bug in the
VF2PostLayout
pass when transpiling for backends with a definedTarget
, where the interaction graph would be built incorrectly. This could result in excessive runtimes due to the graph being far more complex than necessary.
The Pulse expression parser should no longer periodically hang when called from Jupyter notebooks. This is achieved by avoiding an internal
deepycopy
of a recursive object that seemed to be particularly difficult for the memoization to evaluate.
Aer 0.11.1¶
No change
IBM Q Provider 0.19.2¶
No change
Qiskit 0.39.1¶
Terra 0.22.1¶
Prelude¶
Qiskit Terra 0.22.1 is a bugfix release, addressing some minor issues identified since the 0.22.0 release.
Deprecation Notes¶
The
pauli_list
kwarg ofpauli_basis()
has been deprecated aspauli_basis()
now always returns aPauliList
. This argument was removed prematurely from Qiskit Terra 0.22.0 which broke compatibility for users that were leveraging thepauli_list``argument. Now, the argument has been restored but will emit a ``DeprecationWarning
when used. If used it has no effect because since Qiskit Terra 0.22.0 aPauliList
is always returned.
Bug Fixes¶
Fixed the
BarrierBeforeFinalMeasurements
transpiler pass when there are conditions on looseClbit
s immediately before the final measurement layer. Previously, this would fail claiming that the bit was not present in an internal temporary circuit. Fixed #8923
The equality checkers for
QuantumCircuit
andDAGCircuit
(with objects of the same type) will now correctly handle conditions on single bits. Previously, these would produce false negatives for equality, as the bits would use « exact » equality checks instead of the « semantic » checks the rest of the properties of circuit instructions get.
Fixed handling of classical bits in
StochasticSwap
with control flow. Previously, control-flow operations would be expanded to contain all the classical bits in the outer circuit and not contracted again, leading to a mismatch between the numbers of clbits the instruction reported needing and the actual number supplied to it. Fixed #8903
Fixed handling of globally defined instructions for the
Target
class. Previously, two methods,operations_for_qargs()
andoperation_names_for_qargs()
would ignore/incorrectly handle any globally defined ideal operations present in the target. For example:from qiskit.transpiler import Target from qiskit.circuit.library import CXGate target = Target(num_qubits=5) target.add_instruction(CXGate()) names = target.operation_names_for_qargs((1, 2)) ops = target.operations_for_qargs((1, 2))
will now return
{"cx"}
fornames
and[CXGate()]
forops
instead of raising aKeyError
or an empty return.
Fixed an issue in the
Target.add_instruction()
method where it would previously have accepted an argument with an invalid number of qubits as part of theproperties
argument. For example:from qiskit.transpiler import Target from qiskit.circuit.library import CXGate target = Target() target.add_instruction(CXGate(), {(0, 1, 2): None})
This will now correctly raise a
TranspilerError
instead of causing runtime issues when interacting with the target. Fixed #8914
Fixed an issue with the
plot_state_hinton()
visualization function which would result in a misplaced axis that was offset from the actual plot. Fixed #8446 <https://github.com/Qiskit/qiskit-terra/issues/8446>
Fixed the output of the
plot_state_hinton()
function so that the state labels are ordered ordered correctly, and the image matches up with the natural matrix ordering. Fixed #8324
Fixed an issue with the primitive classes,
BackendSampler
andBackendEstimator
when running on backends that have a limited number of circuits in each job. Not all backends support an unlimited batch size (most hardware backends do not) and previously the backend primitive classes would have potentially incorrectly sent more circuits than the backend supported. This has been corrected so thatBackendSampler
andBackendEstimator
will chunk the circuits into multiple jobs if the backend has a limited number of circuits per job.
Fixed an issue with the
BackendEstimator
class where previously setting a run option namedmonitor
to a value that evaluated asTrue
would have incorrectly triggered a job monitor that only worked on backends from theqiskit-ibmq-provider
package. This has been removed so that you can use amonitor
run option if needed without causing any issues.
Fixed an issue with the
Target.build_coupling_map()
method where it would incorrectly returnNone
for aTarget
object with a mix of ideal globally available instructions and instructions that have qubit constraints. Now in such cases theTarget.build_coupling_map()
will return a coupling map for the constrained instruction (unless it’s a 2 qubit operation which will returnNone
because globally there is no connectivity constraint). Fixed #8971
Fixed an issue with the
Target.qargs
attribute where it would incorrectly returnNone
for aTarget
object that contained any globally available ideal instruction.
Fixed the premature removal of the
pauli_list
keyword argument of thepauli_basis()
function which broke existing code using thepauli_list=True
future compatibility path on upgrade to Qiskit Terra 0.22.0. This keyword argument has been added back to the function and is now deprecated and will be removed in a future release.
Fixed an issue in QPY serialization (
dump()
) when a customControlledGate
subclass that overloaded the_define()
method to provide a custom definition for the operation. Previously, this case of operation was not serialized correctly because it wasn’t accounting for using the potentially_define()
method to provide a definition. Fixes #8794
QPY deserialisation will no longer add extra
Clbit
instances to the circuit if there are both looseClbit
s in the circuit and moreQubit
s thanClbit
s.
QPY deserialisation will no longer add registers named q and c if the input circuit contained only loose bits.
Fixed the
SparsePauliOp.dot()
method when run on two operators with real coefficients. To fix this, the dtype thatSparsePauliOp
can take is restricted tonp.complex128
andobject
. Fixed #8992
Fixed an issue in the
circuit_drawer()
function andQuantumCircuit.draw()
method where the only built-in style for thempl
output that was usable wasdefault
. If another built-in style, such asiqx
, were used then a warning about the style not being found would be emitted and the drawer would fall back to use thedefault
style. Fixed #8991
Fixed an issue with the
transpile()
where it would previously fail with aTypeError
if a customTarget
object was passed in via thetarget
argument and a list of multiple circuits were specified for thecircuits
argument.
Fixed an issue with
transpile()
when targeting aTarget
(either directly via thetarget
argument or via aBackendV2
instance from thebackend
argument) that contained an idealMeasure
instruction (one that does not have any properties defined). Previously this would raise an exception trying to parse the target. Fixed #8969
Fixed an issue with the
VF2Layout
pass where it would error when running with aTarget
that had instructions that were missing error rates. This has been corrected so in such cases the lack of an error rate will be treated as an ideal implementation and if no error rates are present it will just select the first matching layout. Fixed #8970
Fixed an issue with the
VF2PostLayout
pass where it would error when running with aTarget
that had instructions that were missing. In such cases the lack of an error rate will be treated as an ideal implementation of the operation.
Fixed an issue with the
VQD
class if more thank=2
eigenvalues were computed. Previously this would fail due to an internal type mismatch, but now runs as expected. Fixed #8982
Fixed a performance bug where the new primitive-based variational algorithms
minimum_eigensolvers.VQE
,eigensolvers.VQD
andSamplingVQE
did not batch energy evaluations per default, which resulted in a significant slowdown if a hardware backend was used.
Zero-operand gates and instructions will now work with
circuit_to_gate()
,QuantumCircuit.to_gate()
,Gate.control()
, and the construction of anOperator
from aQuantumCircuit
containing zero-operand instructions. This edge case is occasionally useful in creating global-phase gates as part of larger compound instructions, though for many uses,QuantumCircuit.global_phase
may be more appropriate.
Fixes issue where
Statevector.evolve()
andDensityMatrix.evolve()
would raise an exeception for nested subsystem evolution for non-qubit subsystems. Fixes issue #8897
Fixes bug in
Statevector.evolve()
where subsystem evolution will return the incorrect value in certain cases where there are 2 or more than non-evolved subsystems with different subsystem dimensions. Fixes issue #8899
Aer 0.11.1¶
Bug Fixes¶
Fixed a potential build error when trying to use CMake 3.18 or newer and building qiskit-aer with GPU support enabled. Since CMake 3.18 or later when building with CUDA the
CMAKE_CUDA_ARCHITECTURES
was required to be set with the architecture value for the target GPU. This has been corrected so that settingAER_CUDA_ARCH
will be used if this was not set.
Fixes a bug in the handling of instructions with clbits in
LocalNoisePass
. Previously, it was accidentally erasing clbits of instructions (e.g. measures) to which the noise is applied in the case ofmethod="append"
.
Fixed the performance overhead of the Sampler class when running with identical circuits on multiple executions. This was accomplished by skipping/caching the transpilation of these identical circuits on subsequent executions.
Fixed compatibility of the
Sampler
andEstimator
primitive classes with qiskit-terra 0.22.0 release. In qiskit-terra 0.22.0 breaking API changes were made to the abstract interface which broke compatibility with these classes, this has been addressed so thatSampler
andEstimator
can now be used with qiskit-terra >= 0.22.0.
IBM Q Provider 0.19.2¶
No change
Qiskit 0.39.0¶
This release also officially deprecates the Qiskit Aer project as part of the Qiskit metapackage.
This means that in a future release pip install qiskit
will no longer include qiskit-aer
.
If you’re currently installing or listing qiskit
as a dependency to get Aer you should upgrade
this to explicitly list qiskit-aer
as well.
The qiskit-aer
project is still active and maintained moving forward but for the Qiskit
metapackage (i.e. what gets installed via pip install qiskit
) the project is moving towards
a model where the Qiskit package only contains the common core functionality for building and
compiling quantum circuits, programs, and applications and packages that build on it or link
Qiskit to hardware or simulators are separate packages.
Terra 0.22.0¶
Prelude¶
The Qiskit Terra 0.22.0 release is a major feature release that includes a myriad of new feature and bugfixes. The highlights for this release are:
Adding initial support to the transpiler for transpiling
QuantumCircuit
objects that contain control flow instructions such asForLoopOp
andWhileLoopOp
.Greatly improved scaling and performance for the
transpile()
function with large numbers of qubits, especially whenoptimization_level=3
is used.External plugin interface for
transpile()
that enables external packages to implement stages for the default pass managers. More details on this can be found atqiskit.transpiler.preset_passmanagers.plugin
. Additionally,BackendV2
backends can now optionally set custom default plugins to use for the scheduling and translation stages.Updated algorithm implementations in
qiskit.algorithms
that leverage theprimitives
classes that implement theBaseSampler
andBaseEstimator
.
New Features¶
Add support for representing an operation that has a variable width to the
Target
class. Previously, aTarget
object needed to have an instance ofOperation
defined for each operation supported in the target. This was used for both validation of arguments and parameters of the operation. However, for operations that have a variable width this wasn’t possible because each instance of anOperation
class can only have a fixed number of qubits. For cases where a backend supports variable width operations the instruction can be added with the class of the operation instead of an instance. In such cases the operation will be treated as globally supported on all qubits. For example, if building a target like:from qiskit.circuit import Parameter, Measure, IfElseOp, ForLoopOp, WhileLoopOp from qiskit.circuit.library import IGate, RZGate, SXGate, XGate, CXGate from qiskit.transpiler import Target, InstructionProperties theta = Parameter("theta") ibm_target = Target() i_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(IGate(), i_props) rz_props = { (0,): InstructionProperties(duration=0, error=0), (1,): InstructionProperties(duration=0, error=0), (2,): InstructionProperties(duration=0, error=0), (3,): InstructionProperties(duration=0, error=0), (4,): InstructionProperties(duration=0, error=0), } ibm_target.add_instruction(RZGate(theta), rz_props) sx_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(SXGate(), sx_props) x_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(XGate(), x_props) cx_props = { (3, 4): InstructionProperties(duration=270.22e-9, error=0.00713), (4, 3): InstructionProperties(duration=305.77e-9, error=0.00713), (3, 1): InstructionProperties(duration=462.22e-9, error=0.00929), (1, 3): InstructionProperties(duration=497.77e-9, error=0.00929), (1, 2): InstructionProperties(duration=227.55e-9, error=0.00659), (2, 1): InstructionProperties(duration=263.11e-9, error=0.00659), (0, 1): InstructionProperties(duration=519.11e-9, error=0.01201), (1, 0): InstructionProperties(duration=554.66e-9, error=0.01201), } ibm_target.add_instruction(CXGate(), cx_props) measure_props = { (0,): InstructionProperties(duration=5.813e-6, error=0.0751), (1,): InstructionProperties(duration=5.813e-6, error=0.0225), (2,): InstructionProperties(duration=5.813e-6, error=0.0146), (3,): InstructionProperties(duration=5.813e-6, error=0.0215), (4,): InstructionProperties(duration=5.813e-6, error=0.0333), } ibm_target.add_instruction(Measure(), measure_props) ibm_target.add_instruction(IfElseOp, name="if_else") ibm_target.add_instruction(ForLoopOp, name="for_loop") ibm_target.add_instruction(WhileLoopOp, name="while_loop")
The
IfElseOp
,ForLoopOp
, andWhileLoopOp
operations are globally supported for any number of qubits. This is then reflected by other calls in theTarget
API such asinstruction_supported()
:ibm_target.instruction_supported(operation_class=WhileLoopOp, qargs=(0, 2, 3, 4)) ibm_target.instruction_supported('if_else', qargs=(0, 1))
both return
True
.
Added new primitive implementations,
BackendSampler
andBackendEstimator
, toqiskit.primitives
. Thes new primitive class implementation wrap aBackendV1
orBackendV2
instance as aBaseSampler
orBaseEstimator
respectively. The intended use case for these primitive implementations is to bridge the gap between providers that do not have native primitive implementations and use that provider’s backend with APIs that work with primitives. For example, theSamplingVQE
class takes aBaseSampler
instance to function. If you’d like to run that class with a backend from a provider without a native primitive implementation you can construct aBackendSampler
to do this:from qiskit.algorithms.minimum_eigensolvers import SamplingVQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import BackendSampler from qiskit.providers.fake_provider import FakeHanoi from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp backend = FakeHanoi() sampler = BackendSampler(backend=backend) operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12])) ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() sampling_vqe = SamplingVQE(sampler, ansatz, optimizer) result = sampling_vqe.compute_minimum_eigenvalue(operator) eigenvalue = result.eigenvalue
If you’re using a provider that has native primitive implementations (such as
qiskit-ibm-runtime
orqiskit-aer
) it is always a better choice to use that native primitive implementation instead ofBackendEstimator
orBackendSampler
as the native implementations will be much more efficient and/or do additional pre and post processing.BackendEstimator
andBackendSampler
are designed to be generic that can work with any backend that returnsCounts
in theirResults
which precludes additional optimization.
Added a new algorithm class,
AdaptVQE
toqiskit.algorithms
This algorithm uses aqiskit.algorithms.minimum_eigensolvers.VQE
in combination with a pool of operators from which to build out anqiskit.circuit.library.EvolvedOperatorAnsatz
adaptively. For example:from qiskit.algorithms.minimum_eigensolvers import AdaptVQE, VQE from qiskit.algorithms.optimizers import SLSQP from qiskit.primitives import Estimator from qiskit.circuit.library import EvolvedOperatorAnsatz # get your Hamiltonian hamiltonian = ... # construct your ansatz ansatz = EvolvedOperatorAnsatz(...) vqe = VQE(Estimator(), ansatz, SLSQP()) adapt_vqe = AdaptVQE(vqe) result = adapt_vqe.compute_minimum_eigenvalue(hamiltonian)
The
BackendV2
class now has support for two new optional hook points enabling backends to inject custom compilation steps as part oftranspile()
andgenerate_preset_pass_manager()
. If aBackendV2
implementation includes the methodsget_scheduling_stage_plugin()
orget_translation_stage_plugin()
the transpiler will use the returned string as the default value for thescheduling_method
andtranslation_method
arguments. This enables backends to run additional custom transpiler passes when targetting that backend by leveraging the transpiler stageplugin
interface. For more details on how to use this see: Custom Transpiler Passes.
Added a new keyword argument,
ignore_backend_supplied_default_methods
, to thetranspile()
function which can be used to disable a backend’s custom selection of a default method if the target backend hasget_scheduling_stage_plugin()
orget_translation_stage_plugin()
defined.
Added a
label
parameter to theBarrier
class’s constructor and thebarrier()
method which allows a user to assign a label to an instance of theBarrier
directive. For visualizations generated withcircuit_drawer()
orQuantumCircuit.draw()
this label will be printed at the top of thebarrier
.from qiskit import QuantumCircuit circuit = QuantumCircuit(2) circuit.h(0) circuit.h(1) circuit.barrier(label="After H") circuit.draw('mpl')
Add new gates
CCZGate
,CSGate
, andCSdgGate
to the standard gates in the Circuit Library (qiskit.circuit.library
).
Added
qiskit.algorithms.eigensolvers
package to include interfaces for primitive-enabled algorithms. This new module will eventually replace the previousqiskit.algorithms.eigen_solvers
. This new module contains an alternative implementation of theVQD
which instead of taking a backend orQuantumInstance
instead takes an instance ofBaseEstimator
, includingEstimator
,BackendEstimator
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
.For example, to use the new implementation with an instance of
Estimator
class:from qiskit.algorithms.eigensolvers import VQD from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Sampler, Estimator from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp h2_op = PauliSumOp(SparsePauliOp( ["II", "IZ", "ZI", "ZZ", "XX"], coeffs=[ -1.052373245772859, 0.39793742484318045, -0.39793742484318045, -0.01128010425623538, 0.18093119978423156, ], )) estimator = Estimator() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() fidelity = ComputeUncompute(Sampler()) vqd = VQD(estimator, fidelity, ansatz, optimizer, k=2) result = vqd.compute_eigenvalues(h2_op) eigenvalues = result.eigenvalues
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field.
Added new algorithms to calculate state fidelities/overlaps for pairs of quantum circuits (that can be parametrized). Apart from the base class (
BaseStateFidelity
) which defines the interface, there is an implementation of the compute-uncompute method that leverages instances of theBaseSampler
primitive:qiskit.algorithms.state_fidelities.ComputeUncompute
.For example:
import numpy as np from qiskit.primitives import Sampler from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.circuit.library import RealAmplitudes sampler = Sampler(...) fidelity = ComputeUncompute(sampler) circuit = RealAmplitudes(2) values = np.random.random(circuit.num_parameters) shift = np.ones_like(values) * 0.01 job = fidelity.run([circuit], [circuit], [values], [values+shift]) fidelities = job.result().fidelities
Added a new module
qiskit.algorithms.gradients
that contains classes which are used to compute gradients using the primitive interfaces defined inqiskit.primitives
. There are 4 types of gradient classes: Finite Difference, Parameter Shift, Linear Combination of Unitary, and SPSA with implementations that either use an instance of theBaseEstimator
interface:or an instance of the
BaseSampler
interface:The estimator-based gradients compute the gradient of expectation values, while the sampler-based gradients return gradients of the measurement outcomes (also referred to as « probability gradients »).
For example:
estimator = Estimator(...) gradient = ParamShiftEstimatorGradient(estimator) job = gradient.run(circuits, observables, parameters) gradients = job.result().gradients
The
Grover
class has a new keyword argument,sampler
which is used to run the algorithm using an instance of theBaseSampler
interface to calculate the results. This new argument supersedes the thequantum_instance
argument and accordingly,quantum_instance
is pending deprecation and will be deprecated and subsequently removed in future releases.Example:
from qiskit import QuantumCircuit from qiskit.primitives import Sampler from qiskit.algorithms import Grover, AmplificationProblem sampler = Sampler() oracle = QuantumCircuit(2) oracle.cz(0, 1) problem = AmplificationProblem(oracle, is_good_state=["11"]) grover = Grover(sampler=sampler) result = grover.amplify(problem)
A new option,
"formatter.control.fill_waveform"
has been added to the pulse drawer (pulse_v2.draw()
andSchedule.draw()
) style sheets. This option can be used to remove the face color of pulses in the output visualization which allows for drawing pulses only with lines.For example:
from qiskit.visualization.pulse_v2 import IQXStandard my_style = IQXStandard( **{"formatter.control.fill_waveform": False, "formatter.line_width.fill_waveform": 2} ) my_sched.draw(style=my_style)
Added a new transpiler pass,
ResetAfterMeasureSimplification
, which is used to replace aReset
operation after aMeasure
with a conditionalXGate
. This pass can be used on backends where aReset
operation is performed by doing a measurement and then a conditional X gate so that this will remove the duplicate implicitMeasure
from theReset
operation. For example:from qiskit import QuantumCircuit from qiskit.transpiler.passes import ResetAfterMeasureSimplification qc = QuantumCircuit(1) qc.measure_all() qc.reset(0) qc.draw('mpl')
result = ResetAfterMeasureSimplification()(qc) result.draw('mpl')
Added a new supported value,
"reverse_linear"
for theentanglement
keyword argument to the constructor for theNLocal
circuit class. ForTwoLocal
circuits (which are subclassess ofNLocal
), ifentanglement_blocks="cx"
then usingentanglement="reverse_linear"
provides an equivalent n-qubit circuit asentanglement="full"
but with only \(n-1\)CXGate
gates, instead of \(\frac{n(n-1)}{2}\).
ScheduleBlock
has been updated so that it can manage unassigned subroutine, in other words, to allow lazy calling of other programs. For example, this enables the following workflow:from qiskit import pulse with pulse.build() as prog: pulse.reference("x", "q0") with pulse.build() as xq0: pulse.play(Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) prog.assign_references({("x", "q0"): xq0})
Now a user can create
prog
without knowing actual implementation of the reference("x", "q0")
, and assign it at a later time for execution. This improves modularity of pulse programs, and thus one can easily write a template pulse program relying on other calibrations.To realize this feature, the new pulse instruction (compiler directive)
Reference
has been added. This instruction is injected into the current builder scope when thereference()
command is used. All references defined in the current pulse program can be listed with thereferences
property.In addition, every reference is managed with a scope to ease parameter management.
scoped_parameters()
andsearch_parameters()
have been added toScheduleBlock
. See API documentation for more details.
Added a new method
SparsePauliOp.argsort()
, which returns the composition of permutations in the order of sorting by coefficient and sorting by Pauli. By using theweight
keyword argument for the method the output can additionally be sorted by the number of non-identity terms in the Pauli, where the set of all Paulis of a given weight are still ordered lexicographically.
Added a new method
SparsePauliOp.sort()
, which will first sort the coefficients using numpy’sargsort()
and then sort by Pauli, where the Pauli sort takes precedence. If the Pauli sort is the same, it will then be sorted by coefficient. By using theweight
keyword argument the output can additionally be sorted by the number of non-identity terms in the Pauli, where the set of all Paulis of a given weight are still ordered lexicographically.
Added a new keyword argument,
wire_order
, to thecircuit_drawer()
function andQuantumCircuit.draw()
method which allows arbitrarily reordering both the quantum and classical bits in the output visualization. For example:from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister qr = QuantumRegister(4, "q") cr = ClassicalRegister(4, "c") cr2 = ClassicalRegister(2, "ca") circuit = QuantumCircuit(qr, cr, cr2) circuit.h(0) circuit.h(3) circuit.x(1) circuit.x(3).c_if(cr, 10) circuit.draw('mpl', cregbundle=False, wire_order=[2, 1, 3, 0, 6, 8, 9, 5, 4, 7])
Added support for the
CSGate
,CSdgGate
andCCZGate
classes to the constructor for the operator classCNOTDihedral
. The input circuits when creating aCNOTDihedral
operator will now support circuits using these gates. For example:from qiskit import QuantumCircuit from qiskit.quantum_info import CNOTDihedral qc = QuantumCircuit(2) qc.t(0) qc.cs(0, 1) qc.tdg(0) operator = CNOTDihedral(qc)
The amplitude estimation algorithm classes:
Now have a new keyword argument,
sampler
on their constructor that takes an instance of an object that implements theBaseSampler
interface includingBackendSampler
,Sampler
, or any provider implementations such as those as those present in qiskit-ibm-runtime and qiskit-aer. This provides an alternative to using thequantum_instance
argument to set the targetBackend
orQuantumInstance
to run the algorithm on. Using aQuantumInstance
is pending deprecation and will be deprecated in a future release.
Added a new class,
BackendV2Converter
, which is used to wrap aBackendV1
instance in aBackendV2
interface. It enables you to have aBackendV2
instance from anyBackendV1
. This enables standardizing access patterns on the newerBackendV2
interface even if you still supportBackendV1
.
Added a new function
convert_to_target()
which is used to take aBackendConfiguration
, and optionally aBackendProperties
andPulseDefaults
and create aTarget
object equivalent to the contents of those objects.
qiskit.quantum_info.BaseOperator
subclasses (such asScalarOp
,SparsePauliOp
andPauliList
) can now be used with the built-in Pythonsum()
function.
A new transpiler pass,
ConvertConditionsToIfOps
was added, which can be used to convert old-styleInstruction.c_if()
-conditioned instructions intoIfElseOp
objects. This is to help ease the transition from the old type to the new type for backends. For most users, there is no need to add this to your pass managers, and it is not included in any preset pass managers.
Refactored gate commutativity analysis into a class
CommutationChecker
. This class allows you to check (based on matrix multiplication) whether two gates commute or do not commute, and to cache the results (so that a similar check in the future will no longer require matrix multiplication).For example we can now do:
from qiskit.circuit import QuantumRegister, CommutationChecker comm_checker = CommutationChecker() qr = QuantumRegister(4) res = comm_checker.commute(CXGate(), [qr[1], qr[0]], [], CXGate(), [qr[1], qr[2]], [])
As the two CX gates commute (the first CX gate is over qubits
qr[1]
andqr[0]
, and the second CX gate is over qubitsqr[1]
andqr[2]
), we will have thatres
isTrue
.This commutativity checking is over-conservative for conditional and parameterized gates, and may return
False
even when such gates commute.
Added a new transpiler pass
CommutativeInverseCancellation
that cancels pairs of inverse gates exploiting commutation relations between gates. This pass is a generalization of the transpiler passInverseCancellation
as it detects a larger set of inverse gates, and as it takes commutativity into account. The pass also avoids some problems associated with the transpiler passCommutativeCancellation
.For example:
from qiskit.circuit import QuantumCircuit from qiskit.transpiler import PassManager from qiskit.transpiler.passes import CommutativeInverseCancellation circuit = QuantumCircuit(2) circuit.z(0) circuit.x(1) circuit.cx(0, 1) circuit.z(0) circuit.x(1) passmanager = PassManager(CommutativeInverseCancellation()) new_circuit = passmanager.run(circuit)
cancels the pair of self-inverse Z-gates, and the pair of self-inverse X-gates (as the relevant gates commute with the CX-gate), producing a circuit consisting of a single CX-gate.
The inverse checking is over-conservative for conditional and parameterized gates, and may not cancel some of such gates.
QuantumCircuit.compose()
will now accept an operand with classical bits if the base circuit has none itself. The pattern of composing a circuit with measurements onto a quantum-only circuit is now valid. For example:from qiskit import QuantumCircuit base = QuantumCircuit(3) terminus = QuantumCircuit(3, 3) terminus.measure_all() # This will now succeed, though it was previously a CircuitError. base.compose(terminus)
The
DAGCircuit
methodsdepth()
andsize()
have a newrecurse
keyword argument for use with circuits that contain control-flow operations (such asIfElseOp
,WhileLoopOp
, andForLoopOp
). By default this isFalse
and will raise an error if control-flow operations are present, to avoid poorly defined results. If set toTrue
, a proxy value that attempts to fairly weigh each control-flow block relative to its condition is returned, even though the depth or size of a concrete run is generally unknowable. See each method’s documentation for how each control-flow operation affects the output.
DAGCircuit.count_ops()
gained arecurse
keyword argument for recursing into control-flow blocks. By default this isTrue
, and all operations in all blocks will be returned, as well as the control-flow operations themselves.
Added an argument
create_preds_and_succs
to the functionscircuit_to_dagdependency()
anddag_to_dagdependency()
that convert fromQuantumCircuit
andDAGCircuit
, respectively, toDAGDependency
. When the value ofcreate_preds_and_succs
is False, the transitive predecessors and successors for nodes inDAGDependency
are not constructed, making the conversions faster and significantly less memory-intensive. The direct predecessors and successors for nodes inDAGDependency
are constructed as usual.For example:
from qiskit.converters import circuit_to_dagdependency from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit circuit_in = QuantumCircuit(2) circuit_in.h(qr[0]) circuit_in.h(qr[1]) dag_dependency = circuit_to_dagdependency(circuit_in, create_preds_and_succs=False)
Added new attributes
Clifford.symplectic_matrix
,Clifford.tableau
,Clifford.z
,Clifford.x
,Clifford.phase
,Clifford.stab
,Clifford.stab_z
,Clifford.stab_x
,Clifford.stab_phase
,Clifford.destab
,Clifford.destab_z
,Clifford.destab_x
,Clifford.destab_phase
to theClifford
class. These can be used instead ofClifford.table
, that will be deprecated in the future.StabilizerTable
andPauliTable
are pending deprecation and will be deprecated in the future release and subsequently removed after that.
The
Commuting2qGateRouter
constructor now has a new keyword argument,edge_coloring
. This argument is used to provide an edge coloring of the coupling map to determine the order in which the commuting gates are applied.
Added a new algorithms interface for creating time evolution algorithms using the primitives
BaseSampler
andBaseEstimator
. This new interface consists of:This new interface is an alternative to the previously existing time evolution algorithms interface available defined with
EvolutionProblem
,EvolutionResult
,RealEvolver
, andImaginaryEvolver
which worked with aQuantumInstance
object instead of primitives. This new interface supersedes the previous interface which will eventually be deprecated and subsequently removed in future releases.
Added new backend classes to
qiskit.providers.fake_provider
:These new classes implement the
BackendV2
interface and are created using stored snapshots of the backend information from the IBM Quantum systemsibm_auckland
,ibm_oslo
,ibm_geneva
, andibm_perth
systems respectively.
The
Z2Symmetries
class has two new methods,convert_clifford()
andtaper_clifford()
. These two methods are the two operations necessary for taperng an operator based on the Z2 symmetries in the object and were previously performed internally via thetaper()
method. However, these methods are now public methods of the class which can be called individually if needed.
The runtime performance for conjugation of a long
PauliList
object by aClifford
using thePauliList.evolve()
has significantly improved. It will now run significantly faster than before.
Added a new abstract class
ClassicalIOChannel
to theqiskit.pulse.channels
module. This class is used to represent classical I/O channels and differentiate these channels from other subclasses ofChannel
. This new class is the base class for theMemorySlot
,RegisterSlot
, andSnapshotChannel
classes. Accordingly, thepad()
canonicalization pulse transform inqiskit.pulse.transforms
will not introduce delays to any instances ofClassicalIOChannel
The
SabreSwap
transpiler pass has a new keyword argument on its constructor,trials
. Thetrials
argument is used to specify the number of random seed trials to attempt. The output from the SABRE algorithm can differ greatly based on the seed used for the random number.SabreSwap
will now run the algorithm withtrials
number of random seeds and pick the best (with the fewest swaps inserted). Iftrials
is not specified the pass will default to use the number of physical CPUs on the local system.
The
SabreLayout
transpiler pass has a new keyword argument on its constructor,swap_trials
. Theswap_trials
argument is used to specify how many random seed trials to run on theSabreSwap
pass internally. It corresponds to thetrials
arugment on theSabreSwap
pass. When set, each iteration ofSabreSwap
will be run internallyswap_trials
times. Ifswap_trials
is not specified the will default to use the number of physical CPUs on the local system.
Added a new function,
estimate_observables()
which uses an implementation of theBaseEstimator
interface (e.g.Estimator
,BackendEstimator
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
) to calculate the expectation values, their means and standard deviations from a list or dictionary of observables. This serves a similar purpose to the pre-existing functioneval_observables()
which performed the calculation using aQuantumInstance
object and has been superseded (and will be deprecated and subsequently removed in future releases) by this new function.
Added a new
Operation
base class which provides a lightweight abstract interface for objects that can be put onQuantumCircuit
. This allows to store « higher-level » objects directly on a circuit (for instance,Clifford
objects), to directly combine such objects (for instance, to compose several consecutiveClifford
objects over the same qubits), and to synthesize such objects at run time (for instance, to synthesizeClifford
in a way that optimizes depth and/or exploits device connectivity). Previously, only subclasses ofqiskit.circuit.Instruction
could be put onQuantumCircuit
, but this interface has become unwieldy and includes too many methods and attributes for general-purpose objects.The new
Operation
interface includesname
,num_qubits
andnum_clbits
(in the future this may be slightly adjusted), but importantly does not includedefinition
(and thus does not tie synthesis to the object), does not includecondition
(this should be part of separate classical control flow), and does not includeduration
andunit
(as these are properties of the output of the transpiler).As of now,
Operation
includesGate
,Reset
,Barrier
,Measure
, and « higher-level » objects such asClifford
. This list of « higher-level » objects will grow in the future.
A
Clifford
is now added to a quantum circuit as anOperation
, without first synthesizing a subcircuit implementing this Clifford. The actual synthesis is postponed to a laterHighLevelSynthesis
transpilation pass.For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford qc = QuantumCircuit(3) cliff = random_clifford(2) qc.append(cliff, [0, 1])
no longer converts
cliff
toqiskit.circuit.Instruction
, which includes synthesizing the clifford into a circuit, when it is appended toqc
.
Added a new transpiler pass
OptimizeCliffords
that collects blocks of consecutiveClifford
objects in a circuit, and replaces each block with a singleClifford
.For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford from qiskit.transpiler.passes import OptimizeCliffords from qiskit.transpiler import PassManager qc = QuantumCircuit(3) cliff1 = random_clifford(2) cliff2 = random_clifford(2) qc.append(cliff1, [2, 1]) qc.append(cliff2, [2, 1]) qc_optimized = PassManager(OptimizeCliffords()).run(qc)
first stores the two Cliffords
cliff1
andcliff2
onqc
as « higher-level » objects, and then the transpiler passOptimizeCliffords
optimizes the circuit by composing these two Cliffords into a single Clifford. Note that the resulting Clifford is still stored onqc
as a higher-level object. This pass is not yet included in any of preset pass managers.
Added a new transpiler pass
HighLevelSynthesis
that synthesizes higher-level objects (for instance,Clifford
objects).For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford from qiskit.transpiler import PassManager from qiskit.transpiler.passes import HighLevelSynthesis qc = QuantumCircuit(3) qc.h(0) cliff = random_clifford(2) qc.append(cliff, [0, 1]) qc_synthesized = PassManager(HighLevelSynthesis()).run(qc)
will synthesize the higher-level Clifford stored in
qc
using the defaultdecompose_clifford()
function.This new transpiler pass
HighLevelSynthesis
is integrated into the preset pass managers, running right afterUnitarySynthesis
pass. Thus,transpile()
will synthesize all higher-level Cliffords present in the circuit.It is important to note that the work done to store
Clifford
objects as « higher-level » objects and to transpile these objects usingHighLevelSynthesis
pass should be completely transparent, and no code changes are required.
SparsePauliOp
s can now be constructed with coefficient arrays that are general Python objects. This is intended for use withParameterExpression
objects; other objects may work, but do not have first-class support. SomeSparsePauliOp
methods (such as conversion to other class representations) may not work when usingobject
arrays, if the desired target cannot represent these general arrays.For example, a
ParameterExpression
SparsePauliOp
could be constructed by:import numpy as np from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp print(SparsePauliOp(["II", "XZ"], np.array([Parameter("a"), Parameter("b")])))
which gives
SparsePauliOp(['II', 'XZ'], coeffs=[ParameterExpression(1.0*a), ParameterExpression(1.0*b)])
Added a new function
plot_distribution()
for plotting distributions over quasi-probabilities. This is suitable forCounts
,QuasiDistribution
andProbDistribution
. Raw dict can be passed as well. For example:from qiskit.visualization import plot_distribution quasi_dist = {'0': .98, '1': -.01} plot_distribution(quasi_dist)
Introduced a new high level synthesis plugin interface which is used to enable using alternative synthesis techniques included in external packages seamlessly with the
HighLevelSynthesis
transpiler pass. These alternative synthesis techniques can be specified for any « higher-level » objects of typeOperation
, as for example forClifford
andLinearFunction
objects. This plugin interface is similar to the one for unitary synthesis. In the latter case, the details on writing a new plugin appear in theqiskit.transpiler.passes.synthesis.plugin
module documentation.
Introduced a new class
HLSConfig
which can be used to specify alternative synthesis algorithms for « higher-level » objects of typeOperation
. For each higher-level object of interest, an objectHLSConfig
specifies a list of synthesis methods and their arguments. This object can be passed toHighLevelSynthesis
transpiler pass or specified as a parameterhls_config
intranspile()
.As an example, let us assume that
op_a
andop_b
are names of two higher-level objects, thatop_a
-objects have two synthesis methodsdefault
which does require any additional parameters andother
with two optional integer parametersoption_1
andoption_2
, thatop_b
-objects have a single synthesis methoddefault
, andqc
is a quantum circuit containingop_a
andop_b
objects. The following code snippet:hls_config = HLSConfig(op_b=[("other", {"option_1": 7, "option_2": 4})]) pm = PassManager([HighLevelSynthesis(hls_config=hls_config)]) transpiled_qc = pm.run(qc)
shows how to run the alternative synthesis method
other
forop_b
-objects, while using thedefault
methods for all other high-level objects, includingop_a
-objects.
Added new methods for executing primitives:
BaseSampler.run()
andBaseEstimator.run()
. These methods execute asynchronously and returnJobV1
objects which provide a handle to the exections. These new run methods can be passedQuantumCircuit
objects (and observables forBaseEstimator
) that are not registered in the constructor. For example:estimator = Estimator() result = estimator.run(circuits, observables, parameter_values).result()
This provides an alternative to the previous execution model (which is now deprecated) for the
BaseSampler
andBaseEstimator
primitives which would take all the inputs via the constructor and calling the primitive object with the combination of those input parameters to use in the execution.
Added
shots
option for reference implementations of primitives. Random numbers can be fixed by givingseed_primitive
. For example:from qiskit.primitives import Sampler from qiskit import QuantumCircuit bell = QuantumCircuit(2) bell.h(0) bell.cx(0, 1) bell.measure_all() with Sampler(circuits=[bell]) as sampler: result = sampler(circuits=[0], shots=1024, seed_primitive=15) print([q.binary_probabilities() for q in result.quasi_dists])
The constructors for the
BaseSampler
andBaseEstimator
primitive classes have a new optional keyword argument,options
which is used to set the default values for the options exposed via theoptions
attribute.
Added the
PVQD
class to the time evolution framework inqiskit.algorithms
. This class implements the projected Variational Quantum Dynamics (p-VQD) algorithm Barison et al..In each timestep this algorithm computes the next state with a Trotter formula and projects it onto a variational form. The projection is determined by maximizing the fidelity of the Trotter-evolved state and the ansatz, using a classical optimization routine.
import numpy as np from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.algorithms.evolvers import EvolutionProblem from qiskit.algorithms.time_evolvers.pvqd import PVQD from qiskit.primitives import Estimator, Sampler from qiskit import BasicAer from qiskit.circuit.library import EfficientSU2 from qiskit.quantum_info import Pauli, SparsePauliOp from qiskit.algorithms.optimizers import L_BFGS_B sampler = Sampler() fidelity = ComputeUncompute(sampler) estimator = Estimator() hamiltonian = 0.1 * SparsePauliOp([Pauli("ZZ"), Pauli("IX"), Pauli("XI")]) observable = Pauli("ZZ") ansatz = EfficientSU2(2, reps=1) initial_parameters = np.zeros(ansatz.num_parameters) time = 1 optimizer = L_BFGS_B() # setup the algorithm pvqd = PVQD( fidelity, ansatz, initial_parameters, estimator, num_timesteps=100, optimizer=optimizer, ) # specify the evolution problem problem = EvolutionProblem( hamiltonian, time, aux_operators=[hamiltonian, observable] ) # and evolve! result = pvqd.evolve(problem)
The
QNSPSA.get_fidelity()
static method now supports an optionalsampler
argument which is used to provide an implementation of theBaseSampler
interface (such asSampler
,BackendSampler
, or any provider implementations such as those present inqiskit-ibm-runtime
andqiskit-aer
) to compute the fidelity of aQuantumCircuit
. For example:from qiskit.primitives import Sampler from qiskit.algorithms.optimizers import QNSPSA fidelity = QNSPSA.get_fidelity(my_circuit, Sampler())
Added a new keyword argument
sampler
to the constructors of the phase estimation classes:This argument is used to provide an implementation of the
BaseSampler
interface such asSampler
,BackendSampler
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
.For example:
from qiskit.primitives import Sampler from qiskit.algorithms.phase_estimators import HamiltonianPhaseEstimation from qiskit.synthesis import MatrixExponential from qiskit.quantum_info import SparsePauliOp from qiskit.opflow import PauliSumOp sampler = Sampler() num_evaluation_qubits = 6 phase_est = HamiltonianPhaseEstimation( num_evaluation_qubits=num_evaluation_qubits, sampler=sampler ) hamiltonian = PauliSumOp(SparsePauliOp.from_list([("X", 0.5), ("Y", 0.6), ("I", 0.7)])) result = phase_est.estimate( hamiltonian=hamiltonian, state_preparation=None, evolution=MatrixExponential(), bound=1.05, )
The
SabreSwap
transpiler pass has significantly improved runtime performance due to a rewrite of the algorithm in Rust.
Symbolic pulse subclasses
Gaussian
,GaussianSquare
,Drag
andConstant
have been upgraded to instantiateSymbolicPulse
rather than the subclass itself. All parametric pulse objects in pulse programs must be symbolic pulse instances, because subclassing is no longer neccesary. Note thatSymbolicPulse
can uniquely identify a particular envelope with the symbolic expression object defined inSymbolicPulse.envelope
.
Added a new function,
sampled_expectation_value()
, that allows for computing expectation values for diagonal operators from distributions such asCounts
andQuasiDistribution
. Valid operators for use with this function are:str
,Pauli
,PauliOp
,PauliSumOp
, andSparsePauliOp
.
A
SamplingVQE
class is introduced, which is optimized for diagonal hamiltonians and leverages asampler
primitive. AQAOA
class is also added that subclassesSamplingVQE
.To use the new
SamplingVQE
with a reference primitive, one can do, for example:from qiskit.algorithms.minimum_eigensolvers import SamplingVQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Sampler from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12])) sampler = Sampler() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() sampling_vqe = SamplingVQE(sampler, ansatz, optimizer) result = sampling_vqe.compute_minimum_eigenvalue(operator) eigenvalue = result.eigenvalue
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field.
Added a new
atol
keyword argument to theSparsePauliOp.equiv()
method to adjust to tolerance of the equivalence check,
Introduced a new plugin interface for transpiler stages which is used to enable alternative
PassManager
objects from an external package in a particular stage as part oftranspile()
or theStagedPassManager
output fromgenerate_preset_pass_manager()
,level_0_pass_manager()
,level_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
. Users can select a plugin to use for a transpiler stage with theinit_method
,layout_method
,routing_method
,translation_method
,optimization_method
, andscheduling_method
keyword arguments ontranspile()
andgenerate_preset_pass_manager()
. A full list of plugin names currently installed can be found with thelist_stage_plugins()
function. For creating plugins refer to theqiskit.transpiler.preset_passmanagers.plugin
module documentation which includes a guide for writing stage plugins.
The
transpile()
has two new keyword arguments,init_method
andoptimization_method
which are used to specify alternative plugins to use for theinit
stage andoptimization
stages respectively.
The
PassManagerConfig
class has 2 new attributes,init_method
andoptimization_method
along with matching keyword arguments on the constructor methods. These represent the user specifiedinit
andoptimization
plugins to use for compilation.
The
SteppableOptimizer
class is added. It allows one to perfore classical optimizations step-by-step using thestep()
method. These optimizers implement the « ask and tell » interface which (optionally) allows to manually compute the required function or gradient evaluations and plug them back into the optimizer. For more information about this interface see: ask and tell interface. A very simple use case when the user might want to do the optimization step by step is for readout:import random import numpy as np from qiskit.algorithms.optimizers import GradientDescent def objective(x): return (np.linalg.norm(x) - 1) ** 2 def grad(x): return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x) initial_point = np.random.normal(0, 1, size=(100,)) optimizer = GradientDescent(maxiter=20) optimizer.start(x0=initial_point, fun=objective, jac=grad) for _ in range(maxiter): state = optimizer.state # Here you can manually read out anything from the optimizer state. optimizer.step() result = optimizer.create_result()
A more complex case would be error handling. Imagine that the function you are evaluating has a random chance of failing. In this case you can catch the error and run the function again until it yields the desired result before continuing the optimization process. In this case one would use the ask and tell interface.
import random import numpy as np from qiskit.algorithms.optimizers import GradientDescent def objective(x): if random.choice([True, False]): return None else: return (np.linalg.norm(x) - 1) ** 2 def grad(x): if random.choice([True, False]): return None else: return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x) initial_point = np.random.normal(0, 1, size=(100,)) optimizer = GradientDescent(maxiter=20) optimizer.start(x0=initial_point, fun=objective, jac=grad) while optimizer.continue_condition(): ask_data = optimizer.ask() evaluated_gradient = None while evaluated_gradient is None: evaluated_gradient = grad(ask_data.x_center) optimizer.state.njev += 1 optmizer.state.nit += 1 cf = TellData(eval_jac=evaluated_gradient) optimizer.tell(ask_data=ask_data, tell_data=tell_data) result = optimizer.create_result()
Transitioned
GradientDescent
to be a subclass ofSteppableOptimizer
.
The
subset_fitter
method is added to theTensoredMeasFitter
class. The implementation is restricted to mitigation patterns in which each qubit is mitigated individually, e.g.[[0], [1], [2]]
. This is, however, the most widely used case. It allows theTensoredMeasFitter
to be used in cases where the numberical order of the physical qubits does not match the index of the classical bit.
Control-flow operations are now supported through the transpiler at optimization levels 0 and 1 (e.g. calling
transpile()
orgenerate_preset_pass_manager()
with keyword argumentoptimization_level=1
). One can now construct a circuit such asfrom qiskit import QuantumCircuit qc = QuantumCircuit(2, 1) qc.h(0) qc.measure(0, 0) with qc.if_test((0, True)) as else_: qc.x(1) with else_: qc.y(1)
and successfully transpile this, such as by:
from qiskit import transpile from qiskit_aer import AerSimulator backend = AerSimulator(method="statevector") transpiled = transpile(qc, backend)
The available values for the keyword argument
layout_method
are « trivial » and « dense ». Forrouting_method
, « stochastic » and « none » are available. Translation (translation_method
) can be done using « translator » or « unroller ». Optimization levels 2 and 3 are not yet supported with control flow, nor is circuit scheduling (i.e. providing a value toscheduling_method
), though we intend to expand support for these, and the other layout, routing and translation methods in subsequent releases of Qiskit Terra.In order for transpilation with control-flow operations to succeed with a backend, the backend must have the requisite control-flow operations in its stated basis. Qiskit Aer, for example, does this. If you simply want to try out such transpilations, consider overriding the
basis_gates
argument totranspile()
.
The following transpiler passes have all been taught to understand control-flow constructs in the form of
ControlFlowOp
instructions in a circuit:Layout-related
Routing-related
Translation-related
Optimization-related
These passes are most commonly used via the preset pass managers (those used internally by
transpile()
andgenerate_preset_pass_manager()
), but are also available for other uses. These passes will now recurse into control-flow operations where appropriate, updating or analysing the internal blocks.
Added a new
TrotterQRTE
class that implements theRealTimeEvolver
interface that uses anqiskit.primitives.BaseEstimator
to perform the calculation. This new class supersedes the previously availableqiskit.algorithms.TrotterQRTE
class (which will be deprecated and subsequenty removed in future releases) that used aBackend
orQuantumInstance
to perform the calculation.
DAGCircuit.substitute_node_with_dag()
now takespropagate_condition
as a keyword argument. This defaults toTrue
, which was the previous behavior, and copies any condition on the node to be replaced onto every operation node in the replacement. If set toFalse
, the condition will not be copied, which allows replacement of a conditional node with a sub-DAG that already faithfully implements the condition.
DAGCircuit.substitute_node_with_dag()
can now take a mapping for itswires
parameter as well as a sequence. The mapping should map bits in the replacement DAG to the bits in the DAG it is being inserted into. This permits an easier style of construction for callers when the input node has both classical bits and a condition, and the replacement DAG may use these out-of-order.
Added the
qiskit.algorithms.minimum_eigensolvers
package to include interfaces for primitive-enabled algorithms.VQE
has been refactored in this implementation to leverage primitives.To use the new implementation with a reference primitive, one can do, for example:
from qiskit.algorithms.minimum_eigensolvers import VQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp h2_op = SparsePauliOp( ["II", "IZ", "ZI", "ZZ", "XX"], coeffs=[ -1.052373245772859, 0.39793742484318045, -0.39793742484318045, -0.01128010425623538, 0.18093119978423156, ], ) estimator = Estimator() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() vqe = VQE(estimator, ansatz, optimizer) result = vqe.compute_minimum_eigenvalue(h2_op) eigenvalue = result.eigenvalue
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field.
Upgrade Notes¶
For
Target
objects that only contain globally defined 2 qubit operations without any connectivity constaints the return from theTarget.build_coupling_map()
method will now returnNone
instead of aCouplingMap
object that containsnum_qubits
nodes and no edges. This change was made to better reflect the actual connectivity constraints of theTarget
because in this case there are no connectivity constraints on the backend being modeled by theTarget
, not a lack of connecitvity. If you desire the previous behavior for any reason you can reproduce it by checking for aNone
return and manually building a coupling map, for example:from qiskit.transpiler import Target, CouplingMap from qiskit.circuit.library import CXGate target = Target(num_qubits=3) target.add_instruction(CXGate()) cmap = target.build_coupling_map() if cmap is None: cmap = CouplingMap() for i in range(target.num_qubits): cmap.add_physical_qubit(i)
The default value for the
entanglement
keyword argument on the constructor for theRealAmplitudes
andEfficientSU2
classes has changed from"full"
to"reverse_linear"
. This change was made because the output circuit is equivalent but uses only \(n-1\) instead of \(\frac{n(n-1)}{2}\)CXGate
gates. If you desire the previous default you can explicity setentanglement="full"
when calling either constructor.
Added a validation check to
BaseSampler.run()
. It raises an error if there is no classical bit.
Behavior of the
call()
pulse builder function has been upgraded. When aScheduleBlock
instance is called by this method, it internally creates aReference
in the current context, and immediately assigns the called program to the reference. Thus, theCall
instruction is no longer generated. Along with this change, it is prohibited to call different blocks with the samename
argument. Such operation will result in an error.
For most architectures starting in the following release of Qiskit Terra, 0.23, the
tweedledum
package will become an optional dependency, instead of a requirement. This is currently used by some classical phase-oracle functions. If your application or library needs this functionality, you may want to prepare by addingtweedledum
to your package’s dependencies immediately.tweedledum
is no longer a requirement on macOS arm64 (M1) with immediate effect in Qiskit Terra 0.22. This is because the provided wheels for this platform are broken, and building from the sdist is not reliable for most people. If you manually install a working version oftweedledum
, all the dependent functionality will continue to work.
The
._layout
attribute of theQuantumCircuit
object has been changed from storing aLayout
object to storing a data class with 2 attributes,initial_layout
which contains aLayout
object for the initial layout set during compilation andinput_qubit_mapping
which contains a dictionary mapping qubits to position indices in the original circuit. This change was necessary to provide all the information for a post-transpiled circuit to be able to fully reverse the permutation caused by initial layout in all situations. While this attribute is private and shouldn’t be used externally, it is the only way to track the initial layout throughtranspile()
so the change is being documented in case you’re relying on it. If you have a use case for the_layout
attribute that is not being addressed by the Qiskit API please open an issue so we can address this feature gap.
The constructors for the
SetPhase
,ShiftPhase
,SetFrequency
, andShiftFrequency
classes will now raise aPulseError
if the value passed in via thechannel
argument is not an instance ofPulseChannel
. This change was made to validate the input to the constructors are valid as the instructions are only valid for pulse channels and not other types of channels.
The
plot_histogram()
function has been modified to return an actual histogram of discrete binned values. The previous behavior for the function was despite the name to actually generate a visualization of the distribution of the input. Due to this disparity between the name of the function and the behavior the function behavior was changed so it’s actually generating a proper histogram of discrete data now. If you wish to preserve the previous behavior of plotting a probability distribution of the counts data you can leverage theplot_distribution()
to generate an equivalent graph. For example, the previous behavior ofplot_histogram({'00': 512, '11': 500})
can be re-created with:from qiskit.visualization import plot_distribution import matplotlib.pyplot as plt ax = plt.subplot() plot_distribution({'00': 512, '11': 500}, ax=ax) ax.set_ylabel('Probabilities')
Text(0, 0.5, 'Probabilities')
The
qiskit.pulse.builder
contextsinline
andpad
have been removed. These were first deprecated in Terra 0.18.0 (July 2021). There is no replacement forinline
; one can simply write the pulses in the containing scope. Thepad
context manager has had no effect since it was deprecated.
The output from the
SabreSwap
transpiler pass (including whenoptimization_level=3
orrouting_method
orlayout_method
are set to'sabre'
when callingtranspile()
) with a fixed seed value may change from previous releases. This is caused by a new random number generator being used as part of the rewrite of theSabreSwap
pass in Rust which significantly improved the performance. If you rely on having consistent output you can run the pass in an earlier version of Qiskit and leverageqiskit.qpy
to save the circuit and then load it using the current version.
The
Layout.add()
behavior when not specifying aphysical_bit
has changed from previous releases. In previous releases, a new physical bit would be added based on the length of theLayout
object. For example if you had aLayout
with the physical bits 1 and 3 successive calls toadd()
would add physical bits 2, 4, 5, 6, etc. While if the physical bits were 2 and 3 then successive calls would add 4, 5, 6, 7, etc. This has changed so that insteadLayout.add()
will first add any missing physical bits between 0 and the max physical bit contained in theLayout
. So for the 1 and 3 example it now adds 0, 2, 4, 5 and for the 2 and 3 example it adds 0, 1, 4, 5 to theLayout
. This change was made for both increased predictability of the outcome, and also to fix a class of bugs caused by the unexpected behavior. As physical bits on a backend always are contiguous sequences from 0 to \(n\) adding new bits when there are still unused physical bits could potentially cause the layout to use more bits than available on the backend. If you desire the previous behavior, you can specify the desired physical bit manually when callingLayout.add()
.
The deprecated method
SparsePauliOp.table
attribute has been removed. It was originally deprecated in Qiskit Terra 0.19. Instead thepaulis()
method should be used.
Support for returning a
PauliTable
from thepauli_basis()
function has been removed. Similarly, thepauli_list
argument on thepauli_basis()
function which was used to switch to aPauliList
(now the only return type) has been removed. This functionality was deprecated in the Qiskit Terra 0.19 release.
The fake backend objects
FakeJohannesburg
,FakeJohannesburgV2
,FakeAlmaden
,FakeAlmadenV2
,FakeSingapore
, andFakeSingaporeV2
no longer contain the pulse defaults payloads. This means for theBackendV1
based classes theBackendV1.defaults()
method and pulse simulation viaBackendV1.run()
is no longer available. ForBackendV2
based classes thecalibration
property for instructions in theTarget
is no longer populated. This change was done because these systems had exceedingly large pulse defaults payloads (in total ~50MB) due to using sampled waveforms instead of parameteric pulse definitions. These three payload files took > 50% of the disk space required to install qiskit-terra. When weighed against the potential value of being able to compile with pulse awareness or pulse simulate these retired devices the file size is not worth the cost. If you require to leverage these properties you can leverage an older version of Qiskit and leverageqpy
to transfer circuits from older versions of qiskit into the current release.
isinstance
check with pulse classesGaussian
,GaussianSquare
,Drag
andConstant
will be invalidated because these pulse subclasses are no longer instantiated. They will still work in Terra 0.22, but you should begin transitioning immediately. Instead of using type information,SymbolicPulse.pulse_type
should be used. This is assumed to be a unique string identifer for pulse envelopes, and we can use string equality to investigate the pulse types. For example,from qiskit.pulse.library import Gaussian pulse = Gaussian(160, 0.1, 40) if isinstance(pulse, Gaussian): print("This is Gaussian pulse.")
This code should be upgraded to
from qiskit.pulse.library import Gaussian pulse = Gaussian(160, 0.1, 40) if pulse.pulse_type == "Gaussian": print("This is Gaussian pulse.")
With the same reason, the class attributes such as
pulse.__class__.__name__
should not be accessed to get pulse type information.
The exception
qiskit.exceptions.QiskitIndexError
has been removed and no longer exists as per the deprecation notice from qiskit-terra 0.18.0 (released on Jul 12, 2021).
The deprecated arguments
epsilon
andfactr
for the constructor of theL_BFGS_B
optimizer class have been removed. These arguments were originally deprecated as part of the 0.18.0 release (released on July 12, 2021). Instead theftol
argument should be used, you can refer to the scipy docs on the optimizer for more detail on the relationship between these arguments.
The preset pass managers for levels 1 and 2, which will be used when
optimization_level=1
oroptimization_level=2
withtranspile()
orgenerate_preset_pass_manager()
and output fromlevel_1_pass_manager()
andlevel_2_pass_manager()
, will now useSabreLayout
andSabreSwap
by default instead of the previous defaultsDenseLayout
andStochasticSwap
. This change was made to improve the output quality of the transpiler, theSabreLayout
andSabreSwap
combination typically results in fewerSwapGate
objects being inserted into the output circuit. If you would like to use the previous default passes you can setlayout_method='dense'
androuting_method='stochastic'
ontranspile()
orgenerate_preset_pass_manager()
to leverageDenseLayout
andStochasticSwap
respectively.
The implicit use of
approximation_degree!=1.0
by default in in thetranspile()
function whenoptimization_level=3
is set has been disabled. The transpiler should, by default, preserve unitarity of the input up to known transformations such as one-sided permutations and similarity transformations. This was broken by the previous use ofapproximation_degree=None
leading to incorrect results in cases such as Trotterized evolution with many time steps where unitaries were being overly approximated leading to incorrect results. It was decided that transformations that break unitary equivalence should be explicitly activated by the user. If you desire the previous default behavior where synthesizedUnitaryGate
instructions are approximated up to the error rates of the target backend’s native instructions you can explicitly setapproximation_degree=None
when callingtranspile()
withoptimization_level=3
, for example:transpile(circuit, backend, approximation_degree=None, optimization_level=3)
Change the default of maximum number of allowed function evaluations (
maxfun
) inL_BFGS_B
from 1000 to 15000 to match the SciPy default. This number also matches the default number of iterations (maxiter
).
Updated
ProbDistribution
andQuasiDistribution
to store the information of the number of bits if bitstrings without prefix « 0b » are given.ProbDistribution.binary_probabilities()
andQuasiDistribution.binary_probabilities()
use the stored number of bits as the default value of the number of bits.
RZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
have been upgraded to skip stretching CX gates implemented by non-echoed cross resonance (ECR) sequence to avoid termination of the pass with unexpected errors. These passes take new argumentverbose
that controls whether the passes warn when this occurs. Ifverbose=True
is set, pass raises user warning when it enconters non-ECR sequence.
The visualization module
qiskit.visualization
has seen some internal reorganisation. This should not have affected the public interface, but if you were accessing any internals of the circuit drawers, they may now be in different places. The only parts of the visualization module that are considered public are the components that are documented in this online documentation.
Deprecation Notes¶
Importing the names
Int1
,Int2
,classical_function
andBooleanExpression
directly fromqiskit.circuit
is deprecated. This is part of the move to maketweedledum
an optional dependency rather than a full requirement. Instead, you should import these names fromqiskit.circuit.classicalfunction
.
Modules
qiskit.algorithms.factorizers
andqiskit.algorithms.linear_solvers
are deprecated and will be removed in a future release. They are replaced by tutorials in the Qiskit Textbook: Shor HHL
The
random_stabilizer_table()
has been deprecated and will be removed in a future release. Instead therandom_pauli_list()
function should be used.
The pulse-module function
qiskit.pulse.utils.deprecated_functionality
is deprecated and will be removed in a future release. This was a primarily internal-only function. The same functionality is supplied byqiskit.utils.deprecate_function
, which should be used instead.
The method of executing primitives has been changed. The
BaseSampler.__call__()
andBaseEstimator.__call__()
methods were deprecated. For example:estimator = Estimator(...) result = estimator(circuits, observables, parameters) sampler = Sampler(...) result = sampler(circuits, observables, parameters)
should be rewritten as
estimator = Estimator() result = estimator.run(circuits, observables, parameter_values).result() sampler = Sampler() result = sampler.run(circuits, parameter_values).result()
Using primitives as context managers is deprecated. Not all primitives have a context manager available. When available (e.g. in
qiskit-ibm-runtime
), the session’s context manager provides equivalent functionality.circuits
,observables
, andparameters
in the constructor was deprecated.circuits
andobservables
can be passed fromrun
methods.run
methods do not supportparameters
. Users need to resort parameter values by themselves.
The unused argument
qubit_channel_mapping
in theRZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
transpiler passes have been deprecated and will be removed in a future release. This argument is no longer used and has no effect on the operation of the passes.
Bug Fixes¶
Fixed an issue where
Pauli.evolve()
andPauliList.evolve()
would raise a dtype error when evolving by certain Clifford gates which modified the Pauli’s phase. Fixed #8438
Fixed a bug in
QuantumCircuit.initialize()
andQuantumCircuit.prepare_state()
that caused them to not accept a singleQubit
as argument to initialize.
The method
QuantumCircuit.while_loop()
will now resolve classical bit references in its condition in the same way thatQuantumCircuit.if_test()
andInstructionSet.c_if()
do.
The
DAGCircuit
methodsdepth()
,size()
andDAGCircuit.count_ops()
would previously silently return results that had little-to-no meaning if control-flow was present in the circuit. Thedepth()
andsize()
methods will now correctly throw an error in these cases, but have a newrecurse
keyword argument to allow the calculation of a proxy value, whilecount_ops()
will by default recurse into the blocks and count the operations within them.
Fixed an issue in the
DenseLayout
transpiler pass where any looseQubit
objects (i.e. not part of aQuantumRegister
) that were part of aQuantumCircuit
would not be included in the outputLayout
that was generated by the pass.
The
Operator.from_circuit()
constructor method has been updated so that it can handle the layout output fromtranspile()
and correctly reverse the qubit permutation caused by layout in all cases. Previously, if your transpiled circuit used looseQubit
objects, multipleQuantumRegister
objects, or a singleQuantumRegister
with a name other than"q"
the constructor would have failed to create anOperator
from the circuit. Fixed #8800.
Fixed a bug where decomposing an instruction with one qubit and one classical bit containing a single quantum gate failed. Now the following decomposes as expected:
block = QuantumCircuit(1, 1) block.h(0) circuit = QuantumCircuit(1, 1) circuit.append(block, [0], [0]) decomposed = circuit.decompose()
Fixed initialization of empty symplectic matrix in
from_symplectic()
inPauliList
class For example:from qiskit.quantum_info.operators import PauliList x = np.array([], dtype=bool).reshape((1,0)) z = np.array([], dtype=bool).reshape((1,0)) pauli_list = PauliList.from_symplectic(x, z)
Fix a problem in the
GateDirection
transpiler pass for theCZGate
. The CZ gate is symmetric, so flipping the qubit arguments is allowed to match the directed coupling map.
Fixed issues with the
DerivativeBase.gradient_wrapper()
method when reusing a circuit sampler between the calls and binding nested parameters.
Fixed an issue in the
mpl
andlatex
circuit drawers, when setting theidle_wires
option to False when there was abarrier
in the circuit would cause the drawers to fail, has been fixed. Fixed #8313
Fixed an issue in
circuit_drawer()
andQuantumCircuit.draw()
with thelatex
method where anOSError
would be raised on systems whose temporary directories (e.g/tmp
) are on a different filesystem than the working directory. Fixes #8542
Nesting a
FlowController
inside another in aPassManager
could previously cause some transpiler passes to become « forgotten » during transpilation, if the passes returned a newDAGCircuit
rather than mutating their input. NestedFlowController
s will now affect the transpilation correctly.
Comparing
QuantumCircuit
andDAGCircuit
s for equality was previously non-deterministic if the circuits contained more than one register of the same type (e.g. two or moreQuantumRegister
s), sometimes returningFalse
even if the registers were identical. It will now correctly compare circuits with multiple registers.
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will now correctly define the qubit parameters forUnitaryGate
operations that do not affect all the qubits they are defined over. Fixed #8224.
There were two bugs in the
text
circuit drawer that were fixed. These appeared whenvertical_compression
was set tomedium
, which is the default. The first would sometimes cause text to overwrite other text or gates, and the second would sometimes cause the connections between a gate and its controls to break. See #8588.
Fixed an issue with the
UnitarySynthesis
pass where a circuit with 1 qubit gates and aTarget
input would sometimes fail instead of processing the circuit as expected.
The
GateDirection
transpiler pass will now respect the available values for gate parameters when handling parametrised gates with aTarget
.
Fixed an issue in the
SNOBFIT
optimizer class when an internal error would be raised during the execution of theminimize()
method if no input bounds where specified. This is now checked at call time to quickly raise aValueError
if required bounds are missing from theminimize()
call. Fixes #8580
Fixed an issue in the output callable from the
get_energy_evaluation()
method of theVQD
class will now correctly call the specifiedcallback
when run. Previously the callback would incorrectly not be used in this case. Fixed #8575
Fixed an issue when
circuit_drawer()
was used withreverse_bits=True
on a circuit without classical bits that would cause a potentially confusing warning aboutcregbundle
to be emitted. Fixed #8690
The OpenQASM 3 exporter (
qiskit.qasm3
) will now correctly handle OpenQASM built-ins (such asreset
andmeasure
) that have a classical condition applied byc_if()
. Previously the condition would have been ignored.
Fixed an issue with the
SPSA
class where internally it was trying to batch jobs into even sized batches which would raise an exception if creating even batches was not possible. This has been fixed so it will always batch jobs successfully even if they’re not evenly sized.
Fixed the behavior of
Layout.add()
which was potentially causing the output oftranspile()
to be invalid and contain more Qubits than what was available on the target backend. Fixed: #8667
Fixed an issue with the
state_to_latex()
function: passing a latex string to the optionalprefix
argument of the function would raise an error. Fixed #8460
The function
state_to_latex()
produced not valid LaTeX in presence of close-to-zero values, resulting in errors whenstate_drawer()
is called. Fixed #8169.
GradientDescent
will now correctly count the number of iterations, function evaluations and gradient evaluations. Also the documentation now correctly states that the gradient is approximated by a forward finite difference method.
Fix deprecation warnings in
NaturalGradient
, which now uses theStandardScaler
to scale the data before fitting the model if thenormalize
parameter is set toTrue
.
Aer 0.11.0¶
No change
IBM Q Provider 0.19.2¶
No change
Qiskit 0.38.0¶
Terra 0.21.2¶
No change
Aer 0.11.0¶
Prelude¶
The Qiskit Aer 0.11.0 release highlights are:
The migration to a new self-contained Python namespace
qiskit_aer
The introduction of the
AerStatevector
classThe introduction of Aer implementations of
primitives
,Sampler
andEstimator
Introduction of support for running with cuQuantum
New Features¶
Added support for
BackendV2
tofrom_backend()
. Now it can generate aNoiseModel
object from an inputBackendV2
instance. When aBackendV2
input is used onfrom_backend()
the two deprecated options,standard_gates
andwarnings
, are gracefully ignored.
Added Aer implementation of
primitives
,Sampler
andBaseSampler
andBaseEstimator
interfaces leverage qiskit aer to efficiently perform the computation of the primitive operations. You can refer to theqiskit.primitives
docs for a more detailed description of the primitives API.
Added a shared library to Qiskit Aer that allows external programs to use Aer’s simulation methods. This is an experimental feature and its API may be changed without the deprecation period.
Added support for M1 macOS systems. Precompiled binaries for supported Python versions >=3.8 on arm64 macOS will now be published on PyPI for this and future releases.
Added support for cuQuantum, NVIDIA’s APIs for quantum computing, to accelerate statevector, density matrix and unitary simulators by using GPUs. This is experiemental implementation for cuQuantum Beta 2. (0.1.0) cuStateVec APIs are enabled to accelerate instead of Aer’s implementations by building Aer by setting path of cuQuantum to
CUSTATEVEC_ROOT
. (binary distribution is not available currently.) cuStateVector is enabled by settingdevice='GPU'
andcuStateVec_threshold
options. cuStateVec is enabled when number of qubits of input circuit is equal or greater thancuStateVec_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.
Upgrade Notes¶
MPI parallelization for large number of qubits is optimized to apply multiple chunk-swaps as all-to-all communication that can decrease data size exchanged over MPI processes. This upgrade improve scalability of parallelization.
Set default
fusion_max_qubit
andfusion_threshold
depending on the configuredmethod
forAerSimulator
. Previously, the default values offusion_max_qubit
andfusion_threshold
were5
and14
respectively for all simulation methods. However, their optimal values depend on running methods. If you depended on the previous defaults you can explicitly setfusion_max_qubit=5
orfusion_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 withqiskit-terra
by beingqiskit.providers.aer
. This was problematic for several reasons, and this release moves away from it. For the time beingimport qiskit.providers.aer
will continue to work and redirect toqiskit_aer
automatically. Imports from the legacyqiskit.provider.aer
namespace will emit aDeprecationWarning
in the future. To avoid any potential issues starting with this release, updating all imports fromqiskit.providers.aer
toqiskit_aer
and fromqiskit.Aer
toqiskit_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 asSaveStatevector
).
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.
IBM Q Provider 0.19.2¶
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 inQuantumInstance
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 theinplace=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 ifsymengine
was installed and the bound expression was not a plain1j
. 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 whosectrl_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 ofdrive_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.
Aer 0.10.4¶
No change
IBM Q Provider 0.19.2¶
No change
Qiskit 0.37.1¶
Terra 0.21.1¶
Bug Fixes¶
Fixed an issue in
QuantumCircuit.decompose()
method when passing in a list ofGate
classes for thegates_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 thegates_to_decompose
list.
Fix
to_instruction()
which previously tried to create aUnitaryGate
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]])] )
Fixed an issue with the
marginal_distribution()
function: when a numpy array was passed in for theindices
argument the function would raise an error. Fixed #8283
Previously it was not possible to adjoint a
CircuitStateFn
that has been constructed from aVectorStateFn
. That’s because the statevector has been converted to a circuit with theInitialize
instruction, which is not unitary. This problem is now fixed by instead using theStatePreparation
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 exisitingsettings
reset both the new and previous optimizer settings to the defaults. This notably led to a bug ifOptimizer
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 individualSymbolicPulse
orWaveform
instance was not properly reflected by parameter validation. In addition, QPY scheduledump()
has been fixed to correctly store thelimit_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 theZZFeatureMap
, where usingentanglement="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.
Aer 0.10.4¶
No change
IBM Q Provider 0.19.2¶
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:
Support for serialization of a pulse
ScheduleBlock
viaqiskit.qpy
. The QPY Format has been updated to version 5 which includes a definition for including the pulse schedules. To support this, a newSymbolicPulse
class was introduced to enable defining parametric pulse waveforms via symbolic expressions.Improvements to working with preset pass managers. A new function
generate_preset_pass_manager()
enables easily generating a pass manager equivalent to whattranspile()
will use internally. Additionally, preset pass managers are now instances ofStagedPassManager
which makes it easier to modify sections.A refactor of the internal data structure of the
QuantumCircuit.data
attribute. It previously was a list of tuples in the form(instruction, qubits, clbits)
and now is a list ofCircuitInstruction
objects. TheCircuitInstruction
objects is backwards compatible with the previous tuple based access, however with runtime overhead cost.
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 aPassManager
subclass that has a pipeline with defined phases to perform circuit compilation. Each phase is aPassManager
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()
andSparsePauliOp.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 a new function,
marginal_distribution()
, which is used to marginalize an input dictionary of bitstrings to an integer (such asCounts
). This is similar in functionality to the existingmarginal_counts()
function with three key differences. The first is thatmarginal_counts()
works with either a counts dictionary or aResults
object whilemarginal_distribution()
only works with a dictionary. The second is thatmarginal_counts()
does not respect the order of indices in itsindices
argument whilemarginal_distribution()
does and will permute the output bits based on theindices
order. The third difference is thatmarginal_distribution()
should be faster as its implementation is written in Rust and streamlined for just marginalizing a dictionary input.
Added the
@
(__matmul__
) binary operator toBaseOperator
subclasses in theqiskit.quantum_info
module. This is shorthand to call the classes”dot
method (A @ B == A.dot(B)
).
Added a new optional argument,
reps
, toQuantumCircuit.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 conventionalParametricPulse
, 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 asQEOM
.
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.clear()
which is used to remove all instructions from aQuantumCircuit
.
Added a new method
QuantumCircuit.copy_empty_like()
which is used to get a cleared copy of aQuantumCircuit
instance. This is logically equivalent toqc.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
andparameters
. Using these arguments theinstruction_supported()
method can now be used for checking that a specific operation with parameter values are supported by aTarget
object. For example, if you want to check if aTarget
namedtarget
supports running aRXGate
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
iftarget
supports runningRXGate
with \(\theta = \frac{\pi}{2}\) andFalse
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 theProductFormula
andPauliEvolutionGate
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
generate_preset_pass_manager()
which can be used to quickly generate a presetPassManager
object that mirrors thePassManager
used internally by thetranspile()
function. For example:from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.providers.fake_provider import FakeWashingtonV2 # Generate an optimization level 3 pass manager targeting FakeWashingtonV2 pass_manager = generate_preset_pass_manager(3, FakeWashingtonV2())
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 themarginal_counts()
method which only works on thememory
field in aResults
object.
The primitives interface has been extended to accept objects in addition to indices as arguments to the
__call__
method. Theparameter_values
argument can now be optional.
The OpenQASM 3 exporter (
qiskit.qasm3
) now supports exporting circuits with explicit delays, such as fromQuantumCircuit.delay()
.
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. Therouting_method
kwarg oftranspile()
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 aUnitaryGate
.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 bytranspile()
whenrouting_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 likeSabreSwap
(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 passFindCommutingPauliEvolutions
identifies blocks of Pauli evolutions made of commuting two-qubit terms. Here, a swap strategy is specified by the classSwapStrategy
. 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
andbasis_gates
. These options enable you to specify theTarget
or supported basis gates respectively to describe the target backend. If any of the operations in the circuit are in thetarget
orbasis_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: new_schedule = qpy.load(fd)[0]
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 thepost_layout
field is present (in addition to the requiredlayout
field) theproperty_set
when theApplyLayout
pass is run the pass will update the layout to apply the new layout. This will return aDAGCircuit
with the qubits in the new physical order and thelayout
property set will be updated so that it maps the virtual qubits from the original layout to the physical qubits in the newpost_layout
field.
The preset pass managers generated by
level_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
which correspond tooptimization_level
1, 2, and 3 respectively on thetranspile()
function now run theVF2PostLayout
pass after running the routing pass. This enables the transpiler to potentially find a different set of physical qubits on the target backend to run the circuit on which have lower error rates. TheVF2PostLayout
pass will not be run if you manually specify alayout_method
,routing_method
, orinitial_layout
arguments totranspile()
. If the pass can find a better performing subset of qubits on backend to run the physical circuit it will adjust the layout of the circuit to use the alternative qubits instead.
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.
Upgrade Notes¶
The pulse classes in
qiskit.pulse.library
are now subclasses ofSymbolicPulse
rather thanParametricPulse
. The available classes remain unchanged asGaussian
,GaussianSquare
,Drag
, andConstant
.SymbolicPulse
has full backward compatibility, and there should be no loss of functionality.
The data type of each element in
QuantumCircuit.data
has changed. It used to be a simple 3-tuple of anInstruction
, a list ofQubit
s, and a list ofClbit
s, whereas it is now an instance ofCircuitInstruction
.The attributes of this new class are
operation
,qubits
andclbits
, corresponding to the elements of the previous tuple. However,qubits
andclbits
are nowtuple
instances, notlist
s.This new class will behave exactly like the old 3-tuple if one attempts to access its index its elements, or iterate through it. This includes casting the
qubits
andclbits
elements to lists. This is to assist backwards compatibility. Starting from Qiskit Terra 0.21, this is no longer the preferred way to access these elements. Instead, you should use the attribute-access form described above.This has been done to allow further developments of the
QuantumCircuit
data structure in Terra, without constantly breaking backwards compatibility. Planned developments include dynamic parameterized circuits, and an overall reduction in memory usage of deep circuits.
The
python-constraint
dependency, which is used solely by theCSPLayout
transpiler pass, is no longer in the requirements list for the Qiskit Terra package. This is because theCSPLayout
pass is no longer used by default in any of the preset pass managers fortranspile()
. While the pass is still available, if you’re using it you will need to manually installpython-contraint
or when you installqiskit-terra
you can use thecsp-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
, andBaseProvider
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 beingBackendV2
,JobV1
, andProviderV1
.
The previously deprecated
backend
argument for the constructor of theRZXCalibrationBuilder
transpiler pass has been removed. It was originally deprecated in the 0.19.0 release. Instead you should query theBackend
object for theinstruction_schedule_map
andqubit_channel_mapping
and pass that directly to the constructor. For example, with aBackendV1
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 deprecatedtype
,op
,qargs
,cargs
, andwire
kwargs and attributes have been removed. These were originally deprecated in the 0.19.0 release. Theop
,qargs
, andcargs
kwargs and attributes can be accessed only on instances ofDAGOpNode
, and thewire
kwarg and attribute are only on instances ofDAGInNode
orDAGOutNode
.
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()
orPauli.dot()
instead.to_spmatrix
Use
Pauli.to_matrix()
with argumentsparse=True
instead.kron
Use
Pauli.expand()
, but beware that this returns a new object, rather than mutating the existing one.update_z
andupdate_x
Set the
z
andx
attributes of the object directly.insert_paulis
Use
Pauli.insert()
.append_paulis
Use
Pauli.expand()
.delete_qubits
Use
Pauli.delete()
.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.
Removed the
optimize
method from theOptimizer
classes, which is superseded by theminimize()
method as direct replacement. The one exception isSPSA
, where the deprecation warning was not triggered so the method there is still kept.
Result
was modified so that it always containsdate
,status
, andheader
attributes (set toNone
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.
Instruction
labels are now type-checked on instruction creation.
QPY serialization has been upgraded to serialize
QuantumCircuit
withQuantumCircuit.calibrations
. As of QPY Version 5, only calibration entries ofScheduleBlock
type can be serialized.
The definition of
XXPlusYYGate
has been changed. See #7969 for details.
The preset pass managers generated by
level_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
and used by thetranspile()
function’soptimization_level
argument at 1, 2, and 3 respectively no longer set a hard time limit on theVF2Layout
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 customPassManager
that sets thetime_limit
argument on the constructor for theVF2Layout
pass.
Deprecation Notes¶
Calling
timeline_drawer()
with an unscheduled circuit has been deprecated. All circuits, even one consisting only of delay instructions, must be transpiled with thescheduling_method
keyword argument oftranspile()
set, to generate schedule information being stored inQuantumCircuit.op_start_times
.
The NetworkX converter functions for the
DAGCircuit.to_networkx()
andfrom_networkx()
, along with theDAGDependency.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 theDAGCircuit
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
andHAS_PIL
) from theqiskit.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 throughqiskit.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 inqiskit.test.mock
have been accessible inqiskit.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
orSampler
object as a function are renamed fromcircuit_indices
andobservable_indices
tocircuits
andobservables
.
The
qobj_id
andqobj_header
keyword arguments for theexecute()
function have been deprecated and will be removed in a future release. Since the removal of theBaseBackend
class these arguments don’t have any effect as no backend supports execution with aQobj
object directly and instead only work withQuantumCircuit
objects directly.
The arguments
x
,z
andlabel
to the initializer ofPauli
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 ofx
andz
should be passed positionally as a single tuple (Pauli((z, x))
). A stringlabel
should be passed positionally in the first argument (Pauli("XYZ")
).
The
SPSA.optimize()
method is deprecated in favor ofSPSA.minimize()
, which can be used as direct replacement. Note that this method returns a complete result object with more information than before available.
The
circuits
argument ofqpy.dump()
has been deprecated and replaced withprograms
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 argumentdo_checks=False
.
The
timeline_drawer()
visualization will no longer misalign classical register slots.
Parameter validation for
GaussianSquare
is now consistent before and after construction. Refer to #7882 for more details.
The
BackendV2
-based fake backends in theqiskit.providers.fake_provider
module, such asFakeMontrealV2
, now support theDelay
operation in theirtarget
attributes. Previously,QuantumCircuit
objects that contained delays could not be compiled to these backends.
Fixed a bug in
TridiagonalToeplitz.eigs_bounds()
, which caused incorrect eigenvalue bounds to be returned in some cases with negative eigenvalues. Refer to #7939 for more details.
Fixed a bug in which the LaTeX statevector drawer ignored the
max_size
parameter.
Fixed support in the
PassManagerConfig.from_backend()
constructor method for building aPassManagerConfig
object from aBackendV2
instance. Previously this wasn’t handled correctly and would fail when running with aBackendV2
object.
Fixed support for QPY serialization (
qpy.dump()
) and deserialization (qpy.load()
) of aQuantumCircuit
object containing customControlledGate
objects. Previously, an exception would be raised byqpy.load()
when trying to reconstruct the customControlledGate
. Fixed #7999.
Fixed support for QPY serialization (
qpy.dump()
) and deserialization (qpy.load()
) of aQuantumCircuit
object containing customMCPhaseGate
objects. Previously, an exception would be raised byqpy.load()
when trying to reconstruct theMCPhaseGate
.
Fixed support for QPY serialization (
qpy.dump()
) and deserialization (qpy.load()
) of aQuantumCircuit
object containing controlled gates with an open control state. Previously, the open control state would be lost by the serialization process and the reconstructed circuit.
Fixed
QuantumCircuit.reverse_bits()
with circuits containing registerlessQubit
andClbit
. For example, the following will now work:from qiskit.circuit import QuantumCircuit, Qubit, Clbit qc = QuantumCircuit([Qubit(), Clbit()]) qc.h(0).c_if(qc.clbits[0], 0) qc.reverse_bits()
Fixed the
ConfigurableFakeBackend.t2
attribute, which was previously incorrectly set based on the providedt1
value.
Fixed an issue with
BackendV2
-based fake backend classes from theqiskit.providers.fake_provider
module such asFakeMontrealV2
where the value for thedt
attribute (and theTarget.dt
attribute) were not properly being converted to seconds. This would cause issues when using these fake backends with scheduling.
Fixed a bug in
plot_histogram()
when thenumber_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 thebasis_gates
option.
Fixed the getter of
OptimizerResult.nit
, which previously returned the number of Jacobian evaluations instead of the number of iterations.
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 thebasis_gates
keyword argument or implicitly via aTarget
input via thetarget
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 aTarget
that didn’t have any qubit restrictions on the operations (e.g. in the case of an ideal simulator target) was specified with thetarget
keyword argument for the constructor.
The method
qiskit.result.marginal_counts()
, when passed aResult
from a pulse backend, would fail, because it contains an array ofExperimentResult
objects, each of which have anQobjExperimentHeader
, and thoseExperimentHeaders
lack creg_sizes instance-variables. If theResult
came from a simulator backend (e.g. Aer), that instance-variable would be there. We fixmarginal_counts
so that it skips logic that needs creg_sizes if the field is not present, or non-None.
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will now correctly define the qubit parameters forUnitaryGate
operations that do not affect all the qubits they are defined over. Fixed #8224.
Fixed an issue with reproducibility of the
transpile()
function when running withoptimization_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 theseed_transpiler
argument was set.
Aer 0.10.4¶
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
andnotifyAll
were deprecated in Python 3.10 (October 2021) and will be removed in Python 3.12 (October 2023). PR #1133 replaces them withthreading.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 theqiskit.providers.fake_provider
module such asFakeMontrealV2
, where the values for thedtm
anddt
attributes and the associated attributeTarget.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 anindices
parameter containing non-zero elements. Previously, shots whose hexadecimal result representation was sufficiently small could raise aValueError
. See #8044.
The OpenQASM 3 exporter (
qiskit.qasm3
) will now outputinput
oroutput
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 aBackendV2
-based backend and setting thescheduling_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.
Fixed a bug in the
RZXCalibrationBuilder
transpiler pass that was causing pulses to sometimes be constructed with incorrect durations. See #7994.
The
SabreSwap
transpiler pass, used intranspile()
whenrouting_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 asfor coefficient in statevector
) and correctly report its length underlen
. Previously it would try and and access out-of-bounds data and raise aQiskitError
. See #8039.
Aer 0.10.4¶
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.
IBM Q Provider 0.19.1¶
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¶
QPY deserialization with the
qpy.load()
function of a directly instantiatedUCPauliRotGate
object in a circuit will fail because the rotation axis argument to the class isn’t stored in a standard place. To workaround this you can instead use the subclasses:UCRXGate
,UCRYGate
, orUCRZGate
(based on whether you’re using a rotation axis of"X"
,"Y"
, or"Z"
respectively) which embeds the rotation axis in the class constructor and will work correctly in QPY.
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, norXXMinusYYGate
.
Bug Fixes¶
Fixed
Clifford
,Pauli
andCNOTDihedral
operator initialization from compatible circuits that containDelay
instructions. These instructions are treated as identities when converting to operators.
Fixed an issue where the
eval_observables()
function would raise an error if itsquantum_state
argument was of typeStateFn
.eval_observables
now correctly supports all input types denoted by its type hints.
Fixed an issue with the visualization function
dag_drawer()
and methodDAGCircuit.draw()
where previously the drawer would fail when attempting to generate a visualization for aDAGCircuit
object that contained aQubit
orClbit
which wasn’t part of aQuantumRegister
orClassicalRegister
. Fixed #7915.
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.
The
QuantumInstance
class used by many algorithms (likeVQE
) was hard-coding the value for a sleep while it looped waiting for the job status to be updated. It now respects the configured sleep value as set per thewait
attribute in the initializer ofQuantumInstance
.
Fixed an issue with the
schedule
function where callers specifying alist
ofQuantumCircuit
objects with a single entry would incorrectly be returned a singleSchedule
object instead of alist
.
Fixed an issue with the
plot_error_map
visualization function which prevented it from working when run with a backend that had readout error defined in the provided backend’sBackendProperties
or when running with aBackendV2
backend. Fixed #7879.
Fixed a bug that could result in exponential runtime and nontermination when a
Pauli
instance is given to methodinit_observables()
.
Fixed
SabreSwap
, and by extensiontranspile()
withoptimization_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 extensionSabreLayout
andtranspile()
atoptimization_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.
Fixed an issue with QPY deserialization via the
qpy.load()
function of theUCRXGate
,UCRYGate
, andUCRZGate
classes. Previously, a QPY file that contained any of these gates would error when trying to load the file. Fixed #7847.
Aer 0.10.4¶
No change
Ignis 0.7.0¶
No change
IBM Q Provider 0.19.1¶
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¶
Terra 0.20.0¶
No change
Aer 0.10.4¶
Upgrade Notes¶
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. Themetadata
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 theQuantumCircuit.metadata
attribute is not used to run the simulation so now the contents are no serialized and instead are directly attached to theqiskit.result.Result
object without attempting to JSON serialize the contents. Fixed #1435
Ignis 0.7.0¶
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 theqiskit.providers.ibmq.runtime.IBMRuntimeService.run()
method.
Upgrade Notes¶
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.
Deprecation Notes¶
The
image
keyword in theqiskit.providers.ibmq.runtime.IBMRuntimeService.run()
method is deprecated. You should instead specify the image to use in theoptions
keyword.
Bug Fixes¶
Fixes issue #190. Now
qiskit.providers.ibmq.runtime.RuntimeEncoder
andqiskit.providers.ibmq.runtime.RuntimeDecoder
have been updated to handle instances of the Instruction class.Fixes issue #74 where numpy ndarrays with object types could not be serialized.
qiskit.providers.ibmq.runtime.RuntimeEncoder
andqiskit.providers.ibmq.runtime.RuntimeDecoder
have been updated to handle these ndarrays.
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 aTarget
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 fromQuantumCircuit
and using backends. For example, theBaseEstimator
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, theBaseSampler
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 newOperator
object from aQuantumCircuit
. While this was possible normally using the default constructor, theOperator.from_circuit()
method provides additional options to adjust how the operator is created. Primarily this lets you permute the qubit order based on a setLayout
. 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 byOperator(circuit)
before transpilation.
Added a new method
DAGCircuit.copy_empty_like()
to theDAGCircuit
class. This method is used to create a new copy of an existingDAGCircuit
object with the same structure but empty of any instructions. This method is the same as the private method_copy_circuit_metadata()
, but instead is now part of the public API of the class.
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 moduleqiskit.test.mock
which will be deprecated in Qiskit 0.21.0.
Added a new gate class,
LinearFunction
, that efficiently encodes a linear function (i.e. a function that can be represented by a sequence ofCXGate
andSwapGate
gates).
Added a new transpiler pass
CollectLinearFunctions
that collects blocks of consecutiveCXGate
andSwapGate
gates in a circuit, and replaces each block with aLinearFunction
gate.
Added a new transpiler pass
LinearFunctionsSynthesis
that synthesizes anyLinearFunction
gates in using the Patel-Markov-Hayes algorithm. When combined with theCollectLinearFunctions
transpiler pass this enables to collect blocks of consecutiveCXGate
andSwapGate
gates in a circuit, and re-synthesize them using the Patel-Markov-Hayes algorithm.
Added a new transpiler pass
LinearFunctionsToPermutations
that replaces aLinearFunction
gate by aPermutation
circuit whenever possible.
FlowController
classes (such asConditionalController
) can now be nested inside aPassManager
instance when using thePassManager.append()
method. This enables the use of nested logic to control the execution of passes in thePassManager
. 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 theBasisTranslator
pass (in theunroll
step) in each loop iteration if theunroll_condition
is met.
The constructors for the
ZFeatureMap
andZZFeatureMap
classes have a new keyword argumentparameter_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 withGate
objects that haveParameterExpression
parameters. An illustrative example of usingParameter
s withTemplateOptimization
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) # Add the calibrations 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
DAGOpNode
,DAGInNode
andDAGOutNode
classes now define a custom__repr__
method which outputs a representation. Per the Python documentation the output is a string representation that is roughly equivalent to the Python string used to create an equivalent object.
The performance of the
SparsePauliOp.simplify()
method has greatly improved by replacing the use ofnumpy.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 theSparsePauliOp
class for testing the equivalence of aSparsePauliOp
with anotherSparsePauliOp
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 aTarget
for each backend.BackendV2
based versions of all the existing backends are added except for three old backendsFakeRueschlikon
,FakeTenerife
andFakeTokyo
as they do not have snapshots files available which are required for creating a new fake backend class based onBackendV2
.These new V2 fake backends will enable testing and development of new features introduced by
BackendV2
andTarget
such as improving the transpiler.
Added a new gate class
XXMinusYYGate
to the circuit library (qiskit.circuit.library
) for the XX-YY interaction. This gate can be used to implement the bSwap gate and its powers. It also arises in the simulation of superconducting fermionic models.
Added new gate class,
XXPlusYYGate
, to the circuit library (qiskit.circuit.library
). This gate is a 2-qubit parameterized XX+YY interaction, also known as an XY gate, and is based on the gate described in https://arxiv.org/abs/1912.04424.
The
FakeBogota
,FakeManila
,FakeRome
, andFakeSantiago
fake backends which can be found in theqiskit.providers.fake_provider
module can now be used as backends in Pulse experiments as they now include aPulseDefaults
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 aTarget
object representing the compilation target for the pass. If it is specified it supersedes thebasis_gates
kwarg. If a target is specified, the pass will respect the gates and qubits for the instructions defined in theTarget
when deciding which gates to consolidate into a unitary.
The
Target
class has a new method,instruction_supported()
which is used to query the target to see if an instruction (the combination of an operation and the qubit(s) it is executed on) is supported on the backend modelled by theTarget
.
Added a new kwarg,
metadata_serializer
, to theqpy.dump()
function for specifying a customJSONEncoder
subclass for use when serializing theQuantumCircuit.metadata
attribute and a dual kwargmetadata_deserializer
to theqpy.load()
function for specifying aJSONDecoder
subclass. By default thedump()
andload()
functions will attempt to JSON serialize and deserialize with the stdlib default json encoder and decoder. SinceQuantumCircuit.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 newmetadata_serializer
argument fordump()
enables users to specify a customJSONEncoder
that will be used with the internaljson.dump()
call for serializing theQuantumCircuit.metadata
dictionary. This can then be paired with the newmetadata_deserializer
argument of theqpy.load()
function to decode those custom JSON encodings. Ifmetadata_serializer
is specified ondump()
butmetadata_deserializer
is not specified onload()
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()] circuits[0].metadata = {"key": CustomObject("Circuit 1")} circuits[1].metadata = {"key": CustomObject("Circuit 2")} with io.BytesIO() as qpy_buf: dump(circuits, qpy_buf, metadata_serializer=CustomSerializer) qpy_buf.seek(0) new_circuits = load(qpy_buf, metadata_deserializer=CustomDeserializer)
The
DenseLayout
pass has a new keyword argument on its constructor,target
. This argument is used to specify aTarget
object representing the compilation target for the pass. If it is specified it supersedes the other arguments on the constructor,coupling_map
andbackend_prop
.
The
Target
class has a new method,operation_names_for_qargs()
. This method is used to get the operation names (i.e. lookup key in the target) for the operations on a givenqargs
tuple.
A new pass
DynamicalDecouplingPadding
has been added to theqiskit.transpiler.passes
module. This new pass supersedes the existingDynamicalDecoupling
pass to work with the new scheduling workflow in the transpiler. It is a subclass of theBasePadding
pass and depends on having scheduling and alignment analysis passes run prior to it in aPassManager
. This new pass can take apulse_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 inBackendConfiguration.timing_constraints
. Additionally the pass also has anextra_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 tomiddle
which is identical to conventional behavior. The new strategysplit_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 whenpulse_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 theSparsePauliOp
class that truncates real and imaginary parts of coefficients individually. This is different from theSparsePauliOp.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 a new kwarg,
target
, to the constructor for theGatesInBasis
transpiler pass. This new argument can be used to optionally specify aTarget
object that represents the backend. When set thisTarget
will be used for determining whether aDAGCircuit
contains gates outside the basis set and thebasis_gates
argument will not be used.
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
andQFI
classes can now calculate the imaginary part of expectation value gradients. When using a different measurement basis, i.e.-Y
instead ofZ
, we can measure the imaginary part of gradients The measurement basis can be set with theaux_meas_op
argument.For the gradients,
aux_meas_op = Z
computes0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]
andaux_meas_op = -Y
computes0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]
. For the QFIs,aux_meas_op = Z
computes4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]
andaux_meas_op = -Y
computes4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]
. For example:from qiskit import QuantumRegister, QuantumCircuit from qiskit.opflow import CircuitStateFn, Y from qiskit.opflow.gradients.circuit_gradients import LinComb 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 prob_grad = LinComb(aux_meas_op=aux_meas_op).convert(operator=op, params=params)
The
InstructionDurations
class now has support for working with parameters of an instruction. Each entry in anInstructionDurations
object now consists of a tuple of(inst_name, qubits, duration, parameters, unit)
. This enables anInstructionDurations
to define durations for an instruction given a certain parameter value to account for different durations with different parameter values on an instruction that takes a numeric parameter.
Added a new value for the
style
keyword argument on the circuit drawer functioncircuit_drawer()
andQuantumCircuit.draw()
method,iqx_dark
. Whenstyle
is set toiqx_dark
with thempl
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 ofmatplotlib
by askingif 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 thememory
field of an inputResult
object. For example, if the inputresult
argument is a qiskitResult
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 extensiontranspile()
when run withoptimization_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 theRAYON_NUM_THREADS
environment variable to an integer value. For example, settingRAYON_NUM_THREADS=4
will run theStochasticSwap
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 theStochasticSwap
transpiler pass but it likely will be used other parts of Qiskit in the future. When this env variable is set toTRUE
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, inStochasticSwap
if the pass is being run as part of atranspile()
call with > 1 circuit that is being executed in parallel withmultiprocessing
viaparallel_map()
theStochasticSwap
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 setQISKIT_FORCE_THREADS=TRUE
.
New fake backend classes are available under
qiskit.providers.fake_provider
. These include mocked versions ofibm_cairo
,ibm_hanoi
,ibmq_kolkata
,ibm_nairobi
, andibm_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 asInitialize
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 optimizingU1Gate
,U2Gate
, andPhaseGate
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()
andPauliList.evolve()
now have a new keyword argument,frame
, which is used to perform an evolution of a Pauli by a Clifford. Ifframe='h'
(default) then it does the Heisenberg picture evolution of a Pauli by a Clifford (\(P' = C^\dagger P C\)), and ifframe='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 indecompose_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 fromQuantumCircuit
which abstracts away the details of the underlying execution on aBackend
. 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 theBaseEstimator
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
(seeBaseSampler
for the abstract class definition) andEstimator
(seeBaseEstimator
for the abstract class definition). Reference implementations are included in theqiskit.primitives
module and are built using theqiskit.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 aBackend
.
Added a new module,
qiskit.qpy
, which contains the functionality previously exposed inqiskit.circuit.qpy_serialization
. The public functions previously exposed atqiskit.circuit.qpy_serialization
,dump()
andload()
are now available from this new module (although they are still accessible fromqiskit.circuit.qpy_serialization
but this will be deprecated in a future release). This new module was added in the interest of the future direction of the QPY file format, which in future versions will support representingpulse
Schedule
andScheduleBlock
objects in addition to theQuantumCircuit
objects it supports today.
Added a new attribute,
qubit_properties
to theTarget
class. This attribute contains a list ofQubitProperties
objects for each qubit in the target. For example:target.qubit_properties[2]
will contain the
QubitProperties
for qubit number 2 in the target.For
BackendV2
authors, if you were previously definingQubitProperties
directly on yourBackendV2
implementation by overridingBackendV2.qubit_properties()
this will still work fine. However, if you do move the definition to the underlyingTarget
object and remove the specializedBackendV2.qubit_properties()
implementation which will enable using qubit properties in the transpiler and also maintain API compatibility with your previous implementation.
Added a new function,
qiskit.algorithms.eval_observables()
, which is used to evaluate observables given a boundQuantumCircuit
. It originates from a private method,_eval_aux_ops()
, of theqiskit.algorithms.VQE
class but the neweval_observables()
function is now more general so that it can be used in other algorithms, for example time evolution algorithms.
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 theRAYON_NUM_THREADS
environment variable to an integer value. For example, settingRAYON_NUM_THREADS=4
will run theDenseLayout
pass with 4 threads.
The internal computations of
Statevector.expectation_value()
andDensityMatrix.expectation_value()
methods have been reimplemented in the Rust programming language. This new implementation is multithreaded and by default for aStatevector
orDensityMatrix
>= 19 qubits will spawn a thread pool with the number of logical CPUs available on the local system. You can you can control the number of threads used by setting theRAYON_NUM_THREADS
environment variable to an integer value. For example, settingRAYON_NUM_THREADS=4
will only use 4 threads in the thread pool.
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 aTarget
object which represents the compilation target for the pass. When it’s specified it will supersede the values set forbasis_gates
,coupling_map
, andbackend_props
.
The
UnitarySynthesisPlugin
abstract plugin class has a new optional attribute implementations can add,supports_target
. If a plugin has this attribute set toTrue
aTarget
object will be passed in theoptions
payload under thetarget
field. The expectation is that thisTarget
object will be used in place ofcoupling_map
,gate_lengths
,basis_gates
, andgate_errors
.
Introduced a new transpiler pass workflow for building
PassManager
objects for schedulingQuantumCircuit
objects in the transpiler. In the new workflow scheduling and alignment passes are allAnalysisPass
objects that only update the property set of the pass manager, specifically new property set itemnode_start_time
, which holds the absolute start time of each opnode. A separateTransformationPass
such asPadDelay
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 multipleDAGCircuit
instances recreated during each pass. In addition, scheduling occured in each pass to obtain instruction start time. Now the required pass chain becomesscheduling -> alignment -> padding
where theDAGCircuit
update only occurs at the end with thepadding
pass.For those who are creating custom
PassManager
objects that involve circuit scheduling you will need to adjust yourPassManager
to insert one of theBasePadding
passes (currently eitherPadDelay
orPadDynamicalDecoupling
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 therun()
method of your customPassManager
.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 = [ ALAPSchedule(instruction_durations), PadDelay()), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), AlignMeasures(alignment=timing_constraints.acquire_alignment), ] pm.append(scheduling)
you can instead use:
from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay pm = PassManager() scheduling = [ ALAPScheduleAnalysis(instruction_durations), PadDelay()), ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), PadDelay() ] pm.append(scheduling)
which will both be more efficient and also align instructions based on any hardware constraints.
Added a new transpiler pass
ConstrainedReschedule
pass. TheConstrainedReschedule
pass considers both hardware alignment constraints that can be definied in aBackendConfiguration
object,pulse_alignment
andacquire_alignment
. This new class supersedes the previosuly existingAlignMeasures
as it performs the same alignment (via the property set) for measurement instructions in addition to general instruction alignment. By setting theacquire_alignment
constraint argument for theConstrainedReschedule
pass it is a drop-in replacement ofAlignMeasures
when paired with a newBasePadding
pass.
Added two new transpiler passes
ALAPScheduleAnalysis
andASAPScheduleAnalysis
which superscede theALAPSchedule
andASAPSchedule
as part of the reworked transpiler workflow for schedling. The new passes perform the same scheduling but in the property set and relying on aBasePadding
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), PadDelay(), ] ) draw(pm.run(circuit))
As you can see in the timeline view, the measurement on
q_2
starts before the conditional X gate on theq_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.transpiler.passes import ALAPScheduleAnalysis, PadDelay 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([ALAPScheduleAnalysis(durations), PadDelay()]) 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
andMemorySlot
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.
Added a new transpiler pass
PadDynamicalDecoupling
which supersedes theDynamicalDecoupling
pass as part of the reworked transpiler workflow for scheduling. This new pass will insert dynamical decoupling sequences into the circuit per any scheduling and alignment analysis that occured in earlier passes.
The
plot_gate_map()
visualization function and the functions built on top of it,plot_error_map()
andplot_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()
andplot_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 retworkxspring_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 thequbit_coordinates
function to set a custom layout.
The
plot_gate_map()
visualization function and the functions built on top of it,plot_error_map()
andplot_circuit_layout()
, are now able to function with aBackendV2
based backend. Previously, these functions only worked withBaseBackend
orBackendV1
based backends.
Added a new transpiler pass,
SetIOLatency
. This pass takes two argumentsclbit_write_latency
andconditional_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.
A new transpiler pass
PadDelay
has been added. This pass fills idle time on the qubit wires withDelay
instructions. This pass is part of the new workflow for scheduling passes in the transpiler and depends on a scheduling analysis pass (such asALAPScheduleAnalysis
orASAPScheduleAnalysis
) and any alignment passes (such asConstrainedReschedule
) to be run prior toPadDelay
.
The
VF2Layout
transpiler pass has a new keyword argument,target
which is used to provide aTarget
object for the pass. When specified, theTarget
will be used by the pass for all information about the target device. If it is specified, thetarget
option will take priority over thecoupling_map
andproperties
arguments.
Allow callables as optimizers in
VQE
andQAOA
. Now, the optimizer can either be one of Qiskit’s optimizers, such asSPSA
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 astranspile()
andassemble()
) in a subprocess launched outside ofparallel_map()
, it is possible that the parallel dispatch performed insideparallel_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 callingparallel_map()
from a main process should work fine; or you can manually call the CPython standard librarymultiprocessing
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.
Upgrade Notes¶
The classes
Qubit
,Clbit
andAncillaQubit
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 passConsolidateBlocks
.
The minimum supported version of
symengine
is now 0.9.0. This was necessary to improve compatibility with Python’spickle
module which is used internally as part of parallel dispatch withparallel_map()
.
The default value of
QISKIT_PARALLEL
when running with Python 3.9 on Linux is now set toTRUE
. This means when runningparallel_map()
or functions that call it internally, such astranspile()
andassemble()
, 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 theQISKIT_PARALLEL
environment variable toFALSE
, or setting theparallel
option toFalse
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 inqiskit.circuit.library
has been removed. It was originally deprecated in the 0.16.0 release. Instead theGMS
class should be used, as this allows you to create an equivalent 2 qubit MS gate in addition to anMSGate
for any number of qubits.
The previously deprecated
mirror()
method of theInstruction
class has been removed. It was originally deprecated in 0.15.0 release. Instead you should useInstruction.reverse_ops()
.
The previously deprecated
num_ancilla_qubits()
method of theqiskit.circuit.library.PiecewiseLinearPauliRotations
andqiskit.circuit.library.WeightedAdder
classes has been removed. It was originally deprecated in the 0.16.0 release. Instead thePiecewiseLinearPauliRotations.num_ancillas()
andWeightedAdder.num_ancillas()
methods should be used.
The previously deprecated
reverse
argument on the constructor for thePolynomialPauliRotations
class has been removed. It was originally deprecated in the 0.15.0 release. Instead you should use theQuantumCircuit.reverse_bits()
method to reverse thePolynomialPauliRotations
circuit if needed.
The previously deprecated
angle
argument on the constructors for theC3SXGate
andC3XGate
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 theC3XGate.power()
method.
Support for using
np.ndarray
objects as part of theparams
attribute of aGate
object has been removed. This has been deprecated since Qiskit Terra 0.16.0 and now will no longer work. Instead one should create a new subclass ofGate
and explicitly allow anp.ndarray
input by overloading thevalidate_parameter()
method.
A new extra
csp-layout-pass
has been added to the install target forpip install qiskit-terra
, and is also included in theall
extra. This has no effect in Qiskit Terra 0.20, but starting from Qiskit Terra 0.21, the dependencies needed only for theCSPLayout
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 (orpip install
command) to targetqiskit-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
AmplitudeEstimator
now inherits from theABC
class from the Python standard library. This requires any subclass to implement theestimate()
method when previously it wasn’t required. This was done because the original intent of the class was to always be a child class ofABC
, as theestimate()
is required for the operation of anAmplitudeEstimator
object. However, if you were previously defining anAmplitudeEstimator
subclass that didn’t implementestimate()
this will now result in an error.
The error raised by
HoareOptimizer
if the optional dependencyz3
is not available has changed fromTranspilerError
toMissingOptionalLibraryError
(which is both aQiskitError
and anImportError
). 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 aResult
object input, will now marginalize thememory
field of experiment data if it’s set in the inputResult
. Previously, thememory
field in the the input was not marginalized. This change was made because the previous behavior would result in thecounts
field not matching thememory
field aftermarginal_counts()
was called. If the previous behavior is desired it can be restored by settingmarginalize_memory=None
as an argument tomarginal_counts()
which will not marginalize thememory
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 rantranspile()
withoptimization_level
0, 1 (the default), or 2 with a value set forseed_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
name
attribute of thePauliEvolutionGate
class has been changed to always be"PauliEvolution"
. This change was made to be consistent with other gates in Qiskit and enables other parts of Qiskit to quickly identify when a particular operation in a circuit is aPauliEvolutionGate
. For example, it enables the unrolling to Pauli evolution gates.Previously, the name contained the operators which are evolved, which is now available via the
PauliEvolutionGate.label
attribute. If a circuit with aPauliEvolutionGate
is drawn, the gate will still show the same information, which gates are being evolved.
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 aVariationalAlgorithm.initial_point
getter and setter method.
The
pass_manager
kwarg for thetranspile()
function has been removed. It was originally deprecated in the 0.13.0 release. The preferred way to transpile a circuit with a customPassManager
object is to use therun()
method of thePassManager
object.
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 parametrizeSchedule
orScheduleBlock
objects by specifying aParameter
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 areUniformDistribution
,NormalDistribution
, andLogNormalDistribution
. 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 toFakeMumbaiFractionalCX
to differentiate it from theBackendV2
based fake backend for the IBM Mumbai device,qiskit.test.mock.backends.FakeMumbaiV2
. If you were previously relying on theFakeMumbaiV2
class to get a fake backend that had fractional applications ofCXGate
defined in its target you need to useFakeMumbaiFractionalCX
class as theFakeMumbaiV2
will no longer have those extra gate definitions in itsTarget
.
The resolver used by
QuantumCircuit.append()
(and consequently all methods that add an instruction onto aQuantumCircuit
) 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 upQuantumCircuit
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 publicQuantumCircuit.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.
The preset passmanagers in
qiskit.transpiler.preset_passmanagers
for all optimization levels 2 and 3 as generated bylevel_2_pass_manager()
andlevel_3_pass_manager()
have been changed to run theVF2Layout
by default prior to the layout pass. TheVF2Layout
pass will quickly check if a perfect layout can be found and supersedes what was previously done for optimization levels 2 and 3 which were using a combination ofTrivialLayout
andCSPLayout
to try and find a perfect layout. This will result in potentially different behavior whentranspile()
is called by default as it removes a default path for all optimization levels >=2 of using a trivial layout (wherecircuit.qubits[0]
is mapped to physical qubit 0,circuit.qubits[1]
is mapped to physical qubit 1, etc) assuming the trivial layout is perfect. If your use case was dependent on the trivial layout you can explictly request it when transpiling by specifyinglayout_method="trivial"
when callingtranspile()
.
The preset pass manager for optimization level 1 (when calling
transpile()
withoptimization_level=1
or when nooptimization_level
argument is set) as generated bylevel_1_pass_manager()
has been changed so thatVF2Layout
is called by default to quickly check if a a perfect layout can be found prior to theDenseLayout
. However, unlike with optimization level 2 and 3 a trivial layout is still attempted prior to runningVF2Layout
and if it’s a perfect mapping the output fromVF2Layout
will be used.
Deprecation Notes¶
The
max_credits
argument toexecute()
, and all of theQobj
configurations (e.g.QasmQobjConfig
andPulseQobjConfig
), 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 callingexecute()
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 theSuzukiTrotter
class is deprecated and will no longer work in a future release. The product formulae used by theSuzukiTrotter
are only defined when the order is even as the Suzuki product formulae is symmetric.
The
qregs
,cregs
,layout
, andglobal_phase
kwargs to theMatplotlibDrawer
,TextDrawing
, andQCircuitImage
classes, and thecalibrations
kwarg to theMatplotlibDrawer
class, are now deprecated and will be removed in a subsequent release.
Bug Fixes¶
Fixed an error in the circuit conversion functions
circuit_to_gate()
andcircuit_to_instruction()
(and their associated circuit methodsQuantumCircuit.to_gate()
andQuantumCircuit.to_instruction()
) when acting on a circuit with registerless bits, or bits in more than one register.
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()
Added a missing entry from the standard session equivalence library between
CXGate
andCPhaseGate
as well as betweenCXGate
andCRZGate
.
Fixed an issue where running the
==
operator between twoSparsePauliOp
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 returningFalse
.
Fixed support in
transpile()
for passing aInstructionScheduleMap
object to the underlyingPassManager
based on theTarget
forBackendV2
based backends. Previously, thetranspile()
function would not do this processing and any transpiler passes which do not support working with aTarget
object yet would not have access to the default pulse calibrations for the instructions from aBackendV2
backend.
The
AmplitudeAmplifier
is now correctly available from the rootqiskit.algorithms
module directly. Previously it was not included in the re-exported classes off the root module and was only accessible fromqiskit.algorithms.amplitude_amplifiers
. Fixed #7751.
Fixed an issue with the
mpl
backend for the circuit drawer functioncircuit_drawer()
and theQuantumCircuit.draw()
method where gates with conditions would not display properly when a sufficient number of gates caused the drawer to fold over to a second row. Fixed: #7752.
Fixed an issue where the
HHL.construct_circuit()
method under certain conditions would not return a correctQuantumCircuit
. Previously, the function had a rounding error in calculating how many qubits were necessary to represent the eigenvalues which would cause an incorrect circuit output.
Fixed an endianness bug in
BaseReadoutMitigator.expectation_value()
when a stringdiagonal
was passed. It will now correctly be interpreted as little endian in the same manner as the rest of Qiskit Terra, instead of big endian.
Fixed an issue with the
quantum_info.partial_trace()
when the function was asked to trace out no subsystems, it will now correctly return theDensityMatrix
of the input state with all dimensions remaining rather than throwing an error. Fixed #7613
Fixed an issue with the
text
backend for the circuit drawer functioncircuit_drawer()
and theQuantumCircuit.draw()
method when gates that use side text, such as theCPhaseGate
andRZZGate
gate classes, with classical conditions set would not display properly. Fixed #7532.
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. When using thereverse_bits
option with thempl
,latex
, ortext
options, bits without registers did not display in the correct order. Fixed #7303.
Fixed an issue in the
LocalReadoutMitigator.assignment_matrix()
method where it would previously reject an input value for thequbits
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.
Fixed an issue in the
StabilizerState.expectation_value()
method’s expectation value calculation, where the output expectation value would be incorrect if the inputPauli
operator for theoper
argument had a non-trivial phase. Fixed #7441.
An opflow expression containing the Pauli identity
opflow.I
no longer produces anIGate
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 singlePauliOp
. For example,0 * X + I == I
now evaluates to True, whereas it was False prior to this release.
Fixed an issue with the
ALAPSchedule
andASAPSchedule
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.
Fixed support for using
ParameterExpression
instruction paramaters in theRZXCalibrationBuilder
transpiler pass. Previously, if an instruction parameter included a boundParameterExpression
the pass would not be able to handle this correctly.
Stopped the parser in
QuantumCircuit.from_qasm_str()
andfrom_qasm_file()
from accepting OpenQASM programs that identified themselves as being from a language version other than 2.0. This parser is only for OpenQASM 2.0; support for imported circuits from OpenQASM 3.0 will be added in an upcoming release.
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.
Aer 0.10.3¶
No change
Ignis 0.7.0¶
No change
IBM Q Provider 0.18.3¶
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.
Upgrade Notes¶
Starting from Python 3.10, Qiskit Terra will have reduced support for 32-bit platforms. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: 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 aPauliSumOp
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 usingqiskit.utils.algorithm_globals.massive = True
. The check is now efficient even for large numbers of qubits.
DAGCircuit.draw()
and the associated functiondag_drawer()
will now show a more useful error message when the provided filename is not valid.
QuantumCircuit.add_register()
will no longer cause duplicateAncillaQubit
references in a circuit when given anAncillaRegister
whose bits are already present.
Fixed conversion of
QuantumCircuit
s with classical conditions on single, registerlessClbit
s toInstruction
s when using thecircuit_to_instruction()
function or theQuantumCircuit.to_instruction()
method. For example, the following will now work:from qiskit.circuit import QuantumCircuit, Qubit, Clbit qc = QuantumCircuit([Qubit(), Clbit()]) qc.h(0).c_if(qc.clbits[0], 0) qc.to_instruction()
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 ofIIZ + 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
andmpl
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 toNone
, this method would raise an exception instead of treating that instruction as global.
Fixed an issue with the
transpile()
function where it could fail when being passed aTarget
object directly with thetarget
kwarg.
Fixed an issue with the
transpile()
function where it could fail when thebackend
argument was aBackendV2
or aTarget
via thetarget
kwarg that contained ideal globally defined operations.
Fixed an issue where plotting Bloch spheres could cause an
AttributeError
to be raised in Jupyter or when trying to crop figures down to size with Matplotlib 3.3 or 3.4 (but not 3.5). For example, the following code would previously crash with a message:AttributeError: 'Arrow3D' object has no attribute '_path2d'
but will now succeed with all current supported versions of Matplotlib:
from qiskit.visualization import plot_bloch_vector plot_bloch_vector([0, 1, 0]).savefig("tmp.png", bbox_inches='tight')
Fixed a bug in
PauliSumOp.permute()
where the object on which the method is called was permuted in-place, instead of returning a permuted copy. This bug only occured for permutations that left the number of qubits in the operator unchanged.
Fixed the
PauliEvolutionGate.inverse()
method, which previously computed the inverse by inverting the evolution time. This was only the correct inverse if the operator was evolved exactly. In particular, this led to the inverse of Trotterization-based time evolutions being incorrect.
The
QuantumInstance.execute()
method will no longer mutate its input if it is given a list of circuits.
Fixed QPY serialisation of custom instructions which had an explicit no-op definition. Previously these would be written and subsequently read the same way as if they were opaque gates (with no given definition). They will now correctly round-trip an empty definition. For example, the following will now be correct:
import io from qiskit.circuit import Instruction, QuantumCircuit, qpy_serialization # This instruction is explicitly defined as a one-qubit gate with no # operations. empty = QuantumCircuit(1, name="empty").to_instruction() # This instruction will perform some operations that are only known # by the hardware backend. opaque = Instruction("opaque", 1, 0, []) circuit = QuantumCircuit(2) circuit.append(empty, [0], []) circuit.append(opaque, [1], []) qpy_file = io.BytesIO() qpy_serialization.dump(circuit, qpy_file) qpy_file.seek(0) new_circuit = qpy_serialization.load(qpy_file)[0] # Previously both instructions in `new_circuit` would now be opaque, but # there is now a correct distinction. circuit == new_circuit
Added a missing
BackendV2.provider
attribute to implementations of theBackendV2
abstract class. Previously,BackendV2
backends could be initialized with a provider but that was not accessible to users.
Fixed support for the
QuantumInstance
class when running with aBackendV2
backend. Previously, attempting to use aQuantumInstance
with aBackendV2
would have resulted in an error.
Fixed a bug in
VQE
where the parameters of the ansatz were still explicitly ASCII-sorted by their name if the ansatz was resized. This led to a mismatched order of the optimized values in theoptimal_point
attribute of the result object.In particular, this bug occurred if no ansatz was set by the user and the VQE chose a default with 11 or more free parameters.
Stopped the parser in
QuantumCircuit.from_qasm_str()
andfrom_qasm_file()
from accepting OpenQASM programs that identified themselves as being from a language version other than 2.0. This parser is only for OpenQASM 2.0; support for imported circuits from OpenQASM 3.0 will be added in an upcoming release.
Fixed QPY serialization of
QuantumCircuit
objects that contained control flow instructions. Previously if you attempted to serialize a circuit containingIfElseOp
,WhileLoopOp
, orForLoopOp
the serialization would fail. Fixed #7583.
Fixed QPY serialization of
QuantumCircuit
containing subsets of bits from aQuantumRegister
orClassicalRegister
. Previously if you tried to serialize a circuit like this it would incorrectly treat these bits as standaloneQubit
orClbit
without having a register set. For example, if you try to serialize a circuit like:import io from qiskit import QuantumCircuit, QuantumRegister from qiskit.circuit.qpy_serialization import load, dump qr = QuantumRegister(2) qc = QuantumCircuit([qr[0]]) 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 anOverflowError
. 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.
Upgrade Notes¶
Qiskit Aer no longer fully supports 32 bit platforms on Python >= 3.10. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: 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 aQuantumCircuit
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.
Ignis 0.7.0¶
No change
IBM Q Provider 0.18.3¶
No change
Qiskit 0.34.1¶
Terra 0.19.1¶
No change
Aer 0.10.2¶
Bug Fixes¶
Fixed simulation of
for
loops where the loop parameter was not used in the body of the loop. For example, previously this code would fail, but will now succeed:import qiskit from qiskit.providers.aer import AerSimulator qc = qiskit.QuantumCircuit(2) with qc.for_loop(range(4)) as i: qc.h(0) 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.
Ignis 0.7.0¶
No change
IBM Q Provider 0.18.3¶
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.
Terra 0.19.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 support of QASM 3.0 control-flow instructions introduced in Qiskit-Terra 0.19.0. Supported instructions are
ForLoopOp
,WhileLoopOp
,ContinueLoopOp
,BreakLoopOp
,IfElseOp
.
Added a batched-shot simulation optimization for GPU simulations. This optional feature will use available memory on 1 or more GPUs to run multiple simulation shots in parallel for greatly improved performance on multi-shot simulations with noise models and/or intermediate measurements.
This option is enabled by default when using
device="GPU"
and a simulationmethod
of either"statevector"
or"density_matrix"
with theAerSimulator
. It can be disabled by settingbatched_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 byjob.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 theAerSimulator
. Currently this algorithm is used only when all qubits are measured and when the simulatormps_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 theAerSimulator
.
Added a
SaveClifford
instruction for saving the state of the stabilizer simulation method as aClifford
object.Note that this instruction is essentially equivalent to the
SaveStabilizer
instruction, however that instruction will return the saved state as aStabilizerState
object instead of aClifford
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 formdef 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 theLocalNoisePass
using a predefined noise function that returns a tensor product ofthermal_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()
andAerSimulator.from_backend()
has been upgraded to allow adding duration-dependent relaxation errors on circuit delay gates using theRelaxationNoisePass
.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 asnoise_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 allQuantumError
s in the noise model.
Added two utility functions
qiskit.providers.aer.utils.transpile_quantum_error()
andqiskit.providers.aer.utils.transpile_noise_model()
for transpiling the circuits contained inQuantumError
, and all errors in aNoiseModel
.
Added the ability to add
QuantumError
objects directly to aQuantumCircuit
without converting to aKraus
instruction.Circuits containing quantum errors can now be run on the
AerSimulator
andQasmSimulator
simulators as an alternative to, or in addition to, building aNoiseModel
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 andDensityMatrix
classes.
Upgrade Notes¶
The return type of several save instructions have been changed to be the corresponding Qiskit Terra classes rather than raw NumPy arrays or dictionaries. The types that have changed are
save_statevector()
now returns as aStatevector
save_density_matrix()
now returns as aDensityMatrix
save_stabilizer()
now returns asStabilizerState
save_unitary()
now returns asOperator
save_superop()
now returns asSuperOp
save_probabilities_dict()
now returns as aProbDistribution
Changed the default value of
standard_gates
toNone
for all functions inqiskit.providers.aer.noise.errors.standard_errors
as those functions are updated so that they use standard gates by default.
When an unsupported argument is supplied to
approximate_quantum_error()
, it will now raise aNoiseError
instead of aRuntimeError
.
Deprecation Notes¶
Using NumPy
ndarray
methods and attributes on the return type ofsave_statevector()
,save_density_matrix()
,save_unitary()
, andsave_superop()
has been deprecated, and will stop working in a future release. These instructions now returnqiskit.quantum_info
classes for their return types. Partial backwards compatability with treating these objects as NumPy arrays is implemented by forwarding methods to the internal array during the deprecation period.
Passing in a
BackendProperties
object for thebackend
argument ofNoiseModel.from_backend()
has been deprecated, as it is incompatible with duration dependent delay noises, and will be removed in a future release. Pass in a Qiskit TerraBackendV1
object instead.
Deprecated the
number_of_qubits
option of theQuantumError
constructor in favor of automatic determination of the dimension.
Deprecated the
standard_gates
option of theQuantumError
constructor in favor of externalizing such basis-change functionality. In many cases, you can transform any error into an error defined only with specific gates usingapproximate_quantum_error()
.
Deprecated the
standard_gates
option of all functions inqiskit.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 inqiskit.providers.aer.noise.errors.standard_errors
and they should have been provided as private functions.
Deprecated the
standard_gates
option ofNoiseModel.from_backend()
in favor of externalizing such basis-change functionality.
Deprecated
NoiseModel.from_dict()
to make the noise model independent of Qobj (JSON) format.
Deprecated all public variables, functions and classes in
qiskit.providers.aer.noise.utils.noise_transformation
except forapproximate_quantum_error()
andapproximate_noise_model()
, because they are helper functions meant to be used only for implementing theapproximate_*
functions and they should have been provided as private functions.
Deprecated
remap_noise_model()
since the C++ code now automatically truncates and remaps noise models if it truncates circuits.
Other Notes¶
Changes in the implementation of the function
approximate_quantum_error()
may change the resulting approximate error compared to Qiskit Aer 0.9.
Ignis 0.7.0¶
No change
IBM Q Provider 0.18.3¶
Bug Fixes¶
Fix delivered in #1100 for an issue with JSON encoding and decoding when using
ParameterExpression
s in conjunction with Qiskit Terra 0.19.1 and above. Previously, theParameter
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()
andqiskit.circuit.reset.reset()
are deprecated, and will be removed in a future release. Instead, you should access these as methods onQuantumCircuit
: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 error in the circuit conversion functions
circuit_to_gate()
andcircuit_to_instruction()
(and their associated circuit methodsQuantumCircuit.to_gate()
andQuantumCircuit.to_instruction()
) when acting on a circuit with registerless bits, or bits in more than one register. Previously, the number of bits necessary for the created gate or instruction would be calculated incorrectly, often causing an exception during the conversion.
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
ClassicalRegister
s 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 serializingQuantumCircuit
objects that are usingParameterVector
orParameterVectorElement
as parameters. Previously, aParameterVectorElement
parameter was just treated as aParameter
for QPY serialization which meant theParameterVector
context was lost in QPY and the output order ofparameters
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 theqpy_serialization
documentation at param_vector.
Fixed the
qpy_serialization
support for serializing aPauliEvolutionGate
object. Previously, thePauliEvolutionGate
was treated as a custom gate for serialization and would be deserialized as aGate
object that had the same definition and name as the originalPauliEvolutionGate
. However, this would lose the original state from thePauliEvolutionGate
. This has been fixed so that starting in this release aPauliEvolutionGate
in the circuit will be preserved 1:1 across QPY serialization now. The only limitation with this is that it does not support customEvolutionSynthesis
classes. Only the classes available fromqiskit.synthesis
can be used with aPauliEvolutionGate
for qpy serialization.To fix this issue a new QPY format version, version_3, was required. This new format version includes a representation of the
PauliEvolutionGate
class which is described in theqpy_serialization
documentation at PAULI_EVOLUTION.
Two loose functions
qiskit.circuit.measure.measure()
andqiskit.circuit.reset.reset()
were accidentally removed without a deprecation period. They have been reinstated, but are marked as deprecated in favour of the methodsQuantumCircuit.measure()
andQuantumCircuit.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()
andif_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 asIfContext
orControlFlowBuilderBlock
) 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.
Aer 0.9.1¶
No change
Ignis 0.7.0¶
No change
IBM Q Provider 0.18.2¶
Bug Fixes¶
Fix delivered in #1065 for the issue where job kept crashing when
Parameter
was passed in circuit metadata.Fix delivered in #1094 for the issue wherein
qiskit.providers.ibmq.runtime.RuntimeEncoder
does an extra decompose() if the circuit being serialized is aBlueprintCircuit
.
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:
A new version of the abstract Qiskit/hardware interface, in the form of
BackendV2
, which comes with a new data structureTarget
to allow backends to better model their constraints for the transpiler.An extensible plugin interface to the
UnitarySynthesis
transpiler pass, allowing users or other packages to extend Qiskit Terra’s synthesis routines with new methods.Control-flow instructions, for representing
for
andwhile
loops andif
/else
statements inQuantumCircuit
. The simulators in Qiskit Aer will soon be able to work with these new instructions, allowing you to write more dynamic quantum programs.Preliminary support for the evolving OpenQASM 3 specification. You can use the new
qiskit.qasm3
module to serialize yourQuantumCircuit
s into OpenQASM 3, including the new control-flow constructs.
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 passDecompose
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
orrz
gates, but leave (for example)x
gates untouched.
Added the
termination_checker
argument to theSPSA
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 version of the
Backend
interface,BackendV2
. This new version is a large change from the previous version,BackendV1
and changes both the user access pattern for properties of the backend (like number of qubits, etc) and how the backend represents its constraints to the transpiler. The execution of circuits (via therun()
method) remains unchanged. With aBackendV2
backend instead of having a separateconfiguration()
,properties()
, anddefaults()
methods that constructBackendConfiguration
,BackendProperties
, andPulseDefaults
objects respectively, like in theBackendV1
interface, the attributes contained in those output objects are accessible directly as attributes of theBackendV2
object. For example, to get the number of qubits for a backend withBackendV1
you would do:num_qubits = backend.configuration().n_qubits
while with
BackendV2
it is:num_qubits = backend.num_qubits
The other change around this is that the number of attributes exposed in the abstract
BackendV2
class is designed to be a hardware/vendor agnostic set of the required or optional fields that the rest of Qiskit can use today with any backend. Subclasses of the abstractBackendV2
class can add support for additional attributes and methods beyond those defined inBackendV2
, but these will not be supported universally throughout Qiskit.The other critical change that is primarily important for provider authors is how a
BackendV2
exposes the properties of a particular backend to the transpiler. WithBackendV2
this is done via aTarget
object. TheTarget
, which is exposed via thetarget
attribute, is used to represent the set of constraints for running circuits on a particular backend. It contains the subset of information previously exposed by theBackendConfiguration
,BackendProperties
, andPulseDefaults
classes which the transpiler can actively use. When migrating a provider to useBackendV2
(or when creating a new provider package) the construction of backend objects will primarily be around creating aTarget
object for the backend.
Added a new
Target
class to thetranspiler
module. TheTarget
class is designed to represent the constraints of backend to the compiler. TheTarget
class is intended to be used with aBackendV2
backend and is how backends will model their constraints for the transpiler moving forward. It combines the previously distinct fields used for controlling thetranspile()
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 enablesBackend
authors to optionally specify basic validation on the user supplied values for fields in theOptions
object. For example, if you had anOptions
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 ifshots
is being updated the proposed new value is within the valid range.
Added a new transpiler analysis pass,
ContainsInstruction
, to theqiskit.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 Hadamard 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 ofapply_prefix()
. The new function returns a tuple of scaled value and prefix from a given float value. For example, a value1.3e8
will be converted into(130, "M")
that can be used to display a value in the user friendly format, such as130 MHz
.
The values
"gate_error"
and"balanced"
are now available for theobjective
option in the construction of theBIPMapping
object, and"balanced"
is now the default.The
"gate_error"
objective requires passing aBackendProperties
instance in thebackend_prop
kwarg, which contains the 2q-gate gate errors used in the computation of the objectives. The"balanced"
objective will use theBackendProperties
instance if it is given, but otherwise will assume a CX error rate as given in the new parameterdefault_cx_error_rate
. The relative weights of the gate-error and depth components of the balanced objective can be controlled with the newdepth_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 attributesansatz
andoptimizer
can be reset by assigningNone
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 method
PauliList.group_qubit_wise_commuting()
that partitions aPauliList
into sets of mutually qubit-wise commutingPauli
operators. For example:from qiskit.quantum_info import PauliList, Pauli pauli_list = PauliList([Pauli("IY"), Pauli("XX"), Pauli("YY"), Pauli("YX")]) pauli_list.group_qubit_wise_commuting()
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 ofibmq_brooklyn
,ibmq_manila
,ibmq_jakarta
, andibmq_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 the
OperatorBase.is_hermitian()
method to check whether the operator is Hermitian or not.NumPyEigensolver
andNumPyMinimumEigensolver
useeigh
oreigsh
to solve the eigenvalue problem when the operator is Hermitian.
Added a new constructor method
PassManagerConfig.from_backend()
. It constructs aPassManagerConfig
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 thebackend.defaults().instruction_schedule_map
. This pass saves users from individually callingQuantumCircuit.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 callInstructionScheduleMap.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 backend = FakeGuadalupe() with pulse.build(backend, name="x") as x_q0: pulse.play(pulse.Constant(160, 0.1), pulse.drive_channel(0)) backend.defaults().instruction_schedule_map.add("x", (0,), x_q0) 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 instmap.add("x", (0, ), my_x_gate_schedule) 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 ofBIPMapping
. The option enables us to specify physical qubits to be used (incoupling_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 originalcoupling_map
and update theQuantumCircuit._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: layout.add_register(reg) 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: overall_layout.add_register(reg) recovered._layout = fill_with_ancilla(overall_layout)
Added the
ignore_pauli_phase
andcopy
arguments to the constructor ofSparsePauliOp
.ignore_pauli_phase
prevents thephase
attribute of an inputPauliList
from being read, which is more performant if thePauliList
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 setcopy=False
.
Improved performance of the following
SparsePauliOp
operations:simplify()
(see #7122)_add()
(see #7138)from_list()
and__init__()
(see other discussion in #7138).
Added the
SparsePauliOp.sum()
method to add together manySparsePauliOp
s. This method has significantly better performance than adding the instances together in a loop. For example, the previous way to add severalSparsePauliOp
s 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)
Added an argument
limit_amplitude
to the constructor ofParametricPulse
, which is the base class ofGaussian
,GaussianSquare
,Drag
andConstant
, to allowing disabling the amplitude limit of 1 on a pulse-by-pulse basis. Withlimit_amplitude=False
, individual pulses may have an amplitude exceeding unity without raising aPulseError
. See #6544 for more detail.
Using
QuantumCircuit.draw()
orcircuit_drawer()
with thelatex
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.
Added the parameter
filename
toplot_gate_map()
andplot_coupling_map()
, which allows saving the resulting images to a file.
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 bytranspile()
when theunitary_synthesis_method
argument is set to'aqc'
. Seeqiskit.transpiler.synthesis.aqc
for full details.
Added a
filter_function
argument toQuantumCircuit.depth()
andQuantumCircuit.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])
Added a new transpiler pass,
CollectMultiQBlocks
, to theqiskit.transpiler.passes
module. This pass is used to collect sequences of uninterrupted gates acting on groups of qubits. It provides a similar function to the existingCollect2qBlocks
pass, but while that pass is designed and optimized to find 2 qubit blocks this new pass will work to find blocks of any size.
There is a builder interface for the new control-flow operations on
QuantumCircuit
, such as the newForLoopOp
,IfElseOp
, andWhileLoopOp
. The interface uses the same circuit methods, i.e.QuantumCircuit.for_loop()
,QuantumCircuit.if_test()
andQuantumCircuit.while_loop()
, which are overloaded so that if thebody
parameter is not given, they return a context manager. Entering one of these context managers pushes a scope into the circuit, and captures all gate calls (and other scopes) and the resources these use, and builds up the relevant operation at the end. For example, you can now do:qc = QuantumCircuit(2, 2) with qc.for_loop(range(5)) as i: qc.rx(i * math.pi / 4, 0)
This will produce a
ForLoopOp
onqc
, which knows that qubit 0 is the only resource used within the loop body. These context managers can be nested, and will correctly determine their widths. You can useQuantumCircuit.break_loop()
andQuantumCircuit.continue_loop()
within a context, and it will expand to be the correct width for its containing loop, even if it is nested in furtherQuantumCircuit.if_test()
blocks.The
if_test()
context manager provides a chained manager which, if desired, can be used to create anelse
block, such as by:qreg = QuantumRegister(2) creg = ClassicalRegister(2) qc = QuantumCircuit(qreg, creg) qc.h(0) qc.cx(0, 1) qc.measure(0, 0) with qc.if_test((creg, 0)) as else_: qc.x(1) with else_: qc.z(1)
The manager will ensure that the
if
andelse
bodies are defined over the same set of resources.
Introduced a new transpiler pass
InverseCancellation
that generalizes theCXCancellation
pass to cancel any self-inverse gates or gate-inverse pairs. It can be used by initializingInverseCancellation
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 kwargsinstruction_schedule_map
andqubit_channel_mapping
which take aInstructionScheduleMap
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 aBaseBackend
orBackendV1
object directly to the pass with thebackend
argument.
The
Statevector
s 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 theconvention
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
andQNSPSA
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 themax_evals_grouped
kwarg on the constructor forVQE
when using eitherSPSA
orQNSPSA
as theoptimizer
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)
, andRZX(pi/6)
} specifically by including'rzx'
in theirbasis_gates
list when callingtranspile()
. Quantum information package users can find the method itself under theXXDecomposer
class.
Added a transpiler pass
Optimize1qGatesSimpleCommutation
, which optimizes a circuit according to a strategy of commuting single-qubit gates around to discover resynthesis opportunities.
Added a
max_job_tries
parameter toQuantumInstance
, 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 settingmax_job_tries=-1
. Fixes #6872 and #6821.
The
latex
output method for thecircuit_drawer()
function and theQuantumCircuit.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 thecircuit_drawer()
function and theQuantumCircuit.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 thecircuit_drawer()
function and theQuantumCircuit.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 toqiskit.transpiler.passes
. This pass is used to check if theDAGCircuit
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 toTrue
if all the gates in theDAGCircuit
are in the configured basis set orFalse
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"]
Added two new constructor methods,
from_heavy_hex()
andfrom_heavy_square()
, to theCouplingMap
class. These constructor methods are used to create aCouplingMap
that are a heavy hex or heavy square graph as described in Chamberland et al., 2020.For example:
from qiskit.transpiler import CouplingMap cmap = CouplingMap.from_heavy_hex(5) cmap.draw()
from qiskit.transpiler import CouplingMap cmap = CouplingMap.from_heavy_square(5) cmap.draw()
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 algorithmExactReciprocal
was updated to process this new information. See #6971 for more details.
Added two new classes,
CompleteMeasFitter
andTensoredMeasFitter
to theqiskit.utils.mitigation
module. These classes are for use only as values for themeasurement_error_mitigation_cls
kwarg of theQuantumInstance
class. The instantiation and usage of these classes (or anything else inqiskit.utils.mitigation
) outside of themeasurement_error_mitigation_cls
kwarg should be treated as an internal private API and not relied upon.
The
ListOp
class inqiskit.opflow
now has acoeffs
attribute, which returns a list of the coefficients of the operator list, with the overall coefficient (