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.43.1 |
0.24.1 |
0.12.0 |
0.20.2 |
2023-06-02 |
||
0.43.0 |
0.24.0 |
0.12.0 |
0.20.2 |
2023-05-04 |
||
0.42.1 |
0.23.3 |
0.12.0 |
0.20.2 |
2023-03-21 |
||
0.42.0 |
0.23.2 |
0.12.0 |
0.20.2 |
2023-03-10 |
||
0.41.1 |
0.23.2 |
0.11.2 |
0.20.1 |
2023-02-23 |
||
0.41.0 |
0.23.1 |
0.11.2 |
0.20.0 |
2023-01-31 |
||
0.40.0 |
0.23.0 |
0.11.2 |
0.19.2 |
2023-01-26 |
||
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 |
নোট
For the 0.7.0
, 0.7.1
, and 0.7.2
meta-package releases the
Qiskit Versioning policy was not formalized yet.
Notable Changes¶
Qiskit 0.43.1¶
Terra 0.24.1¶
Prelude¶
Qiskit Terra 0.24.1 is the first patch release to 0.24.0. This fixes some bugs that have been discovered since the release of 0.24.0.
Upgrade Notes¶
Changed
QuantumCircuit.assign_parameters()
to bind assigned integer and float values directly into the parameters ofInstruction
instances in the circuit rather than binding the values wrapped within aParameterExpression
. This change should have little user impact asfloat(QuantumCircuit.data[i].operation.params[j])
still produces afloat
(and is the only way to access the value of aParameterExpression
). Also,Instruction()
parameters could already befloat
as well as aParameterExpression
, so code dealing with instruction parameters should already handle both cases. The most likely chance for user impact is in code that usesisinstance
to check forParameterExpression
and behaves differently depending on the result. Additionally, qpy serializes the numeric value in a boundParameterExpression
at a different precision than afloat
(see also the related bug fix note aboutQuantumCircuit.assign_parameters()
).
Bug Fixes¶
Updated
plot_gate_map()
,plot_error_map()
, andplot_circuit_layout()
to support 433 qubit heavy-hex coupling maps. This allows coupling map visualizations for IBM Quantum'sibm_seattle
backend.
Changed the binding of numeric values with
QuantumCircuit.assign_parameters()
to avoid a mismatch between the values of circuit instruction parameters and corresponding parameter keys in the circuit's calibration dictionary. Fixed #9764 and #10166. See also the related upgrade note regardingQuantumCircuit.assign_parameters()
.
Fixed a bug in
BlockCollapser
where classical bits were ignored when collapsing a block of nodes.
Fixed a bug in
replace_block_with_op()
andreplace_block_with_op()
that led to ignoring classical bits.
Fixed a bug in
QuantumCircuit.compose()
where theSwitchCaseOp.target
attribute in the subcircuit was not correctly mapped to a register in the base circuit.
Fix a bug in
RZXCalibrationBuilder
where calling calibration with wrong parameters would crash instead of raising an exception.
Fixed an issue with the
BooleanExpression.from_dimacs_file()
constructor method where the exception type raised when tweedledum wasn't installed was not the expectedMissingOptionalLibrary
. Fixed #10079
Using
initial_layout
in calls totranspile()
will no longer error if the circuit contains qubits not in any registers, or qubits that exist in more than one register. See #10125.
Fixed the gate decomposition of multi-controlled Z rotation gates added via
QuantumCircuit.mcrz()
. Previously, this method implemented a multi-controlled phase gate, which has a relative phase difference to the Z rotation. To obtain the previousQuantumCircuit.mcrz()
behaviour, useQuantumCircuit.mcp()
.
Fixed an issue with the
PassManagerConfig.from_backend()
constructor when building aPassManagerConfig
object from aBackendV1
instance that didn't have a coupling map attribute defined. Previously, the constructor would incorrectly create aCouplingMap
object with 0 qubits instead of usingNone
. Fixed #10171
Fixes a bug introduced in Qiskit 0.24.0 where numeric rotation angles were no longer substituted for symbolic ones before preparing for two-qubit synthesis. This caused an exception to be raised because the synthesis routines require numberic matrices.
Fix a bug in which running
Optimize1qGatesDecomposition
in parallel would raise an error due to OneQubitGateErrorMap not being picklable.
Fix a bug in the
VF2Layout
andVF2PostLayout
passes where the passes were failing to account for the 1 qubit error component when evaluating a potential layout.
Aer 0.12.0¶
No change
IBM Q Provider 0.20.2¶
No change
Qiskit 0.43.0¶
Terra 0.24.0¶
Prelude¶
This is a major feature release that includes numerous new features and bugfixes.
This release is the final release with support for running Qiskit with Python 3.7. Starting in the next minor version release Python >=3.8 will be required to run Qiskit.
The highlights of this release:
QuantumInstance, OpFlow, and algorithms usage deprecation¶
This release officially deprecates the QuantumInstance
class (and
its associated helper methods and classes), the qiskit.opflow
module,
and any usage of those in qiskit.algorithms
. This deprecation comes
from a long thread of work that started in Qiskit Terra 0.21.0 to refactor
the qiskit.algorithms
module to be based on the computational
primitives
. There are associated migration guides for any
existing users to migrate to the new workflow:
QuantumInstance
migration guide: https://qisk.it/qi_migration
Opflow
migration guide: https://qisk.it/opflow_migrationAlgorithms migration guide: https://qisk.it/algo_migration
OpenQASM2 improvements¶
This release includes a major refactoring for the OpenQASM 2.0 support
in Qiskit. The first change is the introduction of a new parser for OpenQASM
2.0 in the qiskit.qasm2
module. This new module replaces the
existing qiskit.qasm
module. The new parser is more explicit and
correct with respect to the language specification. It is also implemented in
Rust and is significantly faster than the previous parser. Paired with the
new parser the OpenQASM 2.0 exporter underwent a large refactor that
improved the correctness of the output when using the
QuantumCircuit.qasm()
method to generate QASM output from a
QuantumCircuit
object.
Transpiler support for devices with disjoint connectivity¶
The transpiler now supports targeting backends with disjoint connectivity. Previously, the transpiler only supported backends which were fully connected (where there is a path to run operations between all pairs of qubits in the backend). Now, if a backend has disconnected connectivity the transpiler is able to reason about how to apply layout (Layout Stage) and routing (Routing Stage) for the backend. If the input circuit is not able to be executed on the hardware given the lack of connectivity between connected components, a descriptive error will be returned.
For example, the Heron device outlined in IBM Quantum's
hardware roadmap
describes a future backend which will have shared control hardware
and real-time classical communication between separate quantum processors.
This support enables the Target
to accurately model these types
of future devices or other hardware with similar constraints.
Switch Operation¶
This release adds a new control flow operation, the switch statement. This is
implemented using a new operation class SwitchCaseOp
and the
QuantumCircuit.switch()
method. This allows switching on a numeric
input (such as a classical register or bit) and executing the circuit that
corresponds to the matching value.
New Features¶
Added the functions
add_deprecation_to_docstring()
,deprecate_arg()
, anddeprecate_func()
to theqiskit.utils
module.add_deprecation_to_docstring()
will rewrite the function's docstring to include a Sphinx.. deprecated::
directive so that the deprecation shows up in docs and withhelp()
. The deprecation decorators fromqiskit.utils
calladd_deprecation_to_docstring()
already for you; but you can call it directly if you are using different mechanisms for deprecations.@deprecate_func
replaces@deprecate_function
and is used to deprecate an entire function. It will auto-generate most of the deprecation message for you.@deprecate_arg
replaces@deprecate_arguments
and is used to deprecate an argument on a function. It will generate a more useful message than the previous function. It is also more flexible, for example it allows setting apredicate
so that you only deprecate certain situations, such as using a deprecated value or data type.
Transpiler Features¶
Added an alternative way to specify in
HLSConfig
the list of synthesis methods used for a given high-level object. As before, a synthesis method can be specified as a tuple consisting of the name of the method and additional arguments. Additionally, a synthesis method can be specified as a tuple consisting of an instance ofHighLevelSynthesisPlugin
and additional arguments. Moreover, when there are no additional arguments, a synthesis method can be specified simply by name or by an instance ofHighLevelSynthesisPlugin
. The following example illustrates the new functionality:from qiskit import QuantumCircuit from qiskit.circuit.library.generalized_gates import PermutationGate from qiskit.transpiler import PassManager from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis from qiskit.transpiler.passes.synthesis.high_level_synthesis import ACGSynthesisPermutation qc = QuantumCircuit(6) qc.append(PermutationGate([1, 2, 3, 0]), [1, 2, 3, 4]) # All of the ways to specify hls_config are equivalent hls_config = HLSConfig(permutation=[("acg", {})]) hls_config = HLSConfig(permutation=["acg"]) hls_config = HLSConfig(permutation=[(ACGSynthesisPermutation(), {})]) hls_config = HLSConfig(permutation=[ACGSynthesisPermutation()]) # The hls_config can then be passed as an argument to HighLevelSynthesis pm = PassManager(HighLevelSynthesis(hls_config=hls_config)) qc_synthesized = pm.run(qc)
Added support to the
CouplingMap
object to have a disjoint connectivity. Previously, aCouplingMap
could only be constructed if the graph was connected. This will enable usingCouplingMap
to represent hardware with disjoint qubits, such as hardware with qubits on multiple separate chips.
Added a new method
CouplingMap.connected_components()
which is used to get a list ofCouplingMap
component subgraphs for a disjointCouplingMap
. If theCouplingMap
object is connected this will just return a singleCouplingMap
equivalent to the original.
Added new rules to the built-in
EquivalenceLibrary
instance:qiskit.circuit.equivalence_library.SessionEquivalenceLibrary
. The new rules added are:
Added high-level-synthesis plugins for
LinearFunction
and forqiskit.quantum_info.Clifford
, extending the set of synthesis methods that can be called fromHighLevelSynthesis
transpiler pass.For
LinearFunction
the available plugins are listed below:Plugin name
High-level synthesis plugin
default
DefaultSynthesisLinearFunction
kms
KMSSynthesisLinearFunction
pmh
PMHSynthesisLinearFunction
For
qiskit.quantum_info.Clifford
the available plugins are listed below:Plugin name
High-level synthesis plugin
default
DefaultSynthesisClifford
ag
AGSynthesisClifford
bm
BMSynthesisClifford
greedy
GreedySynthesisClifford
layers
LayerSynthesisClifford
lnn
LayerLnnSynthesisClifford
Please refer to
qiskit.synthesis
documentation for more information about each individual method.The following example illustrates some of the new plugins:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import LinearFunction from qiskit.quantum_info import Clifford from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis # Create a quantum circuit with one linear function and one clifford qc1 = QuantumCircuit(3) qc1.cx(0, 1) qc1.swap(0, 2) lin_fun = LinearFunction(qc1) qc2 = QuantumCircuit(3) qc2.h(0) qc2.cx(0, 2) cliff = Clifford(qc2) qc = QuantumCircuit(4) qc.append(lin_fun, [0, 1, 2]) qc.append(cliff, [1, 2, 3]) # Choose synthesis methods that adhere to linear-nearest-neighbour connectivity hls_config = HLSConfig(linear_function=["kms"], clifford=["lnn"]) # Synthesize qct = HighLevelSynthesis(hls_config)(qc) print(qct.decompose())
Added a new transpiler pass,
MinimumPoint
which is used primarily as a pass to check a loop condition in aPassManager
. This pass will track the state of fields in the property set over its past executions and set a boolean field when either a fixed point is reached over the backtracking depth or selecting the minimum value found if the backtracking depth is reached. This is an alternative to theFixedPoint
which simply checks for a fixed value in a property set field between subsequent executions.
Added a new method,
swap_nodes()
, to theDAGCircuit
to allow swapping nodes which are partially connected. Partially connected here means that the two nodes share at least one edge (which represents a qubit or clbit). If the nodes do not share any edges aDAGCircuitError
is raised.
Add a new synthesis algorithm
synth_cz_depth_line_mr()
of a CZ circuit for linear nearest neighbor (LNN) connectivity in 2-qubit depth of 2n+2 using CX and phase gates (S, Sdg or Z). The synthesized circuit reverts the order of the qubits. The synthesis algorithm is based on the paper of Maslov and Roetteler (https://arxiv.org/abs/1705.09176).
Add a new synthesis algorithm
synth_clifford_depth_lnn()
of a Clifford circuit for LNN connectivity in 2-qubit depth of 9n+4 (which is still not optimal), using the layered Clifford synthesis (synth_clifford_layers()
),synth_cnot_depth_line_kms()
to synthesize the CX layer in depth 5n, andsynth_cz_depth_line_mr()
to synthesize each of the CZ layers in depth 2n+2. This PR will be followed by another PR based on the recent paper of Maslov and Yang (https://arxiv.org/abs/2210.16195), that synthesizes the CX-CZ layers in depth 5n for LNN connectivity and performs further optimization, and hence reduces the depth of a Clifford circuit to 7n-4 for LNN connectivity.
Equivalences between the controlled Pauli rotations and translations to two-Pauli rotations are now available in the equivalence library for Qiskit standard gates. This allows, for example, to translate a
CRZGate
to aRZZGate
plusRZGate
or aCRYGate
to a singleRZXGate
plus single qubit gates:from qiskit.circuit import QuantumCircuit from qiskit.compiler import transpile angle = 0.123 circuit = QuantumCircuit(2) circuit.cry(angle, 0, 1) basis = ["id", "sx", "x", "rz", "rzx"] transpiled = transpile(circuit, basis_gates=basis) print(transpiled.draw())
Added a new option,
copy_operations
, tocircuit_to_dag()
to enable optionally disabling deep copying the operations from the inputQuantumCircuit
to the outputQuantumCircuit
. In cases where the input :class`~.QuantumCircuit` is not used anymore after conversion this deep copying is unnecessary overhead as any shared references wouldn't have any potential unwanted side effects if the inputQuantumCircuit
is discarded.
Added a new option,
copy_operations
, todag_to_circuit()
to enable optionally disabling deep copying the operations from the inputDAGCircuit
to the outputQuantumCircuit
. In cases where the inputDAGCircuit
is not used anymore after conversion this deep copying is unnecessary overhead as any shared references wouldn't have any potential unwanted side effects if the inputDAGCircuit
is discarded.
Added a new function
passmanager_stage_plugins()
to theqiskit.transpiler.preset_passmanagers.plugin
module. This function is used to obtain a mapping from plugin names to their their class type. This enables identifying and querying any defined pass manager stage plugin's documentation. For example:>>> from qiskit.transpiler.preset_passmanagers.plugin import passmanager_stage_plugins >>> passmanager_stage_plugins('routing')['lookahead'].__class__ qiskit.transpiler.preset_passmanagers.builtin_plugins.LookaheadSwapPassManager >>> help(passmanager_stage_plugins('routing')['lookahead']) Help on BasicSwapPassManager in module qiskit.transpiler.preset_passmanagers.builtin_plugins object: class BasicSwapPassManager(qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) | Plugin class for routing stage with :class:`~.BasicSwap` ...
The transpiler pass
Error
now also accepts callable inputs for itsmsg
parameter. If used these input callables will be passed theproperty_set
attribute of the pass and are expected to return a string which will be used for the error message when the pass is run. For example:from qiskit.transpiler.passes import Error def error_message(property_set): size = property_set["size'] return f"The circuit size is: {size}" error_pass = Error(error_message)
When
error_pass
is included in a pass manager it will error using the message"The circuit size is: n"
wheren
is the circuit size set in the property set (typically from the previous execution of theSize
pass).
The
build_coupling_map()
method has a new keyword argument,filter_idle_qubits
which when set toTrue
will remove any qubits from the outputCouplingMap
that don't support any operations.
The
GateDirection
transpiler pass can now correctly handleSwapGate
instances that may be present in the circuit when executing on a circuit. In these cases if the swap gate's qubit arguments are on the non-native direction of an edge, the pass will flip the argument order.
The
RZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
transpiler passes now will correctly use anECRGate
for the entangling gate if the backend's native entangling gate isECRGate
. Previously, the passes would only function correctly if the entangling gate wasCXGate
.
Added a new constructor for the
Target
class,Target.from_configuration()
, which lets you construct aTarget
object from the separate object types for describing the constraints of a backend (e.g. basis gates,CouplingMap
,BackendProperties
, etc). For example:target = Target.from_configuration( basis_gates=["u", "cx", "measure"], coupling_map=CouplingMap.from_line(25), )
This will construct a
Target
object that hasUGate
,CXGate
, andMeasure
globally available on 25 qubits which are connected in a line.
Added a new function
synth_cnot_phase_aam()
which is used to synthesize cnot phase circuits for all-to-all architectures using the Amy, Azimzadeh, and Mosca method. This function is identical to the availableqiskit.transpiler.synthesis.graysynth()
function but has a more descriptive name and is more logically placed in the package tree. This new function supersedes the legacy function which will likely be deprecated in a future release.
Internal tweaks to the routing algorithm in
SabreSwap
, used in transpilation of non-dynamic circuits at all non-zero optimization levels, have sped up routing for very large circuits. For example, the time to route a depth-5QuantumVolume
circuit for a 1081-qubit heavy-hex coupling map is approximately halved.
The runtime performance of the
Optimize1qGatesDecomposition
transpiler pass has been significantly improved. This was done by both rewriting all the computation for the pass in Rust and also decreasing the amount of intermediate objects created as part of the pass's execution. This should also correspond to a similar improvement in the runtime performance oftranspile()
with theoptimization_level
keyword argument set to1
,2
, or3
.
Add a new synthesis method
synth_stabilizer_layers()
of a stabilizer state into layers. It provides a similar decomposition to the synthesis described in Lemma 8 of Bravyi and Maslov, (arxiv:2003.09412) without the initial Hadamard-free sub-circuit which does not affect the stabilizer state.
Add a new synthesis method
synth_stabilizer_lnn()
of a stabilizer state for linear nearest neighbor connectivity in 2-qubit depth of 2n+2 and two distinct CX layers, using CX and phase gates (S, Sdg or Z). The synthesis algorithm is based on the paper of Maslov and Roetteler (https://arxiv.org/abs/1705.09176).
The
SabreLayout
pass now supports running against a target with a disjointCouplingMap
. When targeting a disjoint coupling the inputDAGCircuit
is split into its connected components of virtual qubits, each component is mapped to the connected components of theCouplingMap
, layout is run on each connected component in isolation, and then all layouts are combined and returned. Note when therouting_pass
argument is set the pass doesn't support running with disjoint connectivity.
The following layout and routing transpiler passes from the
qiskit.transpiler.passes
modules now will support accepting aTarget
object which is used to model the constraints of a target backend via the first positional argument (currently named eithercoupling_map
orbackend_properties
).The list of passes with the new support for
Target
input are:
The pass manager construction helper function
generate_embed_passmanager()
will now also accept aTarget
for it's sole positional argument (currently namedcoupling_map
). This can be used to construct a layout embeddingPassManager
from aTarget
object instead of from aCouplingMap
.
The following layout and routing transpiler passes from the
qiskit.transpiler.passes
modules have a new keyword argument,target
which takes in aTarget
object which is used to model the constraints of a target backend. If thetarget
keyword argument is specified it will be used as the source of truth for any hardware constraints used in the operation of the transpiler pass. It will supersede any other arguments for specifying hardware constraints, typically those arguments which take aCouplingMap
,InstructionScheduleMap
or a basis gate list. The list of these passes with the newtarget
argument are:
The pass manager construction helper function
generate_scheduling()
has a new keyword argumenttarget
which is used to specify aTarget
object to model the constraints of the target backend being compiled for when generating a newPassManager
. If specified this new argument will supersede the other argumentinst_map
.
The
default
plugin used by theUnitarySynthesis
transpiler pass now chooses one and two-qubit unitary synthesis based on the error rates reported in theTarget
. In particular, it runs all possible synthesis methods supported by the plugin and chooses the option which will result in the lowest error. For a one-qubit decomposition, it can target Pauli basis (e.g. RZ-RX-RZ or RZ-RY-RZ), generic unitary basis (e.g. U), and a few others. For a two-qubit decomposition, it can target any supercontrolled basis (e.g. CNOT, iSWAP, B) or multiple controlled basis (e.g. CZ, CH, ZZ^.5, ZX^.2, etc.).
The interface for
UnitarySynthesisPlugin
has two new optional propertiessupports_gate_lengths_by_qubit
andsupports_gate_errors_by_qubit
which when set will add the fieldsgate_lengths_by_qubit
andgate_errors_by_qubit
respectively to the input options to the plugin'srun()
method. These new fields are an alternative view of the data provided bygate_lengths
andgate_errors
but instead have the form:{(qubits,): [Gate, length]}
(whereGate
is the instance ofGate
for that definition). This allows plugins to reason about working with gates of the same type but but that have different parameters set.
Added a new transpiler pass,
UnrollForLoops
, which is used to unroll anyForLoopOp
operations in a circuit. This pass unrolls for-loops when possible, if there are noContinueLoopOp
orBreakLoopOp
inside the body block of the loop. For example:from qiskit.transpiler.passes import UnrollForLoops from qiskit import QuantumCircuit unroll_pass = UnrollForLoops() qc = QuantumCircuit(1) # For loop over range 5 with qc.for_loop(range(5)) as i: qc.rx(i, 0) # Unroll loop into 5 rx gates unroll_pass(qc).draw("mpl")
Added a new parameter
max_trials
to passVF2PostLayout
which, when specified, limits the number of layouts discovered and compared when searching for the best layout. This differs from existing parameterscall_limit
andtime_limit
(which are used to limit the number of state visits performed by the VF2 algorithm and the total time spent by passVF2PostLayout
, respectively) in that it is used to place an upper bound on the time spent scoring potential layouts, which may be useful for larger devices.
The
CheckMap
transpiler pass has a new keyword argument on its constructor,property_set_field
. This argument can be used to specify a field in the property set to store the results of the analysis. Previously, it was only possible to store the result in the field"is_swap_mapped"
(which is the default). This enables you to store the result of multiple instances of the pass in aPassManager
in different fields.
Circuits Features¶
Added a new gate class,
GlobalPhaseGate
, which can be used to add a global phase on theQuantumCircuit
instance.
Added a new attribute,
layout
, to theQuantumCircuit
class. This attribute is typically populated bytranspile()
orPassManager.run()
(when the Layout Stage and Routing Stage are run in thePassManager
) and contains aTranspileLayout
which contains the information about the permutation of the input circuit duringtranspile()
.
Added a new argument,
var_order
, to thePhaseOracle
class's constructor to enable setting the order in which the variables in the logical expression are being considered. For example:from qiskit.tools.visualization import plot_histogram from qiskit.primitives import Sampler from qiskit.circuit.library import PhaseOracle from qiskit.algorithms import Grover, AmplificationProblem oracle = PhaseOracle('((A & C) | (B & D)) & ~(C & D)', var_order=['A', 'B', 'C', 'D']) problem = AmplificationProblem(oracle=oracle, is_good_state=oracle.evaluate_bitstring) grover = Grover(sampler=Sampler()) result = grover.amplify(problem) print(result.circuit_results[0])
A new OpenQASM 2 parser is available in
qiskit.qasm2
. This has two entry points:qasm2.load()
andqasm2.loads()
, for reading the source code from a file and from a string, respectively:import qiskit.qasm2 program = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; h q[0]; cx q[0], q[1]; """ bell = qiskit.qasm2.loads(program)
This new parser is approximately 10x faster than the existing ones at
QuantumCircuit.from_qasm_file()
andQuantumCircuit.from_qasm_str()
for large files, and has less overhead on each call as well. The new parser is more extensible, customisable and generally also more type-safe; it will not attempt to output custom Qiskit objects when the definition in the OpenQASM 2 file clashes with the Qiskit object, unlike the current exporter. See theqiskit.qasm2
module documentation for full details and more examples.
Improve the decomposition of multi-controlled Pauli-X and Pauli-Y rotations with
QuantumCircuit.mcrx()
andQuantumCircuit.mcry on :math:`n()
controls to \(16n - 40\) CX gates, for \(n \geq 4\). This improvement is based on arXiv:2302.06377.
Qiskit now supports the representation of
switch
statements, using the newSwitchCaseOp
instruction and theQuantumCircuit.switch()
method. This allows switching on a numeric input (such as a classical register or bit) and executing the circuit that corresponds to the matching value. Multiple values can point to the same circuit, andCASE_DEFAULT
can be used as an always-matching label.You can also use a builder interface, similar to the other control-flow constructs to build up these switch statements:
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister qreg = QuantumRegister(2) creg = ClassicalRegister(2) qc = QuantumCircuit(qreg, creg) qc.h([0, 1]) qc.measure([0, 1], [0, 1]) with qc.switch(creg) as case: with case(0): # if the register is '00' qc.z(0) with case(1, 2): # if the register is '01' or '10' qc.cx(0, 1) with case(case.DEFAULT): # the default case qc.h(0)
The
switch
statement has support throughout the Qiskit compiler stack; you cantranspile()
circuits containing it (if the backend advertises its support for the construct), and it will serialize to QPY.The
switch
statement is not currently a feature of OpenQASM 3, but it is under active design and consideration, which is expected to be adopted in the near future. Qiskit Terra has experimental support for exporting this statement to the OpenQASM 3 syntax proposed in the linked pull request, using an experimental feature flag. To export aswitch
statement circuit (such as the one created above) to OpenQASM 3 using this speculative support, do:from qiskit import qasm3 qasm3.dumps(qc, experimental=qasm3.ExperimentalFeatures.SWITCH_CASE_V1)
Algorithms Features¶
Added a new attribute
eigenvalue_threshold
to theAdaptVQE
class for configuring a new kind of threshold to terminate the algorithm once the eigenvalue changes less than a set value.
Added a new attribute
gradient_threshold
to theAdaptVQE
class which will replace thethreshold
in the future. This new attribute behaves the same as the existingthreshold
attribute but has a more accurate name, given the introduction of additional threshold options in the class.
Added the
EstimationProblem.has_good_state
attribute, which allows to check whether anEstimationProblem
has a customEstimationProblem.is_good_state
or if it is the default. This is useful for checks in amplitude estimators, such asAmplitudeEstimation
, which only support the default implementation.
Adds a flag
local
to theComputeUncompute
state fidelity class that allows to compute the local fidelity, which is defined by averaging over single-qubit projectors.
Gradient classes rearrange the gradient result according to the order of the input parameters now.
Example:
from qiskit.algorithms.gradients import ParamShiftEstimatorGradient from qiskit.circuit import QuantumCircuit, Parameter from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp # Create a circuit with a parameter p = {i: Parameter(f'p{i}') for i in range(3)} qc = QuantumCircuit(1) qc.rx(p[0], 0) qc.ry(p[1], 0) qc.rz(p[2], 0) op = SparsePauliOp.from_list([("Z", 1)]) param_values = [0.1, 0.2, 0.3] # Create a gradient object estimator = Estimator() grad = ParamShiftEstimatorGradient(estimator) result = grad.run(qc, op, [param_values]).result() # would produce a gradient of the form [df/dp0, df/dp1, df/dp2] result = grad.run(qc, op, [param_values], parameters=[[p[2], p[0]]]).result() # would produce a gradient of the form [df/dp2, df/dp0]
Added support for handling time-dependent Hamiltonians (i.e. singly parametrized operators) to the
TrotterQRTE
class. To facilitate working with this, added thenum_timesteps
attribute and a matching keyword argument to theTrotterQRTE
constructor to control the number of time steps to divide the full evolution.
Added support for observable evaluations at every time-step during the execution of the
TrotterQRTE
class. TheTimeEvolutionProblem.aux_operators
is evaluated at every time step if theProductFormula.reps
attribute of the inputproduct_formula
argument in the constructor is set to 1.
Added extensions to the
VQD
algorithm, which allow to pass a list of optimizers and initial points for the different minimization runs. For example, thek
-th initial point andk
-th optimizer will be used for the optimization of thek-1
-th exicted state.
Quantum Information Features¶
Added two new constructor methods,
Clifford.from_matrix()
andClifford.from_operator()
, that create aClifford
object from its unitary matrix and operator representation respectively.
The constructor of
Clifford
now can take any Clifford gate object up to 3 qubits as long it implements ato_matrix
method, including parameterized gates such asRz(pi/2)
, which were not convertible before.
Added new utility functions:
commutator()
,anti_commutator()
, anddouble_commutator()
which are used to compute commutators for any object implementing theLinearOp
abstract base class such asQuantumChannel
,SparsePauliOp
, orScalarOp
.
Added the method
StabilizerState.equiv
, that checks if the generating sets of two stabilizer states generate the same stabilizer group. For example, the stabilizer group of the two-qubit Bell state contains the four elements \(\{II, XX, -YY, ZZ\}\) and hence can be generated by either \([XX, ZZ]\), \([XX, -YY]\) or \([-YY, ZZ]\).
Added a new method,
partial_transpose()
, to theqiskit.quantum_info
module'sDensityMatrix
class. This method is used to compute the partial transposition of a density matrix, which is necessary for detecting entanglement between bipartite quantum systems.
Added a method
qiskit.quantum_info.Operator.apply_permutation()
that pre-composes or post-composes an Operator with a Permutation. This method works for general qudits.Here is an example to calculate \(P^\dagger.O.P\) which reorders Operator's bits:
import numpy as np from qiskit.quantum_info.operators import Operator op = Operator(np.array(range(576)).reshape((24, 24)), input_dims=(2, 3, 4), output_dims=(2, 3, 4)) perm = [1, 2, 0] inv_perm = [2, 0, 1] conjugate_op = op.apply_permutation(inv_perm, front=True).apply_permutation(perm, front=False)
The conjugate operator has dimensions (4, 2, 3) x (4, 2, 3), which is consistent with permutation moving qutrit to position 0, qubit to position 1, and the 4-qudit to position 2.
Natively support the construction of
SparsePauliOp
objects withParameterExpression
coefficients, without requiring the explicit construction of an object-array. Now the following is supported:from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp x = Parameter("x") op = SparsePauliOp(["Z", "X"], coeffs=[1, x])
Added the
SparsePauliOp.assign_parameters()
method andSparsePauliOp.parameters
attribute to assign and query unbound parameters inside aSparsePauliOp
. This function can for example be used as:from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp x = Parameter("x") op = SparsePauliOp(["Z", "X"], coeffs=[1, x]) # free_params will be: ParameterView([x]) free_params = op.parameters # assign the value 2 to the parameter x bound = op.assign_parameters([2])
Pulse Features¶
Added new
SymbolicPulse
classes to the pulse library (qiskit.pulse.library
) The new pulses in the library are:These new classes are instances of
ScalableSymbolicPulse
. With the exception of theSawtooth
phase, behavior is identical to that of the corresponding waveform generator function (e.g.sin()
). The phase for theSawtooth
class is defined such that a phase of \(2\pi\) shifts by a full cycle.
Added support to QPY (
qiskit.qpy
) for working with pulseScheduleBlock
instances with unassigned references, and preserving the data structure for the reference to subroutines. This feature allows users to serialize and deserialize a template pulse program for tasks such as pulse calibration. For example:from qiskit import pulse from qiskit import qpy with pulse.build() as schedule: pulse.reference("cr45p", "q0", "q1") pulse.reference("x", "q0") pulse.reference("cr45p", "q0", "q1") with open('template_ecr.qpy', 'wb') as fd: qpy.dump(schedule, fd)
A new method
CalibrationEntry.user_provided()
has been added to calibration entries. This method can be called to check whether the entry is defined by an end user or backend.
Added a new method
Target.get_calibration()
which provides convenient access to the calibration of an instruction in aTarget
object This method can be called with parameter args and kwargs, and it returns a pulse schedule built with parameters when the calibration is templated with parameters.
Providers Features¶
The
BackendV2Converter
class has a new keyword argument,filter_faulty
, on its constructor. When this argument is set toTrue
the converter class will filter out any qubits or operations listed as non-operational in theBackendProperties
payload for the inputBackendV1
. While not extensively used aBackendProperties
object supports annotating both qubits and gates as being non-operational. Previously, if a backend had set that flag on any qubits or gates the outputBackendV2
instance and itsTarget
would include all operations whether they were listed as operational or not. By leveraging the new flag you can filter out these non-operational qubits and gates from theTarget
. When the flag is set the output backend will still be listed as the full width (e.g. a 24 qubit backend with 4 qubits listed as not operational will still show it has 24 qubits) but the faulty qubits will not have any operations listed as being supported in theTarget
.
The
Options
class now implements the theMapping
protocol and__setitem__
method. This means thatOptions
instances now offer the same interface as standard dictionaries, except for the deletion methods (__delitem__, pop, clear). Key assignments are validated by the validators, if any are registered.
Visualization Features¶
Added a new function,
staged_pass_manager_drawer()
, which is used for visualizing aStagedPassManager
instance. It draws the full pass manager with each stage represented as an outer box.For example:
from qiskit.visualization import staged_pass_manager_drawer from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.providers.fake_provider import FakeSherbrooke backend = FakeSherbrooke() pm = generate_preset_pass_manager(3, backend) staged_pass_manager_drawer(pm)
The
StagedPassManager.draw()
method has been updated to include visualization of the stages in addition to the overall pass manager. The stages are represented by outer boxes in the visualization. In previous releases the stages were not included in the visualization. For example:from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.providers.fake_provider import FakeSherbrooke backend = FakeSherbrooke() pm = generate_preset_pass_manager(3, backend) pm.draw(pm)
Added a new keyword argument,
figsize
, to theplot_bloch_multivector()
function. This argument can be used to set a size for individual Bloch sphere sub-plots. For example, if there are \(n\) qubits andfigsize
is set to(w, h)
, then the overall figure width is set to \(n \cdot w\), while the overall height is set to \(h\).
Added a new keyword argument,
font_size
, to theplot_bloch_multivector()
function. This argument can be used to control the font size in the output visualization.
Added two new keyword arguments,
title_font_size
andtitle_pad
, to theplot_bloch_multivector()
function. These arguments can be used to control the font size of the overall title and its padding respectively.
Upgrade Notes¶
The minimum supported Rust version (MSRV) has been increased from 1.56.1 to 1.61.0. If you're are building Qiskit from source you will now need to ensure that you have at least Rust 1.61.0 installed to be able to build Qiskit. This change was made because several upstream dependencies have increased their MSRVs.
Removed the usage of primitives with the context manager and the initialization with circuits, (observables only for Estimator), and parameters which was deprecated in the Qiskit Terra 0.22.0 release in October 2022.
PrimitiveJob.submit()
no longer blocks on execution finishing. As a result,Sampler.run()
,BackendSampler.run()
,Estimator.run()
andBaseEstimator.run()
do not block untilPrimitiveJob.result()
method is called.
Transpiler Upgrade Notes¶
The maximum number of trials evaluated when searching for the best layout using
VF2Layout
andVF2PostLayout
is now limited inlevel_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
to2 500
,25 000
, and250 000
, respectively. Previously, all found possible layouts were evaluated. This change was made to prevent transpilation from hanging during layout scoring for circuits with many connected components on larger devices, which scales combinatorially since each connected component would be evaluated in all possible positions on the device. To perform a full search as before, manually runVF2PostLayout
over the transpiled circuit in strict mode, specifying0
formax_trials
.
The previously deprecated
condition
attribute of theDAGDepNode
class has been removed. It was marked as deprecated in the 0.18 release (07-2021). Instead you should use thecondition
attribute of theop
attribute to access the condition of an operation node. For other node types there is no condition to access.
The default value of
metadata
in bothDAGCircuit
andDAGDependency
has been changed fromNone
to{}
for compatibility with the matchingmetadata
attribute ofQuantumCircuit
.
The
CouplingMap.__eq__`()
method has been updated to check that the edge lists of the underlying graphs contain the same elements. Under the assumption that the underlying graphs are connected, this check additionally ensures that the graphs have the same number of nodes with the same labels. Any code usingCouplingMap() == CouplingMap()
to check object equality should be updated toCouplingMap() is CouplingMap()
.
When running the
transpile()
function with aBackendV1
based backend or aBackendProperties
via thebackend_properties
keyword argument that has any qubits or gates flagged as faulty the function will no longer try to automatically remap the qubits based on this information. The method by whichtranspile()
attempted to do this remapping was fundamentally flawed and in most cases of such a backend it would result an internal error being raised. In practice very few backends ever set the fields inBackendProperties
to flag a qubit or gate as faulty. If you were relying ontranspile()
to do this re-mapping for you, you will now need to manually do that and pass a mapped input to thecoupling_map
andbackend_properties
arguments which has filtered out the faulty qubits and gates and then manually re-map the output.
The result of transpilations for fixed seeds may have changed compared to previous versions of Qiskit Terra. This is because of internal tweaks to the routing algorithm used by
SabreSwap
andSabreLayout
, which are the default routing and layout passes respectively, to make them significantly faster for large circuits.
Circuits Upgrade Notes¶
The
QuantumCircuit
metadata
attribute now always returns a dictionary, and can only be set to a dictionary. Previously, its default value wasNone
, and could be manually set toNone
or a dictionary.
Algorithms Upgrade Notes¶
The deprecated modules
factorizers
andlinear_solvers
, containingHHL
andShor
have been removed fromqiskit.algorithms
. These functionalities were originally deprecated as part of the 0.22.0 release (released on October 13, 2022). You can access the code through the Qiskit Textbook instead: Linear Solvers (HHL) , Factorizers (Shor)
Pulse Upgrade Notes¶
Target.update_from_instruction_schedule_map()
no longer raisesKeyError
norValueError
when qubits are missing in the target instruction orinst_name_map
is not provided for the undefined instruction. In the former case, it just ignores the inputInstructionScheduleMap
's definition for undefined qubits. In the latter case, a gate mapping is pulled from the standard Qiskit gates and finally, a custom opaqueGate
object is defined from the schedule name if no mapping is found.
Providers Upgrade Notes¶
The deprecated
max_credits
argument toexecute()
,assemble()
and all of theQobj
configurations (e.g.QasmQobjConfig
andPulseQobjConfig
) has been removed. This argument dates back to early versions of Qiskit which was tied more closely to the IBM Quantum service offering. At that time themax_credits
field was part of the "credit system" used by IBM Quantum's service offering. However, that credit system has not been in use on IBM Quantum backends for nearly three years and also Qiskit is not tied to IBM Quantum's service offerings anymore (and hasn't been for a long time). If you were relying on this option in some way for a backend you will need to ensure that yourBackendV2
implementation exposes amax_credits
field in itsOptions
object.
The
name
attribute on theBackendV2
based fake backend classes inqiskit.providers.fake_provider
have changed from earlier releases. Previously, the names had a suffix"_v2"
to differentiate the class from theBackendV1
version. This suffix has been removed as having the suffix could lead to inconsistencies with other snapshotted data used to construct the backend object.
Deprecation Notes¶
The modules
qiskit.opflow
,qiskit.utils.backend_utils
,qiskit.utils.mitigation
,qiskit.utils.measurement_error_mitigation
, classqiskit.utils.QuantumInstance
and methodsfind_regs_by_name()
,run_circuits()
have been deprecated and will be removed in a future release. UsingQuantumInstance
is superseded byBaseSampler
. See Opflow Migration. See QuantumInstance Migration.
Transpiler Deprecations¶
The transpiler routing pass,
BIPMapping
has been deprecated and will be removed in a future release. It has been replaced by an external plugin package:qiskit-bip-mapper
. Details for this new package can be found at the package's github repository:https://github.com/qiskit-community/qiskit-bip-mapper
The pass was made into a separate plugin package for two reasons, first the dependency on CPLEX makes it harder to use and secondly the plugin packge more cleanly integrates with
transpile()
.
Misspelled
aquire_alignment
in the classTarget
has been replaced by correct spellingacquire_alignment
. The old constructor argument aquire_alignment andTarget.aquire_alignment
are deprecated and will be removed in a future release. UseTarget.acquire_alignment
instead to get and set the alignment constraint value.
Circuits Deprecations¶
Setting the
QuantumCircuit
metadata
attribute toNone
has been deprecated and will no longer be supported in a future release. Instead, users should set it to an empty dictionary if they want it to contain no data.
Algorithms Deprecations¶
All of the following features are now deprecated, after having been made pending deprecation since 0.22.0. More information is available at https://qisk.it/algo_migration.
Module
qiskit.algorithms.minimum_eigen_solvers
is deprecated and superseded byqiskit.algorithms.minimum_eigensolvers
.Module
qiskit.algorithms.eigen_solvers
is deprecated and superseded byqiskit.algorithms.eigensolvers
.Module
qiskit.algorithms.evolvers
is deprecated and superseded byqiskit.algorithms.time_evolvers
.Class
qiskit.algorithms.TrotterQRTE
is deprecated and superseded byqiskit.algorithms.time_evolvers.trotterization.TrotterQRTE
.Using
QuantumInstance
orBackend
is deprecated and superseded byBaseSampler
in the following classes:Using
QuantumInstance
orBackend
orExpectationBase
is deprecated and superseded byBaseSampler
in the following static method:get_fidelity()
Function
eval_observables()
is deprecated and superseded byestimate_observables()
function.
Quantum Information Deprecations¶
The
PauliTable
andStabilizerTable
are deprecated and will be removed in a future release. Instead, thePauliList
should be used. With this change,table()
has been deprecated so that you should operate directly fromtableau()
without it.
Pulse Deprecations¶
Assignment of complex values to
ParameterExpression
in any Qiskit Pulse object now raises aPendingDeprecationWarning
. This will align the Pulse module with other modules where such assignment wasn't possible to begin with. The typical use case for complex parameters in the module was the SymbolicPulse library. As of Qiskit-Terra 0.23.0 all library pulses were converted from complex amplitude representation to real representation using two floats (amp,angle), as used in theScalableSymbolicPulse
class. This eliminated the need for complex parameters. Any use of complex parameters (and particularly custom-built pulses) should be converted in a similar fashion to avoid the use of complex parameters.
Bug Fixes¶
The
AmplitudeEstimation
class now correctly warns if anEstimationProblem
with a setis_good_state
property is passed as input, as it is not supported and ignored. Previously, the algorithm would silently ignore this option leading to unexpected results.
QuantumCircuit.append()
will now correctly raise an error if given an incorrect number of classical bits to apply to an operation. Fix #9385.
The
BarrierBeforeFinalMeasurements
andMergeAdjacentBarriers
transpiler passes previously had a non-deterministic order of their emittedBarrier
instructions. This did not change the semantics of circuits but could, in limited cases where there were non-full-width barriers, cause later stochastic transpiler passes to see a different topological ordering of the circuit and consequently have different outputs for fixed seeds. The passes have been made deterministic to avoid this.
The return type of
run()
will now always be the same as that of its first argument. Passing a single circuit returns a single circuit, passing a list of circuits, even of length 1, returns a list of circuits. See #9798.
Fixed a bug where
PauliOp.adjoint()
did not return a correct value for Paulis with complex coefficients, likePauliOp(Pauli("iX"))
. Fixed #9433.
Fixed an issue with the circuit drawer function
circuit_drawer()
andQuantumCircuit.draw()
method when displaying instruction parameters that typeQuantumCircuit
which would result in an illegible drawing. Fixed #9908
Fixed an issue with the circuit drawer function
circuit_drawer()
andQuantumCircuit.draw()
method when using thetext
method and the argumentvertical_compression="low"
where it would use an incorrect character for the top-right corner of boxes used to represent gates in the circuit.
Fixed an issue with the
Gate.control()
method where it previously would incorrectly handlestr
orNone
input types for thectrl_state
argument.
Fixed an edge case in the construction of
Pauli
instances; a string with an optional phase and no qubits is now a valid label, making an operator with no qubits (such asPauli("-i")
). This was already possible when using the array forms, or empty slices. Fixed #9720.
Fixed an issue when using the
pulse
macromeasure()
when working with aBackendV2
based backend. Previously, trying to useqiskit.pulse.macros.measure()
with aBackendV2
based backend would have resulted in an error. Fixed #9488
Fixed an issue with the
marginal_distribution()
function where it would incorrectly raise an error when an input counts dictionary was using a numpy integer type instead of the Python int type. The underlying function always would handle the different types correctly, but the input type checking was previously incorrectly raising aTypeError
in this case.
Fixed a bug where
Parameter.is_real()
did not returnNone
when the parameter is not bound. Fixed #8619.
Circuits containing
C3SXGate
can now be output and read in again safely from the OpenQASM 2.0 exporter (QuantumCircuit.qasm()
) and parser (QuantumCircuit.from_qasm_str()
).
Fixed a bug in QPY (
qiskit.qpy
) where circuits containing gates of classMCXGate
,MCXGrayCode
, andMCXRecursive
, andMCXVChain
would fail to serialize. See #9390.
Fixed the transpiler routing passes
StochasticSwap
,SabreSwap
,LookaheadSwap
, andBasicSwap
so that they consistently raise aTranspilerError
when their respective.run()
method is called if the passes were initialized withcoupling_map=None
. Previously, these passes would raise errors in this case but they were all caused by side effects and the specific exception was not predictable. Fixed #7127
Manually setting an item in
QuantumCircuit.data
will now correctly allow the operation to be any object that implementsOperation
, not just acircuit.Instruction
. Note that any manual mutation ofQuantumCircuit.data
is discouraged; it is not usually any more efficient than building a new circuit object, as checking the invariants surrounding parametrised objects can be surprisingly expensive.
Fixed a bug when constructing
DAGDependency
from within theTemplateOptimization
transpiler pass, which could lead to incorrect optimizations.
Fixed a bug in
TensoredOp.to_matrix()
where the global coefficient of the operator was multiplied to the final matrix more than once. Now, the global coefficient is correclty applied, independent of the number of tensored operators or states. Fixed #9398.
Fixed global-phase handling in the
UnrollCustomDefinitions
transpiler pass if the instruction in question had a global phase, but no instructions in its definition field.
Fixed the the type annotations for the
transpile()
function. The return type is now narrowed correctly depending on whether a single circuit or a list of circuits was passed.
Fixed a bug where
IterativePhaseEstimation
was generating the wrong circuit, causing the algorithm to fail for simple cases. Fixed #9280.
A bug has been fixed which had allowed broadcasting when a
PauliList
is initialized fromPauli
s or labels. For instance, the codePauliList(["XXX", "Z"])
now raises aValueError
rather than constructing the equivalent ofPauliList(["XXX", "ZZZ"])
.
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will no longer emit duplicate definitions for gates that appear in other gates' definitions. See #7771, #8086, #8402, #8558, and #9805.
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will now handle multiple and nested definitions ofUnitaryGate
. See #4623, #6712, #7772, and #8222.
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will now output definitions for gates used only in other gates' definitions in a correct order. See #7769 and #7773.
Standard gates defined by Qiskit, such as
RZXGate
, will now have properly parametrised definitions when exported using the OpenQASM 2 exporter (QuantumCircuit.qasm()
). See #7172.
Quantum volume circuits (
QuantumVolume
) are now supported by the OpenQASM 2 exporter (QuantumCircuit.qasm()
). See #6466 and #7051.
The OpenQASM 2 exporter will now output gates with no known definition with
opaque
statements, rather than failing. See #5036.
An issue that prevented
transpile()
from working when passed a list ofCouplingMap
objects was fixed. Note that passing such a list of coupling maps is deprecated and will not be possible starting with Qiskit Terra 0.25. Fixes #9885.
Previous to this release, the
figsize
argument ofplot_bloch_multivector()
was not used by the visualization, making it impossible to change its size (e.g. to shrink it for single-qubit states). This release fixes it by introducing a use for thefigsize
argument.
Fixed an issue in
transpile()
withoptimization_level=1
(as well as in the preset pass managers returned bygenerate_preset_pass_manager()
andlevel_1_pass_manager()
) where previously if therouting_method
andlayout_method
arguments were not set and no control flow operations were present in the circuit then in cases where routing was required theVF2PostLayout
transpiler pass would not be run. This was the opposite of the expected behavior becauseVF2PostLayout
is intended to find a potentially better performing layout after a heuristic layout pass and routing are run. Fixed #9936
Construction of a
Statevector
from aQuantumCircuit
containing zero-qubit operations will no longer raise an error. These operations impart a global phase on the resulting statevector.
Fixed an issue in tranpiler passes for padding delays, which did not respect target's constraints and inserted delays even for qubits not supporting
Delay
instruction.PadDelay
andPadDynamicalDecoupling
are fixed so that they do not pad any idle time of qubits such that the target does not supportDelay
instructions for the qubits. Also legacy scheduling passesASAPSchedule
andALAPSchedule
, which pad delays internally, are fixed in the same way. In addition,transpile()
is fixed to callPadDelay
with atarget
object so that it works correctly when called withscheduling_method
option. Fixed #9993
Fixed the type annotations on the
QuantumCircuit.assign_parameters()
method to correctly reflect the change in return type depending on the value of theinplace
argument.
Fixed a performance scaling issue with the
VF2Layout
andVF2PostLayout
passes in the preset pass managers andtranspile()
, which would occur when transpiling circuits with many connected components on large devices. Now the transpiler passes set upper bounds on the number of potential layouts that will be evaluated.
Fixed an issue in the
state_to_latex()
function where it would potentially produce invalid LaTeX due to unintended coefficient rounding. This could also result in errors when thestate_drawer()
was called. Fixed #9297.
Aer 0.12.0¶
No change
IBM Q Provider 0.20.2¶
No change
Qiskit 0.42.1¶
Terra 0.23.3¶
Prelude¶
Qiskit Terra 0.23.3 is a minor bugfix release.
Bug Fixes¶
Fixes a bug in the
Optimize1qGatesDecomposition
transformation pass where the score for substitutions was wrongly calculated when the gate errors are zero.
The method
ECRGate.inverse()
now returns anotherECRGate
instance rather than a custom gate, since it is self inverse.
Clip probabilities in the
QuantumState.probabilities()
andQuantumState.probabilities_dict()
methods to the interval[0, 1]
. This fixes roundoff errors where probabilities could e.g. be larger than 1, leading to errors in the shot emulation of the sampler. Fixed #9761.
Fixed a bug in the
BackendSampler
where the binary probability bitstrings were truncated to the minimal number of bits required to represent the largest outcome as integer. That means that if e.g.{"0001": 1.0}
was measured, the result was truncated to{"1": 1.0}
.
Fixed an issue with the
PassManagerConfig.from_backend()
constructor method when it was used with aBackendV1
based simulator backend. For some simulator backends which did not populate some optional fields the constructor would error. Fixed #9265 and #8546
Fixed the
BackendSampler
andBackendEstimator
to run successfully with a custombound_pass_manager
. Previously, the execution for single circuits with abound_pass_manager
would raise aValueError
because a list was not returned in one of the steps.
The
GateDirection
transpiler pass will no longer reject gates that have been given explicit calibrations, but do not exist in the generic coupling map or target.
Fixed an issue with the
CommutationChecker
class where it would attempt to internally allocate an array for \(2^{n}\) qubits when it only needed an array to represent \(n\) qubits. This could cause an excessive amount of memory for wide gates, for example a 4 qubit gate would require 32 gigabytes instead of 2 kilobytes. Fixed #9197
Getting empty calibration from
InstructionProperties
raises AttributeError has been fixed. Now it returnsNone
.
Fixed
qasm()
so that it appends;
afterreset
instruction.
Register and parameter names will now be escaped during the OpenQASM 3 export (
qasm3.dumps()
) if they are not already valid identifiers. Fixed #9658.
QPY (using
qpy.load()
) will now correctly deserializeStatePreparation
instructions. Previously, QPY would error when attempting to load a file containing one. Fixed #8297.
Fixed a bug in
random_circuit()
with 64 or more qubits andconditional=True
, where the resulting circuit could have an incorrectly typed value in its condition, causing a variety of failures during transpilation or other circuit operations. Fixed #9649.
Fixed an issue with the
OneQubitEulerDecomposer
class's methodsangles()
andangles_and_phase()
would error if the input matrix was of a dtype other thancomplex
/np.cdouble
. In earlier releases this worked fine but this stopped working in Qiskit Terra 0.23.0 when the internals ofOneQubitEulerDecomposer
were re-written in Rust. Fixed #9827
Aer 0.12.0¶
No change
IBM Q Provider 0.20.2¶
No change
Qiskit 0.42.0¶
Terra 0.23.2¶
No change
Aer 0.12.0¶
Prelude¶
The Qiskit Aer 0.12.0 release highlights are:
Added a new GPU tensor network simulator based on cuTensorNet
Added a new
AerDensityMatrix
class to theqiskit_aer.quantum_info
moduleGreatly improving the runtime performance of the
AerSimulator
and the legacyQasmSimulator
,StatevectorSimulator
, andUnitarySimulator
classes by directly converting the inputQuantumCircuit
objects to an internal C++ representation instead of first serializing the circuit to aQasmQobj
. This improvement will be most noticeable for circuits with a small number of qubits or parameterized circuits using theparameter_binds
keyword argument.
New Features¶
Added a new class method
from_backend_properties()
to theNoiseModel
. This enables constructing a newNoiseModel
from aBackendProperties
object. Similar functionality used to be present in theNoiseModel.from_backend()
constructor, however it was removed since aBackendProperties
object alone doesn't contain sufficient information to create aNoiseModel
object.
Added a new class,
AerDensityMatrix
, to theqiskit_aer.quantum_info
module. This class is used to provide the same interface to the upstreamDensityMatrix
class in Qiskit but backed by Qiskit Aer's simulation.
Added a new keyword argument,
abelian_grouping
, to theEstimator
. This argument is used to control whether theEstimator
will group the input observables into qubit-wise commutable observables which reduces the number of circuit executions required to compute the expectation value and improves the runtime performance of theEstimator
. By default this is set toTrue
.
AerState
has a new methodinitialize_density_matrix()
that sets a density matrix toAER::QV::DensityMatrix
. This method will be called inq.i.states.DensityMatrix
to initialize its data withndarray
.initialize_density_matrix()
has a boolean argument that specifies copy or share ofndarray
data. If the data is shared with C++ and python, the data must not be collected in python while C++ accesses it.
The overhead for running simulations with
run()
(for all simulator backend classess) has been greatly reduced. This was accomplished by no longer internally serializingQuantumCircuit
objects intoQasmQobj
and instead theQuantumCircuit
object directly to an internal C++ circuit structure used for simulation. This improvement is most noticeable for simulations of circuts with a small number of qubits or parameterized circuits using theparameter_binds
keyword argument ofrun()
. Note that pulse simualation (via the now deprecatedPulseSimulator
) and DASK-based simulation still use the internal serialization and will not see this performance improvement.
Added a new method to the
AerJob
,circuits()
, which returns a list ofQuantumCircuit
objects. This method returnsNone
if Qobj is used for simulation.
AerState
andAerStatevector
now support applyingKraus
operators. InAerStatevector
, one of the Kraus operators is applied randomly to the quantum state based on the error probabilities.
Added a new simulation method based on NVIDIA's cuTensorNet APIs of cuQuantum SDK. This provides a GPU accelerated general tensor network simulator that can simulate any quantum circuit, by internally translating the circuit into a tensor network to perform the simulation. To use this simulation method, set
method="tensor_network"
anddevice="GPU"
when initializing anAerSimulator
object. For example:from qiskit_aer import AerSimulator tensor_net_sim = AerSimulator(method="tensor_network", device="GPU")
This method supports both statevector and density matrix simulations. Noise simulation can also be done with a density matrix single shot simulation if there are not any
SaveStatevector
operations in the circuit.This new simulation method also supports parallelization with multiple GPUs and MPI processes by using tensor network slicing technique. However, this type of simulation will likely take a very long time if the input circuits are complicated.
The
BLA_VENDOR
environment variable can now be specified to use a different BLAS library when building Qiskit Aer from source. By default if this is not specified OpenBLAS will be used by default. If the BLAS library specified in BLA_VENDOR` can not be found then the Cmake build process will stop.
Known Issues¶
This release of Qiskit Aer is not compatible with the Conan 2.X release series. If you are building Qiskit Aer from source manually ensure that you are using a Conan 1.x release. Compatibility with newer versions of Conan will be fixed in a future release. You can refer to issue #1730 for more details.
Upgrade Notes¶
The default behavior of the
Estimator
primitive will now group the input observable into qubit-wise commutable observables. The grouping reduces the number of circuits to be executed and improves the performance. If you desire the previous behavior you can initialize yourEstimator
instance with the keyword argumentabelian_grouping=False
.
Removed the usage of primitives with the context manager and the initialization with circuits, (observables only for Estimator), and parameters which has been deprecated in the Qiskit Terra 0.22.0 release in October 2022.
The behavior of
run()
method has changed when invalid or otherwise unsimulatableQuantumCircuit
objects are passed as an input. Previously, in these cases therun()
method would return anAerJob
whoseresult()
method would return aResult
with theERROR
orPARTIAL COMPLETED
(depending on whether all the circuit inputs or only some were invalid or not). Starting in this release instead of returning a result object with these statuses an exception will be raised instead. This change was necessary because of the performance improvements by no longer internally serializing theQuantumCircuit
objects to a Qobj before passing it to C++, instead the direct conversion fromQuantumCircuit
now errors directly when trying to simulate a circuit Qiskit Aer is unable to execute. If you desire the previous behavior you can build Qiskit Aer in standalone mode and manually serialize yourQuantumCircuit
objects to a JSON representation of theQasmQobj
which you then pass to the standalone Aer binary which will retain the previous behavior.
A deprecated method
add_nonlocal_quantum_error()
inNoiseModel
has been removed. No alternative method is available. If you want to add non-local quantum errors, you should write a transpiler pass that inserts your own quantum error into a circuit, and run the pass just before running the circuit on Aer simulator.
The
NoiseModel.from_backend()
now has changed not to acceptBackendProperties
object as abackend
argument. Use newly addedNoiseModel.from_backend_properties()
method instead.
A deprecated
standard_gates
argument broadly used in several methods and functions (listed below) acrossnoise
module has been removed.NoiseModel.from_backend()
andnoise.device.basic_device_gate_errors()
kraus_error()
,mixed_unitary_error()
,pauli_error()
anddepolarizing_error()
innoise.errors.standard_errors
QuantumError.__init__()
No alternative means are available because the user should be agnostic about how the simulator represents noises (quantum errors) internally.
The constructor of
QuantumError
has now dropped the support of deprecated json-like input fornoise_ops
argument. Use the new styple input fornoise_ops
argument instead, for example,from qiskit.circuit.library import IGate, XGate from qiskit_aer.noise import QuantumError error = QuantumError([ ((IGate(), [1]), 0.9), ((XGate(), [1]), 0.1), ]) # json-like input is no longer accepted (the following code fails) # error = QuantumError([ # ([{"name": "I", "qubits": [1]}], 0.9), # ([{"name": "X", "qubits": [1]}], 0.1), # ])
Also it has dropped deprecated arguments:
number_of_qubits
: UseQuantumCircuit
to definenoise_ops
instead.atol
: UseQuantumError.atol
attribute instead.standard_gates
: No alternative is available (users should not too much care about internal representation of quantum errors).
The deprecated
noise.errors.errorutils
module has been entirely removed and no alternatives are available. All functions in the module were helper functions meant to be used only for implementing functions instandard_errors
(i.e. they should have been provided as private functions) and no longer used in it.
The deprecated
utils.noise_remapper
have been entirely removed and no alternatives are available since the C++ code now automatically truncates and remaps noise models if it truncates circuits.
All deprecated functions (
pauli_operators()
andreset_operators()
) and class (NoiseTransformer
) inutils.noise_transformation
module have been removed, and no alternatives are available. They were in fact private functions/class used only for implementingapproximate_quantum_error()
and should not have been public.
The previously deprecated
qobj
argument name of theAerSimulator
andPulseSimulator
classes'run()
method has now been removed. This argument name was deprecated as part of the Qiskit Aer 0.8.0 release and has been by thecircuits
andschedules
argument name respectively.
Aer's
setup.py
has been updated to no longer attempt to make calls topip
to install build requirements, both manually and via thesetup_requires
option insetuptools.setup
. The preferred way to build Aer is to use a PEP 517-compatible builder such as:pip install .
This change means that a direct call to
setup.py
will no longer work if the build requirements are not installed. This is inline with modern Python packaging guidelines.
Deprecation Notes¶
Support for running Qiskit Aer with Python 3.7 support has been deprecated and will be removed in a future release. This means starting in a future release you will need to upgrade the Python version you're using to Python 3.8 or above.
The
PulseSimulator
backend has been deprecated and will be removed in a future release. If you're using thePulseSimulator
backend to perform pulse level simulation, instead you should use the Qiskit Dynamics library instead to perform the simulation. Qiskit Dynamics provides a more flexible and robust pulse level simulation framework than thePulseSimulator
backend.
The
qobj()
method of theAerJob
class is now deprecated and will be removed in a future release. The use of the qobj format as input torun()
has been deprecated since qiskit-aer 0.9.0 and in most cases this method would returnNone
now anyway. If you'd like to get the input to therun()
method now you can use thecircuits()
method instead, which will return theQuantumCircuit
objects that were simulated in the job.
A
warnings
argument broadly used in several methods and functions acrossnoise
module has been deprecated in favor of the use of filtering functions in Python's standardwarnings
library.
Bug Fixes¶
Fixed an issue when creating a new
AerStatevector
instance from anumpy.ndarray
that had non-contiguous memory. Previously, this would result in unexpected behavior (and a potential error) as theAerStatevector
assumed the input array was contiguous. This has been fixed so that memory layout is checked and thenumpy.ndarray
will be copied internally as a contiguous array before using it.
Fixed an issue with the
Sampler
class where it would previously fail if the inputQuantumCircuit
contained multiple multiple classical registers. Fixed #1679
The bits count of classical register used on the GPU was not set before calculating free available memory for chunks that causes infinite loop. So this fix set bits count before allocating chunks if batch shots execution is enabled.
Fix build errors and test errors when enabling GPU but disabling cuQuantum.
Fixed an issue in the matrix product state simulation method (i.e. setting the keyword argument
method="matrix_product_state"
when initializing anAerSimulator
object) where the simulator would incorrectly sort the qubits prior to performing measurment potentially resulting in an infinite loop. This has been fixed so the measurement of the qubits occurs in the order of the current MPS structure and then sorting afterwards as a post-processing step. This also will likely improve the performance of the simulation method and enable more accurate representation of entangled states. Fixed #1694
The
AerSimulator
backend with methods:statevector
density_matrix
matrix_product_state
stabilizer
now report that they support
break_loop
andcontinue_loop
instructions when used as backends for the Terratranspile()
function. The simulators already did support these, but had just not been reporting it.
IBM Q Provider 0.20.2¶
This release removes the overly restrictive version constraints set in the
requirements for the package added in 0.20.1. For the 0.20.1 the only dependency
that was intended to have a version cap was the requests-ntlm
package as its
new release was the only dependency which currently has an incompatibility with
qiskit-ibmq-provider
. The other version caps which were added as part of
0.20.1 were causing installation issues in several environments because it made
the qiskit-ibmq-provider
package incompatible with the dependency versions
used in other packages.
Qiskit 0.41.1¶
Terra 0.23.2¶
Prelude¶
The Qiskit Terra 0.23.2 patch release fixes further bugs identified in the 0.23 series.
Bug Fixes¶
Add the following Clifford gates, that already exist in the circuit library, to the
Clifford
class:SXGate
,SXdgGate
,CYGate
,DCXGate
,iSwapGate
andECRGate
.
Add a decomposition of an
ECRGate
into Clifford gates (up to a global phase) to the standard equivalence library.
Fixed an issue with the
BackendV2Converter
class when wrapping aBackendV1
-based simulator. It would error if either theonline_date
field in theBackendConfiguration
for the simulator was not present or if the simulator backend supported ideal implementations of gates that involve more than 1 qubit. Fixed #9562.
Fixed an incorrect return value of the method
BackendV2Converter.meas_map()
that had returned the backenddt
instead.
Fixed missing return values from the methods
BackendV2Converter.drive_channel()
,measure_channel()
,acquire_channel()
andcontrol_channel()
.
The deprecated
Qubit
andClbit
propertiesregister
andindex
will now be correctly round-tripped by QPY (qiskit.qpy
) in all valid usages ofQuantumRegister
andClassicalRegister
. In earlier releases in the Terra 0.23 series, this information would be lost. In versions before 0.23.0, this information was partially reconstructed but could be incorrect or produce invalid circuits for certain register configurations.The correct way to retrieve the index of a bit within a circuit, and any registers in that circuit the bit is contained within is to call
QuantumCircuit.find_bit()
. This method will return the correct information in all versions of Terra since its addition in version 0.19.
Fixed an issue with the
InstructionScheduleMap.has_custom_gate()
method, where it would always returnTrue
when theInstructionScheduleMap
object was created byTarget
. Fixed #9595.
Fixed a bug in the NumPy-based eigensolvers (
NumPyMinimumEigensolver
/NumPyEigensolver
) and in the SciPy-based time evolvers (SciPyRealEvolver
/SciPyImaginaryEvolver
), where operators that support conversion to sparse matrices, such asSparsePauliOp
, were converted to dense matrices anyways.
Fixed a bug in
generate_basic_approximations()
where the inverse of theSdgGate
was not correctly recognized asSGate
. Fixed #9585.
Fixed a bug in the
VQD
algorithm where the energy evaluation function could not process batches of parameters, making it incompatible with optimizers withmax_evals_grouped>1
. Fixed #9500.
Fixed bug in
QNSPSA
which raised a type error when the computed fidelities happened to be of typeint
but the perturbation was of typefloat
.
Aer 0.11.2¶
No change
IBM Q Provider 0.20.1¶
Since qiskit-ibmq-provider
is now deprecated, the dependencies have been bumped and fixed to the
latest working versions. There was an issue with the latest version of the requests-ntlm
package
which caused some end to end tests to fail.
Qiskit 0.41.0¶
Terra 0.23.1¶
Prelude¶
Qiskit Terra 0.23.1 is a small patch release to fix bugs identified in Qiskit Terra 0.23.0
Bug Fixes¶
An edge case of pickle
InstructionScheduleMap
with non-picklable iterablearguments
is now fixed. Previously, using an unpickleable iterable as thearguments
parameter toInstructionScheduleMap.add()
(such asdict_keys
) could cause parallel calls totranspile()
to fail. These arguments will now correctly be normalized internally tolist
.
Fixed a performance bug in
ReverseEstimatorGradient
where the calculation did a large amount of unnecessary copies if the gradient was only calculated for a subset of parameters, or in a circuit with many unparameterized gates.
Fixed a bad deprecation of
Register.name_format
which had made the class attribute available only from instances and not the class. When trying to send dynamic-circuits jobs to hardware backends, this would frequently cause the error:AttributeError: 'property' object has no attribute 'match'
Fixed #9493.
Aer 0.11.2¶
No change
IBM Q Provider 0.20.0¶
Prelude¶
This release of the qiskit-ibmq-provider
package marks the package as deprecated and will be retired and archived
in the future. The functionality in qiskit-ibmq-provider
has been supersceded by 3 packages qiskit-ibm-provider
,
qiskit-ibm-runtime
, and qiskit-ibm-experiment
which offer different subsets of functionality that
qiskit-ibmq-provider
contained. You can refer to the table here:
https://github.com/Qiskit/qiskit-ibmq-provider#migration-guides
for links to the migration guides for moving from qiskit-ibmq-provider
to its replacmeent packages.
Deprecation Notes¶
As of version 0.20.0,
qiskit-ibmq-provider
has been deprecated with its support ending and eventual archival being no sooner than 3 months from that date. The function provided by qiskit-ibmq-provider is not going away rather it has being split out to separate repositories. Please see https://github.com/Qiskit/qiskit-ibmq-provider#migration-guides.
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.
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.
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).
Calls to run a quantum circuit with
dynamic=True
now raise an error that asks the user to install the newqiskit-ibm-provider
.
Qiskit 0.40.0¶
This release officially deprecates the Qiskit IBMQ provider project as part of the Qiskit metapackage.
This means that in a future release, pip install qiskit
will no longer automatically include qiskit-ibmq-provider
.
If you're currently installing or listing qiskit
as a dependency to get qiskit-ibmq-provider
, you
should update to explicitly include qiskit-ibmq-provider
as well. This is being done as the Qiskit
project moves towards a model where the qiskit
package only contains the common core functionality for
building and compiling quantum circuits, programs, and applications.
Packages that build on that core or link Qiskit to hardware or simulators will be installable as separate packages.
Terra 0.23.0¶
Prelude¶
Qiskit Terra 0.23.0 is a major feature release that includes a multitude of new features and bugfixes. The highlights for this release are:
Support for importing OpenQASM 3 programs and creating
QuantumCircuit
objects from the input program via two new functionsqiskit.qasm3.load()
andqiskit.qasm3.loads()
.Improvements to the library of synthesis algorithms included in Qiskit. This includes the following new synthesis functions:
Clifford Synthesis
Linear Function Synthesis:
Permutation Synthesis:
SolovayKitaevDecomposition
detailed in: https://arxiv.org/abs/quant-ph/0505030New plugins for
HighLevelSynthesis
:
ACGSynthesisPermutation
KMSSynthesisPermutation
BasicSynthesisPermutation
New plugin for
UnitarySynthesis
Performance improvements to
SabreLayout
. The pass is now primarily written in Rust which can lead to a runtime improvement, however the bigger improvement is in the quality of the output (on average, fewerSwapGate
gates introduced bySabreSwap
). For example, runningSabreLayout
andSabreSwap
on Bernstein Vazirani circuits targeting theFakeSherbrooke
backend yields the following results:![]()
This release also deprecates support for running with Python 3.7. A DeprecationWarning
will now be emitted if you run Qiskit with Python 3.7. Support for Python 3.7 will be removed
as part of the 0.25.0 release (currently planned for release in July 2023), at which point
you will need Python 3.8 or newer to use Qiskit.
New Features¶
The pulses in
qiskit.pulse.library
can be initialized with new parameter
angle
, such that two float parameters could be provided:amp
andangle
. Initialization with complexamp
is still supported.
The
AdaptVQE
class has a new attribute,eigenvalue_history
, which is used to track the lowest achieved energy per iteration of the AdaptVQE. For example:from qiskit.algorithms.minimum_eigensolvers import VQE from qiskit.algorithms.minimum_eigensolvers.adapt_vqe import AdaptVQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import EvolvedOperatorAnsatz from qiskit.opflow import PauliSumOp from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp from qiskit.utils import algorithm_globals excitation_pool = [ PauliSumOp( SparsePauliOp(["IIIY", "IIZY"], coeffs=[0.5 + 0.0j, -0.5 + 0.0j]), coeff=1.0 ), PauliSumOp( SparsePauliOp(["ZYII", "IYZI"], coeffs=[-0.5 + 0.0j, 0.5 + 0.0j]), coeff=1.0 ), PauliSumOp( SparsePauliOp( ["ZXZY", "IXIY", "IYIX", "ZYZX", "IYZX", "ZYIX", "ZXIY", "IXZY"], coeffs=[ -0.125 + 0.0j, 0.125 + 0.0j, -0.125 + 0.0j, 0.125 + 0.0j, 0.125 + 0.0j, -0.125 + 0.0j, 0.125 + 0.0j, -0.125 + 0.0j, ], ), coeff=1.0, ), ] ansatz = EvolvedOperatorAnsatz(excitation_pool, initial_state=self.initial_state) optimizer = SLSQP() h2_op = PauliSumOp.from_list( [ ("IIII", -0.8105479805373266), ("ZZII", -0.2257534922240251), ("IIZI", +0.12091263261776641), ("ZIZI", +0.12091263261776641), ("IZZI", +0.17218393261915543), ("IIIZ", +0.17218393261915546), ("IZIZ", +0.1661454325638243), ("ZZIZ", +0.1661454325638243), ("IIZZ", -0.2257534922240251), ("IZZZ", +0.16892753870087926), ("ZZZZ", +0.17464343068300464), ("IXIX", +0.04523279994605788), ("ZXIX", +0.04523279994605788), ("IXZX", -0.04523279994605788), ("ZXZX", -0.04523279994605788), ] ) algorithm_globals.random_seed = 42 calc = AdaptVQE(VQE(Estimator(), ansatz, self.optimizer)) res = calc.compute_minimum_eigenvalue(operator=h2_op) print(calc.eigenvalue_history)
the returned value of
calc.history
should be roughly[-1.85727503]
as there is a single iteration.
The runtime logging when running the
AdaptVQE
has been improved. When running the class now,DEBUG
andINFO
level log messages will be emitted as the class runs.
Added a new transpiler pass,
CollectAndCollapse
, to collect and to consolidate blocks of nodes in a circuit. This pass is designed to be a general base class for combined block collection and consolidation. To be completely general, the work of collecting and collapsing the blocks is done via functions provided during instantiating the pass. For example, theCollectLinearFunctions
has been updated to inherit fromCollectAndCollapse
and collects blocks ofCXGate
andSwapGate
gates, and replaces each block with aLinearFunction
. TheCollectCliffords
which is also now based onCollectAndCollapse
, collects blocks of "Clifford" gates and replaces each block with aClifford
.The interface also supports the option
do_commutative_analysis
, which allows to exploit commutativity between gates in order to collect larger blocks of nodes. For example, collecting blocks of CX gates in the following circuit:qc = QuantumCircuit(2) qc.cx(0, 1) qc.z(0) qc.cx(1, 0)
using
do_commutative_analysis
enables consolidating the two CX gates, as the first CX gate and the Z gate commute.
Added a new class
BlockCollector
that implements various collection strategies, and a new classBlockCollapser
that implements various collapsing strategies. CurrentlyBlockCollector
includes the strategy to greedily collect all gates adhering to a given filter function (for example, collecting all Clifford gates), andBlockCollapser
includes the strategy to consolidate all gates in a block to a single object (or example, a block of Clifford gates can be consolidated to a singleClifford
).
Added a new
CollectCliffords
transpiler pass that collects blocks of Clifford gates and consolidates these blocks intoqiskit.quantum_info.Clifford
objects. This pass inherits fromCollectAndCollapse
and in particular supports the optiondo_commutative_analysis
. It also supports two additional optionssplit_blocks
andmin_block_size
. See the release notes forCollectAndCollapse
andCollectLinearFunctions
for additional details.
The
CollectLinearFunctions
transpiler pass has several new arguments on its constructor:do_commutative_analysis
: enables exploiting commutativity between gates in order to collect larger blocks of nodes.split_blocks
: enables spliting collected blocks into sub-blocks over disjoint subsets of qubits. For example, in the following circuit:qc = QuantumCircuit(4) qc.cx(0, 2) qc.cx(1, 3) qc.cx(2, 0) qc.cx(3, 1) qc.cx(1, 3)
the single block of CX gates over qubits
{0, 1, 2, 3}
can be split into two disjoint sub-blocks, one over qubits{0, 2}
and the other over qubits{1, 3}
.min_block_size
: allows to specify the minimum size of the block to be consolidated, blocks with fewer gates will not be modified. For example, in the following circuit:qc = QuantumCircuit(4) qc.cx(1, 2) qc.cx(2, 1)
the two CX gates will be consolidated when
min_block_size
is 1 or 2, and will remain unchanged whenmin_block_size
is 3 or larger.
Added a depth-efficient synthesis algorithm
synth_cnot_depth_line_kms()
for linear reversible circuitsLinearFunction
over the linear nearest-neighbor architecture, following the paper: https://arxiv.org/abs/quant-ph/0701194.
The
DAGCircuit.replace_block_with_op()
method will now return the newDAGOpNode
that is created when the block is replaced. Previously, calling this method would not return anything.
Added a depth-efficient synthesis algorithm
synth_permutation_depth_lnn_kms()
forPermutation
over the linear nearest-neighbor architecture, following the paper: https://arxiv.org/abs/quant-ph/0701194
Added a new class
PermutationGate
for representing permutation logic as a circuit element. Unlike the existingPermutation
circuit library element which had a static definition this new class avoids synthesizing a permutation circuit when it is declared. This delays the actual synthesis to the transpiler. It also allows enables using several different algorithms for synthesizing permutations, which are available as high-level-synthesis permutation plugins.Another key feature of the
PermutationGate
is that implements the__array__
interface for efficiently returning a unitary matrix for a permutation.
Added several high-level-synthesis plugins for synthesizing permutations:
BasicSynthesisPermutation
: applies to fully-connected architectures and is based on sorting. This is the previously used algorithm for constructing quantum circuits for permutations.ACGSynthesisPermutation
: applies to fully-connected architectures but is based on the Alon, Chung, Graham method. It synthesizes any permutation in depth 2 (measured in terms of SWAPs).KMSSynthesisPermutation
: applies to linear nearest-neighbor architectures and corresponds to the recently added Kutin, Moulton, Smithline method.
For example:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import PermutationGate from qiskit.transpiler import PassManager from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPluginManager # Create a permutation and add it to a quantum circuit perm = PermutationGate([4, 6, 3, 7, 1, 2, 0, 5]) qc = QuantumCircuit(8) qc.append(perm, range(8)) # Print available plugin names for synthesizing permutations # Returns ['acg', 'basic', 'default', 'kms'] print(HighLevelSynthesisPluginManager().method_names("permutation")) # Default plugin for permutations # Returns a quantum circuit with size 6 and depth 3 qct = PassManager(HighLevelSynthesis()).run(qc) print(f"Default: {qct.size() = }, {qct.depth() = }") # KMSSynthesisPermutation plugin for permutations # Returns a quantum circuit with size 18 and depth 6 # but adhering to the linear nearest-neighbor architecture. qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("kms", {})]))).run(qc) print(f"kms: {qct.size() = }, {qct.depth() = }") # BasicSynthesisPermutation plugin for permutations # Returns a quantum circuit with size 6 and depth 3 qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("basic", {})]))).run(qc) print(f"basic: {qct.size() = }, {qct.depth() = }") # ACGSynthesisPermutation plugin for permutations # Returns a quantum circuit with size 6 and depth 2 qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("acg", {})]))).run(qc) print(f"acg: {qct.size() = }, {qct.depth() = }")
Added new classes for Quantum Fisher Information (QFI) and Quantum Geometric Tensor (QGT) algorithms using
primitives
,qiskit.algorithms.gradients.QFI
andqiskit.algorithms.gradients.LinCombQGT
, to the gradients module:qiskit.algorithms.gradients
. For example:from qiskit.circuit import QuantumCircuit, Parameter from qiskit.algorithms.gradients import LinCombQGT, QFI estimator = Estimator() a, b = Parameter("a"), Parameter("b") qc = QuantumCircuit(1) qc.h(0) qc.rz(a, 0) qc.rx(b, 0) parameter_value = [[np.pi / 4, 0]] qgt = LinCombQGT(estimator) qgt_result = qgt.run([qc], parameter_value).result() qfi = QFI(qgt) qfi_result = qfi.run([qc], parameter_value).result()
Added a new keyword argument,
derivative_type
, to the constructor for theLinCombEstimatorGradient
. This argument takes aDerivativeType
enum that enables specifying to compute only the real or imaginary parts of the gradient.
Added a new option
circuit_reverse_bits
to the user config file. This allows users to set a boolean for their preferred default behavior of thereverse_bits
argument of the circuit drawersQuantumCircuit.draw()
andcircuit_drawer()
. For example, adding a section to the user config file in the default location~/.qiskit/settings.conf
with:[default] circuit_reverse_bits = True
will change the default to display the bits in reverse order.
Added a new class
Z2Symmetries
toqiskit.quantum_info
which is used to identify any \(Z_2\) symmetries from an inputSparsePauliOp
.
Added a new pulse directive
TimeBlockade
. This directive behaves almost identically to the delay instruction, but will be removed before execution. This directive is intended to be used internally within the pulse builder and helpsScheduleBlock
represent instructions with absolute time intervals. This allows the pulse builder to convertSchedule
intoScheduleBlock
, rather than wrapping withCall
instructions.
Added primitive-enabled algorithms for Variational Quantum Time Evolution that implement the interface for Quantum Time Evolution. The
qiskit.algorithms.VarQRTE
class is used for real and theqiskit.algorithms.VarQITE
class is used for imaginary quantum time evolution according to a variational principle passed.Each algorithm accepts a variational principle which implements the
ImaginaryVariationalPrinciple
abstract interface. The following implementations are included:For example:
from qiskit.algorithms import TimeEvolutionProblem, VarQITE from qiskit.algorithms.time_evolvers.variational import ImaginaryMcLachlanPrinciple from qiskit.circuit.library import EfficientSU2 from qiskit.quantum_info import SparsePauliOp import numpy as np observable = SparsePauliOp.from_list( [ ("II", 0.2252), ("ZZ", 0.5716), ("IZ", 0.3435), ("ZI", -0.4347), ("YY", 0.091), ("XX", 0.091), ] ) ansatz = EfficientSU2(observable.num_qubits, reps=1) init_param_values = np.zeros(len(ansatz.parameters)) for i in range(len(ansatz.parameters)): init_param_values[i] = np.pi / 2 var_principle = ImaginaryMcLachlanPrinciple() time = 1 evolution_problem = TimeEvolutionProblem(observable, time) var_qite = VarQITE(ansatz, var_principle, init_param_values) evolution_result = var_qite.evolve(evolution_problem)
Added rules for converting
XXPlusYYGate
andXXMinusYYGate
to other gates to theSessionEquivalenceLibrary
. This enables runningtranspile()
targeting a backend orTarget
that uses these gates.
Added two new fake backends,
FakePrague
andFakeSherbrooke
to theqiskit.providers.fake_provider
module.FakePrague
provides a backend with a snapshot of the properties from the IBM Prague Egret R1 backend andFakeSherbrooke
provides a backend with a snapshot of the properties from the IBM Sherbrooke Eagle R3 backend.
Added a new keyword argument,
allow_unknown_parameters
, to theParameterExpression.bind()
andParameterExpression.subs()
methods. When set this new argument enables passing a dictionary containing unknown parameters to these methods without causing an error to be raised. Previously, this would always raise an error without any way to disable that behavior.
The
BaseEstimator.run()
method'sobservables
argument now accepts astr
or sequence ofstr
input type in addition to the other types already accepted. When used the input string format should match the Pauli string representation accepted by the constructor forPauli
objects.
Added a new constructor method
QuantumCircuit.from_instructions()
that enables creating aQuantumCircuit
object from an iterable of instructions. For example:from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit.circuit.quantumcircuitdata import CircuitInstruction from qiskit.circuit import Measure from qiskit.circuit.library import HGate, CXGate qr = QuantumRegister(2) cr = ClassicalRegister(2) instructions = [ CircuitInstruction(HGate(), [qr[0]], []), CircuitInstruction(CXGate(), [qr[0], qr[1]], []), CircuitInstruction(Measure(), [qr[0]], [cr[0]]), CircuitInstruction(Measure(), [qr[1]], [cr[1]]), ] circuit = QuantumCircuit.from_instructions(instructions) circuit.draw("mpl")
The
Clifford
class now takes an optionalcopy
keyword argument in its constructor. If set toFalse
, then aStabilizerTable
provided as input will not be copied, but will be used directly. This can have performance benefits, if the data in the table will never be mutated by any other means.
The performance of
Clifford.compose()
has been greatly improved for all numbers of qubits. For operators of 20 qubits, the speedup is on the order of 100 times.
Added a new synthesis function
synth_clifford_layers()
, for synthesizing aClifford
into layers. The algorithm is based on S. Bravyi, D. Maslov, Hadamard-free circuits expose the structure of the Clifford group, arxiv:2003.09412. This decomposes the Clifford into 8 layers of gates including two layers of CZ gates, and one layer of CX gates. For example, a 5-qubit Clifford circuit is decomposed into the following layers:┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐ q_0: ┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├ │ ││ ││ ││ ││ ││ ││ ││ │ q_1: ┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├ │ ││ ││ ││ ││ ││ ││ ││ │ q_2: ┤2 S2 ├┤2 CZ ├┤2 CX_dg ├┤2 H2 ├┤2 S1 ├┤2 CZ ├┤2 H1 ├┤2 Pauli ├ │ ││ ││ ││ ││ ││ ││ ││ │ q_3: ┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├ │ ││ ││ ││ ││ ││ ││ ││ │ q_4: ┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├ └─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘
This method will allow to decompose a
Clifford
in 2-qubit depth \(7n+2\) for linear nearest neighbor (LNN) connectivity.
The return types for the
power()
methods on several standard library gate classes have been updated to return more specific gate objects that result in a less lossy and more efficient output. For example, runningpower()
now returns anIGate
instance instead ofUnitaryGate
as was done previously.The full list of output types that have been improved are:
Table 17 Output for power()
¶Gate Class
Output Class from
power()
The
EquivalenceLibrary
is now represented internally as aPyDiGraph
, this underlying graph object can be accesed from the newgraph
attribute. This attribute is intended for use internally in Qiskit and therefore should always be copied before being modified by the user to prevent possible corruption of the internal equivalence graph.
The
Operator.from_circuit()
constructor method now will reverse the output permutation caused by the routing/swap mapping stage of the transpiler. By default if a transpiled circuit had Swap gates inserted the output matrix will have that permutation reversed so the returned matrix will be equivalent to the original un-transpiled circuit. If you'd like to disable this default behavior theignore_set_layout
keyword argument can be set toTrue
to do this (in addition to previous behavior of ignoring the initial layout from transpilation). If you'd like to manually set a final layout you can use the newfinal_layout
keyword argument to pass in aLayout
object to use for the output permutation.
Added support to the
GateDirection
transpiler pass to handle the the symmetricRXXGate
,RYYGate
, andRZZGate
gates. The pass will now correctly handle these gates and simply reverse the qargs order in place without any other modifications.
Added support for using the Python exponentiation operator,
**
, withGate
objects is now supported. It is equivalent to running theGate.power()
method on the object.For example:
from qiskit.circuit.library import XGate sx = XGate() ** 0.5
Added new
GaussianSquareDrag
pulse shape to theqiskit.pulse.library
module. This pulse shape is similar toGaussianSquare
but uses theDrag
shape during its rise and fall. The correction from the DRAG pulse shape can suppress part of the frequency spectrum of the rise and fall of the pulse which can help avoid exciting spectator qubits when they are close in frequency to the drive frequency of the pulse.
Added a new keyword argument,
method
, to the constructors for theFiniteDiffEstimatorGradient
andFiniteDiffSamplerGradient
classes. Themethod
argument accepts a string to indicate the computation method to use for the gradient. There are three methods, available"central"
,"forward"
, and"backward"
. The definition of the methods are:Method
Computation
"central"
\(\frac{f(x+e)-f(x-e)}{2e}\)
"forward"
\(\frac{f(x+e) - f(x)}{e}\)
"backward"
\(\frac{f(x)-f(x-e)}{e}\)
where \(e\) is the offset epsilon.
All gradient classes in
qiskit.algorithms.gradients
now preserve unparameterized operations instead of attempting to unroll them. This allows to evaluate gradients on custom, opaque gates that individual primitives can handle and keeps a higher level of abstraction for optimized synthesis and compilation after the gradient circuits have been constructed.
Added a
TranslateParameterizedGates
pass to map only parameterized gates in a circuit to a specified basis, but leave unparameterized gates untouched. The pass first attempts unrolling and finally translates if a parameterized gate cannot be further unrolled.
The
CollectCliffords
transpiler pass has been expanded to collect and combine blocks of "clifford gates" intoClifford
objects, where "clifford gates" may now also include objects of typeLinearFunction
,Clifford
, andPauliGate
. For example:from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import LinearFunction, PauliGate from qiskit.quantum_info.operators import Clifford from qiskit.transpiler.passes import CollectCliffords from qiskit.transpiler import PassManager # Create a Clifford cliff_circuit = QuantumCircuit(2) cliff_circuit.cx(0, 1) cliff_circuit.h(0) cliff = Clifford(cliff_circuit) # Create a linear function lf = LinearFunction([[0, 1], [1, 0]]) # Create a pauli gate pauli_gate = PauliGate("XYZ") # Create a quantum circuit with the above and also simple clifford gates. qc = QuantumCircuit(4) qc.cz(0, 1) qc.append(cliff, [0, 1]) qc.h(0) qc.append(lf, [0, 2]) qc.append(pauli_gate, [0, 2, 1]) qc.x(2) # Run CollectCliffords transpiler pass qct = PassManager(CollectCliffords()).run(qc)
All the gates will be collected and combined into a single
Clifford
. Thus the final circuit consists of a singleClifford
object.
CouplingMap
is now implicitly iterable, with the iteration being identical to iterating through the output ofCouplingMap.get_edges()
. In other words,from qiskit.transpiler import CouplingMap coupling = CouplingMap.from_line(3) list(coupling) == list(coupling.get_edges())
will now function as expected, as will other iterations. This is purely a syntactic convenience.
Added a new function
synth_cnot_count_full_pmh()
which is used to synthesize linear reversible circuits for all-to-all architectures using the Patel, Markov and Hayes method. This function is identical to the availableqiskit.transpiler.synthesis.cnot_synth()
function but has a more descriptive name and is more logically placed in the package tree. This new function supersedes the legacy function which will likely be deprecated in a future release.
InstructionScheduleMap
has been updated to store backend calibration data in the format of PulseQobj JSON and invokes conversion when the data is accessed for the first time, i.e. lazy conversion. This internal logic update drastically improves the performance of loading backend especially with many calibration entries.
New module
qiskit.pulse.calibration_entries
has been added. This contains several wrapper classes for different pulse schedule representations.ScheduleDef
CallableDef
PulseQobjDef
These classes implement the
get_schedule()
andget_signature()
methods that returns pulse schedule and parameter names to assign, respectively. These classes are internally managed by theInstructionScheduleMap
or backendTarget
, and thus they will not appear in a typical user programs.
Introduced a new subclass
ScalableSymbolicPulse
, as a subclass ofSymbolicPulse
. The new subclass behaves the same asSymbolicPulse
, except that it assumes that the envelope of the pulse includes a complex amplitude pre-factor of the form \(\text{amp} * e^{i \times \text{angle}}\). This envelope shape matches many common pulses, including all of the pulses in the Qiskit Pulse library (which were also converted toamp
,angle
representation in this release).The new subclass removes the non-unique nature of the
amp
,angle
representation, and correctly compares pulses according to their complex amplitude.
Added a new keyword argument,
dtype
, to thePauliSumOp.from_list()
method. When specified this argument can be used to specify thedtype
of the numpy array allocated for theSparsePauliOp
used internally by the constructedPauliSumOp
.
Support for importing OpenQASM 3 programs into Qiskit has been added. This can most easily be accessed using the functions
qasm3.loads()
andqasm3.load()
, to load a program directly from a string and indirectly from a filename, respectively. For example, one can now do:from qiskit import qasm3 circuit = qasm3.loads(""" OPENQASM 3.0; include "stdgates.inc"; qubit q; qubit[5] qr; bit c; bit[5] cr; h q; c = measure q; if (c) { h qr[0]; cx qr[0], qr[1]; cx qr[0], qr[2]; cx qr[0], qr[3]; cx qr[0], qr[4]; } else { h qr[4]; cx qr[4], qr[3]; cx qr[4], qr[2]; cx qr[4], qr[1]; cx qr[4], qr[0]; } cr = measure qr; """)
This will load the program into a
QuantumCircuit
instance in the variablecircuit
.Not all OpenQASM 3 features are supported at first, because Qiskit does not yet have a way to represent advanced classical data processing. The capabilities of the importer will increase along with the capabilities of the rest of Qiskit. The initial feature set of the importer is approximately the same set of features that would be output by the exporter (
qasm3.dump()
andqasm3.dumps()
).Note that Qiskit's support of OpenQASM 3 is not meant to provide a totally lossless representation of
QuantumCircuit
s. For that, consider usingqiskit.qpy
.
The
primitives
-based gradient classes defined by theBaseEstimatorGradient
andBaseSamplerGradient
abstract classes have been updated to simplify extending the base interface. There are three new internal overridable methods,_preprocess()
,_postprocess()
, and_run_unique()
._preprocess()
enables a subclass to customize the input gradient circuits and parameters,_postprocess
enables to customize the output result, and_run_unique
enables calculating the gradient of a circuit with unique parameters.
The
SabreLayout
transpiler pass has greatly improved performance as it has been re-written in Rust. As part of this rewrite the pass has been transformed from an analysis pass to a transformation pass that will run both layout and routing. This was done to not only improve the runtime performance but also improve the quality of the results. The previous functionality of the pass as an analysis pass can be retained by manually setting therouting_pass
argument or using the newskip_routing
argument.
The
SabreLayout
transpiler pass has a new constructor argumentlayout_trials
. This argument is used to control how many random number generator seeds will be attempted to runSabreLayout
with. When set the SABRE layout algorithm is runlayout_trials
number of times and the best quality output (measured in the lowest number of swap gates added) is selected. These seed trials are executed in parallel using multithreading to minimize the potential performance overhead of running layout multiple times. By default if this is not specified theSabreLayout
pass will default to using the number of physical CPUs are available on the local system.
Added two new classes
SciPyRealEvolver
andSciPyImaginaryEvolver
that implement integration methods for time evolution of a quantum state. The value and standard deviation of observables as well as the times they are evaluated at can be queried asTimeEvolutionResult.observables
andTimeEvolutionResult.times
. For example:from qiskit.algorithms.time_evolvers.time_evolution_problem import TimeEvolutionProblem from qiskit.quantum_info import SparsePauliOp from qiskit.quantum_info.states.statevector import Statevector from qiskit.algorithms import SciPyImaginaryEvolver initial_state = Statevector.from_label("+++++") hamiltonian = SparsePauliOp("ZZZZZ") evolution_problem = TimeEvolutionProblem(hamiltonian, 100, initial_state, {"Energy":hamiltonian}) classic_evolver = SciPyImaginaryEvolver(num_timesteps=300) result = classic_evolver.evolve(evolution_problem) print(result.observables)
Added the
SolovayKitaev
transpiler pass to run the Solovay-Kitaev algorithm for approximating single-qubit unitaries using a discrete gate set. In combination with the basis translator, this allows to convert any unitary circuit to a universal discrete gate set, which could be implemented fault-tolerantly.This pass can e.g. be used after compiling to U and CX gates:
from qiskit import transpile from qiskit.circuit.library import QFT from qiskit.transpiler.passes.synthesis import SolovayKitaev qft = QFT(3) # optimize to general 1-qubit unitaries and CX transpiled = transpile(qft, basis_gates=["u", "cx"], optimization_level=1) skd = SolovayKitaev() # uses T Tdg and H as default basis discretized = skd(transpiled) print(discretized.count_ops())
The decomposition can also be used with the unitary synthesis plugin, as the "sk" method on the
UnitarySynthesis
transpiler pass:from qiskit import QuantumCircuit from qiskit.quantum_info import Operator from qiskit.transpiler.passes import UnitarySynthesis circuit = QuantumCircuit(1) circuit.rx(0.8, 0) unitary = Operator(circuit).data unitary_circ = QuantumCircuit(1) unitary_circ.unitary(unitary, [0]) synth = UnitarySynthesis(basis_gates=["h", "s"], method="sk") out = synth(unitary_circ) out.draw('mpl')
Random-circuit generation with
qiskit.circuit.random.random_circuit()
is now significantly faster for large circuits.
Random-circuit generation with
qiskit.circuit.random.random_circuit()
will now output all "standard" gates in Qiskit's circuit library (qiskit.circuit.library
). This includes two 4-qubit gatesC3SXGate
andRC3XGate
, and the allowed values ofmax_operands
have been expanded accordingly.
The
Optimize1qGatesDecomposition
transpiler pass has a new keyword argument,target
, on its constructor. This argument can be used to specify aTarget
object that represnts the compilation target. If used it superscedes thebasis
argument to determine if an instruction in the circuit is present on the target backend.
The
UnrollCustomDefinitions
transpiler pass has a new keyword argument,target
, on its constructor. This argument can be used to specify aTarget
object that represnts the compilation target. If used it superscedes thebasis_gates
argument to determine if an instruction in the circuit is present on the target backend.
Added the
ReverseEstimatorGradient
class for a classical, fast evaluation of expectation value gradients based on backpropagation or reverse-mode gradients. This class uses statevectors and thus provides exact gradients but scales exponentially in system size. It is designed for fast reference calculation of smaller system sizes. It can for example be used as:from qiskit.circuit.library import EfficientSU2 from qiskit.quantum_info import SparsePauliOp from qiskit.algorithms.gradients import ReverseEstimatorGradient observable = SparsePauliOp.from_sparse_list([("ZZ", [0, 1], 1)], num_qubits=10) circuit = EfficientSU2(num_qubits=10) values = [i / 100 for i in range(circuit.num_parameters)] gradient = ReverseEstimatorGradient() result = gradient.run([circuit], [observable], [values]).result()
Added a new keyword argument,
use_dag
to the constructor for theOneQubitEulerDecomposer
class. Whenuse_dag
is set toTrue
the output from the decomposer will be aDAGCircuit
object instead ofQuantumCircuit
object. This is useful for transpiler passes that useOneQubitEulerDecomposer
(such asOptimize1qGatesDecomposition
) as working directly with aDAGCircuit
avoids the overhead of converting betweenQuantumCircuit
andDAGCircuit
.
Added the ability for analysis passes to set custom heuristic weights for the
VF2Layout
andVF2PostLayout
transpiler passes. If an analysis pass sets thevf2_avg_error_map
key in the property set, its value is used for the error weights instead of the error rates from the backend'sTarget
(orBackendProperties
forBackendV1
). The value should be anErrorMap
instance, where each value represents the avg error rate for all 1 or 2 qubit operation on those qubits. If a value isNaN
, the corresponding edge is treated as an ideal edge (or qubit for 1q operations). For example, an error map created as:from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap error_map = ErrorMap(3) error_map.add_error((0, 0), 0.0024) error_map.add_error((0, 1), 0.01) error_map.add_error((1, 1), 0.0032)
describes a 2 qubit target, where the avg 1q error rate is
0.0024
on qubit 0 and0.0032
on qubit 1, the avg 2q error rate for gates that operate on (0, 1) is 0.01, and (1, 0) is not supported by the target. This will be used for scoring if it's set for thevf2_avg_error_map
key in the property set whenVF2Layout
andVF2PostLayout
are run. For example:from qiskit.transpiler import AnalysisPass, PassManager, Target from qiskit.transpiler.passes import VF2Layout from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap from qiskit.circuit.library import CZGate, UGate from qiskit.circuit import Parameter class CustomVF2Scoring(AnalysisPass): """Set custom score for vf2.""" def run(self, dag): error_map = ErrorMap(3) error_map.add_error((0, 0), 0.0024) error_map.add_error((0, 1), 0.01) error_map.add_error((1, 1), 0.0032) self.property_set["vf2_avg_error_map"] = error_map target = Target(num_qubits=2) target.add_instruction( UGate(Parameter('theta'), Parameter('phi'), Parameter('lam')), {(0,): None, (1,): None} ) target.add_instruction( CZGate(), {(0, 1): None} ) vf2_pass = VF2Layout(target=target, seed=1234568942) pm = PassManager([CustomVF2Scoring(), vf2_pass])
That will run
VF2Layout
with the custom scoring fromerror_map
for a 2 qubitTarget
that doesn't contain any error rates.
Upgrade Notes¶
When initializing any of the pulse classes in
qiskit.pulse.library
:providing a complex
amp
argument with a finiteangle
will result inPulseError
now. For example, instead of callingGaussian(duration=100,sigma=20,amp=0.5j)
one should useGaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2)
instead now. The pulse envelope which used to be defined asamp * ...
is in turn defined asamp * exp(1j * angle) * ...
. This change was made to better support Qiskit Experiments where the amplitude and angle of pulses are calibrated in separate experiments.
For Python 3.7 singledispatchmethod is now a dependency. This was added to enable leveraging the method dispatch mechanism in the standard library of newer versions of Python. If you're on Python >= 3.8 there is no extra dependency required.
The previously deprecated
MSBasisDecomposer
transpiler pass available via theqiskit.transpiler.passes
module has been removed. It was originally deprecated as part of the Qiskit Terra 0.16.0 release (10-16-2020). Instead theBasisTranslator
transpiler pass should be used instead to translate a circuit into an appropriate basis with aRXXGate
EquivalenceLibrary
objects that are initialized with thebase
attribute will no long have a shared reference with theEquivalenceLibrary
passed in. In earlier releases if you mutatedbase
after it was used to create a newEquivalenceLibrary
instance both instances would reflect that change. This no longer is the case and updates tobase
will no longer be reflected in the newEquivalenceLibrary
. For example, if you created an equivalence library with:import math from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import XGate from qiskit.circuit.equivalence import EquivalenceLibrary original_lib = EquivalenceLibrary() qc = QuantumCircuit(1) qc.rx(math.pi, 0) original_lib.add_equivalence(XGate(), qc) new_lib = EquivalenceLibrary(base=original_lib)
if you modified
original_lib
with:import from qiskit.circuit.library import SXGate qc = QuantumCircuit(1) qc.rx(math.pi / 2, 0) original_lib.add_equivalence(SXGate(), qc)
in previous releases
new_lib
would also include the definition ofSXGate
after it was added tooriginal_lib
, but in this release this no longer will be the case. This change was made because of the change in internal data structure to be a graph, which improved performance of theEquivalenceLibrary
class, especially when there are multiple runs of theBasisTranslator
transpiler pass.
The
initial_state
argument for the constructor of theNLocal
class along with assigning directly to theNLocal.initial_state
atrribute must be aQuantumCircuit
now. Support for using other types for this argument and attribute is no longer supported. Support for other types was deprecated as part of the Qiskit Terra 0.18.0 release (July 2021).
The LaTeX array drawers (e.g.
array_to_latex
,Statevector.draw('latex')
) now use the same sympy function as the ket-convention drawer. This means it may render some numbers differently to previous releases, but will provide a more consistent experience. For example, it may identify new factors, or rationalize denominators where it did not previously. The defaultprecision
has been changed from 5 to 10.
The QPY version format version emitted by
dump()
has been increased to version 6. 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 6. This change was necessary to support the introduction ofScalableSymbolicPulse
which was handled by adding aclass_name_size
attribute to the header of the dumpedSymbolicPulse
objects.
The
__hash__
method for theSymbolicPulse
was removed. This was done to reflect the mutable nature (via parameter assignment) of this class which could result in errors when usingSymbolicPulse
in situtations where a hashable object was required. This means the builtinhash()
method and usingSymbolicPulse
as keys in dictionaries or set members will no longer work.
The names of
Register
instances (which includes instances ofQuantumRegister
andClassicalRegigster
) are no longer constrained to be valid OpenQASM 2 identifiers. This is being done as the restriction is overly strict as Qiskit becomes more decoupled from OpenQASM 2, and even the OpenQASM 3 specification is not so restrictive. If you were relying on registers having valid OpenQASM 2 identifier names, you will need to begin escaping the names. A simplistic version of this could be done, for example, by:import re import string def escape(name: str) -> str: out = re.sub(r"\W", "_", name, flags=re.ASCII) if not out or out[0] not in string.ascii_lowercase: return "reg_" + out return out
The
QuantumCircuit
methodsu1
,u2
,u3
, and their controlled variantscu1
,cu3
andmcu1
have been removed following their deprecation in Qiskit Terra 0.16.0. This was to remove gate names that were usually IBM-specific, in favour of the more general methodsp()
,u()
,cp()
andcu()
. The gate classesU1Gate
,U2Gate
andU3Gate
are still available for use withQuantumCircuit.append()
, so backends can still support bases with these gates explicitly given.
The
QuantumCircuit
methodscombine
andextend
have been removed following their deprecation in Qiskit Terra 0.17.0. This was done because these functions were simply less powerful versions ofQuantumCircuit.compose()
, which should be used instead.The removal of
extend
also means that the+
and+=
operators are no longer defined forQuantumCircuit
. Instead, you can use the&
and&=
operators respectively, which useQuantumCircuit.compose()
.
The previously deprecated functions:
qiskit.circuit.measure.measure()
andqiskit.circuit.reset.reset()
have been removed. These functions were deprecated in the Qiskit Terra 0.19.0 release (December, 2021). Instead you should use theQuantumCircuit.measure()
andQuantumCircuit.reset()
methods of theQuantumCircuit
object you wish to append aMeasure
orReset
operation to.
The previously deprecated
ParameterView
methods which were inherited fromset
have been removed fromParameterView
, the type returned byQuantumCircuit.parameters
. The specific methods which have been removed are:add()
difference()
difference_update()
discard()
intersection()
intersection_update()
issubset()
issuperset()
symmetric_difference()
symmetric_difference_update()
union()
update()
along with support for the Python operators:
ixor
:^=
isub
:-=
ior
:|=
These were deprecated in the Qiskit Terra 0.17.0 release (April, 2021). The
ParameterView
type is now a general sequence view type and doesn't support theseset
operations any longer.
The previously deprecated NetworkX converter methods for the
DAGCircuit
andDAGDependency
classes:DAGCircuit.to_networkx()
,DAGCircuit.from_networkx()
, andDAGDependency.to_networkx()
have been removed. These methods were originally deprecated as part of the Qiskit Terra 0.21.0 release (June, 2022). Qiskit has been using rustworkx as its graph library since the qiskit-terra 0.12.0 release and since then the NetworkX converter function have been a lossy process. They were originally added so that users could leverage NetworkX's algorithms library to leverage functionality not present inDAGCircuit
and/or rustworkx. However, since that time bothDAGCircuit
and rustworkx has matured and offers more functionality and theDAGCircuit
is tightly coupled to rustworkx for its operation and having these converter methods provided limited functionality and therefore have been removed.
tweedledum
has been removed as a core requirement of Qiskit Terra. The functionality provided (qiskit.circuit.classicalfunction
) is still available, iftweedledum
is installed manually, such as by:pip install tweedledum
This change was made because
tweedledum
development has slowed to the point of not keeping up with new Python and OS releases, and was blocking some Qiskit users from installing Qiskit.
The lazy optional checkers
HAS_MATPLOTLIB
,HAS_PIL
,HAS_PYLATEX
andHAS_PDFTOCAIRO
are no longer exposed fromqiskit.visualization
, having been deprecated in Qiskit Terra 0.21. The canonical location for these (and many other lazy checkers) isqiskit.utils.optionals
, and all four objects can be found there.
The previously deprecated
gate
argument to the constructor of theDecompose
transpiler pass, along with its matching attributeDecompose.gate
have been removed. The argument and attribute were deprecated as part of the Qiskit Terra 0.19.0 release (December, 2021). Instead thegates_to_decompose
argument for the constructor along with theDecompose.gates_to_decompose
attribute should be used instead. Thegates_to_decompose
argument and attribute should function the same, but has a more explicit name and also enables specifying lists of gates instead of only supporting a single gate.
The previously deprecated
label
argument for the constructor of theMCMT
andMCMTVChain
classes has been removed. It was deprecated as of the Qiskit Terra 0.19.0 release (Decemeber, 2021). Using thelabel
argument on these classes was undefined behavior as they are subclasses ofQuantumCircuit
instead ofInstruction
. This would result in the assigned label generally being ignored. If you need to assign alabel
to an instance ofMCMT
orMCMTVChain
you should convert them to anGate
instance withto_gate()
and then assign the desired label tolabel
attribute. For example:from qiskit.circuit.library import MCMT, XGate mcmt_circuit = MCMT(XGate(), 3, 2) mcmt_gate = mcmt_circuit.to_gate() mcmt_gate.label = "Custom MCMT X"
The
retworkx
dependency for Qiskit has been removed and replaced byrustworkx
library. These are the same packages, butrustworkx
is the new name forretworkx
which was renamed as part of their combined 0.12.0 release. If you were previously using retworkx 0.12.0 with Qiskit then you already installed rustworkx (retworkx 0.12.0 was just a redirect shim for backwards compatibility). This change was made to migrate to the new package name which will be the only supported package in the future.
The default behavior of the
SabreLayout
compiler pass has changed. The pass is no longer anAnalysisPass
and by default will compute the initital layout, apply it to the circuit, and will also runSabreSwap
internally and apply the swap mapping and set thefinal_layout
property set with the permutation caused by swap insertions. This means for users runningSabreLayout
as part of a customPassManager
will need to adjust the pass manager to account for this (unless they were setting therouting_pass
argument forSabreLayout
). This change was made in the interest of improving the quality output, the layout and routing quality are highly coupled andSabreLayout
will now run multiple parallel seed trials and to calculate which seed provides the best results it needs to perform both the layout and routing together. There are three ways you can adjust the usage in your custom pass manager. The first is to avoid using embedding in your preset pass manager. If you were previously running something like:from qiskit.transpiler import PassManager from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.passes.SabreLayout pm = PassManager() pm.append(SabreLayout(coupling_map) pm += common.generate_embed_passmanager(coupling_map)
to compute the layout and then apply it (which was typically followed by routing) you can adjust the usage to just simply be:
from qiskit.transpiler import PassManager from qiskit.transpiler.preset_passmanagers import common from qiskit.transpiler.passes.SabreLayout pm = PassManager() pm.append(SabreLayout(coupling_map)
as
SabreLayout
will apply the layout and you no longer need the embedding stage. Alternatively, you can specify therouting_pass
argument which will revertSabreLayout
to its previous behavior. For example, if you want to runSabreLayout
as it was run in previous releases you can do something like:from qiskit.transpiler.passes import SabreSwap, SabreLayout routing_pass = SabreSwap( coupling_map, "decay", seed=seed, fake_run=True ) layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)
which will have
SabreLayout
run as an analysis pass and just set thelayout
property set. The final approach is to leverage theskip_routing
argument onSabreLayout
, when this argument is set toTrue
it will skip applying the found layout and inserting the swap gates from routing. However, doing this has a runtime penalty asSabreLayout
will still be computing the routing and just does not use this data. The first two approaches outlined do not have additional overhead associated with them.
The layouts computed by the
SabreLayout
pass (when run without therouting_pass
argument) 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 theSabreLayout
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. Alternatively you can explicitly set therouting_pass
argument to an instance ofSabreSwap
to mirror the previous behavior ofSabreLayout
:from qiskit.transpiler.passes import SabreSwap, SabreLayout routing_pass = SabreSwap( coupling_map, "decay", seed=seed, fake_run=True ) layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)
which will mirror the behavior of the pass in the previous release. Note, that if you were using the
swap_trials
argument onSabreLayout
in previous releases when adjusting the usage to this form that you will need to settrials
argument on theSabreSwap
constructor if you want to retain the previous output with a fixed seed.
The exact circuit returned by
qiskit.circuit.random.random_circuit
for a given seed has changed. This is due to efficiency improvements in the internal random-number generation for the function.
The version requirement for the optional feature package
qiskit-toqm
, installable viapip install qiskit-terra[toqm]
, has been upgraded from version0.0.4
to0.1.0
. To use thetoqm
routing method withtranspile()
you must now use qiskit-toqm version0.1.0
or newer. Older versions are no longer discoverable by the transpiler.
The output
QuasiDistribution
from theSampler.run
method has been updated to filter out any states with a probability of zero. Now if a valid state is missing from the dictionary output it can be assumed to have a 0 probability. Previously, all possible outcomes for a given number of bits (e.g. for a 3 bit result000
,001
,010
,011
,100
,101
,110
, and111
) even if the probability of a given state was 0. This change was made to reduce the size of the output as for larger number of bits the output size could be quite large. Also, filtering the zero probability results makes the output consistent with other implementations ofBaseSampler
.
The behavior of the pulse builder when a
Schedule
is called has been upgraded. Called schedules are internally converted intoScheduleBlock
representation and now reference mechanism is always applied rather than appending the schedules wrapped by theCall
instruction. Note that the converted block doesn't necessary recover the original alignment context. This is simply an ASAP aligned sequence of pulse instructions with absolute time intervals. This is an upgrade of internal representation of called pulse programs and thus no API changes. However theCall
instruction andSchedule
no longer appear in the builder's pulse program. This change guarantees the generated schedule blocks are always QPY compatible. If you are filtering the output schedule instructions byCall
, you can access to theScheduleBlock.references
instead to retrieve the called program.
RZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
transpiler pass have been upgraded to generateScheduleBlock
. This change guarantees the transpiled circuits are always QPY compatible. If you are directly usingrescale_cr_inst()
, method from another program or a pass subclass to rescale cross resonance pulse of the device, now this method is turned into a pulse builder macro, and you need to use this method within the pulse builder context to adopts to new release. The method call injects a play instruction to the context pulse program, instead of returning aPlay
instruction with the stretched pulse.
Deprecation Notes¶
Support for running Qiskit with Python 3.7 support has been deprecated and will be removed in the qiskit-terra 0.25.0 release. This means starting in the 0.25.0 release you will need to upgrade the Python version you're using to Python 3.8 or above.
The class
LinearFunctionsSynthesis
class is now deprecated and will be removed in a future release. It has been superseded by the more generalHighLevelSynthesis
class which should be used instead. For example, you can instantiate an instance ofHighLevelSynthesis
that will behave the same way asLinearFunctionSynthesis
with:from qiskit.transpiler.passes import HighLevelSynthesis from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig HighLevelSynthesis( HLSConfig( linear_function=[("default", {})], use_default_on_unspecified=False, ) )
Support for passing in lists of argument values to the
transpile()
function is deprecated and will be removed in the 0.25.0 release. This is being done to facilitate greatly reducing the overhead for parallel execution for transpiling multiple circuits at once. If you're using this functionality currently you can calltranspile()
multiple times instead. For example if you were previously doing something like:from qiskit.transpiler import CouplingMap from qiskit import QuantumCircuit from qiskit import transpile qc = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) qc.measure_all() cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)] results = transpile([qc] * 6, coupling_map=cmaps)
instead you should run something like:
from itertools import cycle from qiskit.transpiler import CouplingMap from qiskit import QuantumCircuit from qiskit import transpile qc = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) qc.measure_all() cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)] results = [] for qc, cmap in zip(cycle([qc]), cmaps): results.append(transpile(qc, coupling_map=cmap))
You can also leverage
parallel_map()
ormultiprocessing
from the Python standard library if you want to run this in parallel.
The legacy version of the pulse drawer present in the
qiskit.visualization.pulse
has been deprecated and will be removed in a future release. This includes theScheduleDrawer
and :class`WaveformDrawer` classes. This module has been superseded by theqiskit.visualization.pulse_v2
drawer and the typical user APIpulse_drawer()
andPulseBlock.draw()
are already updated internally to useqiskit.visualization.pulse_v2
.
The
pulse.Instruction.draw()
method has been deprecated and will removed in a future release. The need for this method has been superseded by theqiskit.visualization.pulse_v2
drawer which doesn't requireInstrucion
objects to have their own draw method. If you need to draw a pulse instruction you should leverage thepulse_drawer()
instead.
The import
qiskit.circuit.qpy_serialization
is deprecated, as QPY has been promoted to the top level. You should import the same objects fromqiskit.qpy
instead. The old path will be removed in a future of Qiskit Terra.
The
qiskit.IBMQ
object is deprecated. This alias object lazily redirects attribute access toqiskit.providers.ibmq.IBMQ
. As theqiskit-ibmq-provider
package has been supersceded byqiskit-ibm-provider
package which maintains its own namespace maintaining this alias is no longer relevant with the new package. If you were relying on theqiskit.IBMQ
alias you should update your usage to useqiskit.providers.ibmq.IBMQ
directly instead (and also consider migrating toqiskit-ibm-provider
, see the migration guide for more details).
Several public methods of pulse Qobj converters have been deprecated and in a future release they will no longer be directly callable. The list of methods is:
In
InstructionToQobjConverter
,convert_acquire()
convert_bundled_acquires()
convert_set_frequency()
convert_shift_frequency()
convert_set_phase()
convert_shift_phase()
convert_delay()
convert_play()
convert_snapshot()
In
QobjToInstructionConverter
,convert_acquire()
convert_set_phase()
convert_shift_phase()
convert_set_frequency()
convert_shift_frequency()
convert_delay()
bind_pulse()
convert_parametric()
convert_snapshot()
Instead of calling any of these methods directly they will be implicitly selected when a converter instance is directly called. For example:
converter = QobjToInstructionConverter() converter(pulse_qobj)
The
qiskit.visualization.state_visualization.num_to_latex_ket()
andqiskit.visualization.state_visualization.num_to_latex_terms()
functions have been deprecated and will be removed in a future release. These function were primarily used internally by the LaTeX output fromStatevector.draw()
andDensityMatrix.draw()
which no longer are using these function and are leverging sympy for this instead. If you were using these functions you should cosinder using Sympy's nsimplify() latex() functions.
The method
Register.qasm()
is deprecated and will be removed in a future release. This method is found on the subclassesQuantumRegister
andClassicalRegister
. The deprecation is because theqasm()
method promotes a false view of the responsible party for safe conversion to OpenQASM 2; a single object alone does not have the context to provide a safe conversion, such as whether its name clashes after escaping it to produce a valid identifier.
The class-variable regular expression
Register.name_format
is deprecated and wil be removed in a future release. The names of registers are now permitted to be any valid Python string, so the regular expression has no use any longer.
The functions
qiskit.quantum_info.synthesis.decompose_clifford()
andqiskit.quantum_info.synthesis.decompose_cnot_dihedral()
are deprecated and will be removed in a future release. They are replaced by the two functionsqiskit.synthesis.synth_clifford_full()
andqiskit.synthesis.synth_cnotdihedral_full()
respectively.
Bug Fixes¶
Fixed an issue in the
PauliOp.adjoint()
method where it would return the correct value for Paulis with complex coefficients, for example:PauliOp(Pauli("iX"))
. Fixed #9433.
Fixed an issue with the amplitude estimation algorithms in the
qiskit.algorithms.amplitude_estimators
module (seeamplitude_estimators
) for the usage with primitives built from the abstractBaseSampler
primitive (such asSampler
andBackendSampler
). Previously, the measurement results were expanded to more bits than actually measured which for oracles with more than one qubit led to potential errors in the detection of the "good" quantum states for oracles.
Fixed an issue where the
QuantumCircuit.add_calibrations()
andDAGCircuit.add_calibrations()
methods had a mismatch in their behavior of parameter-formatting logic. PreviouslyDAGCircuit.add_calibrations()
tried to cast every parameter intofloat
,QuantumCircuit.add_calibrations()
used given parameters as-is. This would potentially cause an error when runningtranspile()
on aQuantumCircuit
with pulse gates as the parameters of the calibrations could be kept asParameterExpresion
objects.
Fixed a deserialization issue in QPY's (
qiskit.qpy
)load()
function where circuits containing gates of classMCXGate
,MCXGrayCode
,MCXRecursive
, andMCXVChain
would fail to deserialize. Fixed #9390.
Fixed an issue in
TensoredOp.to_matrix()
where the global coefficient of the operator was multiplied to the final matrix more than once. Now, the global coefficient is correctly applied, independent of the number of tensored operators or states. Fixed #9398.
The output from the
run()
method of the theBackendSampler
class now sets theshots
andstddev_upper_bound
attributes of the returnedQuasiDistribution
. Previously these attributes were missing which prevent some post-processing using the output. Fixed #9311
The OpenQASM 2 exporter method
QuantumCircuit.qasm()
will now emit higher precision floating point numbers for gate parameters by default. In addition, a tighter bound (\(1e-12\) instead of \(1e-6\)) is used for checking whether a given parameter is close to a fraction/power of \(\pi\). Fixed #7166.
Fixed support in the
primitives
module for runningQuantumCircuit
objects with control flow instructions (e.g.IfElseOp
). Previously, theBaseSampler
andBaseEstimator
base classes could not correctly normalize such circuits. However, executing these circuits is dependent on the particular implementation of the primitive supporting control flow instructions. This just fixed support to enable a particular implementation ofBaseSampler
orBaseEstimator
to use control flow instructions.
Fixed an issue with the
PauliOp.matmul()
method where it would return incorrect results withiI
. Fixed #8680.
Fixed an issue with the Approximate Quantum Compiler (
AQC
) class which caused it to return an incorrect circuit when the input unitary had a determinant of -1. Fixed #9327
Fixed an issue with the
QuantumCircuit.compose()
method where it would incorrectly reject valid qubit or clbit specifiers. This has been fixed so that the method now accepts the same set of qubit and clbit specifiers as otherQuantumCircuit
methods, such asappend()
. Fixed #8691.
Fixed an issue with the
QuantumCircuit.compose()
method where it would incorrectly map registers in conditions on the given circuit to complete registers on the base. Previously, the mapping was very imprecise; the bits used within each condition were not subject to the mapping, and instead an inaccurate attempt was made to find a corresponding register. This could also result in a condition on a smaller register being expanded to be on a larger register, which is not a valid transformation. Now, a condition on a single bit or a register will be composed to be on precisely the bits as defined by theclbits
argument. A new aliasing register will be added to the base circuit to facilitate this, if necessary. Fixed #6583.
Fixed an issue with the
transpile()
function when run withoptimization_level
set to1
,2
, or3
and nobackend
,basis_gates
, ortarget
argument specified. If the input circuit had runs of single qubit gates which could be simplified the output circuit would not be as optimized as possible as those runs of single qubit gates would not have been removed. This could have been corrected previously by specifying either thebackend
,basis_gates
, ortarget
arguments on thetranspile()
call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed #9217
Fixed an issue with the
transpile()
function when run withoptimization_level=3
and nobackend
,basis_gates
, ortarget
argument specified. If the input circuit contained any 2 qubit blocks which were equivalent to an identity matrix the output circuit would not be as optimized as possible and and would still contain that identity block. This could have been corrected previously by specifying either thebackend
,basis_gates
, ortarget
arguments on thetranspile()
call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed #9217
Fixed an issue with
LinCombSamplerGradient
where it would potentially raise an error when run with theSampler
class fromqiskit-aer
.
Fixed an issue with
NumPyEigensolver
and by extensionNumPyMinimumEigensolver
where solving forBaseOperator
subclasses other thanOperator
would cause an error.
Fixed an issue in the metadata output from
primitives
where the list made copies by reference and all elements were updated with the same value at every iteration.
Fixed an issue with the
QobjToInstructionConverter
when multiple backends are called and they accidentally have the same pulse name in the pulse library. This was an edge case that could only be caused when a converter instance was reused across multiple backends (this was not a typical usage pattern).
Fixed an issue with the
PVQD
class where the loss function was incorrecly squaring the fidelity. This has been fixed so that the loss function matches the definition in the original algorithm definition.
Fixed a bug in QPY (
qiskit.qpy
) where circuits containing registers whose bits occurred in the circuit after loose bits would fail to deserialize. See #9094.
The class
TwoQubitWeylDecomposition
is now compatible with thepickle
protocol. Previously, it would fail to deserialize and would raise aTypeError
. See #7312.
Fixed an issue with the
LocalReadoutMitigator.quasi_probabilities()
method where theshots
argument was not used. It is now used to set the number of shots in the return object.
Fixed a regression in the construction of
Clifford
objects fromQuantumCircuits
that contain otherClifford
objects.
Fixed an issue with the
TwoQubitWeylDecomposition
class (and its subclasses) to enable the Python standard librarypickle
to serialize these classes. This partially fixed #7312
QuantumCircuit.qasm()
will now correctly escape gate and register names that collide with reserved OpenQASM 2 keywords. Fixes #5043.
Fixed an issue in the
RZXCalibrationBuilder
where the ECR pulse sequence was misaligned. Fixed #9013.
Fixed an issue with the
pulse_drawer()
where in some cases the output visualization would omit some of the channels in a schedule. Fixed #8981.
Aer 0.11.2¶
No change
IBM Q Provider 0.19.2¶
No change
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')
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.052373245772