Qiskit SDK 2.4 release notes
2.4.1
Prelude
Qiskit v2.4.1 fixes a small number of bugs identified since the release of Qiskit v2.4.0.
Bug Fixes
-
Fixed a panic in
RemoveIdentityEquivalentwhen the global phase of the circuit containedParameterVectorElementobjects. The message was:Cannot clone pointer into Python heap without the thread being attached.
See #16053.
-
Fixed
qpy.load()for QPY versions >=13, whereDelayinstructions with integer durations could deserialize to incorrect types. This could cause later code to raise errors, such asqasm3.dumps_experimental()returning an error saying “Failed to parse parameter value”. See #16076 for more detail.
2.4.0
Prelude
Qiskit 2.4.0 is a new feature release of the Qiskit SDK. The highlights of this release are:
- Support for building Python extension modules that use the Qiskit C API and can be safely distributed in Python wheels: This release makes it practical to move performance‑critical or low‑level components using Qiskit into compiled extensions that leverage Qiskit’s C API. These extensions can now be packaged and distributed as ordinary Python wheels using standard Python tooling.
- Initial porting of QPY serialization and deserialization internals to Rust: This greatly speeds up both generating and loading QPY payloads and is also a starting point towards adding QPY support to the C API.
- Expansion of the C API’s functionality: The C API now exposes DAG-based representations through an opaque
QkDagtype, along with DAG-level transpiler pass functions that operate directly on this representation. Additional features include support for parameterized circuits, instructions for Pauli-based computations, and a circuit text drawer.- Improvements to the Clifford+T transpilation pipeline: We have significantly improved the Clifford+T transpilation pipeline for targeting discrete Clifford+T basis gate sets, delivering higher compilation quality and substantially faster runtimes. In particular, Qiskit now uses the
gridsynthalgorithm as the default method for synthesizing RZ rotations in a discrete basis, replacing the Solovay-Kitaev decomposition used in prior releases.
C API Features
-
Added
QkTranspilerStageStateas a way of keeping a shared state between transpilation stages. -
Added a new function,
qk_circuit_draw(), to enable visualizing a quantum circuit as text through the C API. The function usesQkCircuitDrawerConfigto configure visualization options. Refer to the function documentation for more details. -
Added the C API function
qk_dag_replace_block_with_unitary(), which replaces a block of nodes in a DAG circuit with a new node representing a unitary gate. The function returns the index of the newly created node. -
Added the C API function
qk_dag_substitute_node_with_unitary(), which substitutes an operation in a node in a DAG circuit by a unitary gate. -
Added the C API function
qk_circuit_instruction_kind()for querying the kind of a specific instruction in a quantum circuit. This function returns aQkOperationKindenum value to identify the type of operation at a given index within the circuit. -
Added the C API function
qk_circuit_inst_unitary()to extract the unitary matrix associated with a specific unitary instruction in a quantum circuit. This function populates a provided output array with the unitary matrix, enabling C callers to access the unitary transformations defined within the circuit. -
The C API now provides
qk_api_version(), which returns the version of the library that has been loaded at runtime. The return format is the same asQISKIT_VERSION_HEX. -
The functions
qk_dag_borrow_from_python()andqk_dag_convert_from_python()allow for extracting C-native types from a Python-spaceDAGCircuit. C modules can create a Python-spaceDAGCircuitusingqk_dag_to_python(). -
The functions
qk_target_borrow_from_python()andqk_target_convert_from_python()allow for extracting C-native types from a Python-spaceTarget. -
Qiskit now supports building Python extension modules that use Qiskit C API from a version of Qiskit loaded by Python. These extension modules can then be safely distributed in wheels.
To compile an extension module, you must:
- define the
QISKIT_PYTHON_EXTENSIONmacro before#include <qiskit.h>. - call
qk_import()before attempting to use any Qiskit C API functions, once per compilation unit (typically a single.cfile). Typically this will be in your extension module’sPyInit_*function.
We intend to make it possible to have multiple compilation units using the Qiskit C API in an extension module in a later release of Qiskit.
Beware that Qiskit’s C API is still unstable; extension modules compiled against Qiskit 2.4 are not guaranteed to be able to run against Qiskit 2.5 or later. Qiskit will commit to this stability at a later date.
- define the
-
The fields
QkObsTerm.bit_termsandindicescan now be null pointers if their correspondinglenis zero. -
The arguments
coeffs,bit_termsandindicestoqk_obs_new()can now be null pointers if their corresponding lengths are zero. -
The C API now supports converting
QkCircuitto and from Python-space objects, using the methods:qk_circuit_borrow_from_python()qk_circuit_convert_from_python()qk_circuit_to_python_full()qk_circuit_to_python()
Note that
qk_circuit_to_python()is not new, but its behavior changed in Qiskit 2.4 to return the Python object that directly corresponds toQkCircuit(seeQuantumCircuit._data), instead ofQuantumCircuititself.qk_circuit_to_python_full()replaces the old method. -
QkObsnow supports two methods for borrowing a view of the observable from a Python-spaceSparseObservable. These are: -
QkQuantumRegisterandQkClassicalRegisternow have conversions to and from Python space. These use the functions: -
Added DAG-based variants of the standalone transpiler pass functions in the C API. These new functions operate directly on
QkDagobjects instead ofQkCircuit, avoiding the overhead of circuit-to-DAG and DAG-to-circuit conversions when chaining multiple passes together. The new functions follow the naming conventionqk_transpiler_pass_*and include:qk_transpiler_pass_elide_permutations()qk_transpiler_pass_check_gate_direction()qk_transpiler_pass_gate_direction()qk_transpiler_pass_optimize_1q_sequences()qk_transpiler_pass_remove_diagonal_gates_before_measure()qk_transpiler_pass_remove_identity_equivalent()qk_transpiler_pass_split_2q_unitaries()
These are useful when building custom transpilation pipelines in C where you want to apply multiple passes sequentially without repeated conversions between circuit and DAG representations.
-
Added a scaled operator addition to the
QkObsinterface,qk_obs_scaled_add()andqk_obs_scaled_add_inplace(). -
Added two new functions for in-place arithmetic operations on
QkObs, namelyqk_obs_add_inplace()andqk_obs_multiply_inplace(). -
A new Python-space module,
qiskit.capi, provides basic access to installation details about the Qiskit C API bundled with the Python package. -
The C API header files (
qiskit.hand its auxiliary files) are now bundled inside the Python-spaceqiskitpackage. You can find the location of the include directory to add to your compiler’s search path usingqiskit.capi.get_include(). -
Added C API bindings for the Instantaneous Quantum Polynomial-time (IQP) circuit generator in the circuit library. The new functions
qk_circuit_library_iqp()andqk_circuit_library_random_iqp()let C callers construct IQP circuits either from an explicit integer interaction matrix (with an optional symmetry check) or from a reproducible random instance. -
Added support for a Pauli-based computation gate set to the C API.
QkPauliProductRotationrepresents a generic Pauli-product rotation, andQkPauliProductMeasurementa generic Pauli-product measurement. These instructions can be added to aQkCircuitusing the new functionsqk_circuit_pauli_product_rotation()andqk_circuit_pauli_product_measurement(), respectively. To retrieve Pauli-product rotation data from a circuit, you can useqk_circuit_inst_pauli_product_rotation(), provided that the instruction kind returned byqk_circuit_instruction_kind()isQkOperationKind_PauliProductRotation. Analogously, Pauli-product measurements can be retrieved viaqk_circuit_inst_pauli_product_measurement()if the kind isQkOperationKind_PauliProductMeasurement. -
Added
qk_transpiler_pass_standalone_litinski_transformation()to apply a Litinski transformation to aQkCircuitin the C API. This is the equivalent of Python’sLitinskiTransformationpass. -
Added
qk_transpiler_pass_standalone_convert_to_pauli_rotations()to convert aQkCircuitmade up of standard gates and measurements into Pauli-based computation format usingQkPauliProductRotationandQkPauliProductMeasurementinstructions. This is the equivalent of Python’sConvertToPauliRotationspass. -
Added support to add parameterized gates to circuits using the new
qk_circuit_parameterized_gate()function, which specifies the gate parameters asQkParam *objects. For example:QkCircuit *qc = qk_circuit_new(100, 0); QkParam *theta = qk_param_new_symbol("theta"); uint32_t qubit[1] = {0}; const QkParam* params[1] = {theta}; qk_circuit_parameterized_gate(qc, QkGate_RX, qubit, params); // add RX(theta) to the circuit -
Added
qk_circuit_num_param_symbols()to query the number of unbound symbols present in the circuit. -
The
qk_transpiler_pass_standalone_remove_identity_equivalent()standalone transpiler pass function is now multithreaded by default. This improves the runtime performance of the pass when running the pass on large circuits. You can control the threading behavior using theRAYON_NUM_THREADSenvironment variable. You can refer to the function’s documentation on how to use this environment variable. -
Included to the C API the Suzuki-Trotter evolution by adding the circuit generator in the circuit library. The new function
qk_circuit_library_suzuki_trotter()can be used as follows:#include <qiskit.h> // Create the observable QkObs *obs = qk_obs_zero(1); // Add the pauli terms QkBitTerm op1_bits[1] = {QkBitTerm_X}; QkObsTerm term1 = {(QkComplex64){1.0, 0.0}, 1, op1_bits, (uint32_t[1]){0}, 1}; qk_obs_add_term(obs, &term1); QkBitTerm op2_bits[1] = {QkBitTerm_Y}; QkObsTerm term2 = {(QkComplex64){1.0, 0.0}, 1, op2_bits, (uint32_t[1]){0}, 1}; qk_obs_add_term(obs, &term2); // Call the evolution QkCircuit *qc = qk_circuit_library_suzuki_trotter(obs, 2, 1, 0.1, true, false); // Free the objects qk_obs_free(obs); qk_circuit_free(qc); -
The
qk_transpile()function now will run theVF2PostLayouttranspiler pass as part of optimization levels 1, 2, and 3. The pass is configured to run in the same way as the Python preset pass managers run ingenerate_preset_pass_manager(). You can refer to the Pythontranspilerdocumentation for more details on the configuration.
Circuits Features
-
Added a
PauliProductMeasurement.pauli()method to return the underlyingPaulimeasured by the instruction, including its global phase of+1or-1. -
The formally private attribute
QuantumCircuit._datais now public API, but only as a handle for passing to C-API functions expectingQkCircuit. The type of the object is not specified in the public API, nor are any methods on it. -
QuantumCircuit.compose()can be up to approximately two times faster when composing very long circuits onto another. -
Added support for
SparseObservabletoevolved_operator_ansatz(). -
A new
PauliProductRotationGatehas been added, which represents generic Pauli product rotations of the form for a Pauli product and a rotation angle . Together with thePauliProductMeasurement, these gates form a basis for Pauli-based computation. -
The
RCCXGateis self-inverse. TheRCCXGate.inverse()now returns a newRCCXGateinstance instead of an instance ofGatewith a custom definition. -
Introduced a new unary negation operation
negate(), allowing users to negate float and duration expressions. In case a scalar is passed, it is automatically lifted to the correct type.Example usage:
from qiskit.circuit import ClassicalRegister from qiskit.circuit.classical import expr, types qc = QuantumCircuit(2, 2) in_var1 = qc.add_input("in1", types.Float()) with qc.if_test(expr.greater(in_var1, 0.2)) as else_: qc.rz(0.3, 0) with else_: with qc.if_test(expr.greater(expr.negate(in_var1), 0.2)): qc.rz(-0.3, 0)
Providers Features
-
The
BasicSimulatornow automatically detects and optimizes simulation of Clifford circuits by using the stabilizer formalism viaStabilizerState. This provides significant performance improvements for circuits containing only Clifford gates (H, S, CX, CZ, X, Y, Z, etc.), with polynomial scaling instead of exponential scaling in the number of qubits. Non-Clifford circuits continue to use the existing statevector simulation method. This optimization is transparent to users and requires no code changes.For example:
from qiskit import QuantumCircuit from qiskit.providers.basic_provider import BasicSimulator # Clifford circuit (Bell state) qc = QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1]) # Automatically uses optimized StabilizerState simulation backend = BasicSimulator() result = backend.run(qc, shots=1000).result() counts = result.get_counts()
Quantum Information Features
-
Added the
PauliLindbladMap.generators()method, which provides a more convenient accessor for the map’s generator terms. This is an alias for the existingPauliLindbladMap.get_qubit_sparse_pauli_list_copy()method and aligns with the naming conventions used in Aer and Runtime for similar classes. -
Added the
SparseObservable.evolve()method, which conjugates aSparseObservableby aPauli. Internally this uses a static lookup table to avoid any matrix calculations.As an example:
from qiskit.quantum_info import SparseObservable, Pauli obs = SparseObservable("Y") pauli = Pauli("X") evolved = obs.evolve(pauli)
Transpiler Features
-
Added a new
filter_fnargument to the analysis passesCollect1qRunsandCollect2qBlocks. This optional callable allows to filter collected circuits based on custom criteria, for example to return only single-qubits runs with at least one Hadamard gate, or only 2-qubit blocks with at least 3 CX-gates. -
Added a new transpiler pass,
SynthesizeRZRotations, which replaces all single-qubitRZGaterotation gates with floating-point angles by equivalent Clifford+T sequences.The synthesis accuracy can be controlled by either specifying an
approximation_degree, or alternatively by explicitly setting bothsynthesis_errorandcache_error.Example usage:
from qiskit import QuantumCircuit from qiskit.transpiler.passes import SynthesizeRZRotations qc = QuantumCircuit(1) qc.rz(1.23, 0) rz_synthesis_pass = SynthesizeRZRotations(approximation_degree=0.9999) synthesized_qc = rz_synthesis_pass(qc) synthesized_qc.draw("mpl")
-
The
StandardEquivalenceLibrarynow includes anRXXGate/RYYGate-based equivalence forXXMinusYYGate, matching the one that already existed forXXPlusYYGate. -
Extended the transpiler pass
SubstitutePi4Rotations, to handle more standard gates: -
Added the function
clifford_t_pass_manager()that creates a pass manager for transpiling into Clifford+T basis sets. This function is automatically invoked bygenerate_preset_pass_manager()when the target basis consists of Clifford+T gates.The generated transpilation pipeline consisting of the following stages:
- Initialization: Decomposes larger gates into 1-qubit and 2-qubits gates and performs logical optimizations.
- Layout: Applies the default layout strategy used for continuous basis sets.
- Routing: Applies the default routing strategy used for continuous basis sets.
- RZ translation: Translates the circuit into Clifford+RZ basis.
- RZ optimization: Optimizes the circuit within Clifford+RZ basis.
- T translation: Translates the circuit into Clifford+T basis.
- T optimization: Optimizes the circuit within Clifford+T basis.
- Scheduling: Applies the default scheduling strategy used for continuous basis sets.
These stages are still experimental and subject to change. In particular, they are not yet exposed as transpiler stage plugins (unlike the stages for continuous basis sets).
For best results, consider including both and into the specified Clifford+T basis and as many Clifford gates as possible. For example:
basis_gates = get_clifford_gate_names() + ["t", "tdg"] -
The standard equivalence library has been expanded and refined:
-
The
OptimizeCliffordTtranspiler optimization pass now accepts abasis_gatesargument, preferring decompositions that use Clifford gates from the target basis. -
Added a new argument called
insert_barrierto theLitinskiTransformationpass. Iffix_clifford=Trueandinsert_barrier=True, a barrier is added in between the Pauli-based computation part of the circuit and the final cliffords. -
Added an argument
use_pprto theLitinskiTransformationpass, which, ifTrue, uses the Rust-nativePauliProductRotationGateto represent Pauli product rotations. This improves performance and ergonomics, since thePauliProductRotationGatedirectly represents single Pauli products instead of generic sums of Paulis. Ifuse_ppr=False(the default), the pass keeps usingPauliEvolutionGateobjects to represent the rotations. -
Added a new transpiler pass
ConvertToPauliRotations, that converts a quantum circuit containing single-qubit, two-qubit and three-qubit standard gates, barriers and measurements, into an equivalent circuit containingPauliProductRotationGategates andPauliProductMeasurementinstructions. -
The
RemoveIdentityEquivalenttranspiler pass is now multithreaded by default. This improves the runtime performance of the pass when running the pass on large circuits. You can control the threading behavior using theRAYON_NUM_THREADSenvironment variable. You can refer to the function’s documentation on how to use this environment variable. -
Added a new argument
min_distanceto theSabrePreLayoutpass, that specifies the distance for the first VF2 run with the augmented coupling map. Settingmin_distance > 1skips all smaller-distance checks, and in particular skips the distance-1 check which corresponds to running theVF2Layoutpass. -
The
call_limit_vf2argument of theSabrePreLayoutpass can now be a 2-tuple, similarly to thecall_limitargument ofVF2Layout. When a 2-tuple, the first item is used before the first match is found, then the limit swaps to the second after. -
The
OptimizeCliffordTtranspiler optimization pass now also replaces chains of consecutive Clifford+T gates when the T-count stays the same but the Clifford count is reduced. -
The fast-path main loop of
UnitarySynthesisnow aggressively caches its helper two-qubit decomposer objects internally, which makes the whole pass approximately 2x faster in its standard calling position in the preset pass managers.
Visualization Features
-
The
CouplingMap.draw()function now supports passing layout methods to be used inrustworkx.visualization.graphviz_draw()which is called internally. This enables you to adjust the graphviz graph layout algorithm used for visualizing theCouplingMapobject. -
Added a new
barrier_label_lenparameter (default 16) toQuantumCircuit.draw()andcircuit_drawer(). When aBarrierlabel exceeds this length, it is truncated and"..."is appended. This prevents very long barrier labels from making circuit diagrams unreadable. The parameter is supported by all three drawer backends (text, mpl, latex).
C API Upgrade Notes
-
qk_circuit_to_python()no longer returns a completeQuantumCircuit, but only the type ofQuantumCircuit._data. The new methodqk_circuit_to_python_full()provides the old functionality. -
qk_obs_to_python()now both requires and takes ownership of the given observable. You now must not free the observable after calling this function. This is consistent with all other*_to_pythonfunctions in the C API, and avoids the overhead of cloning the data. -
QkInstruction.paramswas changed from a pointer todoubleto a pointer toconst QkParam *objects. This change happened because gate parameters in the C API are no longer restricted to fixed numeric values, but may also be parameterized expressions with unbound symbols, which are represented by aQkParam *. -
The
QISKIT_VERSION_NUMERICsymbol was removed from the header file, after being marked deprecated in Qiskit 2.2. UseQISKIT_VERSION_HEXinstead, which correctly includes information about the pre-release status. -
Modified
QkTargetOpto useQkParamas the type for itsQkTargetOp.paramsattribute. Allowing users to access any free or fixed parameter in an operation. -
The
qk_transpile_stage_optimization()function has a new required argument,layoutwhich takes a mutable pointer to aQkTranspileLayoutobject which represents the layout of the transpile pipeline up until that point. Typically this will be the object as returned fromqk_transpile_stage_layout()andqk_transpile_stage_routing(). This is necessary because at optimization level 3 the optimization stage will run theVF2PostLayoutpass which can change the layout and that needs to be tracked when running the stage.
OpenQASM Upgrade Notes
- Previous OpenQASM 3 code generated by
qiskit.qasm3did not include the type in the iterator variable. The exporter now includes an explicit type, following the OpenQASM 3.0 specification.
Synthesis Upgrade Notes
- The serialization format used by
SolovayKitaevDecomposition.save_basic_approximations()andSolovayKitaevDecomposition.load_basic_approximations()has been upgraded. Files saved with Qiskit 2.3 or earlier will not be compatible with Qiskit 2.4 or later.
Transpiler Upgrade Notes
- The internal random number generator usage for the
CSPLayoutpass has been changed. This means that for a fixed seed the pass will potentially return different results from previous releases. Seeded results are not guaranteed to be stable between releases for thetranspilerbut if you were relying on the exact results from this pass you can run the pass in an early release and useqpyto save the output and load it with the latest release.
Miscellaneous Upgrade Notes
-
Qiskit now builds on the manylinux_2_28 image, which effectively increases the required version of
glibcon Linux hosts to 2.28, up from 2.17. This should be supported on Debian 10+ (buster), Ubuntu 18.10+ (cosmic), Fedora 29+ and RHEL 8+.NumPy on Python 3.14 already requires glibc 2.28, so in practice, Qiskit was already not usable on platforms limited to the manylinux2014 dependencies with later Python versions. The glibc version was updated for all Python versions for consistency in the build.
It may continue to be possible to build Qiskit from source using older versions of
glibc, though this will no longer be tested in CI.
C API Deprecations
- Deprecate the
qk_transpiler_standalone_optimize_1q_sequences()in favor of usingqk_transpiler_pass_standalone_optimize_1q_sequences()as it sticks closer to the naming convention of the C standalone transpiler passes.
Build System Changes
-
The C API headers are now built into the distribution location by an in-repo binary
qiskit-bindgen-c, rather than in the build script ofqiskit-cext. Themakerecipemake cheader(and the completemake c) still produce the complete distribution artifact indist/c. -
The build system now reads the environment variable
QISKIT_BUILD_PROFILEto choose whether to build inreleaseordebugmodes. If this is not set,pip install .will (continue to) default to release mode, andpip install -e .to debug mode. -
The minimum version of CMake required to build and run the C-API test suite has been lowered to 3.20 from 3.27. Qiskit does not commit to any particular policy around the version of CMake required, but will make a best-effort attempt to match the repositories of common and still-supported Linux distributions.
-
Qiskit now manages its additional development dependencies using separate PEP 735 dependency-groups entries for different tasks, replacing the old monolithic requirements-dev.txt and requirements-optional.txt files.
-
Packages depending on the Qiskit C API to build can now specify Qiskit as a Python-space build dependency, then use
qiskit.capi.get_include()to find the header files.
Known Issues
-
Qiskit v2.2 and v2.3 can generate unreadable QPY files for circuits containing a
ParameterExpressionwhere all the containedParameterinstances were cancelled out of the final expression. For example, if the expression0*x + 1.5appears in a circuit, Qiskit v2.2 and v2.3 will both produce a QPY file that cannot be read by any version of Qiskit, including themselves and v2.4, due to errors in the QPY generation.This error will typically appear (in Qiskit v2.4, at least) as a
QpyErrorwith a message such as “malformed expression: stack was empty before expression completed”.
Bug Fixes
-
QuantumCircuit.append()now correctly rejects duplicate classical bits in thecargsargument, matching the behavior ofqargs. While classical bits can in theory be copied, unlike quantum bits, the internal data model of Qiskit cannot represent multiple use of the same bit, and circuits using this would typically experience internal library panics or nonsensical downstream simulator behavior due to the data-model assumption violation. -
Fixed a mismatch in
QkTargetOpin which the length of the array stored inQkTargetOp.paramsdid not match the number exposed byQkTargetOp.num_params. Wildcard parameters are now represented byNAN, and the length of the array will always beQkTargetOp.num_params. This bug was only present in 2.3.0rc1. -
Fixed a runtime cost linear in the number of bits of the base circuit in
QuantumCircuit.compose(). This could cause performance problems when repeatedly composing small circuits with no clbits onto a base with a very large number of clbits. -
Countsobjects will now correctly error on construction if the keys are not all in the same format. -
Fixed a bug in
CommutationCheckerwhere certain Rust-backed gates, such asUnitaryGate, could bypass matrix size limits, leading to the construction of excessively large matrices. -
Fixed a bug in
evolved_operator_ansatz(), where setting theparameter_prefixargument to a single string could cause an error if identity terms were removed, depending on the order of operators. -
Fixed a bug where the loop variable of a
ForLoopOpwas incorrectly tracked in the outer circuit’s parameter table, causing it to appear inQuantumCircuit.parametersand makingassign_parameters()raise an internalRuntimeError. See #15657 for details. -
Fixed an unclear error message in
Initialize.inverse(), which now immediately raises a clear error indicating that the instruction is not invertible. See #15595. -
Fixed MCX synthesis methods to handle correctly the edge case where
num_ctrl_qubitsis . Fixed #15665. -
Fixed an issue in the
qk_transpile()andqk_transpile_stage_optimization()C API functions when usingoptimization_level=3inQkTranspileOptions. Previously, the internal minimum-point tracking logic failed to update the DAG after finding a better candidate circuit, which could result in circuits with suboptimal depth and size. -
ParameterExpressioninstances with cancelled-out variables (likex - x) will now retain the reference toxafter a round-trip through QPY and pickle. -
ParameterExpressioninstances that evaluated to a bare value (like0*x + 2) will now successfully round-trip through QPY and pickle. -
Fixed a bug around
PauliEvolutionGate, where the average gate fidelity was slightly larger than the actual fidelity. This had knock-on effects in passes such asRemoveIdentityEquivalent, which would remove gates at slightly larger angles than it should have. This has now been fixed and thePauliEvolutionGateis guaranteed to handle cutoffs the same way as other standard rotation gates. -
Fixed commutativity check between two
PauliProductMeasurementinstructions in the case that both instructions measure to the same classical bit. In this case, the later measurement overwrites the result of the earlier measurement, and consequently, interchanging the two measurement instructions inside the quantum circuit is generally invalid. -
Fixed
synth_qft_line()to correctly synthesize circuits with 32 or more qubits. -
Fixed a bug in the
ElidePermutationstranspiler pass that caused it to crash when handling single-qubit permutations. -
Fixed an issue with
QuantumCircuit.compose()when called withfront=Trueand an explicitqubitsmapping, which could incorrectly raise aValueErrorinstead of returning the correct circuit. See #15834. -
Fixed the
Gate.control()method to correctly handle the edge case wherenum_ctrl_qubitsis . Previously, this could raise an error or cause a core dump. Now it returns a copy of the original gate. Fixed #15666. -
Fixed the
QuantumCircuit.mcrx(),QuantumCircuit.mcry(),QuantumCircuit.mcrz(),QuantumCircuit.mcp(), andQuantumCircuit.mcx()methods when appending multi-controlled gates with no control qubits. Previously, this could lead to memory overflows. This case is now handled correctly. Fixed #15664. -
Fixed the definition of
MCPhaseGatefor the case of controls qubits. -
Fixed an issue in
BasisTranslatorwhere circuits containing nested control flow operations did not have the transformation applied to their control flow blocks. See #13162, #14025, and #15734. -
The OpenQASM 3 exporter (
qiskit.qasm3) now includes the type for the iterator in for loops. Fixes #13725. -
QuantumCircuit.remove_final_measurements()will no longer emit a spurious warning about trying to add registers when called on a circuit with a set layout.
Other Notes
- The
SabrePreLayoutpass is simplified to leverage improvements in theVF2Layoutpass. The expensive post-processing step to minimize “extra” edges in the layout has been removed, as this optimization is now handled more efficiently by internal scoring mechanism ofVF2Layout. Consequently, theimprove_layoutargument is now obsolete and has no effect.