Qiskit SDK 2.0 release notes
2.0.3
Prelude
Qiskit v2.0.3 is a bugfix release for the v2.0 minor version series.
Bug Fixes
-
ApplyLayoutwill now correctly handle the case of applying a zero-qubitLayout. Previously, it would claim that no layout had been set, even if the"layout"field of thePropertySetwas equal toLayout(). -
Fixed an issue in the
ElidePermutationstranspiler pass, where the output permutation was not updated correctly in the presence ofPermutationGateoperations. This would result in an incorrect output circuit and an incorrectvirtual_permutation_layoutproperty in theproperty_setbeing set. When run as part of a largerPassManagerthis would also result in an incorrectTranspileLayoutbeing returned in theQuantumCircuit.layoutin the output circuit. -
Fixed a bug in the
HighLevelSynthesispass when unrolling nested/customInstructionobjects. If theQuantumCircuitreturned byInstruction.definitionof a custom object contained anyClbitobjects, these classical bits would incorrectly use the internal index inside theInstruction.definitionQuantumCircuitinstead of mapping them to the corresponding index in the outerQuantumCircuit. -
Fixed a bug in the
PauliEvolutionSynthesisDefaultandPauliEvolutionSynthesisRustiqplugins that modified the .synthesis attribute of the original circuit when settingpreserve_order=False. The behavior of the plugins has been restored and the original circuit is now preserved throughout the transpilation pipeline. -
Fixed a compatibility issue with the minimum supported version of rustworkx, 0.15. With certain inputs the
VF2LayoutandVF2PostLayoutwere previously using a rustworkx method that was added in rustworkx 0.16.0 which would cause an error when using an older rustworkx release which is listed as supported. -
SabreLayoutandSabreSwapwill no longer panic when applying the routing result to a circuit that usesexpr.VarorStretchobjects in a nested control-flow scope. -
qiskit.circuit.library.quantum_volume()was updated to handle anumpy.random.Generatoras input for itsseedargument. Previously, such a generator argument would result in aTypeError.
2.0.2
Prelude
Qiskit v2.0.2 is a bugfix release for the v2.0 minor version series.
Bug Fixes
-
Fixed the
nameattribute of theOrGateclass so that it now is set to"or"to uniquely identify this gate. It was previously incorrectly set to"and"which made it impossible to distinguish it fromAndGateor have synthesis plugins to synthesize anOrGate. -
Fixed an issue in the
ConsolidateBlockstranspiler pass where it would fail to consolidate some blocks if the KAK gate selected (either directly or via the target) is supercontrolled and notCXGate. Fixed #14413 -
Fixed a bug in the circuit functions
evolved_operator_ansatz(),qaoa_ansatz()andhamiltonian_variational_ansatz(), where the parameters had a zero complex component. This was normally not an issue unless the parameter was translated to SymPy using theParameterExpression.sympify()method, which would then raise an error.
2.0.1
Prelude
Qiskit v2.0.1 is a minor bugfix release for the v2.0.x release series.
Bug Fixes
-
Fixed a visualization bug in the text circuit drawer where post-transpilation control-flow operations could have their closing “bracket” rendered vertically out of order. See #14271 for more detail.
-
Fixed a bug in the
UnitarySynthesistranspiler pass, where the pass ignored thesynth_gatesparameter and only synthesized theunitarygates. The pass now correctly synthesizes all gates specified in thesynth_gatesparameter. Fixed #14343. -
Added missing
reprsupport forDuration. -
Added missing support for Python pickling of
Duration. This was preventing parallel transpilation of circuits withdelay()instructions that use duration expressions. -
Fixed a problem in the
HighLevelSynthesistranspiler pass that caused it to erroneously terminate early on certain circuits with control flow operations. Fixed #14338 -
Fixed the construction of Instantaneous Quantum Polynomial time (IQP) circuits in
IQPand byiqp(). The previous implementation incorrectly used powers of the gate instead of powers of the gate. -
SabreLayoutwill now correctly propagate a circuit’snameandmetadatafields when performing as a joint layout and routing pass. -
Fixed a problem in the
SolovayKitaevSynthesisunitary synthesis plugin, where repeatedly running the plugin with different basis gates incorrectly reused the basis gates from the first run only. This problem was due to ignoring the basis gates when caching basic approximations. -
Fixed a problem in the
SolovayKitaevtranspiler pass where the pass could crash due to encountering a 180 degree rotation in the internal recursion, which was not handled correctly. -
Fixed a problem in the
SolovayKitaevtranspiler pass where the generated approximation could have a phase that differs by from the correct value. This resulted due to the internal representation, which requires additional handling to obtain the correct sign of the qubit gate matrix. Fixed #9552 -
Circuits containing delays with stretches (see
QuantumCircuit.add_stretch()) can now successfully compile using the preset pass-managers (transpile()andgenerate_preset_pass_manager()) when targetting a backend that has alignment constraints, for example IBM Quantum Eagle devices likeibm_sherbrooke. -
The fallback error heuristic in
VF2LayoutandVF2PostLayout, used when there were no reported error rates, could previously assign errors greater than one, and have unpredictable effects on the resulting layout scores.
2.0.0
Prelude
We are pleased to release Qiskit v2.0.0, with new features that improve its performance and capabilities. The feature highlights of Qiskit v2.0.0 include:
- The introduction of a C API for building and interacting with
SparseObservableobjects. This first compiled language interface represents an important milestone in the evolution of Qiskit and will grow in scope throughout the v2.x release series. The initial iteration of the C API is an experimental feature, and there may be breaking API changes in minor versions following our version strategy.- The addition of a new
BoxOpcontrol-flow op that maps to the OpenQASM 3 concept of a box and allows to group series of instructions for later processing and custom scheduling. This operator is useful for applications such as twirling, noise-learning, and stretch-based scheduling among others.- The ability to create
stretchdurations forDelayinstructions, which enable expressing relationships between timing-aware instructions. The newStretchtype extends the existing classical expression system, allowing design intent to be captured at circuit construction time and resolved at compile time. See the OpenQASM documentation for details.- Improved synthesis when a
Targetcontains fractional two qubit basis gates with support for arbitrary angles such asRZXGateorRZZGate, which significantly reduces gate counts in the synthesized circuits.- Improved runtime performance, particularly during the circuit construction step, where benchpress benchmarking shows a 2x speedup over Qiskit v1.3. This improvement is achieved through a combination of contributions, including leveraging additional native Rust gate representations, such as
UnitaryGate, and removing legacy data model elements.
In line with our semantic versioning policy, documented at the time of the v1.0.0 release, this major release also includes API changes that are not backward-compatible with the v1.x release series. In particular, several deprecated components of the Qiskit data model have been removed, such as the .c_if() method, the qobj module, BackendV1, and qiskit.pulse, as well as the deprecated V1 primitive reference implementations. You can refer to the upgrade release notes sections for more details on all of these removals and API changes. The removed APIs are still supported in the Qiskit v1.4.x release which will receive bug fixes for another six months and will have security updates for one year.
New Features
-
Support for the Linux aarch64 platform has been promoted to tier 1 support as documented in:
/guides/install-qiskit#operating-system-support
from its previous support level of tier 2 in the v1.x release series.
-
Introduced a new C API to build and interact with sparse observables. While the API surface in this release is fairly small - covering only the
SparseObservableclass - it represents an important milestone in the evolution of Qiskit, as this is the first time the SDK exposes a public interface in C and it lays the foundation for future expansions of the Qiskit C interface. As this is the first public interface in C this is an experimental feature, and if necessary the API may change in a minor version release.Detailed syntax and additional information can be found in the C API documentation. A minimal example to construct the 100-qubit observable
2 X0 Y1 Z2is:#include <complex.h> #include <qiskit.h> #include <stdint.h> #include <stdio.h> int main(int argc, char *argv[]) { // build a 100-qubit empty observable uint32_t num_qubits = 100; QkObs *obs = qk_obs_zero(num_qubits); // add the term 2 * (X0 Y1 Z2) to the observable complex double coeff = 2; QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z}; uint32_t indices[3] = {0, 1, 2}; QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits}; qk_obs_add_term(obs, &term); // print some properties printf("num_qubits: %u\n", qk_obs_num_qubits(obs)); printf("num_terms: %lu\n", qk_obs_num_terms(obs)); // free the memory allocated for the observable qk_obs_free(obs); return 0; }
Circuits Features
-
Added a new
get_control_flow_name_mapping()convenience function that returns a mapping of Qiskit control-flow operation names to their corresponding classes.Example usage:
from qiskit.circuit import get_control_flow_name_mapping ctrl_flow_name_map = get_control_flow_name_mapping() if_else_object = ctrl_flow_name_map["if_else"] print(if_else_object)<class 'qiskit.circuit.controlflow.if_else.IfElseOp'> -
Added a new circuit method,
QuantumCircuit.estimate_duration(), to estimate the duration of a scheduled circuit after transpilation. The circuit duration is estimated by finding the longest path on a scheduled circuit based on the durations provided by a givenTarget. This method only works for simple circuits that do not contain control flow or other classical feed-forward operations.Use this method instead of the deprecated
QuantumCircuit.durationattribute if you need an estimate of the full circuit duration.Example usage:
from qiskit import QuantumCircuit, transpile from qiskit.providers.fake_provider import GenericBackendV2 backend = GenericBackendV2(num_qubits=3, seed=42) circ = QuantumCircuit(3) circ.cx(0, 1) circ.measure_all() circ.delay(1e15, 2) circuit_dt = transpile(circ, backend, scheduling_method="asap") duration = circuit_dt.estimate_duration(backend.target, unit="s") print("Estimated duration: ", duration) -
Added two new classes:
BitFlipOracleGateandPhaseOracleGate.BitFlipOracleGatewas introduced as an alternative to directly synthesizingBooleanExpression, which has been removed in Qiskit v2.0.PhaseOracleGatewas added as an alternative toPhaseOracle, as the latter will be deprecated throughout the v2.x releases. Both classes share the interface ofPhaseOracle, except for theevaluate_bitstringmethod, which is no longer present.BitFlipOracleGatesynthesizes a bit-flip oracle instead of a phase-flip oracle, meaning it acts on one additional qubit and can be viewed as applying a controlled-X operation, where the control is determined by the value of the expression encoded by the oracle.from qiskit import QuantumCircuit from qiskit.circuit.library.bit_flip_oracle import BitFlipOracleGate qc = QuantumCircuit(5) bool_expr = "(x0 & x1 | ~x2) & x4" oracle = BitFlipOracleGate(bool_expr) qc.compose(oracle, inplace=True) qc.draw('mpl') qc.decompose().draw('mpl')
from qiskit import QuantumCircuit from qiskit.circuit.library.phase_oracle import PhaseOracleGate qc = QuantumCircuit(5) bool_expr = "(x0 & x1 | ~x2) & x4" oracle = PhaseOracleGate(bool_expr) qc.compose(oracle, inplace=True) qc.draw('mpl') qc.decompose().draw('mpl')
-
A new control-flow op,
BoxOp, its associatedQuantumCircuit.box()method and context manager are now available fromqiskit.circuit.The normal way to construct a box is to use the
QuantumCircuit.box()context manager:from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(5) with qc.box(): # This box "uses" qubits 0 and 1. qc.x(0) qc.z(1) # Boxes can be assigned a duration. with qc.box(duration=100, unit="ms"): # This box "uses" qubits 2, 3 and 4. # Qubit 4 undergoes no operations. qc.cx(2, 3) qc.noop(4)The Qiskit “box” maps nearly directly to the OpenQASM 3 concept of a box.
All qubits “used” by the box are timing synchronized at the start and end of the box. In other words, the box has the same “duration” for every qubit it uses, and the start points are synchronized. Other operations at the same scope as the
BoxOpitself see the box as atomic; it is valid to commute an operation past an entire box if the operation commutes with the action of the whole box, but it is not generally valid to move an operation into or out of a box.The principal uses of a box are to group a series of instructions for later processing (such as grouping a partial layer of two-qubit gates), and to schedule a compound block together at one scope while using relative scheduling within the block (such as dynamical decoupling several qubits in a group). Qiskit’s compiler does not yet have built-in passes that will group instructions or schedule instructions with a
BoxOp.The transpiler supports routing and layout in the presence of boxes, and will optimize within the box (up to the
optimization_levelsetting), but does not yet perform optimizations around the atomic structure of boxes. The text- and Matplotlib-based circuit drawers support box. Exporting to QPY and to OpenQASM 3 is supported, although OpenQASM 3 currently has no way of designating idling qubits within a box (it is expected that a spec change will add this in the near future: see the relevant feature proposal). -
Added a new
approximation_degreeargument toCommutationChecker.commute()andCommutationChecker.commute_nodes(). This argument allows you to set the approximation threshold for when gates are evaluated as commuting. See the docstring ofCommutationCheckerfor more information. -
Added a new circuit method,
QuantumCircuit.noop(), which allows qubits to be explicitly marked as used within a control-flow builder scope without adding a corresponding operation to them. -
The classical realtime-expressions module
qiskit.circuit.classicalcan now represent constant expressions. TheExprclass now has a booleanconstattribute which indicates the expression’s const-ness. This allows us to enforce that expressions in certain contexts must be possible to evaluate at compile time.All
Varexpressions are considered to be non-const, while allValueexpressions are const.An expression comprised only of other const expressions is also const:
from qiskit.circuit.classical import expr assert expr.bit_and(5, 6).constAn expression that contains any non-const expression is non-const:
from qiskit.circuit.classical import expr, types assert not expr.bit_and(5, expr.Var.new("a", types.Uint(5)).const -
The classical realtime-expressions module
qiskit.circuit.classicalcan now represent durations by using the new typeDuration.The module
qiskit.circuitalso has a newDurationclass, which can be used as a literal value within classical expressions.The
lift()function can be used to create a value expression from aDurationinstance:from qiskit.circuit import Duration from qiskit.circuit.classical import expr expr.lift(Duration.dt(1000)) # Value(Duration.dt(1000), Duration()) -
The classical realtime-expressions module
qiskit.circuit.classicalcan now represent IEEE-754 double-precision floating point values using the new typeFloat.The
lift()function can be used to create a value expression from a Python float:from qiskit.circuit.classical import expr expr.lift(5.0) # >>> Value(5.0, Float())This type is intended primarily for use in timing-related (
durationandstretch) expressions. It is not compatible with bitwise or logical operations, although it can be used with these if they are first explicitly cast to something else. -
Reduced the number of two-qubit gates when decomposing multi-controlled single-qubit unitary gates. For example:
- For multi-controlled
YGateon 10 qubits, theCXGatecount was reduced by 56%. - For multi-controlled
HGateon 10 qubits, theCXGatecount was reduced by 56%. - For multi-controlled
SXGateandSXdgGateon 10 qubits, theCXGatecount was reduced by 80%. - For multi-controlled
UGateon 10 qubits, theCXGatecount was reduced by 31%.
- For multi-controlled
-
The classical realtime-expressions module
qiskit.circuit.classicalcan now represent arithmetic operationsadd(),sub(),mul(), anddiv()on numeric and timing operands.For example:
from qiskit.circuit import QuantumCircuit, ClassicalRegister, Duration from qiskit.circuit.classical import expr # Subtract two integers cr = ClassicalRegister(4, "cr") qc = QuantumCircuit(cr) with qc.if_test(expr.equal(expr.sub(cr, 2), 3)): pass # Multiply a Duration by a Float with qc.if_test(expr.less(expr.mul(Duration.dt(200), 2.0), Duration.ns(500))): pass # Divide a Duration by a Duration to get a Float with qc.if_test(expr.greater(expr.div(Duration.dt(200), Duration.dt(400)), 0.5)): passFor additional examples, see the module-level documentation linked above.
-
The constructor for
UCGatenow has a new optional argument,mux_simp, which takes a boolean value that enables the search for simplifications of Carvalho et al. This optimization is enabled by default, identifies and removes unnecessary controls from the multiplexer, reducing the number of CX gates and circuit depth, especially in separable state preparation withInitialize. -
The
PauliEvolutionGatenow natively supportsSparseObservables as input. This efficiently allows to handle evolution under projectors, which are implemented as controls of a phase rotation and require less gates than explicitly expanding the projector in terms of Paulis. For example:from qiskit.circuit.library import PauliEvolutionGate from qiskit.quantum_info import SparseObservable obs = SparseObservable("001") evo_proj = PauliEvolutionGate(obs, time=1) print(evo_proj.definition.draw()) -
A new expression node
Stretchhas been added to the classical expression system to representstretchvariables. To create a newstretchvariable, you can useQuantumCircuit.add_stretch(). The resulting expression is a constant expression of typeDuration, which can be used as thedurationargument of adelay().For example, to ensure a sequence of gates between two barriers will be left-aligned, whatever their actual durations are, you can do the following:
from qiskit import QuantumCircuit from numpy import pi qc = QuantumCircuit(5) qc.barrier() qc.cx(0, 1) qc.u(pi/4, 0, pi/2, 2) qc.cx(3, 4) a = qc.add_stretch("a") b = qc.add_stretch("b") c = qc.add_stretch("c") # Use the stretches as Delay duration. qc.delay(a, [0, 1]) qc.delay(b, 2) qc.delay(c, [3, 4]) qc.barrier()The
Stretchexpression is most similar to the existingVarexpression used to represent classical variables in a circuit, except it is constant and is always of typeDuration. It can be used in other expressions (for example, you can multiply it by a numeric constant) andQuantumCircuitprovides full scoping support for it (for example, it can be captured by or declared within a control flow scope).For additional context and examples, refer to the OpenQASM 3 language specification.
-
Added
Gateversions of the single-register arithmetic gates that allow the transpiler to perform high-level optimizations compared to theirQuantumCircuitvariants. These are:ExactReciprocalGate(replacingExactReciprocal)IntegerComparatorGate(replacingIntegerComparator)LinearPauliRotationsGate(replacingLinearPauliRotations)PiecewiseLinearPauliRotationsGate(replacingPiecewiseLinearPauliRotations)PiecewiseChebyshevGate(replacingPiecewiseChebyshev)PiecewisePolynomialPauliRotationsGate(replacingPiecewisePolynomialPauliRotations)PolynomialPauliRotationsGate(replacingPolynomialPauliRotations)LinearAmplitudeFunctionGate(replacingLinearAmplitudeFunction)QuadraticFormGate(replacingQuadraticForm)WeightedSumGate(replacingWeightedAdder)
Primitives Features
- Added a new
to_bool_array()method to theBitArrayclass that returns the bit array as a boolean NumPy array. Theorderargument can be used to specify the endianness of the output array.
Providers Features
-
Added the ability to set the
dtproperty ofGenericBackendV2in the class initializer with a newdtargument. Example usage:from qiskit.providers.fake_provider import GenericBackendV2 backend = GenericBackendV2( num_qubits = 5, basis_gates = ["cx", "id", "rz", "sx", "x"], dt = 2.22*e-10, seed = 42 )
Quantum Information Features
-
Added a new
SparseObservable.to_sparse_list()method to obtain a sparse list representation of aSparseObservable. For example:from qiskit.quantum_info import SparseObservable obs = SparseObservable.from_list([("+II", 1), ("-II", 1)]) print(obs.to_sparse_list()) # [("+", [2], 1), ("-", [2], 1)] -
Added a new
SparseObservable.as_paulis()method to express a sparse observable in terms of Paulis only, by expanding all projectors. For example:from qiskit.quantum_info import SparseObservable obs = SparseObservable("+-") obs_paulis = obs.as_paulis() # 1/4 ( II + XI - IX - XX ) -
Qiskit v2.0.0 supports constructing a
SparsePauliOpfrom aSparseObservableby using the new methodSparsePauliOp.from_sparse_observable(). It is important to remember thatSparseObservableobjects can efficiently represent projectors, which require an exponential number of terms in theSparsePauliOp. -
SparseObservablenow supports operator composition using thecompose()method, similar to otherquantum_infoclasses. This is analagous to matrix multiplication, though the method is entirely matrix free. -
SparseObservable.BitTermhas a new attribute,label, which contains the single-character Python string used to represent the term in string labels. -
The
StabilizerState.expectation_value()method can now accept an operator of typeSparsePauliOp.
Synthesis Features
-
Added a new
TwoQubitControlledUDecomposerclass that decomposes any two-qubit unitary in terms of basis two-qubit fractional gates, such asRZZGate(or two-qubit gates that are locally equivalent toRZZGate, up to single qubit gates).For example:
from qiskit.circuit.library import RZZGate from qiskit.synthesis import TwoQubitControlledUDecomposer from qiskit.quantum_info import random_unitary unitary = random_unitary(4, seed=1) decomposer = TwoQubitControlledUDecomposer(RZZGate, euler_basis="ZXZ") circ = decomposer(unitary) circ.draw(output='mpl') -
The
synth_cnot_depth_line_kms()pass has been ported into Rust, with preliminary benchmarks pointing at a factor of 20x speedup. -
The
synth_cx_cz_depth_line_my()pass has been ported into Rust, with preliminary benchmarks pointing at a factor of 70x speedup. -
Added synthesis functions
synth_integer_comparator_2s()andsynth_integer_comparator_greedy()to compile gates that implement an integer comparison, such asIntegerComparatorGate. The corresponding high-level synthesis plugins areIntComparatorSynthesis2sandIntComparatorSynthesisNoAux. To let the compiler select the optimal decomposition based on the availably auxiliary qubits, useIntComparatorSynthesisDefault. -
Added
synth_weighted_sum_carry()to synthesizeWeightedSumGateobjects. This is currently the only available synthesis method forWeightedSumGate, with the corresponding high-level synthesis pluginWeightedSumSynthesisDefault.
Transpiler Features
-
Added support for working with
Targetobjects that contain two-qubit basis gates that contain arbitrary angles, such asRZZGate, to theConsolidateBlockstranspiler pass. The pass previously would not correctly estimate the number of gates required for a decomposition which would result in blocks not being consolidated whereUnitarySynthesiscould potentially optimize the block. Internally, the gate count estimate is done using theTwoQubitControlledUDecomposerclass.For example:
from qiskit import QuantumCircuit from qiskit.transpiler import generate_preset_pass_manager from qiskit.transpiler.passes import ConsolidateBlocks qc = QuantumCircuit(2) qc.rzz(0.1, 0, 1) qc.rzz(0.2, 0, 1) # basis_gates contains fractional gate (rzz) consolidate_pass = ConsolidateBlocks(basis_gates=["rz", "rzz", "sx", "x", "rx"]) block = consolidate_pass(qc) # consolidate the circuit into a single unitary block block.draw(output='mpl') pm = generate_preset_pass_manager( optimization_level=2, basis_gates=["rz", "rzz", "sx", "x", "rx"] ) tqc = pm.run(qc) # synthesizing the circuit into basis gates tqc.draw(output='mpl') -
Added support for two-qubit fractional basis gates, such as
RZZGate, to theUnitarySynthesistranspiler pass. The decomposition is done using theTwoQubitControlledUDecomposer, and supports both standard and custom basis gates.For example:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_unitary from qiskit.transpiler.passes import UnitarySynthesis from qiskit.converters import circuit_to_dag, dag_to_circuit unitary = random_unitary(4, seed=1) qc = QuantumCircuit(2) qc.append(unitary, [0, 1]) dag = circuit_to_dag(qc) # basis_gates contains fractional gate (rzz) circ = UnitarySynthesis(basis_gates=['rzz', 'rx', 'rz']).run(dag) dag_to_circuit(circ).draw(output='mpl') -
Added a new transpiler pass,
LightCone, that returns the lightcone of a circuit when measuring a subset of qubits or a specific Pauli string.For example, for the following circuit:
running the pass would eliminate the gates that do not affect the outcome:
from qiskit.transpiler.passes.optimization.light_cone import LightCone from qiskit.transpiler.passmanager import PassManager from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(3,1) qc.h(range(3)) qc.cx(0,1) qc.cx(2,1) qc.h(range(3)) qc.measure(0,0) pm = PassManager([LightCone()]) new_circuit = pm.run(qc) new_circuit.draw("mpl")
-
Added a new argument
max_block_widthto theBlockCollectorclass and to theCollectLinearFunctionsandCollectCliffordstranspiler passes. This argument allows you to restrict the maximum number of qubits over which a block of nodes is defined.For example:
from qiskit.circuit import QuantumCircuit from qiskit.transpiler.passes import CollectLinearFunctions qc = QuantumCircuit(5) qc.h(0) qc.cx(0, 1) qc.cx(1, 2) qc.cx(2, 3) qc.cx(3, 4) # Collects all CX-gates into a single block qc1 = CollectLinearFunctions()(qc) qc1.draw(output='mpl') # Collects CX-gates into two blocks of width 3 qc2 = CollectLinearFunctions(max_block_width=3)(qc) qc2.draw(output='mpl') -
Added a new option,
collect_from_back, to theCollectMultiQBlockstranspiler pass. When set toTrue, the blocks are collected in the reverse direction, from the outputs toward the inputs of the circuit. The blocks are still reported following the normal topological order. This leads to an additional flexibility provided by the pass, and additional optimization opportunities when combined with a circuit resynthesis method. -
Added a new
approximation_degreeargument toCommutationAnalysis. This argument allows you to set the approximation threshold for when gates are evaluated to commute. See the class docstring for more information. -
A new transpiler pass,
ContractIdleWiresInControlFlow, is available inqiskit.transpiler.passes. This pass removes qubits from control-flow blocks if the semantics allow it and if the qubit remains idle throughout the control-flow operation. Previously, the routing stage of the preset pass managers could remove idle qubits as an unintended side effect of how the passes operated. Now, this behavior is properly handled as part of an optimization pass. -
A new
"default"routing plugin stage was added. In Qiskit v2.0.0, this is simply an alias for the previous default"sabre". The underlying default algorithm may change over the course of the Qiskit v2.x release series for some or all targets, but you can always set explicitlyrouting_method="sabre"to maintain the current behavior. -
Added a new
"default"translation plugin stage. In Qiskit v2.0.0, this is an alias for the previous default"translator". The underlying default algorithm may change over the course of the Qiskit 2.x series for some or all targets, but you can always settranslation_method="translator"explicitly to maintain the current behavior. -
The
HighLevelSynthesistranspiler pass now synthesizes objects of typeAnnotatedOperationthrough the plugin interface. -
PassManager.run()now accepts aproperty_setargument, which can be set to aMapping-like object to provide the initial values of the pipeline’sPropertySet. This can be used to recommence a partially applied compilation, or to reuse certain analysis from a prior compilation in a new place. -
The scheduling passes
PadDelayandPadDynamicalDecouplingnow have new arguments on their constructors:targetanddurations. These are used to specify theTargetorInstructionDurationsrespectively. For access to the instruction durations when the pass is run, one of the arguments is required. -
Added a new
seconds_to_dt()method to theTargetclass. This is used to translate a duration in seconds to a number of discretized time steps of the system time resolution specified in theTarget.dtattribute. This is typically useful for converting theInstructionProperties.durationvalue to units ofdt. -
The
Split2QUnitariestranspiler pass has been upgraded to handle the case where the unitary in consideration can be written as aSwapGategate and two single-qubit gates. In this case, it splits the unitary and also applies virtual swapping, similar to what is done inElidePermutations. This functionality can be controlled with a new argument,split_swap, in the constructor of :class`.Split2QUnitaries`, which can be used to disable splitting swap equivalent gates.
Misc. Features
-
qiskit.utilsnow contains utilities to provide better control and inspection of Qiskit’smultiprocessingparallelization settings. In particular, one can now useshould_run_in_parallel()to query whetherparallel_map()(and pass managers) will launch subprocesses for suitable inputs, and use the context managershould_run_in_parallel.override()to temporarily override most system and user configuration around this decision.An additional function,
default_num_processes(), reads the default maximum number of subprocesses that Qiskit will use for process-based parallelism. -
A new environment variable,
QISKIT_IGNORE_USER_SETTINGS, now controls whether to read the user settings file onimport qiskit. If set to the stringtrue, the settings file will not be read. This is useful for isolating certain instances of Qiskit from the system environment, such as for testing.
Upgrade Notes
-
Qiskit v2.0 has dropped support for Linux i686 and 32-bit Windows. Starting in Qiskit v2.0.0, a 64-bit platform is required to run Qiskit. This aligns with the trend in the scientific Python community and allows Qiskit to focus on performance improvements for increasingly complex quantum computing hardware.
Qiskit v1.4 will continue to support 32-bit platforms until end-of-life (September 2025), but starting in this 2.0.0 release, Qiskit will no longer publish pre-compiled binaries for them, and offers no guarantee of successful source builds on 32-bit platforms.
-
The minimum supported Rust version for building Qiskit from source is now v1.79. This has been raised from v1.70, the previous minimum supported Rust version in the Qiskit v1.x release series.
-
Qiskit Pulse has been completely removed in this release, following its deprecation in Qiskit v1.3. This includes all pulse module files, pulse visualization functionality, support for
ScheduleBlockand pulse-gate serialization and deserialization in QPY, calibrations management inQuantumCircuit,TargetandDAGCircuit, and pulse-based fake backends. For more details about the removed components related to pulse, see the corresponding sections below.Note that Pulse migration to Qiskit Dynamics, as was the initial plan following the deprecation of Pulse, has been put on hold due to Qiskit Dynamics development priorities. Users wanting to use Qiskit Pulse as a frontend to supporting backends or in other uses cases can still use it in Qiskit versions prior to v2.0.0, which include pulse functionality.
-
The functions
sequenceandschedulefrom thecompilermodule have been removed following their deprecation in Qiskit v1.3. They relied on being able to translate circuits to pulse components using backend definitions, a capability that is no longer present. For this reason they have been removed with no proposed alternative. Note that these removals relate to the Pulse package, which is also being removed in Qiskit 2.0.
Circuits Upgrade Notes
-
BitandRegisteras well as their subclassess are no longer guaranteed to be comparable usingischecks, due to conversions to and from Python which may re-allocate each instance exposed to Python. -
BitandRegister(and their subclasses) can no longer be subclassed. This was never intended to be supported behavior, and doing so would cause unspecified behavior in Qiskit. It is no longer possible to do this as an implementation detail of the classes. -
It is no longer possible to create instances of the base
BitandRegisterclasses. Directly instantiating these classes was clearly documented as something that was not supported, and being able to do it was was just an implementation artifact of the class hierarchy in previous releases. Starting in Qiskit v2.0.0, it is no longer possible to do this. -
The
qiskit.circuit.classicalfunctionmodule has been removed following its deprecation in Qiskit v1.4. That includes theClassicalFunctionclass, its relatedclassical_functionfunction, and theBooleanExpressionclass. This change was made to remove the dependency on thetweedledumlibrary, which is no longer compatible with all of Qiskit’s supported platforms and Python versions.ClassicalFunctionwas exclusively used inPhaseOracle, which has been upgraded to only accept expressions instringformat (see following release note).BooleanExpressionhas been superseded by the newBitFlipOracleGateclass. -
The
PhaseOracleclass no longer depends on thetweedledumlibrary, as the dependency is not actively maintained. The interface has been simplified: it no longer accepts asynthesizerparameter, and theexpressionparameter can only be a string. The previously acceptedClassicalFunctiontype, deprecated in Qiskit v1.4, has been removed in Qiskit v2.0.Despite these upgrades, the standard usage of the
PhaseOracleclass remains unchanged:from qiskit.circuit.library.phase_oracle import PhaseOracle bool_expr = "(x0 & x1 | ~x2) & x4" oracle = PhaseOracle(bool_expr) oracle.draw('mpl')
Note that this change may affect synthesis effectiveness, but was required for compatibility with all of Qiskit’s supported platforms and Python versions.
-
Updated the metric used to check commutations in
CommutationChecker. Two gates are assumed to commute if the average gate fidelity of the commutation is above(1 - 1e-12). This value is chosen to account for round-off errors in the fidelity calculation and for consistency withRemoveIdentityEquivalentandTwoQubitWeylDecomposition. See the class docstring for more information. -
The method
QuantumCircuit.measure_active()has changed the name of the classical register it creates, as the previous name conflicted with anOpenQASMreserved word. Instead ofmeasure, it is now calledmeas, aligning with the register name used bymeasure_all(). -
The
DAGCircuit.control_flow_op_nodes()method has been updated to always return a list, even if it is empty. Previously, it returnedNoneif it was empty, and never returned an empty list, which required special handling. If you need to explicitly test for emptiness in both Qiskit v1.x and v2.x, you can do:control_flow_nodes = dag.control_flow_op_nodes() if not control_flow_nodes: # There are no control-flow nodes. pass -
BlueprintCircuit.copy_empty_like()now returns an emptyQuantumCircuitwith the same number of qubits and clbits, and the same metadata as the original circuit, instead of aBlueprintCircuit. This change addresses unexpected behavior where dealing with an “empty” copy of a blueprint circuit would cause the circuit data to be rebuilt. Note thatBlueprintCircuit.copy()still returns aBlueprintCircuit. WhileBlueprintCircuitis not a public class as it’s an internal type used for building legacy entries inqiskit.circuit.librarythis impacts its subclasses such asNLocalandZZFeatureMap. Refer to theqiskit.circuit.libraryfor a complete list of the classes impacted by this change. Fixed #13535 -
The internal function
qiskit.circuit.add_control.add_controlhas been removed. This function was not part of the public API, it had fragile preconditions to uphold and was a common source of bugs. Uses ofadd_control(SomeGate(...), ...)should change toSomeGate(...).control(...)usingGate.control()instead, which is far safer. -
The
ParameterExpression.sympify()method can now raise aMissingOptionalLibraryexception ifsympyis not installed. In the Qiskit v1.x releases,sympywas always guaranteed to be installed, but starting in v2.0.0, this is no longer a hard requirement and may only be needed if you are using this method. Because this functionality explicitly requiressympyyou need to ensure you havesympyinstalled to use the method. -
The deprecated
DAGNodedagargument has been removed from theDAGNodeclass and its subclasses:DAGOpNode,DAGOutNode, andDAGInNode.The
dagparameter was an optional argument when constructing these objects, but it has been unused and ignored since the v1.3 release, and deprecated since the v1.4 release. -
The following
QuantumCircuitmethods:castcbit_argument_conversioncls_instancescls_prefixqbit_argument_conversion
have been removed, following their deprecation in Qiskit 1.2. These methods were internal helper functions, and never intended to be public API. No replacement is provided.
-
The deprecated attributes for
InstructionandGate:durationandunithave been removed, so you can no longer set theunitordurationarguments for anyqiskit.circuit.Instructionor subclass. These attributes were deprecated in Qiskit v1.3.0 and were used to attach a custom execution duration and unit for that duration to an individual instruction. However, the source of truth of the duration of a gate is theBackendV2Target, which contains the duration for each instruction supported on the backend. The duration of an instruction is not typically user adjustable and is an immutable property of the backend. If you previously used this capability to experiment with different gate durations, you can mutate theInstructionProperties.durationfield in a givenTargetto set a custom duration for an instruction on a backend. (The unit is always in seconds in theTarget.) -
The deprecated attribute for
qiskit.circuit.InstructionandGate:conditionhas been removed. This functionality has been superseded by theIfElseOpclass, which can be used to describe a classical condition in a circuit. This attribute was deprecated in the v1.3.0 release. -
The deprecated methods for
InstructionandGate:c_ifandcondition_bitshave been removed. These methods were deprecated in the v1.3.0 release. This functionality has been superseded by theIfElseOpclass, which can be used to describe a classical condition in a circuit. For example, a circuit previously usingInstruction.c_if()like:from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(2, 2) qc.h(0) qc.x(0).c_if(0, 1) qc.z(1.c_if(1, 0) qc.measure(0, 0) qc.measure(1, 1)can be rewritten as:
qc = QuantumCircuit(2, 2) qc.h(0) with expected.if_test((expected.clbits[0], True)): qc.x(0) with expected.if_test((expected.clbits[1], False)): qc.z(1) qc.measure(0, 0) qc.measure(1, 1) -
The deprecated method
InstructionSet.c_ifhas been removed. This method was deprecated in the 1.3.0 release. This functionality has been superseded by theIfElseOpclass which can be used to describe a classical condition in a circuit. -
As part of Pulse removal in Qiskit v2.0.0, the
calibrationsproperty has been removed from theQuantumCircuit,DAGCircuitandDAGDependencyclasses. In addition to this, the methodhas_calibration_forhas been removed from theQuantumCircuitandDAGCircuitclasses, andadd_calibrationhas been removed fromQuantumCircuit. -
The
qiskit.circuit.classicalfunctionmodule has been removed. This module was dependent on thetweedledumlibrary which is not compatible with newer versions of Python. As an alternative, thePhaseOracleGateandBitFlipOracleGateclasses can be used to generate circuits from boolean expressions. -
The internal representation of
UnitaryGatewhen added to aQuantumCircuithas changed. The object stored in the circuit will not necessarily share a common reference to the object added to the circuit anymore. This behavior was never guaranteed, and mutating theUnitaryGateobject directly or by reference was always unsound and likely to corrupt the circuit, especially when modifying the matrix. If you need to mutate an element in the circuit (which is not recommended as it’s inefficient and error prone), do something like:from qiskit.circuit import QuantumCircuit from qiskit.quantum_info import random_unitary from qiskit.circuit.library import UnitaryGate import numpy as np qc = QuantumCircuit(2) qc.unitary(np.eye(2, dtype=complex)) new_op = UnitaryGate(random_unitary(2)) qc.data[0] = qc.data[0].replace(operation=new_op)This also applies to
DAGCircuit, but you can useDAGCircuit.substitute_node()instead. -
The
CircuitInstruction.paramsattribute for aCircuitInstructionthat contains anUnitaryGatefor itsoperationwill no longer contain the underlying unitary matrix for the gate. This is because the internal representation of the gate no longer treats the matrix object as a parameter. If you need to access the matrix of the gate you can do this either via theCircuitInstruction.matrixor theUnitaryGate.paramsfield of theCircuitInstruction.operation.
Primitives Upgrade Notes
-
As a consequence of the removal of the
BackendV1model, theBackendSamplerV2andBackendEstimatorV2classes no longer accept inputs of typeBackendV1in theirbackendinput argument. -
Primitive V1 implementations and V1-exclusive non-versioned type aliases, deprecated in Qiskit v1.2, have been removed. These interfaces have been superseded by their V2 counterparts. The removal includes the following classes implementing V1 interfaces:
Estimator, in favor of the V2 equivalent,StatevectorEstimatorSampler, in favor of the V2 equivalent,StatevectorSamplerBackendEstimator, in favor of the V2 equivalent,BackendEstimatorV2BackendSampler, in favor of the V2 equivalent,BackendSamplerV2
As well as the following non-versioned type aliases:
BaseEstimator, alias forBaseEstimatorV1BaseSampler, alias forBaseSamplerV1
This removal does NOT affect the explicitly-versioned
BaseEstimatorV1andBaseSamplerV1abstract interface definitions or related result and job classes, which have been kept to maintain backwards compatibility. If you are using a non-versioned V1-type alias such asBaseEstimator, you can directly replace it with the versioned type (BaseEstimatorV1).Additionally, the following utility functions have been removed. These functions were only used in Primitive V1 implementations:
init_circuit: to initialize a circuit from aStatevector, useQuantumCircuit.initialize()instead.init_observable: use the constructor ofSparsePauliOpinstead.final_measurement_mapping: useQuantumCircuit.layout()andSparsePauliOp.apply_layout()to adjust an operator for a layout. Otherwise, usemthree.utils.final_measurement_mapping. See Mthree Utility functions for details.
Providers Upgrade Notes
-
The
configurationmethod ofBasicSimulatorhas been removed following its deprecation in Qiskit v1.3. This method returned aBackendConfigurationinstance, a class that was part of the discontinuedBackendV1workflow and is also removed in Qiskit v2.0.0. The individual configuration elements can now be retrieved directly from the backend or from the containedTargetinstance (backend.target). -
The
run_experimentmethod ofBasicSimulatorhas been removed. This method took an instance of theQasmQobjExperimentclass as an input argument, a class that has been deprecated since Qiskit v1.2 and was removed with theQobjworkflow in Qiskit v2.0.0. -
The
BackendV1model has been removed following its deprecation in Qiskit 1.2.0. This includes theBackendV1class as well as related modules and utils, as they have been superseded by theBackendV2model. The list of removed items includes:-
BackendV1class: the core of the removed model -
All elements in
qiskit/providers/models, as they were used to represent components of theBackendV1model:BackendConfigurationBackendPropertiesBackendStatusQasmBackendConfigurationPulseBackendConfigurationUchannelLOGateConfigPulseDefaultsPulseQobjDefCommandGatePropertiesNduvJobStatus: This class has been superseded by the more widely usedJobStatusPulseDefaults
-
BackendV2Converterclass: used to convert fromBackendV1toBackendV2 -
convert_to_targetfunction: used to build aTargetinstance from legacyBackendV1components (such asBackendConfigurationorBackendProperties) -
BackendPropertyErrorandBackendConfigurationError: exceptions linked to removed classes
-
-
The
BasicSimulatorbackend can no longer simulate classical control flow. It only supported using the.c_if()/.conditionfor modeling control flow, but this construction has now been removed from the Qiskit data model. -
All fake backend classes based on the deprecated
BackendV1have been removed from theproviders.fake_providermodule. These classes have been deprecated since Qiskit 1.2 and were part of the deprecatedBackendV1workflow. Their use in tests has been replaced with theGenericBackendV2class, which allows to create custom instances ofBackendV2that implement a simulatedBackendV2.run(). The removal affects:-
Base classes:
FakeBackendFakePulseBackendFakeQasmBackend
-
Fake backends for special testing purposes:
Fake1QFakeOpenPulse2QFakeOpenPulse3Q
-
Legacy fake backends:
Fake5QV1Fake20QV1Fake7QPulseV1Fake27QPulseV1Fake127QPulseV1
-
-
As part of pulse removal in Qiskit v2.0.0, the following methods have been removed:
qiskit.providers.BackendV2.instruction_schedule_mapqiskit.providers.BackendV2.drive_channelqiskit.providers.BackendV2.measure_channelqiskit.providers.BackendV2.acquire_channelqiskit.providers.BackendV2.control_channel
-
As part of pulse removal in Qiskit v2.0.0, pulse support has been removed from
GenericBackendV2. This includes the ability to initialize the backend with custom calibrations (calibrate_instructionsargument) and pulse channel attributes (drive_channel,measure_channel,acquire_channel,control_channel). -
Removed the abstract base classes
ProviderandProviderV1, which have been deprecated since Qiskit v1.1.0. The abstraction provided by these interface definitions was not offering significant value, only including the attributesname,backends, and aget_backend()method.A rovider, as a concept, will continue existing as a collection of backends. If you’re currently implementing a provider, you can adjust your code by simply removing
ProviderV1as the parent class of your implementation.As part of this change, you will likely want to add an implementation of
get_backendfor backwards compatibility. For example:def get_backend(self, name=None, **kwargs): backend = self.backends(name, **kwargs) if len(backends) > 1: raise QiskitBackendNotFoundError("More than one backend matches the criteria") if not backends: raise QiskitBackendNotFoundError("No backend matches the criteria") return backends[0]
QPY Upgrade Notes
-
The
qpy.load()function can now raise aMissingOptionalLibraryexception if a QPY v10, v11, or v12 payload is passed in that usessymenginesymbolic expressions andsymengineis not installed. The exception is also raised ifsympyis not installed for any other QPY payload prior to v13. In the Qiskit v1.x releases,symengineandsympywere always guaranteed to be installed. However, starting in v2.x this is no longer a hard requirement and may only be needed if you’re deserializing a QPY file that was generated usingsymengine. Parsing these QPY payloads requiressymengineas its usage is part of the format specification for QPY v10, v11, and v12. If the payload requires it, installing a compatible version ofsymengine(0.11.0or0.13.0) is the only option. Similarly,sympywas was used forParameterExpressionencoding for all QPY versions 1 - 12. -
The minimum QPY compatibility version,
QPY_COMPATIBILITY_VERSION, has been raised from 10 (the v1.x release requirement) to 13. This version controls the minimum version of QPY that can be emitted by theqpy.dump()function. This means thatqpy.dump()can only emit QPY v13 and v14 in this release. QPY v13 is still compatible with Qiskit v1.3.x and v1.4.x, which means that payloads generated in Qiskit v2.x with QPY v13 can still be loaded with the Qiskit v1.x release series.This change was necessary because QPY versions 10 -12 require either the
sympyorsymenginelibraries to generate a serialization forParameterExpressionobjects, but in Qiskit 2.x neither library is required for theParameterExpressionobject. -
With the removal of pulse in Qiskit v2.0.0, support for serializing
ScheduleBlockprograms through theqiskit.qpy.dump()function has been removed. Users can still load payloads containing pulse gates by using theqiskit.qpy.load()function, however, they will be treated as opaque custom instructions. LoadingScheduleBlockpayloads is not supported anymore and will cause aQpyErrorexception.
Synthesis Upgrade Notes
-
The
atomic_evolutioncallable argument ofProductFormula(and its subclassesQDrift,LieTrotter, andSuzukiTrotter) has a new function signature. The old signature would take some Pauli operator and time coefficient and return the evolution circuit:def atomic_evolution(pauli_op: SparsePauliOp, time: float) -> QuantumCircuit: evol_circuit = QuantumCircuit(pauli_op.num_qubits) # append operators to circuit return evol_circuitThe new signature directly takes in an existing circuit and should append the evolution of the provided Pauli and given time to this circuit:
def atomic_evolution(evol_circuit: QuantumCircuit, pauli_op: SparsePauliOp, time: float): # append operators to circuit, in-place modificationThis new implementation benefits from significantly better performance.
Transpiler Upgrade Notes
-
Increased the minimum threshold for when gates are assumed to be the identity in
RemoveIdentityEquivalentfrom machine epsilon to1e-12to account for round-off errors in the fidelity calculation and for consistency with the other classes, such asCommutationAnalysisandTwoQubitWeylDecomposition. -
The routing plugin stage name
defaultis now reserved for the Qiskit built-in plugin of the same name. -
The default routing plugin stage is now
"default". In Qiskit v2.0.0, this is simply an alias for the previous default"sabre". The underlying default algorithm may change over the course of the Qiskit v2.x release series for some or all targets, but you can always explicitly setrouting_method="sabre"to maintain the current behavior. -
The translation plugin stage name
defaultis now reserved for the Qiskit built-in plugin of the same name. -
The default translation plugin stage is now
"default". In Qiskit 2.0, this is simply an alias for the previous default"translator". The underlying default algorithm may change over the course of the Qiskit 2.x series for some or all targets, but you can always settranslation_method="translator"explicitly to maintain the current behavior. -
The legacy scheduling passes
ASAPSchedule,ALAPSchedule,DynamicalDecoupling, andAlignMeasureshave been removed in favor of the updated alternativesALAPScheduleAnalysis,ASAPScheduleAnalysis,PadDynamicalDecoupling, andConstrainedReschedulerespectively. These were deprecated in Qiskit v1.1 after the new scheduling workflow superseded the legacy one. -
In the case that neither a
targetnor a set ofbasis_gatesare specified, theHighLevelSynthesistranspiler pass synthesizes circuits with annotated operations with fewer layers of wrappings than before (this happens, for instance, for the circuit produced bymultiplier_cumulative_h18()). -
The keyword argument
property_setis now reserved inBasePassManager.run(), and cannot be used as akwargthat will be forwarded to the subclass’ conversion from the front-end representation to the internal representation. -
The following deprecated uses of the
BackendPropertiesobject in the transpilation pipeline have been removed in Qiskit 2.0:backend_propertiesinput argument intranspile()backend_propertiesinput argument inPassManagerConfigbackend_propertiesinput argument ingenerate_preset_pass_manager()backend_propertiesinput argument ingenerate_routing_passmanager()backend_propertiesinput argument ingenerate_translation_passmanager()backend_propertiesinput argumentTarget.from_configuration()
The following passes have also been updated to only accept a
targetinstead of:backend_propinput argument inDenseLayoutpropertiesinput argument inVF2Layoutpropertiesandcoupling_mapinput arguments inVF2PostLayoutbackend_propsinput argument inUnitarySynthesis
The
BackendPropertiesclass has been deprecated since Qiskit v1.2, because it was part of theBackendV1workflow. Specific instruction properties, such as gate errors or durations can be added to aTargetupon construction through theTarget.add_instruction()method, and communicated to the relevant transpiler passes through thetargetinput argument. -
As a consequence of the removal of the
BackendV1model, the accepted input types of the following transpiler objects have been updated:- The
generate_preset_pass_manager()andtranspile()functions no longer accept inputs of typeBackendV1in theirbackendinput argument. - The
Target.from_configuration()method no longer accepts abackend_propertiesargument - The
Target.target_to_backend_properties()method has been removed
- The
-
The
ResetAfterMeasureSimplificationtranspiler pass now uses anIfElseOpto condition the execution of theXGateinstead of setting aconditionattribute on the gate. This is because theconditionattribute has been removed from the Qiskit data model. -
The deprecated
ConvertConditionsToIfOpstranspiler pass has been removed. The underlyingconditionattribute ofInstructionclass has been removed so this transpiler pass no longer had anything to convert from. Instead you should directly useIfElseOpto classically condition the execution of an operation. -
The
PadDelayandPadDynamicalDecouplingtranspiler passes now require a new argument when constructed. Eithertargetordurationsneed to be specified with aTargetorInstructionDurationsrespectively. Without these, the passes cannot determine the duration of instructions in the circuit and will error. Previously these passes determined these values from the now removeddurationattribute ofInstructionobjects. -
The previously deprecated
AlignMeasurestranspiler pass has been removed. This pass was deprecated in Qiskit v1.1.0. Instead, theConstrainedReschedulepass should be used.ConstrainedRescheduleperforms the same function and also supports aligning to additional timing constraints. -
When scheduling by using
generate_preset_pass_manager()ortranspile(), if theinstruction_durationsargument is specified, the durations are formatted as alist, and they are in units ofdt. You must also set thedtinput argument of the transpilation function. -
Removed the deprecated
DAGNode.sort_keyattribute. This attribute was deprecated in the Qiskit v1.4.0 release. As the lexicographical topological sorting is done internally in Rust and the sort key attribute was unused, this attribute was removed to avoid the overhead from DAG node creation. If you relied on the sort key, you can reproduce it from a given node using something like:def get_sort_key(node: DAGNode): if isinstance(node, (DAGInNode, DAGOutNode)): return str(node.wire) return ",".join( f"{dag.find_bit(q).index:04d}" for q in itertools.chain(node.qargs, node.cargs) ) -
The following
transpile()andgenerate_preset_pass_manager()input arguments, deprecated since Qiskit 1.3 , have been removed from the API:instruction_durationstiming_constraints
In addition to this, the specification of custom basis gates through the
basisgate argument oftranspile()andgenerate_preset_pass_manager(), also deprecated in Qiskit 1.3, is no longer allowed, and aValueErrorwill be raised in these cases.The information formerly provided through these can still be specified via the
backendortargetarguments. You can build a Target instance with defined instruction durations doing:Target.from_configuration(..., instruction_durations=...)For specific timing constraints:
Target.from_configuration(..., timing_constraints=...)And for custom basis gates, you can manually add them to the target or use
.from_configurationwith a custom name mapping, for example:from qiskit.circuit.library import XGate from qiskit.transpiler.target import Target basis_gates = ["my_x", "cx"] custom_name_mapping = {"my_x": XGate()} target = Target.from_configuration( basis_gates=basis_gates, num_qubits=2, custom_name_mapping=custom_name_mapping ) -
The
transpile()andgenerate_preset_pass_manager()interfaces now raise aUserWarningwhen providing acoupling_mapand/orbasis_gatesalong with abackend. In these cases there are multiple sources of truth, the user intentions are not always clear, and there can be conflicts thatgenerate_preset_pass_manager()may not know how to resolve. The suggested alternative is to define a custom target that combines the chosen constraints.One of these situations is the specification of a gate with 3 or more qubits in
backendorbasis_gatestogether with a customcoupling_map. The coupling map does not provide the necessary connectivity details to be able to determine the action of the gate. In these cases,transpile()andgenerate_preset_pass_manager()now raise aValueError. -
As part of Pulse removal in Qiskit 2.0, all pulse and calibration related functionality in the transpiler have been removed.
The following passes and functions have been removed:
qiskit.transpiler.passes.PulseGatespassqiskit.transpiler.passes.ValidatePulseGatespassqiskit.transpiler.passes.RXCalibrationBuilderpassqiskit.transpiler.passes.RZXCalibrationBuilderpassqiskit.transpiler.passes.RZXCalibrationBuilderNoEchopassqiskit.transpiler.passes.EchoRZXWeylDecompositionpassqiskit.transpiler.passes.NoramlizeRXAnglepassqiskit.transpiler.passes.rzx_templates()function
The
inst_mapargument has been removed from the following elements:- The
generate_preset_pass_manager()andtranspile()functions - The
Target.from_configuration()method - The constructor of the
PassManagerConfigclass
Calibration support has been removed:
calibrationhas been removed from theInstructionPropertiesconstructor and is no longer a property of that class.- The
has_calibration,get_calibration,instruction_schedule_mapandupdate_from_instruction_schedule_mapmethods have been removed from theTargetclass.
-
The deprecated
StochasticSwaptranspiler pass, and its associated built-in routing stage plugin “stochastic”, have been removed. These were marked as deprecated in the Qiskit v1.3.0 release. The pass has been superseded by theSabreSwapclass, which should be used instead, as it offers better performance and output quality. For example, if the pass was previously invoked through the transpile function, such as:from qiskit import transpile from qiskit.circuit import QuantumCircuit from qiskit.transpiler import CouplingMap from qiskit.providers.fake_provider import GenericBackendV2 qc = QuantumCircuit(4) qc.h(0) qc.cx(0, range(1, 4)) qc.measure_all() cmap = CouplingMap.from_heavy_hex(3) backend = GenericBackendV2(num_qubits=cmap.size(), coupling_map=cmap) tqc = transpile( qc, routing_method="stochastic", layout_method="dense", seed_transpiler=12342, target=backend.target )this should be replaced with:
tqc = transpile( qc, routing_method="sabre", layout_method="dense", seed_transpiler=12342, target=backend.target ) -
The
qiskit.transpiler.passes.CXCancellationpass has been removed. It was deprecated in favor of class:.InverseCancellation, which is more generic.CXCancellation()is fully semantically equivalent toInverseCancellation([CXGate()]). -
The
SolovayKitaevtranspiler pass no longer raises an exception on circuits that contain single-qubit operations without ato_matrixmethod (such as measures, barriers, and control-flow operations) or parameterized single-qubit operations, but will leave them unchanged. -
Plugins for the translation stage of the preset pass managers are now required to respect
Targetgate directionality in their output. Previously,transpile()andgenerate_preset_pass_manager()would generate aPassManagerthat contained fix-up passes if needed. You must now include these in your own custom stage, if your stage does not guarantee that it respects directionality.You can use the
GateDirectionpass to perform the same fix-ups that Qiskit used to do. For example:from qiskit.transpiler import PassManager from qiskit.transpiler.passes import GateDirection from qiskit.transpiler.preset_passmanagers.plugin import PassManagerStagePlugin class YourTranslationPlugin(PassManagerStagePlugin): def pass_manager(self, pass_manager_config, optimization_level): pm = PassManager([ # ... whatever your current setup is ... ]) # Add the two-qubit directionality-fixing pass. pm.append(GateDirection( pass_manager_config.coupling_map, pass_manager_config.target, )) return pm -
The preset pass managers no longer populates the implicit
pre_optimizationstage of their outputStagedPassManager. You can now safely assign your ownPassManagerto this field. You could previously only append to the existingPassManager. -
The default value for the
generate_routing_passmanager()argumentseed_transpilerhas changed fromNoneto-1. This change was made because this flag was only used to configure theVF2PostLayouttranspiler pass, and for that pass, the randomization typically degrades performance and is not desirable. If you relied on the previous default value, you can restore this behavior by explicitly setting the argumentseed_transpiler=None. If you were explicitly setting a seed value for this parameter, there is no change in behavior.
Visualization Upgrade Notes
-
The
idle_wiresparameter in all circuit drawers has been extended with a new option,"auto", which is now the default behavior. If you still want to display wires without instructions, explicitly setidle_wires=True.When set to
"auto", the behavior is as follows:- If the circuit has a defined
.layoutattribute,idle_wiresis automatically set toFalse(hiding idle wires) - Otherwise,
idle_wiresremainsTrue(showing all wires, as was the previous default)
The following example shows a circuit without a layout displayed by using
idle_wires="auto":qr_0: ──────── ┌───┐┌─┐ qr_1: ┤ H ├┤M├ └───┘└╥┘ cr_0: ══════╬═ ║ cr_1: ══════╩═Once a layout is applied,
idle_wires="auto"setsidle_wirestoFalse, hiding idle wires:┌───┐┌─┐ qr_1 -> 1 ┤ H ├┤M├ └───┘└╥┘ cr_1: ══════╩═If you want to display all wires in a laid-out circuit, set
idle_wires=Trueexplicitly:qr_0 -> 0 ──────── ┌───┐┌─┐ qr_1 -> 1 ┤ H ├┤M├ └───┘└╥┘ ancilla_0 -> 2 ──────╫─ ║ cr_0: ══════╬═ ║ cr_1: ══════╩═As quantum computers scale to more qubits, even small circuits can produce large circuit representations after transpilation. The
"auto"setting helps improve readability by hiding unnecessary wires when possible. - If the circuit has a defined
-
The
array_to_latex()function andOperator.draw()method can now raise aMissingOptionalLibraryexception if thesympylibrary is not installed. In the Qiskit v1.x releases,symengineandsympywere always guaranteed to be installed, but starting in v2.0.0, this is no longer a hard requirement. The LaTeX visualization for a matrix relies on thesympylibrary, so if you’re using this functionality, ensure that you havesympyinstalled. -
As a consequence of the removal of the
BackendV1model, theplot_gate_map(),plot_error_map()andplot_circuit_layout()functions no longer accept inputs of typeBackendV1in theirbackendinput argument. -
The timeline drawer now requires that the
targetargument is specified when called. As instructions no longer contain duration attributes, this extra argument is required to specify the durations for all the supported instructions. Without the argument, the timeline drawer does not have access to this information. -
As part of the Pulse removal in Qiskit 2.0, support for pulse drawing via
qiskit.visualization.pulse_drawerhas been removed.
Misc. Upgrade Notes
-
The
deprecate_functionanddeprecate_argumentsdecorators, deprecated since Qiskit v0.24 (May 2023), have been removed in Qiskit v2.0.0. The currentdeprecate_func()replaces@deprecate_functionand the currentdeprecate_arg()replaces@deprecate_arguments. -
The
assemblefunction and related capabilities (contained in theassemblermodule) have been removed from the codebase following their deprecation in Qiskit v1.2.assemblewas used to generate aQobjin the context of the deprecatedBackendV1workflow. The conversion is no longer necessary, as the transpilation and primitives pipeline handles quantum circuits directly, rendering theQobjobsolete.The removal includes the following public API components:
qiskit.compiler.assemblefunctionqiskit.assembler.assemble_circuitsfunctionqiskit.assembler.assemble_schedulesfunctionqiskit.assembler.disassemblefunctionqiskit.assembler.RunConfigclassqiskit.circuit.Instruction.assemblemethod
-
The
Qobjstructure and related classes, deprecated in Qiskit v1.2.0, have been removed. They were introduced as part of theBackendV1workflow and are no longer necessary for interacting withBackendV2backends. This removal affects the following classes:QobjExperimentHeaderQobjHeaderQasmQobjQasmQobjInstructionQasmQobjExperimentConfigQasmQobjExperimentQasmQobjConfigQasmExperimentCalibrationsGateCalibrationPulseQobjPulseQobjInstructionPulseQobjExperimentConfigPulseQobjExperimentPulseQobjConfigQobjMeasurementOptionPulseLibraryItem
-
The
MeasLevelandMeasReturnTypeclasses, previously defined inqobj/utils.py, have been migrated toresult/models.pyfollowing the removal of theqobjmodule. These classes were not part of the public API. The import path has been updated from:from qiskit.qobj.utils import MeasLevel, MeasReturnTypeto:from qiskit.result import MeasLevel, MeasReturnType. -
The use of positional arguments in the constructor of
Resulthas been disabled. Please set all arguments using kwarg syntax, i.e:Result(backend_name="name", ....). In addition to this, theqobj_idargument will no longer be used in the construction of theResultinternals. It is still possible to setqobj_idas a generic kwarg, which will land in the metadata field with the other generic kwargs. -
As part of pulse removal in Qiskit 2.0.0, the
sequenceandschedule_circuitfunctions fromqiskit.schedulertogether with theScheduleConfigclass have been removed. -
The
qiskit.result.mitigationmodule has been removed following its deprecation in Qiskit v1.3. The removal includes theLocalReadoutMitigatorandCorrelatedReadoutMitigatorclasses as well as the associated utils. There is no alternative path in Qiskit, as their functionality had been superseded by the`mthreeaddon. <https://github.com/Qiskit/qiskit-addon-mthree>`__
Circuits Deprecations
-
The deprecated
QuantumCircuit.durationattribute was not removed in this release as originally planned. It will be removed as part of the Qiskit v3.0.0 release instead. This functionality has been superseded by theQuantumCircuit.estimate_duration()method, which should be used instead. -
The deprecated tuple-like interface for
CircuitInstructionwas not removed in this release as originally planned. It will be removed in Qiskit v3.0.0 instead. Instead, use theoperation,qubits, andclbitsnamed attributes. -
The Multiple-Control-Multiple-Target circuit class
MCMTis now deprecated and was replaced byMCMTGate, which is a properGatesubclass. Using a gate instead of a circuit allows the compiler to reason about the object at a higher level of abstraction and allows multiple synthesis plugins to be applied.
Transpiler Deprecations
-
The deprecated
DAGCircuit.durationattribute was not removed in this release as originally planned. It will be removed as part of the Qiskit v3.0.0 release instead. This functionality has been superseded by theQuantumCircuit.estimate_duration()method, which should be used instead. -
The
propagate_conditionargument ofDAGCircuit.substitute_node()andDAGCircuit.substitute_node_with_dag()has been deprecated. With the removal ofInstruction.conditionfrom the Qiskit data model this option no longer serves a purpose. If it is set it no longer has any effect. It is not removed from the signature to maintain compatibility during the migration from Qiskit 1.x -> 2.0. This option will be removed in Qiskit 3.0. -
The function
generate_pre_op_passmanager()is deprecated. It is no longer used in the Qiskit preset pass managers, and its purpose is defunct; it originally generated a fix-up stage for translation plugins that did not respect ISA directionality. Translation stages are now required to respect directionality, so the functionality is not needed, and most likely, no replacement is required.
Security Issues
- Fixed a security vulnerability in
qpy.load()when loading payloads that usesympyto serializeParameterExpressionobjects and other symbolic expressions. This potentially includes any QPY payload using QPY version < 10, and optionally 10, 11, and 12 depending on the symbolic encoding used in the serialization step (qpy.dump()).
Bug Fixes
-
Fixed an inconsistency in the transpilation process when handling close-to-identity gates, where these gates were evaluated to commute with everything by
CommutationAnalysis, but not removed byRemoveIdentityEquivalent. The underlying issue was caused byRemoveIdentityEquivalentandCommutationAnalysis(and, by extension,CommutativeInverseCancellation) using different metrics. Both now use the average gate fidelity and the same threshold to assess whether a gate should be treated as identity (such as a rotation gate with very small angle). See the docstrings of these classes for more information. Fixed #13547. -
Fixed a bug in
QuantumCircuit.assign_parameters(), which occurred when assigning parameters to standard gates whose definition had already been triggered. In this case, the new values were not properly propagated to the gate instances. While the circuit itself was still compiled as expected, inspecting the individual operations would still show the old parameter.For example:
from qiskit.circuit.library import EfficientSU2 circuit = EfficientSU2(2, flatten=True) circuit.assign_parameters([1.25] * circuit.num_parameters, inplace=True) print(circuit.data[0].operation.params) # would print θ[0] instead of 1.25Fixed #13478.
-
Fixed a bug in
DAGCircuitthat would cause outputVarnodes to become input nodes duringdeepcopyand pickling. -
Fixed an oversight in the
Targetclass where setting a new value for thedtattribute and subsequently callingtarget.durations()would not show the updateddtvalue in the returnedInstructionDurationsobject. This is now fixed through an invalidation of the internal target instruction durations cache in thedtsetter. -
Fixed a problem in the
BasisTranslatortranspiler pass where the global phase of the DAG was not updated correctly. Fixed #14074. -
Fixed a bug in the
HighLevelSynthesistranspiler pass, where it would synthesize any instruction for which a synthesis plugin is available, regardless of whether the instruction is already supported by the target or a part of the explicitly passedbasis_gates. This behavior is now fixed, so that such already supported instructions are no longer synthesized. -
The
InverseCancellationtranspilation pass now runs inside of control-flow blocks. Previously, it ignored pairs of gates that could be cancelled when they were defined within classical blocks. Refer to #13437 for more details. -
Fixed a bug with multi-controlled rotations where the rotation angle was a
ParameterExpression. Attempting synthesis in this case would lead to an error stating that the gate cannot be synthesized with an unbound parameter. This bug affected multi-controlled rotation circuit methodsQuantumCircuit.mcrx(), :meth:.QuantumCircuit.mcry, andQuantumCircuit.mcrz(), as well as when callingRXGate.control(),RYGate.control(), orRZGate.control()when the rotation angle was aParameterExpression. Now, these multi-controlled rotation circuits can be synthesized without raising an error. -
Fixed a bug in QPY (
qiskit.qpy) where circuits containing gates of classMCMTGatewould fail to serialize. See #13965. -
Fixed a bug that caused
Statevector.expectation_value()to yield incorrect results for the identity operator when the statevector was not normalized. Fixed #13029 -
Converting a quantum circuit to a gate with
converters.circuit_to_instruction()now properly fails when given circuit contains control flow instructions. -
Calling an
AnalysisPassor aTransformationPasslike a function (as inpass_ = MyPass(); pass_(qc)) will now respect any requirements that the pass might have. For example, scheduling passes such asALAPScheduleAnalysisrequire thatTimeUnitConversionruns before them. Running the pass by using aPassManageralways respected this requirement, but until now, it was not respected when calling the pass directly. -
When a
TranspilerErrorsubclass is raised by a pass inside a call toPassManger.run(), the exception will now be propagated through losslessly, rather than becoming a chained exception with an erased type. -
SabreSwapwill no longer contract idle qubit wires out of control-flow blocks during routing. This was generally a valid optimization, but not an expected side effect of a routing pass. You can now use theContractIdleWiresInControlFlowpass to perform this contraction. -
Fixed a per-process based non-determinism in
SparsePauliOp.to_matrix. The exact order of the floating-point operations in the summation would previously vary per process, but will now be identical between different invocations of the same script. See #13413.