Qiskit SDK 1.2 release notes
1.2.4
Prelude
Qiskit 1.2.4 is a patch release that fixes a QPY problem introduced in the yanked 1.2.3 bugfix release. In 1.2.3, an error would be raised when loading a QPY file that was generated with a different symengine version from the version installed when loading.
Bug Fixes
- Fixed an issue introduced in the now yanked 1.2.3 bugfix release that would cause an exception with the error message “Qiskit doesn’t support loading a symengine payload generated with symengine >= 1.0” to be raised whenever loading a QPY file that was generated with a different symengine version from the version installed when loading. This issue could only occur in 1.2.3.
1.2.3
Prelude
Qiskit 1.2.3 is a patch release fixing a problem in QPY that could cause files generated by one Python environment to fail to load in a different Python environment, despite the format supposedly being transferable. This is related to differences in the version of the library symengine
, which QPY should have protected against.
Known Issues
-
Versions of Qiskit before 1.2.4 will not be able to load QPY files dumped using
qpy.dump()
, even withversion
set appropriately, if:- there are unbound
ParameterExpression
objects in the QPY file, - the
use_symengine=True
flag was set (which is the default in Qiskit >= 1.0.0) inqpy.dump()
, and - the version of
symengine
installed in the generating and loading environments are not within the same minor version.
This applies regardless of the version of Qiskit used in the generation (at least up to Qiskit 1.2.4 inclusive).
If you want to maximize compatibility with versions of Qiskit < 1.2.3, you should set
use_symengine=False
. Versions of Qiskit >= 1.2.3 should not require this. - there are unbound
-
QPY files from the Qiskit 0.45 series can, under a very specific and unlikely set of circumstances, fail to load with any newer version of Qiskit, including Qiskit 1.2.4. The criteria are:
- the
QuantumCircuit
orScheduleBlock
to be dumped contained unboundParameterExpression
objects, - the installed version of
symengine
was in the 0.9 series (which was the most recent release during the support window of Qiskit 0.45), and - the
use_symengine=True
flag was set (which was not the default).
Later versions of Qiskit used during generation are not affected, because they required newer versions than
symengine
0.9.In this case, you can recover the QPY file by reloading it with an environment with Qiskit 0.45.3 and
symengine
0.9.2 installed. Then, useqpy.dump()
withuse_symengine=False
to re-export the file. This will then be readable by any newer version of Qiskit. - the
Upgrade Notes
- The supported versions of symengine have been pre-emptively capped at < 0.14.0 (which is expected to be the next minor version, as of this release of Qiskit). This has been done to protect against a potential incompatibility in
qpy
when serializingParameterExpression
objects. The serialization used in QPY Format versions 10, 11, and 12 forParameterExpression
objects is tied to the symengine version used to generate it, and there is the potential for a future symengine release to not be compatible. This upper version cap is to prevent a future release of symengine causing incompatibilities when trying to load QPY files usingqpy.load()
.
Bug Fixes
-
Fixed an issue with
qpy.load()
when loading a QPY file containing aParameterExpression
, if the versions ofsymengine
installed in the generating and loading environments were not the same. For example, if a QPY file containingParameterExpression
objects was generated using Qiskit 1.2.2 withsymengine==0.11.0
installed, Qiskit 1.2.2 withsymengine==0.13.0
installed would be unable to load it.Previously, an error would have been raised by
symengine
around this version mismatch. This has been worked around forsymengine
0.11 and 0.13 (there was no 0.12). However, if you’re trying to use different versions ofsymengine
and there is a mismatch, this version of Qiskit still might not work.
1.2.2
Prelude
Qiskit 1.2.2 is a minor bugfix release for the 1.2 series.
Bug Fixes
-
Fixed a bug in the transpiler pass
ElidePermutations
where the qubit mapping was not updated correctly in the presence ofPermutationGate
s. -
Fixed a potential source of non-determinism in
DenseLayout
(and by extensionSabreLayout
) when targeting aCouplingMap
orTarget
that has more than one subgraph with the same degree of connectivity. In these case the exact output layout from the pass could previously fluctuate based on the number of local CPUs and thread execution speed. -
The
HighLevelSynthesis
transpiler pass no longer raises an exception when encountering a custom gate that is called “qft” but is not an instance ofQFTGate
. Instead, the synthesis plugins for QFT gates ignore such a gate, and the gate’s definition is used (if provided). -
Fixed a bug in the circuit drawers, which could fail or omit wires if
idle_wires=False
. Fixed #13128 and #13146. -
Fixed an issue when calling
transpile()
or the methodStagedPassManager.run()
of a pass manager generated bygenerate_preset_pass_manager()
, usingoptimization_level
2 or 3 when therouting_method
argument is set to"none"
to explicitly disable routing. Previously under these conditions the transpiler would run theElidePermutations
pass as part of the init stage, as under normal conditions this is a useful optimization to removeSwapGate
andPermutationGate
instances from the circuit. But whenrouting_method="none"
this optimization wasn’t expected as it permutes the circuit in a similar manner to routing, which shouldn’t be performed whenrouting_method="none"
. This has been fixed by no longer runningElidePermutations
ifrouting_method="none"
is set. Fixed #13144. -
The OpenQASM 3 exporter has restored its behavior of accepting non-standard-library include files in the
includes
argument toqasm3.dump()
,dumps()
, andExporter
. These will insert a suitableinclude
statement into the output as before, and the exporter remains unaware of the intended gates in that include file; you should pass the gates you expect it to define in thebasis_gates
argument to the same functions.We expect to improve the export mechanism against non-standard include files in a future release of Qiskit.
1.2.1
Prelude
Qiskit 1.2.1 is a minor bugfix release for the 1.2 series.
Bug Fixes
-
Fixed an issue with the visualizations of some backends/coupling maps that showed as folded on their own. The default ``neato` setting <https://graphviz.org/docs/layouts/neato/>`_ works well in most cases. However,
prism
overlap returns a more regular layout for other scenarios. -
Parametric controlled standard-library gates (such as
CRXGate
) will now get correctly extracted to a Rust-space standard gate when usingQuantumCircuit.append()
and the gate object. Previously there was a discrepancy where using theQuantumCircuit.crx()
method would cause a correct extraction in Rust space, but theappend()
form would not. The bug should generally not have caused any unsoundness from Python. -
Fixed a bug in
TwoQubitBasisDecomposer
where the Rust-based code would panic if the given KAK gate was not a default version of the standard gates (for example, usingCXGate(ctrl_state=0)
). Fixed #12998. -
Fixed a bug where
InstructionDurations.from_backend()
did not work forBackendV2
backends. Fixed #12760. -
Fixed the definition of the
CUGate
matrix in Rust-space. While this was not noticable when handling theCUGate
purely on the Python side, this had knock-on effects when transpiler passes were using the Rust representation, such as could happen inConsolidate2qBlocks
. Fixed #13118. -
Fixed a bug in
HoareOptimizer
where a controlled gate was simplified by removing its controls but the new gate was not handled correctly. Fixed #13079. -
generate_preset_pass_manager()
now correctly raises an exception, ifseed_transpiler
is set to an invalid value (i.e., it is not a non-negative integer). Fixed #12938. -
Fixed an edge case in
SabreLayout
, where, in rare cases on large devices and challenging circuits, the routing would fail. This was due to the release valve making more than one two-qubit gate routable, where only one was expected. Fixed #13081. -
Fixed a bug in
Split2QUnitaries
where it would fail to run on circuits with customGate
objects that did not implement__array__
. See #12970. -
Fixed a bug in
StatePreparation
where thenormalize
argument was ignored for input arrays. Fixed #12984. -
Fixed a bug where various synthesis methods created circuits without quantum or classical registers. This also affected functions that internally used the synthesis methods, such as
Clifford.to_circuit()
. While the circuits were valid, this could cause issues when comparing circuits with registers. Fixed #13041. -
Fixed a bug that caused the method
Initialize.gates_to_uncompute()
fail. Fixed #12969. -
Fixed an edge case when transpiling a circuit with
optimization_level
2 or 3 with an incomplete 1-qubit basis gate set on a circuit containing 2-qubit gates, that can be implemented as a product of single qubit gates. This bug is resolved by restrictingSplit2QUnitaries
to consider onlyUnitaryGate
objects. Fixed #12970.
1.2.0
Prelude
The Qiskit 1.2.0 release focuses mainly on improving performance and quality of the compiler. Also, it is the last release supporting Python 3.8. In Qiskit 1.3.0 the minimal required Python version will be 3.9. Among a wide range of new features, improvements, and fixes, the release highlights are:
- The circuit infrastructure, including gates and operations, is moved to Rust. This enables a series of speedups in circuit construction and circuit manipulation.
- Leveraging the above point, parts of the synthesis library are now constructing circuits in Rust. This produces a significant speedup when synthesizing operations such as Cliffords, permutations, or linear functions. As example, decomposing 50+ qubit Cliffords benefit from an approximate 1000-fold speedup in runtime.
- The quality of compiled circuits is improved by optimizing with a unitary peephole optimization at the initial stage of the transpilation workflow (at optimization level
>1
), and by using a dense layout as a Sabre layouting trial (at optimization level>0
).
New Features
-
Added a new class
QFTGate
for natively representing Quantum Fourier Transforms (QFTs). The older way of representing QFTs via quantum circuits, seeQFT
, remains for backward compatibility. The new way of representing a QFT via a gate avoids synthesizing its definition circuit when the gate is declared, delaying the actual synthesis to the transpiler. It also allows to easily choose between several different algorithms for synthesizing QFTs, which are available as high-level-synthesis plugins. -
Added a synthesis method
synth_qft_full()
for constructing a QFT circuit assuming a fully-connected architecture. -
Added two high-level-synthesis plugins for synthesizing a
QFTGate
. The classQFTSynthesisFull
is based onsynth_qft_full()
and synthesizes a QFT gate assuming an all-to-all connectivity. The classQFTSynthesisLine
is based onsynth_qft_line()
and synthesizes a QFT gate assuming a linear-nearest-neighbor connectivity. -
Added two parameters to
GenericBackendV2
to exclude error (noise_info
) and pulse channel information (pulse_channels
) from the construction of the backend. These parameters areTrue
by default, replicating the initial default behavior of the constructor. A memory-sensitive user may set these options toFalse
to reduce the memory overhead by 40x when transpiling on large- scaleGenericBackendV2
. -
The
StabilizerState
class now has a new methodStabilizerState.probabilities_dict_from_bitstring()
allowing the user to pass single bitstring to measure an outcome for. Previouslly theStabilizerState.probabilities_dict()
would be utilized and would at worst case calculate () number of probability calculations (depending on the state), even if a user wanted a single result. With this new method the user can calculate just the single outcome bitstring value a user passes to measure the probability for. As the number of qubits increases, the more prevelant the performance enhancement may be (depending on the state) as only 1 bitstring result is measured. -
Implemented
UniformSuperpositionGate
class, which allows the creation of a uniform superposition state using the Shukla-Vedula algorithm. This feature facilitates the creation of quantum circuits that produce a uniform superposition state , where is a positive integer representing the number of computational basis states with an amplitude of . This implementation supports the efficient creation of uniform superposition states, requiring only qubits and gates. Usage example:from qiskit import QuantumCircuit from qiskit.circuit.library.data_preparation import UniformSuperpositionGate M = 5 num_qubits = 3 usp_gate = UniformSuperpositionGate(M, num_qubits) qc = QuantumCircuit(num_qubits) qc.append(usp_gate, list(range(num_qubits))) qc.draw()
Circuits Features
-
Added a new function
random_clifford_circuit()
toqiskit.circuit
, that allows to generate a pseudo-random Clifford circuit with gates from the standard library. Example usage:from qiskit.circuit.random import random_clifford_circuit circ = random_clifford_circuit(num_qubits=2, num_gates=6) circ.draw(output='mpl')
-
Added support for
AnnotatedOperation.params
andAnnotatedOperation.validate_parameter()
, which enable circuit-level parameter handling (such as binding parameters) for annotated operations. -
CircuitInstruction
andDAGOpNode
each have new methods to query various properties of their internalOperation
, without necessarily needing to access it. These methods are:CircuitInstruction.is_standard_gate()
andDAGOpNode.is_standard_gate()
,CircuitInstruction.is_controlled_gate()
andDAGOpNode.is_controlled_gate()
,CircuitInstruction.is_directive()
andDAGOpNode.is_directive()
,CircuitInstruction.is_control_flow()
andDAGOpNode.is_control_flow()
, andCircuitInstruction.is_parameterized()
andDAGOpNode.is_parameterized()
.
If applicable, using any of these methods is significantly faster than querying
CircuitInstruction.operation
orDAGOpNode.op
directly, especially if the instruction or node represents a Qiskit standard gate. This is because the standard gates are stored natively in Rust, and their Python representation is only created when requested. -
A native rust representation of Qiskit’s standard gate library has been added. When a standard gate is added to a
QuantumCircuit
orDAGCircuit
it is now represented in a more efficient manner directly in Rust. Accessing that gate object from a circuit or DAG will return a new Python object representing the standard gate. This leads to faster and more efficient transpilation and manipulation of circuits for functionality written in Rust. -
The
random_circuit()
function has a new feature where users can specify a distributionnum_operand_distribution
(a dict) that specifies the ratio of 1-qubit, 2-qubit, 3-qubit, and 4-qubit gates in the random circuit. For example, ifnum_operand_distribution = {1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25}
is passed to the function then the generated circuit will have approximately 25% of 1-qubit, 2-qubit, 3-qubit, and 4-qubit gates. Also it should be noted that the ifnum_operand_distribution
is not specified thenmax_operands
will default to 4 and a random circuit with a random gate distribution will be generated. If bothnum_operand_distribution
andmax_operands
are specified at the same time thennum_operand_distribution
will be used to generate the random circuit.Example usage:
from qiskit.circuit.random import random_circuit circ = random_circuit( num_qubits=6, depth=5, num_operand_distribution={1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25} ) circ.draw(output="mpl")
-
Improved performance of the method
DAGCircuit.quantum_causal_cone()
by not examining the same non-directive node multiple times when reached from different paths. -
Added the
insert_barriers
keyword argument to theQuantumCircuit.repeat()
method. Setting it toTrue
will insert barriers between circuit repetitions. -
Replacing the internal synthesis algorithm of
StatePreparation
andInitialize
of Shende et al. by the algorithm given inIsometry
of Iten et al. The new algorithm reduces the number of CX gates and the circuit depth by a factor of 2. -
ParameterExpression
now supports the unary+
operator.
Primitives Features
-
Added a new method
BitArray.postselect()
that returns all shots containing specified bit values. Example usage:from qiskit.primitives.containers import BitArray ba = BitArray.from_counts({'110': 2, '100': 4, '000': 3}) print(ba.postselect([0,2], [0,1]).get_counts()) # {'110': 2, '100': 4}
-
The metadata of Primitives V2 implementations, i.e.,
StatevectorSampler
,StatevectorEstimator
,BackendSamplerV2
andBackendEstimatorV2
, has been updated to match that of IBM quantum devices.version
andcircuit_metadata
are added for all V2 implementationsshots
is added forBackendSamplerV2
andBackendEstimatorV2
precision
is renamed withtarget_precision
forStatevectorEstimator
Note that the metadata of
StatevectorEstimator
does not haveshots
because the class computes expectation values withStatevector
and shots are not used.
OpenQASM Features
-
The internal symbol table of the OpenQASM 3 exporter (
qiskit.qasm3
) has been rewritten, which should result in cleaner outputs when using Qiskit standard-library gates that are not in the OpenQASM 3 standard-library headers, and more deterministic outputs. For example, using severalRZXGate
s will now result in only a single parametric definition, and when naming collisions occur, the symbol table will assign a deterministic counter to make names unique, rather than a non-deterministic integer (previously, the object identity was used). -
The vendored version of the OpenQASM 3.0 standard library has been updated to match the state as of commit 4ca1d79383. This should generally have no effect on your use of Qiskit, unless you were retrieving our vendored file for your own use.
Synthesis Features
-
MCXRecursive
with control qubits and a single clean auxiliary qubit now requires at most CX gates. -
MCXVChain
has two new Boolean parameters relative_phase and action_only. Ifaction_only
isTrue
the circuit does not clean the dirty qubits. Ifrelative_phase
isTrue
the gate is implemented up to a global phase. Both parameters are used to optimize the decomposition ofMCXVChain
. -
MCXVChain
with controls and dirty auxiliary qubits now requires CX gates. -
Port
synth_permutation_acg()
, used to synthesize qubit permutations, to Rust. This produces an approximate 3x performance improvement on 1000 qubit circuits. -
Port
synth_permutation_basic()
, used to synthesize qubit permutations, to Rust. -
Port
synth_cnot_count_full_pmh()
, used to synthesize a linear function into a CX network, to Rust. This produces approximately 44x speedup, as measured on 100 qubit circuits. -
The function
synth_cnot_count_full_pmh()
now allows choosing the (heuristically) optimalsection_size
by setting it toNone
. Then, a value is chosen which attempts to minimize the upper bound on the number of CX gates, that is where is the number of qubits and . -
The function
synth_clifford_bm()
was ported to Rust. Recall that this function optimally synthesizesClifford
operators on 1, 2 or 3 qubits with respect to the number of CX-gates. This leads to a significant increase in performance. For Cliffords over 3 qubits, the speedup in on the order of 80 times. -
The function
synth_clifford_greedy()
that synthesizesClifford
operators was ported to Rust, leading to a significant increase in performance for all numbers of qubits. For Cliffords over 50 qubits, the speedup is on the order of 1000 times. -
Added the
wrap
keyword argument to theProductFormula
classes which (when enabled) wraps individual Pauli evolution terms. This can be useful when visualizing circuits. -
The
atomic_evolution
argument toProductFormula
(and its subclasses) has a new function signature. Rather than taking some Pauli operator and time coefficient and returning the evolution circuit, the new function takes in an existing circuit and should append the evolution of the provided Pauli and given time to this circuit. This new implementation benefits from significantly better performance. -
Improved the performance of
synth_permutation_depth_lnn_kms()
, used to synthesize permutations for linear connectivity, by porting it to Rust.
Transpiler Features
-
Added a new import path option for
generate_preset_pass_manager()
, so that it can now be imported as:from qiskit import generate_preset_pass_manager
instead of having to type the full path:
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
The function is also importable from the
qiskit.transpiler
module as:from qiskit.transpiler import generate_preset_pass_manager
-
Added a new user config file option
sabre_all_threads
and a corresponding environment variableQISKIT_SABRE_ALL_THREADS
. When this flag is set the preset pass managers will run theSabreLayout
andSabreSwap
transpiler passes using all the available CPUs on the local system. Using this option is a tradeoff between determinism of output between different computers and potentially better output with fewerSwapGate
s.These transpiler passes run multiple random trials in parallel and pick the output which results in the fewest
SwapGate
s. As a rule of thumb, if you run more trials, this provides the algorithm more opportunities to find a better result. By default, the preset pass managers use a fixed number of trials, in this release 5 trials for levels 0 and 1, and 20 trials for levels 2 and 3, but these numbers may change in future releases (and were different in historical releases). Using a fixed number of trials results in deterministic results regardless of the local system, because even with a fixed seed if you were to default to the number of local CPUs available the results would different when running between different computers.If the default number of trials for a given optimization level is higher than the number of local CPUs it will use the optimization level default which is higher.
-
Added a new pass
Split2QUnitaries
that iterates over all two-qubit gates or unitaries in a circuit and replaces them with two single-qubit unitaries, if possible without introducing errors, i.e., the two-qubit gate/unitary is actually a tensor product of single-qubit unitaries. -
The passes
Collect2qBlocks
,ConsolidateBlocks
andSplit2QUnitaries
have been added to theinit
stage of the preset pass managers with optimization level 2 and optimization level 3. The modification of theinit
stage should allow for a more efficient routing for quantum circuits that either:- contain two-qubit unitaries/gates that are actually a product of single-qubit gates, or
- contain multiple two-qubit gates in a continuous block of two-qubit gates.
In the former case, the routing of the two-qubit gate can simply be skipped as no real interaction between a pair of qubits occurs. In the latter case, the lookahead space of routing algorithms is not ‘polluted’ by superfluous two-qubit gates, i.e., for routing it is sufficient to only consider one single two-qubit gate per continuous block of two-qubit gates. These passes are not run if the pass managers target a
Target
that has a discrete basis gate set, i.e., all basis gates have are not parameterized. -
The performance of
StarPreRouting
, used to find a star graph connectivity subcircuit, is improved by performing the heavy lifting in Rust space. -
The
SabreLayout
transpiler pass has been updated to always run an additional trial using the same algorithm asDenseLayout
to choose a starting point for Sabre’s layout algorithm. The starting point used by the layout algorithm can have a large influence on the quality of the results. By defaultSabreLayout
still start withlayout_trials
random trials but in addition there will be a single trial that uses the densest subgraph of the connectivity graph as the starting point. This may yield better results in some cases especially on cases with smaller circuits for larger coupling maps. -
A new
dt
argument has been added togenerate_preset_pass_manager()
to match the set of arguments oftranspile()
. This will allow for the internal conversion of transpilation constraints to aTarget
representation.
Visualization Features
-
The user configuration file has a new option
circuit_idle_wires
, which takes a Boolean value. This allows users to set their preferred default behavior of theidle_wires
option of the circuit drawersQuantumCircuit.draw()
andcircuit_drawer()
. For example, adding a section to~/.qiskit/settings.conf
with:[default] circuit_idle_wires = false
will change the default to not display idle wires.
Misc. Features
- Added a new build-time environment variable
QISKIT_NO_CACHE_GATES
which when set to a value of1
(i.e.QISKIT_NO_CACHE_GATES=1
) decreases the memory overhead of aCircuitInstruction
andDAGOpNode
object at the cost of increased runtime on multiple accesses toCircuitInstruction.operation
andDAGOpNode.op
. If this environment variable is set when building the Qiskit Python package from source the caching of the return of these attributes will be disabled.
Circuits Upgrade Notes
-
The
annotated
argument of theGate.control()
method is nowNone
by default, which allows Qiskit to choose whether to annotate a controlled operation. If the concrete implementation (annotated=False
) is available, it will be returned by default. Otherwise, the annotated implementation will be returned (annotated=True
). This allows, for example, to defer the synthesis of controlled, parameterized gates. -
The
Operation
instances ofDAGOpNode.op
being returned will not necessarily share a common reference to the underlying object anymore. This was never guaranteed to be the case and mutating theDAGOpNode.op
directly by reference was unsound and always likely to corrupt the DAG’s internal state tracking Due to the internal refactor of theQuantumCircuit
andDAGCircuit
to store standard gates in Rust, the output object fromDAGOpNode.op
will now likely be a copy instead of a shared instance. If you need to mutate an element should ensure that you do:op = dag_node.op op.params[0] = 3.14159 dag.substitute_node(dag_node, op)
instead of doing something like:
dag_node.op.params[0] = 3.14159
which will not work for any standard gate in this release. It would have likely worked by chance in a previous release but was never an API guarantee.
-
The
Operation
instances ofCircuitInstruction.operation
being returned will not necessarily share a common reference to the underlying object anymore. This was never guaranteed to be the case and mutating theCircuitInstruction.operation
directly by reference was unsound and always likely to corrupt the circuit, especially when parameters were in use. Due to the internal refactor of theQuantumCircuit
to store standard gates in Rust, the output object fromCircuitInstruction.operation
will now likely be a copy instead of a shared instance. If you need to mutate an element in the circuit (which is strongly not recommended as it’s inefficient and error prone) you should ensure that you do:from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(1) qc.p(0) op = qc.data[0].operation op.params[0] = 3.14 qc.data[0] = qc.data[0].replace(operation=op)
instead of doing something like:
from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(1) qc.p(0) qc.data[0].operation.params[0] = 3.14
which will not work for any standard gates in this release. It would have likely worked by chance in a previous release but was never an API guarantee.
Primitives Upgrade Notes
-
BitArray.slice_bits()
andBitArray.slice_shots()
will now raiseIndexError
when indices are out of bounds. They used to raiseValueError
in the case. -
BitArray.__getitem__()
will now raiseIndexError
when indices are out of bounds or the number of dimensions of indices does not match that ofBitArray
. They used to raiseValueError
in the case.
Synthesis Upgrade Notes
LieTrotter
andSuzukiTrotter
no longer wrap the individually evolved Pauli terms into gate definitions. If you rely on a certain decomposition level of your circuit, you have to remove one level ofQuantumCircuit.decompose()
or add thewrap=True
keyword argument to your synthesis object.
Transpiler Upgrade Notes
-
Optimization levels 2 and 3 now additionally employ peephole optimization is now employed before the translation/synthesis stage (previously this was only done in the optimization stage). The effects of peephole optimization include the removal of gates that are very close to the identity, for example, controlled-phase gates with a rotational angle smaller than .
-
The default routing pass used by optimization level 0 for
generate_preset_pass_manager()
andtranspile()
has been changed fromStochasticSwap
toSabreSwap
. TheSabreSwap
pass performs exactly the same function but performs better in both runtime and output quality (in number of swap gates and depth) compared toStochasticSwap
. Foroptimization_level=0
this shouldn’t matter because it’s not expected to run routing for the typical use case of level 0.If you were relying on the previous default routing algorithm for any reason you can use the
routing_method
argument fortranspile()
andgenerate_preset_pass_manager()
to"stochastic"
to use theStochasticSwap
pass. -
The
generate_preset_pass_manager()
function has been upgraded to, when possible, internally convert transpiler constraints into aTarget
instance. If a backend input of typeBackendV1
is provided, it will be converted toBackendV2
to expose itsTarget
. This change does not require any user action.
Misc. Upgrade Notes
- The minimum version of rustworkx required to run this release has been increased from 0.14.0 to 0.15.0. This is required because Qiskit is now using new functionality added in the rustworkx 0.15.0 release which improves performance.
Circuits Deprecations
-
The following circuit methods were not intended for public use, but were accidentally left documented in the public API during the 1.0 release. They are now deprecated from Qiskit 1.2 and will be removed in Qiskit 2.0:
-
Treating
CircuitInstruction
as a tuple-like iterable is deprecated, and this legacy path way will be removed in Qiskit 2.0. You should use the attribute-access fieldsCircuitInstruction.operation
,CircuitInstruction.qubits
, andCircuitInstruction.clbits
instead. For example:from qiskit.circuit import QuantumCircuit qc = QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1]) # Deprecated. for op, qubits, clbits in qc.data: pass # New style. for instruction in qc.data: op = instruction.operation qubits = instruction.qubits clbits = instruction.clbits
Primitives Deprecations
-
Primitive V1 implementations and V1-exclusive non-versioned type aliases are now deprecated in favor of their V2 counterparts. The deprecation is extended to the following classes implementing V1 interfaces:
Estimator
, in favor of the V2 equivalent,StatevectorEstimator
Sampler
, in favor of the V2 equivalent,StatevectorSampler
BackendEstimator
, in favor of the V2 equivalent,BackendEstimatorV2
BackendSampler
, in favor of the V2 equivalent,BackendSamplerV2
As well as the following non-versioned type aliases:
BaseEstimator
, alias forBaseEstimatorV1
BaseSampler
, alias forBaseSamplerV1
This deprecation does not affect the explicitly-versioned
BaseEstimatorV1
andBaseSamplerV1
abstract interface definitions or related result and job classes.
Providers Deprecations
-
The
BackendV1
class is deprecated and it will be removed no earlier than the next major release, 2.0.0. See the migration guide for details on how to update toBackendV2
. -
The Qobj structure and related classes (see
qiskit.qobj
) are now deprecated. They were introduced as part of theBackendV1
workflow and are no longer necessary for interacting withBackendV2
backends.QuantumCircuit
serialiaztion should be done via QPY (seeqiskit.qpy
) or OpenQASM (seeqiskit.qasm2
andqiskit.qasm3
) instead.
Transpiler Deprecations
- The
assemble()
function is now deprecated and will be removed in the 2.0 release. The function was primarily used to create aQobj
, which is no longer necessary inBackendV2
-based workflows. It was also used for binding parameters, a functionality fully covered byQuantumCircuit.assign_parameters()
.
Visualization Deprecations
-
The
justify
argument ofcircuit_drawer()
orQuantumCircuit.draw()
, will no longer support invalid values (previously changing them to the default), and in a future release they will error. Valid justify values are"left"
,"right"
or"none"
. -
The
visualize_transition()
function has been deprecated and will be removed in the 2.0.0 release. This function had a number of limitations which limited its utility to only very specific use cases and did not fit in with the rest of the Qiskit visualization module.
Bug Fixes
-
Fixed a series of issues when controlling parameterized standard gates. The controlled version of some gates (e.g.
RXXGate
orRYGate
for more than 1 control) cannot be synthesized if they contain unbound parameters. Previously, calling.control()
in such a case failed, but now we create anAnnotatedOperation
as placeholder. This allows to insert the controlled gate into a circuit, bind the parameters at a later stage, and then synthesize the operation. Fixes #10311, #10697, and #12135. -
The
SGate
andSdgGate
now correctly return aCSGate
, resp.CSdgGate
, if they are controlled on a single control qubit. -
Fix the calculation of the standard deviation in
BackendEstimatorV2
, by taking into account co-variance of non-commuting Paulis. Fixed Qiskit/qiskit-ibm-runtime#1751. -
Fixed an issue where
circuit_drawer()
or theQuantumCircuit.draw()
method would not raise a warning when an invalid value was passed to thejustify
argument, before changing it to the default. Now, it will raise a warning if an invalid value is passed. Valid justify values are"left"
,"right"
or"none"
. Refer to #12089 for more details. -
Fixed
SparsePauliOp.apply_layout()
andPauli.apply_layout()
to raiseQiskitError
if duplicate indices or negative indices are provided as part of a layout. -
Fixed a bug in the
ConsolidateBlocks
transpiler pass, when the input circuit contains a custom opaque gate and neither thebasis_gates
ortarget
options are set the pass would raise aQiskitError
and fail. This has been corrected so that the in these situations the transpiler pass will not consolidate the block identified containing a custom gate instead of failing. -
Fixed a bug in
PadDynamicalDecoupling
, which previously did not correctly display the error message that a delay is not pulse-aligned, if the previous or following node was an input/output node. Now, the error message is correctly displayed. -
The keyword argument
order
of the functionBitArray.from_bool_array()
should be"little"
or"big"
. Added checks to raise error if an invalid value is entered. -
Improve the decomposition of the gate generated by
QuantumCircuit.mcx()
without using ancilla qubits, so that the number ofCXGate
s will grow quadratically in the number of qubits, as expected, and not exponentially. -
Fixed
SparsePauliOp.apply_layout()
to work correctly with zero-qubit operators. For example, if you previously created a 0 qubit and applied a layout like:op = SparsePauliOp("") op.apply_layout(None, 3)
this would have previously raised an error. Now this will correctly return an operator of the form:
SparsePauliOp(['III'], coeffs=[1.+0.j])
-
Fixed a bug of
StatevectorSampler
that ignored gates withc_if
. It will raise an error becauseStatevector
cannot handlec_if
. -
Fixed an oversight in the
Commuting2qGateRouter
transpiler pass where the quantum register permutations were not added to the pass property set, so they would have to be tracked manually by the user. Now it is possible to access the permutation through the output circuit’slayout
property and plug the pass into any transpilation pipeline without loss of information. -
Fixed a floating-point imprecision when scaling certain pulse units between seconds and nanoseconds. If the pulse was symbolically defined, an unnecessary floating-point error could be introduced by the scaling for certain builds of
symengine
, which could manifest in unexpected results once the symbols were fully bound. Fixed #12392. -
Fixed a bug in
synth_cnot_count_full_pmh()
where providing asection_size
that did not divide the number of qubits without remainder could lead to wrong results. Now anysection_size
(at most equal to the number of qubits) synthesizes the correct circuit. For a (heuristically) optimal value, setsection_size=None
. -
PassManager.run()
will no longer waste time serializing itself when given multiple inputs if it is only going to work in serial. -
Fixed a bug in
plot_coupling_map()
that caused the edges of the coupling map to be colored incorrectly. Fixed #12354. -
The OpenQASM 2.0 parser (
qasm2.load()
andqasm2.loads()
) can now evaluate gate-angle expressions including integer operands that would overflow the system-size integer. These will be evaluated in a double-precision floating-point context, just like the rest of the expression always has been. Beware: an arbitrarily large integer will not necessarily be exactly representable in double-precision floating-point, so there is a chance that however the circuit was generated, it had already lost all numerical precision modulo . -
The OpenQASM 3 exporter (see
qiskit.qasm3
) will now correctly error when asked to use a keyword or other invalid identifier as a “basis gate”, as it has no way of generating correct output in these cases. -
The OpenQASM 3 exporter (
qiskit.qasm3
) will now correctly export multiple instances ofPauliEvolutionGate
from a circuit. Previously, only a single instance would be exported, and all other instances would silently use the same (incorrect) version. -
The OpenQASM 3 exporter (
qiskit.qasm3
) will now correctly escape gate names. Previously, a gate whose name was an invalid OpenQASM 3 identifier would cause invalid OpenQASM 3 to be generated. -
A series of input-handling inconsistencies between
transpile()
andgenerate_preset_pass_manager()
have been fixed. These inconsistencies would lead to different transpilation outputs for the same inputs, orgenerate_preset_pass_manager()
failing for certain input combinations accepted bytranspile()
.