diff --git a/docs/api/qiskit-ibm-provider/release-notes.md b/docs/api/qiskit-ibm-provider/release-notes.md index c8f4385eb75..0d6fef72cf2 100644 --- a/docs/api/qiskit-ibm-provider/release-notes.md +++ b/docs/api/qiskit-ibm-provider/release-notes.md @@ -4,7 +4,9 @@ description: Changes made to Qiskit IBM Provider in_page_toc_max_heading_level: 2 --- -# Release Notes + + +# Qiskit IBM Provider 0.7 release notes diff --git a/docs/api/qiskit-ibm-runtime/release-notes.md b/docs/api/qiskit-ibm-runtime/release-notes.md index 26c8213bc0a..9a616c5b1d6 100644 --- a/docs/api/qiskit-ibm-runtime/release-notes.md +++ b/docs/api/qiskit-ibm-runtime/release-notes.md @@ -4,7 +4,9 @@ description: Changes made to Qiskit Runtime IBM Client in_page_toc_max_heading_level: 2 --- -# Release Notes + + +# Qiskit Runtime IBM Client 0.14 release notes diff --git a/docs/api/qiskit/_toc.json b/docs/api/qiskit/_toc.json index 9756cf8b65b..929a1e39597 100644 --- a/docs/api/qiskit/_toc.json +++ b/docs/api/qiskit/_toc.json @@ -3392,6 +3392,10 @@ { "title": "Release notes", "children": [ + { + "title": "0.45", + "url": "/api/qiskit/release-notes/0.45" + }, { "title": "0.44", "url": "/api/qiskit/release-notes/0.44" diff --git a/docs/api/qiskit/release-notes/0.45.md b/docs/api/qiskit/release-notes/0.45.md new file mode 100644 index 00000000000..02315ecab72 --- /dev/null +++ b/docs/api/qiskit/release-notes/0.45.md @@ -0,0 +1,1389 @@ +--- +title: Qiskit 0.45 release notes +description: Changes made to Qiskit +in_page_toc_max_heading_level: 2 +--- + + + + + +# Qiskit 0.45 release notes + +This page contains the release notes for Qiskit, starting from the point at which the legacy “elements” structure was completely removed. For release notes stretching back through the old “meta-package” structure of Qiskit, see [Legacy Release Notes](legacy_release_notes#legacy-release-notes). + + + + + +## 0.45.0 + + + +### Prelude + +Qiskit 0.45.0 is the last feature release before 1.0. It prepares the ground for the API changes we are planning for our first major version release, including many removals of previously deprecated functionality as well as a series of new deprecations. + + + If your project depends on Qiskit, it may rely on functionality that will no longer be supported in Qiskit 1.0. For this reason, we recommend that you proactively cap your supported version to `<1.0`. + + +Some feature highlights of Qiskit 0.45.0 are: + +* Starting in this release, all unparametrized gates in the Qiskit standard circuit library are now **singletons**. By default, these gates share a single instance in memory, so once a gate of a specific type, let’s say [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate"), is instantiated, any subsequent instances of [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") will be a reference to the first one. This results in a reduced memory usage and construction overhead when using multiple gates of the same type in a circuit. To realize this feature, new base classes have been introduced: [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction") and [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate"). See feature notes for more details. +* We have added a new **generic pass manager interface** that can be found in the new [`qiskit.passmanager`](passmanager#module-qiskit.passmanager "qiskit.passmanager") module. This is a generalization of the pass manager that was used to build the Qiskit transpiler, and it introduces a generic framework to enable users to create new pass managers that use different intermediate representations (IRs). The module includes a generic pass manager base class, flow controllers, and the necessary infrastructure to manage the execution of pass manager tasks. The new interface was used to rebuild the existing pass manager in the [`qiskit.transpiler`](transpiler#module-qiskit.transpiler "qiskit.transpiler") module, cleaning up technical debt in the code, and improving usability and performance. See feature and upgrade notes for more details. +* 0.45.0 allows users to better interact with the **layout permutations** performed by the transpiler. The data contained in the [`TranspileLayout`](qiskit.transpiler.TranspileLayout "qiskit.transpiler.TranspileLayout") class is now more accessible through a series of new methods and attributes. And a new [`SparsePauliOp.apply_layout()`](qiskit.quantum_info.SparsePauliOp#apply_layout "qiskit.quantum_info.SparsePauliOp.apply_layout") method allows to apply a specific layout permutation to a [`SparsePauliOp`](qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp") observable that was built for an input circuit to the transpiler. See feature notes for more details. +* Finally, we have introduced **annotated operations** with the new [`AnnotatedOperation`](qiskit.circuit.AnnotatedOperation "qiskit.circuit.AnnotatedOperation") class, which allows to formulate complex circuit instructions as a base instruction with a set of modifiers. For example, instead of a specific operation type that implements the controlled inverse of a [`RXGate`](qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate"), we can now use an annotated [`RXGate`](qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") with inverse and control attributes. See feature notes for more details. + + + +### Bug Fixes + +* The use of the (deprecated) `Optimizer` class on [`AQC`](qiskit.transpiler.synthesis.aqc.AQC "qiskit.transpiler.synthesis.aqc.AQC") did not have a non-deprecated alternative path, which should have been introduced in Qiskit 0.44. It now accepts a callable that implements the [`Minimizer`](qiskit.algorithms.optimizers.Minimizer "qiskit.algorithms.optimizers.Minimizer") protocol, as explicitly stated in the deprecation warning. The callable can look like the following example: + + > ```python + > from scipy.optimize import minimize + > from qiskit.transpiler.synthesis.aqc.aqc import AQC + > + > optimizer = partial(minimize, args=(), method="L-BFGS-B", options={"maxiter": 200}) + > aqc = AQC(optimizer=optimizer) + > ``` + +* Fixed an issue with the [`Barrier`](qiskit.circuit.library.Barrier "qiskit.circuit.library.Barrier") class. When adding a [`Barrier`](qiskit.circuit.library.Barrier "qiskit.circuit.library.Barrier") instance to a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") with the [`QuantumCircuit.append()`](qiskit.circuit.QuantumCircuit#append "qiskit.circuit.QuantumCircuit.append") method previously there was no validation that the size of the barrier matched the qargs specified. + +* The `BlockCollapser` transpiler pass will now correctly handle circuits that contain more than one condition on the same classical register. + +* `BlueprintCircuit` subclasses will now behave correctly when the semi-public method `QuantumCircuit._append()` is used with the blueprint in an unbuilt state, *i.e.* the circuit will be built before attempting the append. + +* Adjusted zoom, fontsize, and margins in [`plot_state_city()`](qiskit.visualization.plot_state_city "qiskit.visualization.plot_state_city") to fit the plot better for more figure sizes. Corrected the Z-ordering behavior of bars and the zero-amplitude plane, and corrected display of negative real value bars. + + + +### Other Notes + +* Modified the behavior of the [`VF2Layout`](qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") and [`VF2PostLayout`](qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") transpiler passes, which would previously run their internal scoring using multithreading if the input circuits were sufficiently large. The multithreading usage has now been removed from the passes, as it was shown to cause a performance regression instead of an improvement like originally intended. + + + + + +## 0.45.0rc1 + + + +### Circuits Features + +* Added a new class [`AnnotatedOperation`](qiskit.circuit.AnnotatedOperation "qiskit.circuit.AnnotatedOperation") that is a subclass of [`Operation`](qiskit.circuit.Operation "qiskit.circuit.Operation") and represents some “base operation” modified by a list of “modifiers”. The base operation is of type [`Operation`](qiskit.circuit.Operation "qiskit.circuit.Operation") and the currently supported modifiers are of types [`InverseModifier`](qiskit.circuit.InverseModifier "qiskit.circuit.InverseModifier"), [`ControlModifier`](qiskit.circuit.ControlModifier "qiskit.circuit.ControlModifier") and [`PowerModifier`](qiskit.circuit.PowerModifier "qiskit.circuit.PowerModifier"). The modifiers are applied in the order they appear in the list. + + As an example: + + ```python + gate = AnnotatedOperation( + base_op=SGate(), + modifiers=[ + InverseModifier(), + ControlModifier(1), + InverseModifier(), + PowerModifier(2), + ], + ) + ``` + + is logically equivalent to `gate = SGate().inverse().control(1).inverse().power(2)`, or to: + + ```python + gate = AnnotatedOperation( + AnnotatedOperation(SGate(), [InverseModifier(), ControlModifier(1)]), + [InverseModifier(), PowerModifier(2)], + ) + ``` + + However, this equivalence is only logical, the internal representations are very different. + + For convenience, a single modifier can be also passed directly, thus `AnnotatedGate(SGate(), [ControlModifier(1)])` is equivalent to `AnnotatedGate(SGate(), ControlModifier(1))`. + + A distinguishing feature of an annotated operation is that circuit definition is not constructed when the operation is declared, and instead happens only during transpilation, specifically during the [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") transpiler pass. + + An annotated operation can be also viewed as a “higher-level” or a “more abstract” object that can be added onto a quantum circuit. This enables writing transpiler optimization passes that make use of this higher-level representation, for instance removing a gate that is immediately followed by its inverse (note that this reduction might not be possible if both the gate and its inverse are first synthesized into simpler gates). + + In a sense, an annotated operation can be viewed as an extension of [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate"), which also allows adding control to the base operation. In the future we are planning to replace [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate") by [`AnnotatedOperation`](qiskit.circuit.AnnotatedOperation "qiskit.circuit.AnnotatedOperation"). Similar to controlled gates, the transpiler synthesizes annotated operations before layout/routing takes place. + + As of now, the annotated operations can appear only in the top-level of a quantum circuit, that is they cannot appear inside of the recursively-defined `definition` circuit. We are planning to remove this limitation later. + +* Added a new option `max_num_qubits` to [`qiskit.circuit.CommutationChecker.commute()`](qiskit.circuit.CommutationChecker#commute "qiskit.circuit.CommutationChecker.commute") that specifies the maximum number of qubits to consider for the more expensive matrix multiplication-based commutativity check. This avoids trying to internally allocate arrays of size $2^N \times 2^N$. Simpler versions of commutativity check (for instance, two quantum operations commute when they are over disjoint sets of qubits) continue to work without this limit. + +* Added a new argument, `check_input`, to the constructor for the [`UnitaryGate`](qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate") class. This flag is used to disable the default initialization checks that input object represents a unitary matrix. This can be used to speed up the creation of [`UnitaryGate`](qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate") objects if you know the input is already a unitary matrix. This new option should only be used in these cases because if it’s set to `False` and the input is not unitary this will result in an invalid `UnitaryGate` object. + +* A new method [`Parameter.assign()`](qiskit.circuit.Parameter#assign "qiskit.circuit.Parameter.assign") has been added. This method primarily serves as a fast path to improve the performance of [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") for the common case of circuits that predominantly contain “expressions” that are actually just single parameters to be assigned later. + +* The performance of [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") when assigning a single parameter of a circuit that involves many parameters has been improved. + +* Introduced two new classes, [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction") and [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate"), which are subclasses of [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") and [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") respectively, that use a single instance for all objects of that type. The intent behind this class is to minimize the memory and construction overhead of using multiple gates in a circuit with the tradeoff of having global shared state. For this reason this class is only applicable to gates that do not have any unique and/or mutable state stored in an instance. For example, the best example of this is [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") doesn’t contain any state and could leverage [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") (and does starting in this release), while [`RXGate`](qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") stores an angle parameter in an instance and thus can not use [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") because a single shared global instance can not represent the parameter values. + + The other potential issue to be aware of when using singleton classes is that the [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") data model supports some mutable state. Specifically, the [`label`](qiskit.circuit.Instruction#label "qiskit.circuit.Instruction.label"), [`duration`](qiskit.circuit.Instruction#duration "qiskit.circuit.Instruction.duration"), [`unit`](qiskit.circuit.Instruction#unit "qiskit.circuit.Instruction.unit"), and [`condition`](qiskit.circuit.Instruction#condition "qiskit.circuit.Instruction.condition") attributes are all accessible and mutable in the [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") and its direct subclasses. However, this is incompatible with having a shared object via [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction"). For instances of [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction"), setting these attributes directly is not allowed and it will raise an exception. If they are needed for a particular instance, you must ensure you have a mutable instance using [`Instruction.to_mutable()`](qiskit.circuit.Instruction#to_mutable "qiskit.circuit.Instruction.to_mutable") (or use [`Instruction.c_if()`](qiskit.circuit.Instruction#c_if "qiskit.circuit.Instruction.c_if") for [`condition`](qiskit.circuit.Instruction#condition "qiskit.circuit.Instruction.condition")). `label`, `duration` and `unit` can also be given as keyword arguments during class construction. + +* The following standard library gates are now instances of [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate"): + + > * [`DCXGate`](qiskit.circuit.library.DCXGate "qiskit.circuit.library.DCXGate") + > * [`ECRGate`](qiskit.circuit.library.ECRGate "qiskit.circuit.library.ECRGate") + > * [`HGate`](qiskit.circuit.library.HGate "qiskit.circuit.library.HGate") + > * [`IGate`](qiskit.circuit.library.IGate "qiskit.circuit.library.IGate") + > * [`iSwapGate`](qiskit.circuit.library.iSwapGate "qiskit.circuit.library.iSwapGate") + > * [`SGate`](qiskit.circuit.library.SGate "qiskit.circuit.library.SGate") + > * [`SdgGate`](qiskit.circuit.library.SdgGate "qiskit.circuit.library.SdgGate") + > * [`SwapGate`](qiskit.circuit.library.SwapGate "qiskit.circuit.library.SwapGate") + > * [`SXGate`](qiskit.circuit.library.SXGate "qiskit.circuit.library.SXGate") + > * [`SXdgGate`](qiskit.circuit.library.SXdgGate "qiskit.circuit.library.SXdgGate") + > * [`TGate`](qiskit.circuit.library.TGate "qiskit.circuit.library.TGate") + > * [`TdgGate`](qiskit.circuit.library.TdgGate "qiskit.circuit.library.TdgGate") + > * [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") + > * [`RCCXGate`](qiskit.circuit.library.RCCXGate "qiskit.circuit.library.RCCXGate") + > * [`RC3XGate`](qiskit.circuit.library.RC3XGate "qiskit.circuit.library.RC3XGate") + > * [`YGate`](qiskit.circuit.library.YGate "qiskit.circuit.library.YGate") + > * [`ZGate`](qiskit.circuit.library.ZGate "qiskit.circuit.library.ZGate") + + This means that if these classes are instantiated as (e.g.) [`XGate()`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") using all the constructor defaults, they will all share a single global instance. This results in a large reduction in the memory overhead for > 1 object of these types and significantly faster object construction time. + +* Introduced a new class [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate") which is a subclass of [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate") that uses a single instance for all objects of that type. The intent behind this class is to minimize the memory and construction overhead of using multiple gates in a circuit with the tradeoff of having a global shared state. For this reason, this class is only applicable to gates that do not have any unique and/or mutable state stored in an instance. For example, a [`CXGate`](qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate") doesn’t contain any state and thus can leverage [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate") (and does starting in this release). In contrast, [`CRXGate`](qiskit.circuit.library.CRXGate "qiskit.circuit.library.CRXGate") stores an angle parameter as part of its instance data and thus can not use [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate"). + + The other potential issue to be aware of when using [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate") is that the original data model of [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate") supports mutation. Specifically, the [`label`](qiskit.circuit.ControlledGate#label "qiskit.circuit.ControlledGate.label"), [`duration`](qiskit.circuit.ControlledGate#duration "qiskit.circuit.ControlledGate.duration"), [`unit`](qiskit.circuit.ControlledGate#unit "qiskit.circuit.ControlledGate.unit"), [`condition`](qiskit.circuit.ControlledGate#condition "qiskit.circuit.ControlledGate.condition"), and [`ctrl_state`](qiskit.circuit.ControlledGate#ctrl_state "qiskit.circuit.ControlledGate.ctrl_state") attributes are all accessible and mutable in the [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate"), but mutation of these attributes on [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate") subclasses is not allowed, and will raise an exception. These attributes can be customized but only at creation time (i.e. via the constructor). In that case, the newly constructed gate will be a separate instance with the custom state instead of the globally shared instance. You can also use the `SingletonControlledGate.to_mutable()` method to get a mutable copy of a gate object and then mutate the attributes like you would on any other [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") object. + +* The following standard library gates are now instances of [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate"): + + > * [`CHGate`](qiskit.circuit.library.CHGate "qiskit.circuit.library.CHGate") + > * [`CSGate`](qiskit.circuit.library.CSGate "qiskit.circuit.library.CSGate") + > * [`CSdgGate`](qiskit.circuit.library.CSdgGate "qiskit.circuit.library.CSdgGate") + > * [`CSwapGate`](qiskit.circuit.library.CSwapGate "qiskit.circuit.library.CSwapGate") + > * [`CSXGate`](qiskit.circuit.library.CSXGate "qiskit.circuit.library.CSXGate") + > * [`CXGate`](qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate") + > * [`CCXGate`](qiskit.circuit.library.CCXGate "qiskit.circuit.library.CCXGate") + > * [`C3SXGate`](qiskit.circuit.library.C3SXGate "qiskit.circuit.library.C3SXGate") + > * [`C3XGate`](qiskit.circuit.library.C3XGate "qiskit.circuit.library.C3XGate") + > * [`C4XGate`](qiskit.circuit.library.C4XGate "qiskit.circuit.library.C4XGate") + > * [`CYGate`](qiskit.circuit.library.CYGate "qiskit.circuit.library.CYGate") + > * [`CZGate`](qiskit.circuit.library.CZGate "qiskit.circuit.library.CZGate") + + This means that unless a `label`, `condition`, `duration`, `unit`, or `ctrl_state` are set on the instance at creation time they will all share a single global instance whenever a new gate object is created. This results in a large reduction in the memory overhead for > 1 object of these types. + +* Added a new method [`Instruction.to_mutable()`](qiskit.circuit.Instruction#to_mutable "qiskit.circuit.Instruction.to_mutable") and attribute [`Instruction.mutable`](qiskit.circuit.Instruction#mutable "qiskit.circuit.Instruction.mutable") which is used to get a mutable copy and check whether an [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") object is mutable. With the introduction of [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") these methods can be used to have a unified interface to deal with the mutablitiy of instruction objects. + +* Added an attribute [`Instruction.base_class`](qiskit.circuit.Instruction#base_class "qiskit.circuit.Instruction.base_class"), which gets the “base” type of an instruction. Many instructions will satisfy `type(obj) == obj.base_class`, however the singleton instances of [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction") and [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") are subclasses of their base type. You can use the new [`base_class`](qiskit.circuit.Instruction#base_class "qiskit.circuit.Instruction.base_class") attribute to find the base class of these. See the attribute documentation for considerations on when other subclasses may modify their [`base_class`](qiskit.circuit.Instruction#base_class "qiskit.circuit.Instruction.base_class"), and what this means for execution. + +* Added the [`UnitaryOverlap`](qiskit.circuit.library.UnitaryOverlap "qiskit.circuit.library.UnitaryOverlap") circuit to the Qiskit circuit library. It can be used to compute the fidelity of states generated by unitaries by looking at the probability of the output distribution in the all-zeros state or, equivalently, by computing the expectation value of the projector onto the all-zeros state. This is useful in applications such as machine learning, and computing excited states in quantum chemistry, to name a few. + + + +### Pulse Features + +* Enabled circuit-to-pulse scheduling using [`BackendV2`](qiskit.providers.BackendV2 "qiskit.providers.BackendV2"). + + ```python + # import a fake backend which is a sub-class of BackendV2 + from qiskit.providers.fake_provider import FakePerth + from qiskit.compiler.scheduler import schedule + from qiskit.circuit import QuantumCircuit + + qc = QuantumCircuit(1, 1) + qc.x(0) + qc.measure(0,0) + sched = schedule(circuits=qc, backend=FakePerth()) + ``` + + Since [`BackendV2`](qiskit.providers.BackendV2 "qiskit.providers.BackendV2") was not supported by the [`schedule()`](compiler#qiskit.compiler.schedule "qiskit.compiler.schedule") function, this caused the `schedule()` method to error out when the `backend` argument was supplied with an instance of [`BackendV2`](qiskit.providers.BackendV2 "qiskit.providers.BackendV2"). Refer to [#10837](https://github.com/Qiskit/qiskit/issues/10837) for more information. + + + +### OpenQASM Features + +* The OpenQASM 2 module [`qiskit.qasm2`](qasm2#module-qiskit.qasm2 "qiskit.qasm2") has gained the export functions [`dump()`](qasm2#qiskit.qasm2.dump "qiskit.qasm2.dump") and [`dumps()`](qasm2#qiskit.qasm2.dumps "qiskit.qasm2.dumps"). These are used in a very similar manner to the previous [`QuantumCircuit.qasm()`](qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm"): + + ```python + from qiskit import qasm2, QuantumCircuit + qc = QuantumCircuit(2, 2) + qc.h(0) + qc.cx(0, 1) + qc.measure([0, 1], [0, 1]) + print(qasm2.dumps(qc)) + ``` + + The new functions stem from the same code as [`QuantumCircuit.qasm()`](qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm"), which will slowly be phased out and replaced with the new paths, to provide a more coherent interface when compared to the OpenQASM 3 ([`qiskit.qasm3`](qasm3#module-qiskit.qasm3 "qiskit.qasm3")) and QPY ([`qiskit.qpy`](qpy#module-qiskit.qpy "qiskit.qpy")) modules. This is particularly important since the method name [`qasm()`](qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm") gave no indication of the OpenQASM version, and since it was originally added, Qiskit has gained several serialisation modules that could easily become confused. + + + +### QPY Features + +* QPY now supports the use of symengine-native serialization and deserialization for objects of type `ParameterExpression` as well as symbolic expressions in Pulse schedule blocks. This is a faster serialization alternative, but not supported in all platforms. Please check that your target platform is supported by the symengine library before setting this option, as it will be **required** by qpy to deserialize the payload. + + The feature can be enabled through the `use_symengine` parameter in `qpy.dump()`: + + ```python + from qiskit.circuit import QuantumCircuit, Parameter + from qiskit import qpy + + theta = Parameter("theta") + phi = Parameter("phi") + sum_param = theta + phi + + qc = QuantumCircuit(1) + qc.rz(sum_param, 0) + qc.measure_all() + + with open('bell.qpy', 'wb') as fd: + qpy.dump(qc, fd, use_symengine=True) + + with open('bell.qpy', 'rb') as fd: + new_qc = qpy.load(fd)[0] + ``` + + + +### Quantum Information Features + +* Added [`Clifford.from_linear_function()`](qiskit.quantum_info.Clifford#from_linear_function "qiskit.quantum_info.Clifford.from_linear_function") and [`Clifford.from_permutation()`](qiskit.quantum_info.Clifford#from_permutation "qiskit.quantum_info.Clifford.from_permutation") methods that create a [`Clifford`](qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") object from [`LinearFunction`](qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction") and from [`PermutationGate`](qiskit.circuit.library.PermutationGate "qiskit.circuit.library.PermutationGate") respectively. As a consequence, a [`Clifford`](qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") can now be constructed directly from a [`LinearFunction`](qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction"), a [`PermutationGate`](qiskit.circuit.library.PermutationGate "qiskit.circuit.library.PermutationGate"), or a quantum circuit containing such gates. + +* The [`Operator`](qiskit.quantum_info.Operator "qiskit.quantum_info.Operator") class now has a [`draw()`](qiskit.quantum_info.Operator#draw "qiskit.quantum_info.Operator.draw") method allowing it to be displayed as a text matrix, IPython LaTeX object or LaTeX source. The default draw type still is the ASCII `__repr__` of the operator. + +* Added a new method, [`apply_layout()`](qiskit.quantum_info.SparsePauliOp#apply_layout "qiskit.quantum_info.SparsePauliOp.apply_layout"), to the [`SparsePauliOp`](qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp") class. This method is used to apply a [`TranspileLayout`](qiskit.transpiler.TranspileLayout "qiskit.transpiler.TranspileLayout") layout from the transpiler to a [`SparsePauliOp`](qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp") observable that was built for an input circuit to the transpiler. This enables working with [`BaseEstimator`](qiskit.primitives.BaseEstimator "qiskit.primitives.BaseEstimator") implementations and local transpilation more easily. For example: + + ```python + from qiskit.circuit.library import RealAmplitudes + from qiskit.quantum_info import SparsePauliOp + from qiskit.primitives import BackendEstimator + from qiskit.compiler import transpile + from qiskit.providers.fake_provider import FakeNairobiV2 + + psi = RealAmplitudes(num_qubits=2, reps=2) + H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]) + backend = FakeNairobiV2() + estimator = BackendEstimator(backend=backend, skip_transpilation=True) + + thetas = [0, 1, 1, 2, 3, 5] + transpiled_psi = transpile(psi, backend, optimization_level=3) + permuted_op = H1.apply_layout(transpiled_psi.layout) + res = estimator.run(transpiled_psi, permuted_op, thetas) + ``` + + where an input circuit is transpiled locally before it’s passed to `run`. Transpilation expands the original circuit from 2 to 7 qubits (the size of `backend`) and permutes its layout, which is then applied to `H1` using [`apply_layout()`](qiskit.quantum_info.SparsePauliOp#apply_layout "qiskit.quantum_info.SparsePauliOp.apply_layout") to reflect the transformations performed by [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile"). + + + +### Transpiler Features + +* The [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") class is extended to synthesize circuits with objects of type [`AnnotatedOperation`](qiskit.circuit.AnnotatedOperation "qiskit.circuit.AnnotatedOperation"). + +* Added a new analysis [`SabrePreLayout`](qiskit.transpiler.passes.SabrePreLayout "qiskit.transpiler.passes.SabrePreLayout") pass that creates a starting layout for [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout"), writing the layout into the property set value `sabre_starting_layouts`. + + The pass works by augmenting the coupling map with more and more “extra” edges until [`VF2Layout`](qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") succeeds to find a perfect graph isomorphism. More precisely, the augmented coupling map contains edges between nodes that are within a given distance `d` in the original coupling map, and the value of `d` is increased until an isomorphism is found. The pass also optionally minimizes the number of extra edges involved in the layout until a local minimum is found. This involves removing extra edges and calling [`VF2Layout`](qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") to check if an isomorphism still exists. + + Here is an example of calling the [`SabrePreLayout`](qiskit.transpiler.passes.SabrePreLayout "qiskit.transpiler.passes.SabrePreLayout") before [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout"): + + ```python + import math + from qiskit.transpiler import CouplingMap, PassManager + from qiskit.circuit.library import EfficientSU2 + from qiskit.transpiler.passes import SabrePreLayout, SabreLayout + + qc = EfficientSU2(16, entanglement='circular', reps=6, flatten=True) + qc.assign_parameters([math.pi / 2] * len(qc.parameters), inplace=True) + qc.measure_all() + + coupling_map = CouplingMap.from_heavy_hex(7) + + pm = PassManager( + [ + SabrePreLayout(coupling_map=coupling_map), + SabreLayout(coupling_map), + ] + ) + + pm.run(qc) + ``` + +* Added the arguments `coupling_map`, `target` and `use_qubit_indices` to [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") transpiler pass. The argument `target` specifies the target backend, allowing the synthesis plugins called within the pass to access all target-specific information, such as the coupling map and the supported gate set. The argument `coupling_map` only specifies the coupling map, and is only used when `target` is not specified. The argument `use_qubit_indices` indicates whether the high-level-synthesis pass is running before or after the layout is set, that is, whether the qubit indices of higher-level-objects correspond to qubit indices on the target backend. + +* Added the arguments `coupling_map`, `target` and `qubits` to [`HighLevelSynthesisPlugin`](qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin "qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin"). The positional argument `target` specifies the target backend, allowing the plugin to access all target-specific information, such as the coupling map, the supported gate set, and so on. The positional argument `coupling_map` only specifies the coupling map, and is only used when `target` is not specified. The positional argument `qubits` specifies the list of qubits over which the higher-level-object is defined, in case the synthesis is done on the physical circuit. The value of `None` indicates that the layout has not yet been chosen. + + This enables a cleaner separation of synthesis plugins options into general interface options for plugins (that is, `coupling_map`, `target`, and `qubits`) and into plugin-specific options (a free form configuration dictionary specified via `options`). It is worthwhile to note that this change is backward-compatible, if the options `coupling_map`, etc. are not explicitly added to the plugin’s `run()` method, they will appear as part of `options`. + +* The [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") methods [`apply_operation_back()`](qiskit.dagcircuit.DAGCircuit#apply_operation_back "qiskit.dagcircuit.DAGCircuit.apply_operation_back") and [`apply_operation_front()`](qiskit.dagcircuit.DAGCircuit#apply_operation_front "qiskit.dagcircuit.DAGCircuit.apply_operation_front") have gained a `check` keyword argument that can be set `False` to skip validation that the inputs uphold the [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") data-structure invariants. This is useful as a performance optimisation when the DAG is being built from known-good data, such as during transpiler passes. + +* The method [`CouplingMap.reduce()`](qiskit.transpiler.CouplingMap#reduce "qiskit.transpiler.CouplingMap.reduce") now accepts an additional argument `check_if_connected`, defaulted to `True`. This corresponds to the previous behavior, checking whether the reduced coupling map remains connected and raising a `CouplingError` if not so. When set to `False`, the check is skipped, allowing disconnected reduced coupling maps. + +* The constructor for [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") transpiler pass now accepts additional arguments `equivalence_library`, `basis_gates`, and `min_qubits`. The pass can now unroll custom definitions similarly to [`UnrollCustomDefinitions`](qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions"), and as such completely subsumes the functionality of the latter pass. In particular, [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") is now recursive, fixing an oversight in the initial implementation. Thus, when either `target` or `basis_gates` are specified, [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") recursively synthesizes all high-level objects, annotated operations and custom gates in the circuit, leaving only gates that are supported by the target or belong to the equivalence library. This allows to use [`HighLevelSynthesis`](qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") as a drop-in replacement for [`UnrollCustomDefinitions`](qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions"). On the other hand, when neither `target` nor `basis_gates` are specified, the pass synthesizes only the “top-level” high-level objects and annotated operations, i.e. does not recursively descent into the custom gates `definition` field. This is backward-compatible both with [`UnrollCustomDefinitions`](qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions") (which would not do anything) and with the older behavior of the high level synthesis pass, which allows to use it as an intermediate transform, only synthesizing high-level objects as specified by `HLSConfig`. + +* Significantly improved the performance of the [`MergeAdjacentBarriers`](qiskit.transpiler.passes.MergeAdjacentBarriers "qiskit.transpiler.passes.MergeAdjacentBarriers") transpiler pass, which used to rebuild the complete DAG to merge the barriers. + +* Added a new keyword argument, `min_qubits`, to the constructor of the [`BasisTranslator`](qiskit.transpiler.passes.BasisTranslator "qiskit.transpiler.passes.BasisTranslator") transpiler pass. When set to a non-zero value this is used to set a minimum number of qubits to filter operations to translate in the circuit. For example, if `min_qubits=3` is set the [`BasisTranslator`](qiskit.transpiler.passes.BasisTranslator "qiskit.transpiler.passes.BasisTranslator") instance will only translate gates in the circuit that operate on 3 or more qubits. + +* Added a new keyword argument, `min_qubits`, to the constructor of the [`UnrollCustomDefinitions`](qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions") transpiler pass. When set to a non-zero value this is used to set a minimum number of qubits to filter operations to translate in the circuit. For example, if `min_qubits=3` is set the [`UnrollCustomDefinitions`](qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions") instance will only translate gates in the circuit that operate on 3 or more qubits. + +* Added support to the [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") pass to add trials with specified starting layouts. The [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") transpiler pass typically runs multiple layout trials that all start with fully random layouts which then use a routing pass to permute that layout instead of inserting swaps to find a layout which will result in fewer swap gates. This new feature enables running an [`AnalysisPass`](qiskit.transpiler.AnalysisPass "qiskit.transpiler.AnalysisPass") prior to [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") which sets the `"sabre_starting_layout"` field in the property set to provide the [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") with additional starting layouts to use in its internal trials. For example, if you wanted to run [`DenseLayout`](qiskit.transpiler.passes.DenseLayout "qiskit.transpiler.passes.DenseLayout") as the starting point for one trial in [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") you would do something like: + + ```python + from qiskit.providers.fake_provider import FakeSherbrooke + from qiskit.transpiler import AnalysisPass, PassManager + from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager + from qiskit.transpiler.passes import DenseLayout + + class SabreDenseLayoutTrial(AnalysisPass): + + def __init__(self, target): + self.dense_pass = DenseLayout(target=target) + super().__init__() + + def run(self, dag): + self.dense_pass.run(dag) + self.property_set["sabre_starting_layouts"] = [self.dense_pass.property_set["layout"]] + + backend = FakeSherbrooke() + opt_level_1 = generate_preset_pass_manager(1, backend) + pre_layout = PassManager([SabreDenseLayoutTrial(backend.target)]) + opt_level_1.pre_layout = pre_layout + ``` + + Then when the `opt_level_1` [`StagedPassManager`](qiskit.transpiler.StagedPassManager "qiskit.transpiler.StagedPassManager") is run with a circuit the output of the [`DenseLayout`](qiskit.transpiler.passes.DenseLayout "qiskit.transpiler.passes.DenseLayout") pass will be used for one of the [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") trials in addition to the 5 fully random trials that run by default in optimization level 1. + +* Two new transpiler passes are added to generate single-pulse RX gate calibrations on the fly. These single-pulse RX calibrations will reduce the gate time in half, as described in P.Gokhale et al, Optimized Quantum Compilation for Near-Term Algorithms with OpenPulse (2020), [arXiv:2004.11205](https://arxiv.org/abs/2004.11205). + + To reduce the amount of RX calibration data that needs to be generated, [`NormalizeRXAngle`](qiskit.transpiler.passes.NormalizeRXAngle "qiskit.transpiler.passes.optimization.normalize_rx_angle.NormalizeRXAngle") performs three optimizations: wrapping the [`RXGate`](qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") rotation angles to `[0, pi]`, replacing `RX(pi/2)` and `RX(pi)` with [`SXGate`](qiskit.circuit.library.SXGate "qiskit.circuit.library.SXGate") and [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate"), and quantizing the rotation angles. This pass is required to be run before [`RXCalibrationBuilder`](qiskit.transpiler.passes.RXCalibrationBuilder "qiskit.transpiler.passes.calibration.rx_builder.RXCalibrationBuilder"), which generates RX calibrations on the fly. + + The optimizations performed by [`NormalizeRXAngle`](qiskit.transpiler.passes.NormalizeRXAngle "qiskit.transpiler.passes.NormalizeRXAngle") reduce the amount of calibration data and enable us to take advantage of the more accurate, hardware-calibrated pulses. The calibrations generated by [`RXCalibrationBuilder`](qiskit.transpiler.passes.RXCalibrationBuilder "qiskit.transpiler.passes.RXCalibrationBuilder") are bootstrapped from the [`SXGate`](qiskit.circuit.library.SXGate "qiskit.circuit.library.SXGate") calibration, which should be already present in the target. The amplitude is linearly scaled to achieve the desired arbitrary rotation angle. + + Such single-pulse calibrations reduces the [`RXGate`](qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") time in half, compared to the conventional sequence that consists of two [`SXGate`](qiskit.circuit.library.SXGate "qiskit.circuit.library.SXGate") pulses. There could be an improvement in fidelity due to this reduction in gate time. + +* Added new methods to [`TranspileLayout`](qiskit.transpiler.TranspileLayout "qiskit.transpiler.TranspileLayout"), [`initial_index_layout()`](qiskit.transpiler.TranspileLayout#initial_index_layout "qiskit.transpiler.TranspileLayout.initial_index_layout") and [`routing_permutation()`](qiskit.transpiler.TranspileLayout#routing_permutation "qiskit.transpiler.TranspileLayout.routing_permutation"), which are used to generate a list view of the [`TranspileLayout.initial_layout`](qiskit.transpiler.TranspileLayout#initial_layout "qiskit.transpiler.TranspileLayout.initial_layout") and [`TranspileLayout.final_layout`](qiskit.transpiler.TranspileLayout#final_layout "qiskit.transpiler.TranspileLayout.final_layout") attributes respectively. For example, if the [`final_layout`](qiskit.transpiler.TranspileLayout#final_layout "qiskit.transpiler.TranspileLayout.final_layout") attribute was: + + ```python + Layout({ + qr[0]: 2, + qr[1]: 3, + qr[2]: 0, + qr[3]: 1, + }) + ``` + + then [`routing_permutation()`](qiskit.transpiler.TranspileLayout#routing_permutation "qiskit.transpiler.TranspileLayout.routing_permutation") will return: + + ```python + [2, 3, 0, 1] + ``` + +* Added a new method to [`TranspileLayout`](qiskit.transpiler.TranspileLayout "qiskit.transpiler.TranspileLayout"), [`initial_virtual_layout()`](qiskit.transpiler.TranspileLayout#initial_virtual_layout "qiskit.transpiler.TranspileLayout.initial_virtual_layout"), which is equivalent to the [`TranspileLayout.initial_layout`](qiskit.transpiler.TranspileLayout#initial_layout "qiskit.transpiler.TranspileLayout.initial_layout") attribute but gives the option to filter ancilla qubits that were added to the circuit. By default the [`TranspileLayout.initial_layout`](qiskit.transpiler.TranspileLayout#initial_layout "qiskit.transpiler.TranspileLayout.initial_layout") will typically include any ancillas added by the transpiler. + +* Added a new methods, [`final_index_layout()`](qiskit.transpiler.TranspileLayout#final_index_layout "qiskit.transpiler.TranspileLayout.final_index_layout") and [`final_virtual_layout()`](qiskit.transpiler.TranspileLayout#final_virtual_layout "qiskit.transpiler.TranspileLayout.final_virtual_layout") to the [`TranspileLayout`](qiskit.transpiler.TranspileLayout "qiskit.transpiler.TranspileLayout") class. These methods are used to return a final layout (the mapping of input circuit qubits to the final position in the output). This is distinct from the [`final_layout`](qiskit.transpiler.TranspileLayout#final_layout "qiskit.transpiler.TranspileLayout.final_layout") attribute which is the permutation caused by routing as a [`Layout`](qiskit.transpiler.Layout "qiskit.transpiler.Layout") object. The [`final_index_layout()`](qiskit.transpiler.TranspileLayout#final_index_layout "qiskit.transpiler.TranspileLayout.final_index_layout") method returns a list to show the output position for each qubit in the input circuit to the transpiler. For example, with an original circuit: + + ```python + qc = QuantumCircuit(3) + qc.h(0) + qc.cx(0, 1) + qc.cx(0, 2) + ``` + + and the output from the transpiler was: + + ```python + tqc = QuantumCircuit(3) + tqc.h(2) + tqc.cx(2, 1) + tqc.swap(0, 1) + tqc.cx(2, 1) + ``` + + then the output from [`final_index_layout()`](qiskit.transpiler.TranspileLayout#final_index_layout "qiskit.transpiler.TranspileLayout.final_index_layout") would return a list of: + + ```python + [2, 0, 1] + ``` + + The [`final_virtual_layout()`](qiskit.transpiler.TranspileLayout#final_virtual_layout "qiskit.transpiler.TranspileLayout.final_virtual_layout") returns this as a [`Layout`](qiskit.transpiler.Layout "qiskit.transpiler.Layout") object, so the return from the above example would be: + + ```python + Layout({ + qc.qubits[0]: 2, + qc.qubits[1]: 0, + qc.qubits[2]: 1, + }) + ``` + + + +### Visualization Features + +* Added the ability to display conditions as expressions from [`Expr`](circuit_classical#qiskit.circuit.classical.expr.Expr "qiskit.circuit.classical.expr.Expr") in the [`QuantumCircuit.draw()`](qiskit.circuit.QuantumCircuit#draw "qiskit.circuit.QuantumCircuit.draw") method and the [`circuit_drawer()`](qiskit.visualization.circuit_drawer "qiskit.visualization.circuit_drawer") function when visualizing circuits that have [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp") instructions. + +* Added the `"iqp"` and `"iqp-dark"` color styles for the `matplotlib` circuit drawer, which are based on the IBM Quantum Platform color scheme. + +* In `TextDrawer`, operations built from [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp"), including `if`, `else`, `while`, `for`, and `switch/case`, whether directly instantiated or built using methods in [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"), will now fully display the circuits defined in the ControlFlowOps with brackets to delineate the circuits. + +* When defining a custom stylesheet for the pulse timeline drawer [`qiskit.visualization.timeline_drawer()`](qiskit.visualization.timeline_drawer "qiskit.visualization.timeline_drawer"), “generator” functions that have the object attribute `accepts_program` set to `True` will receive an extra keyword argument `program` containing the full scheduled [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") being drawn. + +* The visualizations from the [`plot_gate_map()`](qiskit.visualization.plot_gate_map "qiskit.visualization.plot_gate_map"), [`plot_coupling_map()`](qiskit.visualization.plot_coupling_map "qiskit.visualization.plot_coupling_map"). [`plot_error_map()`](qiskit.visualization.plot_error_map "qiskit.visualization.plot_error_map"), and [`plot_circuit_layout()`](qiskit.visualization.plot_circuit_layout "qiskit.visualization.plot_circuit_layout") functions have been significantly improved for rendering layouts of backends with large numbers of qubits. This was accomplished by leveraging [graphviz](https://graphviz.org/) through rustworkx’s `graphviz_draw()` function to perform a more sophisticated algorithmic graph layout that scales for large numbers of qubits. + + ![\_images/release\_notes-1.png](/images/api/qiskit/release_notes-1.png) + + + +### Misc. Features + +* Added support for expressing the sign of a [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression"). Instead of assigning a concrete value and using [`numpy.sign`](https://numpy.org/doc/stable/reference/generated/numpy.sign.html#numpy.sign "(in NumPy v1.26)") or other library functions, the user can use the instance of the [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") class to calculate the sign and can work with the sign before the expression is fully assigned. + + It can be used as follows: + + ```python + from qiskit.circuit import Parameter + + b = Parameter("phi") + sign_value = b.sign() + print("sign of an unassigned Parameter is: ", sign_value) + print("Sign of a Parameter assigned to -3 is: ", sign_value.assign(b,-3)) + ``` + + Refer to [#10360](https://github.com/Qiskit/qiskit-terra/issues/10360) for more details. + +* [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") now has an advanced-usage keyword argument `uuid` in its constructor, which can be used to make the [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") compare equal to another of the same name. This should not typically be used by users, and is most useful for custom serialisation and deserialisation. + + + +### Circuits Upgrade Notes + +* The [`ControlledGate.definition`](qiskit.circuit.ControlledGate#definition "qiskit.circuit.ControlledGate.definition") of the output from the [`Gate.control()`](qiskit.circuit.Gate#control "qiskit.circuit.Gate.control") method may be different as compared to previous releases. The internal generation of the [`Gate.control()`](qiskit.circuit.Gate#control "qiskit.circuit.Gate.control") method is no longer using the now deprecated [`Unroller`](qiskit.transpiler.passes.Unroller "qiskit.transpiler.passes.Unroller") transpiler pass to generate its definition and this can potentially cause a different definition to be generated. The output [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate") object’s definition will be unitary equivalent to what was generated before. But if you require the exact definition from calling [`Gate.control()`](qiskit.circuit.Gate#control "qiskit.circuit.Gate.control") you can use an earlier release and save the circuit with [`qpy.dump()`](qpy#qiskit.qpy.dump "qiskit.qpy.dump") and then load it with a newer release. + +* The property `num_ancilla_qubits` from the class [`PolynomialPauliRotations`](qiskit.circuit.library.PolynomialPauliRotations "qiskit.circuit.library.PolynomialPauliRotations") has been removed, as deprecated in Qiskit 0.23.0. Instead, use the property [`PolynomialPauliRotations.num_ancillas`](qiskit.circuit.library.PolynomialPauliRotations#num_ancillas "qiskit.circuit.library.PolynomialPauliRotations.num_ancillas"). + +* The following standard library gates: + + > * [`DCXGate`](qiskit.circuit.library.DCXGate "qiskit.circuit.library.DCXGate") + > * [`ECRGate`](qiskit.circuit.library.ECRGate "qiskit.circuit.library.ECRGate") + > * [`HGate`](qiskit.circuit.library.HGate "qiskit.circuit.library.HGate") + > * [`IGate`](qiskit.circuit.library.IGate "qiskit.circuit.library.IGate") + > * [`iSwapGate`](qiskit.circuit.library.iSwapGate "qiskit.circuit.library.iSwapGate") + > * [`SGate`](qiskit.circuit.library.SGate "qiskit.circuit.library.SGate") + > * [`SdgGate`](qiskit.circuit.library.SdgGate "qiskit.circuit.library.SdgGate") + > * [`SwapGate`](qiskit.circuit.library.SwapGate "qiskit.circuit.library.SwapGate") + > * [`SXGate`](qiskit.circuit.library.SXGate "qiskit.circuit.library.SXGate") + > * [`SXdgGate`](qiskit.circuit.library.SXdgGate "qiskit.circuit.library.SXdgGate") + > * [`TGate`](qiskit.circuit.library.TGate "qiskit.circuit.library.TGate") + > * [`TdgGate`](qiskit.circuit.library.TdgGate "qiskit.circuit.library.TdgGate") + > * [`XGate`](qiskit.circuit.library.XGate "qiskit.circuit.library.XGate") + > * [`RCCXGate`](qiskit.circuit.library.RCCXGate "qiskit.circuit.library.RCCXGate") + > * [`RC3XGate`](qiskit.circuit.library.RC3XGate "qiskit.circuit.library.RC3XGate") + > * [`YGate`](qiskit.circuit.library.YGate "qiskit.circuit.library.YGate") + > * [`ZGate`](qiskit.circuit.library.ZGate "qiskit.circuit.library.ZGate") + > * [`CHGate`](qiskit.circuit.library.CHGate "qiskit.circuit.library.CHGate") + > * [`CSGate`](qiskit.circuit.library.CSGate "qiskit.circuit.library.CSGate") + > * [`CSdgGate`](qiskit.circuit.library.CSdgGate "qiskit.circuit.library.CSdgGate") + > * [`CSwapGate`](qiskit.circuit.library.CSwapGate "qiskit.circuit.library.CSwapGate") + > * [`CSXGate`](qiskit.circuit.library.CSXGate "qiskit.circuit.library.CSXGate") + > * [`CXGate`](qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate") + > * [`CCXGate`](qiskit.circuit.library.CCXGate "qiskit.circuit.library.CCXGate") + > * [`C3SXGate`](qiskit.circuit.library.C3SXGate "qiskit.circuit.library.C3SXGate") + > * [`C3XGate`](qiskit.circuit.library.C3XGate "qiskit.circuit.library.C3XGate") + > * [`C4XGate`](qiskit.circuit.library.C4XGate "qiskit.circuit.library.C4XGate") + > * [`CYGate`](qiskit.circuit.library.CYGate "qiskit.circuit.library.CYGate") + > * [`CZGate`](qiskit.circuit.library.CZGate "qiskit.circuit.library.CZGate") + + are no longer able to set [`label`](qiskit.circuit.Gate#label "qiskit.circuit.Gate.label"), [`condition`](qiskit.circuit.Gate#condition "qiskit.circuit.Gate.condition"), [`duration`](qiskit.circuit.Gate#duration "qiskit.circuit.Gate.duration"), or [`unit`](qiskit.circuit.Gate#unit "qiskit.circuit.Gate.unit") (and [`ctrl_state`](qiskit.circuit.ControlledGate#ctrl_state "qiskit.circuit.ControlledGate.ctrl_state") for [`ControlledGate`](qiskit.circuit.ControlledGate "qiskit.circuit.ControlledGate") subclasses) after instantiating an object anymore. You can still set [`condition`](qiskit.circuit.Gate#condition "qiskit.circuit.Gate.condition") through the use [`c_if()`](qiskit.circuit.Gate#c_if "qiskit.circuit.Gate.c_if"). You can use [`to_mutable()`](qiskit.circuit.Gate#to_mutable "qiskit.circuit.Gate.to_mutable") to get a mutable copy of the instruction and then use the setter on that copy instead of the original object. `label`, `duration` and `unit` can be given as keyword arguments to these gates at construction time, and a mutable instance will be returned automatically. This change was necessary as part of converting these classes to be [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") and [`SingletonControlledGate`](circuit_singleton#qiskit.circuit.singleton.SingletonControlledGate "qiskit.circuit.singleton.SingletonControlledGate") types which greatly reduces the memory footprint of repeated instances of these gates. + +* For anything that interacts with [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate"), [`Operation`](qiskit.circuit.Operation "qiskit.circuit.Operation"), or [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") objects or works with these as part of a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") or [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") classes, it is important to note that the use of shared references for instances is much more common now. Previously, it was possible to reuse and share an instance of a circuit operation, but it wasn’t very commonly used and a copy would generate a unique instance. This has changed starting in this release because of [`SingletonInstruction`](circuit_singleton#qiskit.circuit.singleton.SingletonInstruction "qiskit.circuit.singleton.SingletonInstruction") and [`SingletonGate`](circuit_singleton#qiskit.circuit.singleton.SingletonGate "qiskit.circuit.singleton.SingletonGate") being made available (and a large number of standard library gates now built off of them). If your usage of these objects is assuming unique instances for every circuit operation, this becomes a potential issue, as now a shared state will be reused between operations of the same type (that will persist through copy and deep copies). You can rely on the [`Instruction.mutable`](qiskit.circuit.Instruction#mutable "qiskit.circuit.Instruction.mutable") attribute to check the mutability of an object or use [`Instruction.to_mutable()`](qiskit.circuit.Instruction#to_mutable "qiskit.circuit.Instruction.to_mutable") to get a mutable copy of any instruction. + +* More [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") instances (those that return singletons) no longer strictly satisfy (for example): + + ```python + type(XGate()) is XGate + ``` + + The returned object will, however, still be a standard subclass so [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance "(in Python v3.12)") (the correct way to do type checking) will continue to work correctly. Several instructions already had this property (e.g. [`MCXGate`](qiskit.circuit.library.MCXGate "qiskit.circuit.library.MCXGate")), but it is now more common as many more standard gates will do this. + + If you require the “base” type of a gate for some reason, omitting the synthetic singleton subclasses, which cannot be instantiated, see [`Instruction.base_class`](qiskit.circuit.Instruction#base_class "qiskit.circuit.Instruction.base_class"). + +* The definition of [`UnitaryGate`](qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate") for single qubit unitaries is now in terms of [`UGate`](qiskit.circuit.library.UGate "qiskit.circuit.library.UGate") instead of the legacy [`U3Gate`](qiskit.circuit.library.U3Gate "qiskit.circuit.library.U3Gate") class. + + + +### Providers Upgrade Notes + +* The [`QasmSimulatorPy`](qiskit.providers.basicaer.QasmSimulatorPy "qiskit.providers.basicaer.QasmSimulatorPy") python-based simulator included in [`qiskit.providers.basicaer`](providers_basicaer#module-qiskit.providers.basicaer "qiskit.providers.basicaer") now includes `'h'` ([`HGate`](qiskit.circuit.library.HGate "qiskit.circuit.library.HGate")), `'p'` ([`PhaseGate`](qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate")), and `'u'` ([`UGate`](qiskit.circuit.library.UGate "qiskit.circuit.library.UGate")) in its basis gate set. + +* The argument `channel` in the method [`PulseBackendConfiguration.control()`](qiskit.providers.models.PulseBackendConfiguration#control "qiskit.providers.models.PulseBackendConfiguration.control") is removed. It was deprecated in Qiskit 0.33 (with Terra 0.19), released on Dec 2021. Instead use the `qubits` argument. + +* Replaced the argument `qobj[Qobj]` in [`QasmSimulatorPy.run()`](qiskit.providers.basicaer.QasmSimulatorPy#run "qiskit.providers.basicaer.QasmSimulatorPy.run") with `run_input[QuantumCircuit or list]` + + Here is an example to migrate your code: + + ```python + # Importing necessary Qiskit libraries + from qiskit import transpile, QuantumCircuit + from qiskit.aer import QasmSimulator + + # Defining the Quantum Circuit + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0, 1) + qc.measure_all() + + # Transpile the circuit to optimize for the target simulator + simulator = QasmSimulator() + transpiled_circuit = transpile(qc, simulator) + # Run the simulation + job = simulator.run(transpiled_circuit, shots=1024) + # Get the simulation result + result = job.result() + ``` + + All these were deprecated since 0.22 (released on October 13, 2022) and now they are removed. + + + +### Pulse Upgrade Notes + +* The functions `qiskit.scheduler.utils.format_meas_map()`, `qiskit.scheduler.utils.measure()`, and `qiskit.scheduler.utils.measure_all()` had been moved to `qiskit.pulse.utils.format_meas_map()`, `qiskit.pulse.macros.measure()`, and `qiskit.pulse.macros.measure_all()` respectively. The previous location was deprecated in Qiskit 0.20.0 (Terra 0.15.0, released on 2020-08-10) and it is no longer supported. + +* The methods `to_dict` in the classes [`pulse.transforms.AlignmentKind`](pulse#qiskit.pulse.transforms.AlignmentKind "qiskit.pulse.transforms.AlignmentKind"), [`pulse.transforms.AlignEquispaced`](qiskit.pulse.transforms.AlignEquispaced "qiskit.pulse.transforms.AlignEquispaced"), and [`pulse.transforms.AlignFunc`](qiskit.pulse.transforms.AlignFunc "qiskit.pulse.transforms.AlignFunc") are removed. They were deprecatedin Qiskit 0.37 (with Terra 0.21), released on June 2022. + + + +### QPY Upgrade Notes + +* The use of the keyword `circuits` for the first positional argument in the function [`qiskit.qpy.dump()`](qpy#qiskit.qpy.dump "qiskit.qpy.dump") is removed as its usage was deprecated in Qiskit 0.37 (with Terra 0.21), released on June 2022. Instead, use the keyword `programs` can be used instead (or just pass the argument in positionally), which behaves identically. + + + +### Quantum Information Upgrade Notes + +* The method [`qiskit.quantum_info.pauli_basis()`](qiskit.quantum_info.pauli_basis "qiskit.quantum_info.pauli_basis") does not accept the `pauli_list` argument any more. It was deprecated in Qiskit 0.39 (with Terra 0.22), released on Oct 2022. + +* The function `random_stabilizer_table` in the `qiskit.quantum_info.random` module is removed. It was deprecated in Qiskit 0.39 (with Terra 0.22), released on Oct 2022. Instead, use `qiskit.quantum_info.random.random_pauli_list()`. + +* The classes `qiskit.quantum_info.PauliTable` and `qiskit.quantum_info.StabilizerTable` are removed. The function `random_pauli_table()` is also removed. They were deprecated in Qiskit 0.43 (with Terra 0.24), released in May 2023. Instead, you should use [`PauliList`](qiskit.quantum_info.PauliList "qiskit.quantum_info.PauliList") and [`random_pauli_list()`](quantum_info#qiskit.quantum_info.random_pauli_list "qiskit.quantum_info.random_pauli_list"). + +* The arguments `z` and `x` to the initializer of to [`Pauli`](qiskit.quantum_info.Pauli "qiskit.quantum_info.Pauli") were removed, as deprecated in Qiskit Terra 0.17 (released on April, 2021). A pair of `x` and `z` should be passed positionally as a single tuple instead (`Pauli((z, x))`). + +* The argument `label` to the initializer of [`Pauli`](qiskit.quantum_info.Pauli "qiskit.quantum_info.Pauli") was removed, as deprecated in Qiskit Terra 0.17 (released on April, 2021). Pass the label positionally instead, such as `Pauli("XYZ")`. + +* Importing from `qiskit.quantum_info.operators.pauli` is not allowed anymore, as it was deprecated in Qiskit Terra 0.21 (released on June, 2022). Import directly from `qiskit.quantum_info` instead. + + + +### Synthesis Upgrade Notes + +* The parameter `order` in [`synthesis.SuzukiTrotter`](qiskit.synthesis.SuzukiTrotter "qiskit.synthesis.SuzukiTrotter") constructor raises an exception instead of deprecation warning when set in an odd number. Suzuki product formulae are symmetric and therefore only defined for even orders. + + + +### Transpiler Upgrade Notes + +* The plugin name `default` is reserved for the [plugin stages](transpiler_plugins#stage-table) `init`, `layout`, `optimization`, and `scheduling`. These stages previously did not reserve this plugin name, but the `default` name is now used to represent Qiskit’s built-in default method for these stages. If you were using these names for plugins on these stages these will conflict with Qiskit’s usage and you should rename your plugin. + +* Disabled the use of the [`RemoveResetInZeroState`](qiskit.transpiler.passes.RemoveResetInZeroState "qiskit.transpiler.passes.RemoveResetInZeroState") class in the preset passmanagers. Previously, when [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") or [`generate_preset_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager "qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager") was run with `optimization_level` at level 1, 2, or 3, it would run [`RemoveResetInZeroState`](qiskit.transpiler.passes.RemoveResetInZeroState "qiskit.transpiler.passes.RemoveResetInZeroState"). However, this pass prohibited the notion of arbitrary initial states unless explicitly set to zeros with resets. If you need to run the pass as part of your compilation pipeline, you can run something like: + + ```python + pm = generate_preset_pass_manager(1, backend) + pm.init.append(RemoveResetInZeroState()) + pm.run(circuit) + ``` + + to retain this functionality for your circuit compilation. + +* The deprecated transpiler routing pass, `BIPMapping` has been removed. It was marked as deprecated in the Qiskit 0.43.0 release. It has been replaced by an external plugin package: `qiskit-bip-mapper`. Details for this new package can be found at the package’s github repository: + + > [https://github.com/qiskit-community/qiskit-bip-mapper](https://github.com/qiskit-community/qiskit-bip-mapper) + + The pass was made into a separate plugin package for two reasons: first, the dependency on CPLEX makes it harder to use, and secondly, the plugin package integrates more cleanly with [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile"). The optional extra `bip-mapper` to install `cplex` and `docplex` to support this pass has been removed as nothing in Qiskit optionally requires it anymore. + +* The argument `qubits` in the method [`InstructionDurations.get()`](qiskit.transpiler.InstructionDurations#get "qiskit.transpiler.InstructionDurations.get"), does not accept [`Qubit`](qiskit.circuit.Qubit "qiskit.circuit.Qubit") (or a list of them) any more. This functionality was deprecated in Qiskit 0.33 (with Terra 0.19), released on Dec 2021. Instead, use an integer for the qubit indices. + +* Removed the argument `qubit_channel_mapping` in [`RZXCalibrationBuilder`](qiskit.transpiler.passes.RZXCalibrationBuilder "qiskit.transpiler.passes.RZXCalibrationBuilder"), which was deprecated in Qiskit 0.39 (released on Oct 2022, with qiskit-terra 0.22) + +* In [`transpiler.CouplingMap`](qiskit.transpiler.CouplingMap "qiskit.transpiler.CouplingMap") method `subgraph` is removed as deprecated in 0.20. `reduce()` can be used in place of method `subgraph`. + + + +### Visualization Upgrade Notes + +* Removed support for using the keyword `rho` for the first positional argument in [`plot_state_hinton()`](qiskit.visualization.plot_state_hinton "qiskit.visualization.plot_state_hinton"), [`plot_bloch_multivector()`](qiskit.visualization.plot_bloch_multivector "qiskit.visualization.plot_bloch_multivector"), [`plot_state_city()`](qiskit.visualization.plot_state_city "qiskit.visualization.plot_state_city"), [`plot_state_paulivec()`](qiskit.visualization.plot_state_paulivec "qiskit.visualization.plot_state_paulivec"), and [`plot_state_qsphere()`](qiskit.visualization.plot_state_qsphere "qiskit.visualization.plot_state_qsphere"). The use of `rho` has been replaced by `state`, which can be used instead. Removed `qiskit.scheduler.utils` as all contained functions were moved to `qiskit.pulse.macros` and `qiskit.pulse.utils`. All these were deprecated since 0.15 (released on August 06, 2020) and now they are removed. + +* The class constructor arguments `qregs`, `cregs`, `layout` and `global_phase` for `visualization.QCircuitImage` are removed, as they were deprecated in 0.20. + +* The visualization functions: [`plot_gate_map()`](qiskit.visualization.plot_gate_map "qiskit.visualization.plot_gate_map"), [`plot_coupling_map()`](qiskit.visualization.plot_coupling_map "qiskit.visualization.plot_coupling_map"). [`plot_error_map()`](qiskit.visualization.plot_error_map "qiskit.visualization.plot_error_map"), and [`plot_circuit_layout()`](qiskit.visualization.plot_circuit_layout "qiskit.visualization.plot_circuit_layout") now depend on [graphviz](https://graphviz.org/) being installed to function. This change was necessary to enable visualizing backends with larger numbers of qubits. This additional external requirement is in addition to the existing optional dependencies these functions previously required. You find details on how to install graphviz here: [https://graphviz.org/download/](https://graphviz.org/download/) + + + +### Misc. Upgrade Notes + +* The [`QuasiDistribution`](qiskit.result.QuasiDistribution "qiskit.result.QuasiDistribution") values might include floating-point errors. `QuasiDistribution.__repr__` rounds using `numpy.round()` and the parameter `ndigits` can be manipulated with the class attribute `__ndigits__`. The default is `15`. + +* The class `qiskit.qobj.Qobj` is removed. It was deprecated in Qiskit 0.33 (with Terra 0.19), released on Dec 2021. Instead, use [`qiskit.qobj.QasmQobj`](qiskit.qobj.QasmQobj "qiskit.qobj.QasmQobj") or [`qiskit.qobj.PulseQobj`](qiskit.qobj.PulseQobj "qiskit.qobj.PulseQobj"). + +* The decorator `qiskit.utils.deprecation.deprecate_function()` has been deprecated since Qiskit 0.39.0 (released on October 2022, with qiskit-terra 0.22.0) and now is been removed. Use [`qiskit.utils.deprecate_func()`](utils#qiskit.utils.deprecate_func "qiskit.utils.deprecate_func") instead. + +* The function [`execute()`](execute#qiskit.execute_function.execute "qiskit.execute_function.execute") does not accept the arguments `qobj_id` and `qobj_header` any more. Their use was deprecated in Qiskit 0.37 (with Terra 0.21), released on June 2022. + +* The transpilation pass `qiskit.transpiler.passes.CXDirection` is removed. Its use was deprecated in Qiskit 0.37 (with Terra 0.21), released on June 2022. Instead, use the more generic [`GateDirection`](qiskit.transpiler.passes.GateDirection "qiskit.transpiler.passes.GateDirection") pass. + +* The transpilation pass `qiskit.transpiler.passes.CheckCXDirection` is removed. Its use was deprecated in Qiskit 0.37 (with Terra 0.21), released on June 2022. Instead, use the more generic [`CheckGateDirection`](qiskit.transpiler.passes.CheckGateDirection "qiskit.transpiler.passes.CheckGateDirection") pass. + +* Building Qiskit from source now requires a Rust compiler compatible with language version 1.64. This has been increased from the previous minimum supported Rust version of 1.61 for building earlier versions of Qiskit. + + + +### Algorithms Deprecations + +* The algorithm utils in `qiskit.utils.validation` and `qiskit.utils.algorithm_globals` are now deprecated and will be removed in no less than 3 months from the release date. These utils were introduced with the `qiskit.algorithms` module to support legacy and primitive-based algorithm workflows. Now that `qiskit.algorithms` is deprecated and the primitive-based algorithms codebase has been migrated to a standalone [library](https://github.com/qiskit-community/qiskit-algorithms), these utils are no longer used in the context of Qiskit. If your application allows it, we recommend that you migrate your code to use [qiskit\_algorithms](https://github.com/qiskit-community/qiskit-algorithms), where you will be able to import the relevant utilities in `algorithm_globals` and `validation` from `qiskit_algorithms.utils`. Please note that legacy functionality has not been migrated to the new package. + + + +### Circuits Deprecations + +* Passing `None` as the `qargs` or `cargs` arguments to [`DAGCircuit.apply_operation_back()`](qiskit.dagcircuit.DAGCircuit#apply_operation_back "qiskit.dagcircuit.DAGCircuit.apply_operation_back") or [`apply_operation_front()`](qiskit.dagcircuit.DAGCircuit#apply_operation_front "qiskit.dagcircuit.DAGCircuit.apply_operation_front") is deprecated and will be removed in Qiskit 1.0. This has been explicitly against the typing documentation for some time, but silently accepted by Qiskit. Instead, simply pass `()` rather than `None`. + +* The method [`QuantumCircuit.bind_parameters()`](qiskit.circuit.QuantumCircuit#bind_parameters "qiskit.circuit.QuantumCircuit.bind_parameters") is now deprecated and will be removed from the codebase in no less than 3 months from the release date. Its functionality overlapped highly with [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters"), and can be totally replaced by it. Please use [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") instead. + +* Deprecate duplicate gate methods on [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"). The rule applied is that the method names reflect that gate names, e.g. the [`CXGate`](qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate") is added via [`QuantumCircuit.cx()`](qiskit.circuit.QuantumCircuit#cx "qiskit.circuit.QuantumCircuit.cx") and not [`QuantumCircuit.cnot()`](qiskit.circuit.QuantumCircuit#cnot "qiskit.circuit.QuantumCircuit.cnot"). The deprecations are: + + * [`QuantumCircuit.cnot()`](qiskit.circuit.QuantumCircuit#cnot "qiskit.circuit.QuantumCircuit.cnot") in favor of [`QuantumCircuit.cx()`](qiskit.circuit.QuantumCircuit#cx "qiskit.circuit.QuantumCircuit.cx") + * [`QuantumCircuit.toffoli()`](qiskit.circuit.QuantumCircuit#toffoli "qiskit.circuit.QuantumCircuit.toffoli") in favor of [`QuantumCircuit.ccx()`](qiskit.circuit.QuantumCircuit#ccx "qiskit.circuit.QuantumCircuit.ccx") + * [`QuantumCircuit.fredkin()`](qiskit.circuit.QuantumCircuit#fredkin "qiskit.circuit.QuantumCircuit.fredkin") in favor of [`QuantumCircuit.cswap()`](qiskit.circuit.QuantumCircuit#cswap "qiskit.circuit.QuantumCircuit.cswap") + * [`QuantumCircuit.mct()`](qiskit.circuit.QuantumCircuit#mct "qiskit.circuit.QuantumCircuit.mct") in favor of [`QuantumCircuit.mcx()`](qiskit.circuit.QuantumCircuit#mcx "qiskit.circuit.QuantumCircuit.mcx") + * [`QuantumCircuit.i()`](qiskit.circuit.QuantumCircuit#i "qiskit.circuit.QuantumCircuit.i") in favor of [`QuantumCircuit.id()`](qiskit.circuit.QuantumCircuit#id "qiskit.circuit.QuantumCircuit.id") + + Note that [`QuantumCircuit.i()`](qiskit.circuit.QuantumCircuit#i "qiskit.circuit.QuantumCircuit.i") is the only exception to the rule above, but since [`QuantumCircuit.id()`](qiskit.circuit.QuantumCircuit#id "qiskit.circuit.QuantumCircuit.id") more intuively represents the identity and is used more, we chose it over its counterpart. + +* To streamline the structure of Qiskit’s gates and operations, the [`qiskit.extensions`](extensions#module-qiskit.extensions "qiskit.extensions") module is pending deprecation and will be deprecated in a future release. The following objects have been moved to [`qiskit.circuit.library`](circuit_library#module-qiskit.circuit.library "qiskit.circuit.library") + + * [`DiagonalGate`](qiskit.circuit.library.DiagonalGate "qiskit.circuit.library.DiagonalGate"), + * [`HamiltonianGate`](qiskit.circuit.library.HamiltonianGate "qiskit.circuit.library.HamiltonianGate"), + * [`Initialize`](qiskit.circuit.library.Initialize "qiskit.circuit.library.Initialize"), + * [`Isometry`](qiskit.circuit.library.Isometry "qiskit.circuit.library.Isometry"), + * `MCGupDiag`, + * [`UCGate`](qiskit.circuit.library.UCGate "qiskit.circuit.library.UCGate"), + * [`UCPauliRotGate`](qiskit.circuit.library.UCPauliRotGate "qiskit.circuit.library.UCPauliRotGate"), + * [`UCRXGate`](qiskit.circuit.library.UCRXGate "qiskit.circuit.library.UCRXGate"), + * [`UCRYGate`](qiskit.circuit.library.UCRYGate "qiskit.circuit.library.UCRYGate"), + * [`UCRZGate`](qiskit.circuit.library.UCRZGate "qiskit.circuit.library.UCRZGate"), + * [`UnitaryGate`](qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate"). + + These instructions have already been deprecated in this release, + + * [`SingleQubitUnitary`](qiskit.extensions.SingleQubitUnitary "qiskit.extensions.SingleQubitUnitary"), instead use [`library.UnitaryGate`](qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate"), + * [`Snapshot`](qiskit.extensions.Snapshot "qiskit.extensions.Snapshot"), which has been superseded by Qiskit Aer’s save instructions, + + along with their circuit methods + + * [`QuantumCircuit.snapshot()`](qiskit.circuit.QuantumCircuit#snapshot "qiskit.circuit.QuantumCircuit.snapshot"), + * [`QuantumCircuit.squ()`](qiskit.circuit.QuantumCircuit#squ "qiskit.circuit.QuantumCircuit.squ"). + + In addition, the following circuit methods are pending deprecation + + * [`QuantumCircuit.diagonal()`](qiskit.circuit.QuantumCircuit#diagonal "qiskit.circuit.QuantumCircuit.diagonal"), + * [`QuantumCircuit.hamiltonian()`](qiskit.circuit.QuantumCircuit#hamiltonian "qiskit.circuit.QuantumCircuit.hamiltonian"), + * [`QuantumCircuit.isometry()`](qiskit.circuit.QuantumCircuit#isometry "qiskit.circuit.QuantumCircuit.isometry") and [`QuantumCircuit.iso()`](qiskit.circuit.QuantumCircuit#iso "qiskit.circuit.QuantumCircuit.iso"), + * [`QuantumCircuit.uc()`](qiskit.circuit.QuantumCircuit#uc "qiskit.circuit.QuantumCircuit.uc"), + * [`QuantumCircuit.ucrx()`](qiskit.circuit.QuantumCircuit#ucrx "qiskit.circuit.QuantumCircuit.ucrx"), + * [`QuantumCircuit.ucry()`](qiskit.circuit.QuantumCircuit#ucry "qiskit.circuit.QuantumCircuit.ucry"), + * [`QuantumCircuit.ucrz()`](qiskit.circuit.QuantumCircuit#ucrz "qiskit.circuit.QuantumCircuit.ucrz"). + + Since the entire module is pending deprecation, so is [`ExtensionError`](extensions#qiskit.extensions.ExtensionError "qiskit.extensions.ExtensionError"). + +* The little-used [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") class data attributes [`header`](qiskit.circuit.QuantumCircuit#header "qiskit.circuit.QuantumCircuit.header") and [`extension_lib`](qiskit.circuit.QuantumCircuit#extension_lib "qiskit.circuit.QuantumCircuit.extension_lib") are deprecated and scheduled for removal. These respectively held strings of the OpenQASM 2.0 version header statement and `qelib1.inc` include statement. No alternative will be provided; these were mostly intended as internal details. + + + +### Transpiler Deprecations + +* The [`Unroller`](qiskit.transpiler.passes.Unroller "qiskit.transpiler.passes.Unroller") transpiler pass has been deprecated and will be removed in a future release. The [`Unroller`](qiskit.transpiler.passes.Unroller "qiskit.transpiler.passes.Unroller") has been superseded by the [`BasisTranslator`](qiskit.transpiler.passes.BasisTranslator "qiskit.transpiler.passes.BasisTranslator") which provides a similar set of functionality but offers it in a more general manner so that you’re able to translate a circuit to any universal basis set. The [`Unroller`](qiskit.transpiler.passes.Unroller "qiskit.transpiler.passes.Unroller") class only works in situations where the circuit’s gate definitions are recursively defined in terms of the target basis; for Qiskit’s standard library gates this means [`UGate`](qiskit.circuit.library.UGate "qiskit.circuit.library.UGate") and [`CXGate`](qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate"). If you are using the [`Unroller`](qiskit.transpiler.passes.Unroller "qiskit.transpiler.passes.Unroller") pass it can be replaced by using a custom pass manager of the form: + + ```python + from qiskit.transpiler import PassManager + from qiskit.transpiler.passes import UnrollCustomDefinitions, BasisTranslator + from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel + + pm = PassManager( + [ + UnrollCustomDefinitions(sel, basis_gates=basis_gates), + BasisTranslator(sel, target_basis=basis_gates), + ] + ) + pm.run(circuit) + ``` + +* The use of the value `"unroller"` for the `translation_method` keyword argument on the [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") and [`generate_preset_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager "qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager") has been deprecated. This translation stage plugin will be removed from Qiskit in a future release as it has been superseded by the default `"translator"` method which will work similarly to the `"unroller"` plugin but support a broader set of target backends. + + + +### Visualization Deprecations + +* The default `matplotlib` drawer setting now issues a `FutureWarning`, as the default style is changing to the `"iqp"` style (previously known as `"iqx"`). The old default is available as the `"clifford"` style. To silence the warning, you can explicitly set the desired style, e.g.: + + ```python + from qiskit import QuantumCircuit + + circuit = QuantumCircuit(2) + circuit.x(0) + circuit.h(0) + circuit.cp(0.5, 0, 1) + + circuit.draw("mpl", style="clifford") # or style="iqp" + ``` + +* Passing a circuit to [`qiskit.visualization.timeline_drawer()`](qiskit.visualization.timeline_drawer "qiskit.visualization.timeline_drawer") that does not have scheduled node start-time information is deprecated. Only circuits that have gone through one of the scheduling analysis passes (for example [`ALAPScheduleAnalysis`](qiskit.transpiler.passes.ALAPScheduleAnalysis "qiskit.transpiler.passes.ALAPScheduleAnalysis") or [`ASAPScheduleAnalysis`](qiskit.transpiler.passes.ASAPScheduleAnalysis "qiskit.transpiler.passes.ASAPScheduleAnalysis")) can be visualised. If you have used one of the old-style scheduling passes (for example [`ALAPSchedule`](qiskit.transpiler.passes.ALAPSchedule "qiskit.transpiler.passes.ALAPSchedule") or [`ASAPSchedule`](qiskit.transpiler.passes.ASAPSchedule "qiskit.transpiler.passes.ASAPSchedule")), you can propagate the scheduling information by running: + + ```python + from qiskit import transpile + from qiskit.transpiler import InstructionDurations + + scheduled = transpile( + my_old_style_circuit, + optimization_level=0, + scheduling_method="alap", + instruction_durations=InstructionDurations(), + ) + ``` + + This behaviour was previously intended to be deprecated in Qiskit 0.37, but due to a bug in the warning, it was not displayed to users until now. The behaviour will be removed in Qiskit 1.0. + + + + + +### Bug Fixes + +* The maximum number of qubits to consider for matrix multiplication-based commutativity check in [`CommutationChecker`](qiskit.circuit.CommutationChecker "qiskit.circuit.CommutationChecker") is now limited to 3 by default. Fixed [#10488](https://github.com/Qiskit/qiskit-terra/issues/10488) + +* The [`GateDirection`](qiskit.transpiler.passes.GateDirection "qiskit.transpiler.passes.GateDirection") transpiler pass will now use discrete-basis translations rather than relying on a continuous [`RYGate`](qiskit.circuit.library.RYGate "qiskit.circuit.library.RYGate"), which should help make some discrete-basis-set targets slightly more reliable. In general, [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") only has partial support for basis sets that do not contain a continuously-parametrised operation, and so it may not always succeed in these situations, and will almost certainly not produce optimal results. + +* Fixed [`CommutationAnalysis`](qiskit.transpiler.passes.CommutationAnalysis "qiskit.transpiler.passes.CommutationAnalysis") to group gates on a wire into sets, with each set only containing gates that pairwise commute. This prevents `CommutationCancellation` from performing unsound optimizations. See [#8020](https://github.com/Qiskit/qiskit-terra/issues/8020) + +* [`CUGate`](qiskit.circuit.library.CUGate "qiskit.circuit.library.CUGate") will now behave correctly during calls to [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters"). Previously, it would cause various odd errors, often some time after the initial circuit assignment. See [#7326](https://github.com/Qiskit/qiskit/issues/7326), [#7410](https://github.com/Qiskit/qiskit/issues/7410), [#9627](https://github.com/Qiskit/qiskit/issues/9627), [#10002](https://github.com/Qiskit/qiskit/issues/10002), and [#10131](https://github.com/Qiskit/qiskit/issues/10131). + +* The control-flow builder interface (the context-manager forms of [`QuantumCircuit.if_test()`](qiskit.circuit.QuantumCircuit#if_test "qiskit.circuit.QuantumCircuit.if_test"), [`while_loop()`](qiskit.circuit.QuantumCircuit#while_loop "qiskit.circuit.QuantumCircuit.while_loop"), [`for_loop()`](qiskit.circuit.QuantumCircuit#for_loop "qiskit.circuit.QuantumCircuit.for_loop") and [`switch()`](qiskit.circuit.QuantumCircuit#switch "qiskit.circuit.QuantumCircuit.switch")) will now correctly track a separate global-phase advancement within that block. You can add a global-phase advancement to an inner block by assigning to [`QuantumCircuit.global_phase`](qiskit.circuit.QuantumCircuit#global_phase "qiskit.circuit.QuantumCircuit.global_phase") within a builder scope: + + ```python + from math import pi + from qiskit import QuantumCircuit + + qc = QuantumCircuit(3, 3) + qc.global_phase = pi / 2 # Set the outer circuit's global phase. + + with qc.if_test((qc.clbits[0], False)) as else_: + # The global phase advancement in a control-flow block begins at 0, + # because it represents how much the phase will be advanced by an + # execution of the block. The defined phase of the outer scope is not + # affected by this set. + qc.global_phase = pi + with else_: + # Similarly, the `else` block may induce a different global-phase + # advancement to the `if`, so it can also be set separately. + qc.global_phase = 1.5 * pi + + # The phase advancement caused directly by the outer scope is independent + # of the phase advancement conditionally caused by each control-flow path. + assert qc.global_phase == pi / 2 + ``` + + The meaning of [`QuantumCircuit.global_phase`](qiskit.circuit.QuantumCircuit#global_phase "qiskit.circuit.QuantumCircuit.global_phase") is taken to be the global-phase advancement that is inherent to a single execution of the block. It is still a *global* phase advancement, in that if the block is entered, the phase of all qubits in the entire program will be advanced. + +* Fix the coloring of the `"iqx"` and `"iqx-dark"` matplotlib color schemes, which previously drew the [`RZGate`](qiskit.circuit.library.RZGate "qiskit.circuit.library.RZGate"), [`RZZGate`](qiskit.circuit.library.RZZGate "qiskit.circuit.library.RZZGate"), (multi-)controlled [`PhaseGate`](qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate")s and [`iSwapGate`](qiskit.circuit.library.iSwapGate "qiskit.circuit.library.iSwapGate") in the wrong color. + +* The hash of a [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") is now equal to the hashes of any [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") that it compares equal to. Previously the hashes were different, which would cause spurious additional entries in hashmaps when [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") and [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") values were mixed in the same map as it violated Python’s data model. + +* Fixed a bug in QPY serialization ([`qiskit.qpy`](qpy#module-qiskit.qpy "qiskit.qpy")) where controlled unitary gates in a circuit could result would fail to deserialize. Fixed [#10802](https://github.com/Qiskit/qiskit-terra/issues/10802). + +* Fixes the implementation of [`random_statevector()`](quantum_info#qiskit.quantum_info.random_statevector "qiskit.quantum_info.random_statevector") so that it samples from the uniform distribution. + +* The pass [`NoiseAdaptiveLayout`](qiskit.transpiler.passes.NoiseAdaptiveLayout "qiskit.transpiler.passes.NoiseAdaptiveLayout") now takes [`CouplingMap`](qiskit.transpiler.CouplingMap "qiskit.transpiler.CouplingMap") as an optional argument. This is used by the plugin to control on inconsistency between [`configuration()`](qiskit.providers.BackendV1#configuration "qiskit.providers.BackendV1.configuration") and [`properties()`](qiskit.providers.BackendV1#properties "qiskit.providers.BackendV1.properties"), like in the case of [`FakeMelbourne`](qiskit.providers.fake_provider.FakeMelbourne "qiskit.providers.fake_provider.FakeMelbourne"). Fixed [#7677](https://github.com/Qiskit/qiskit-terra/issues/7677). + +* The methods [`QuantumCircuit.copy()`](qiskit.circuit.QuantumCircuit#copy "qiskit.circuit.QuantumCircuit.copy") and [`copy_empty_like()`](qiskit.circuit.QuantumCircuit#copy_empty_like "qiskit.circuit.QuantumCircuit.copy_empty_like") will now raise an error if the `name` argument is incorrectly typed, instead of generating an invalid circuit. + +* The `"decay"` heuristic of [`SabreSwap`](qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap") and [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") now tracks the depth correctly on physical qubits rather than mistakenly tracking the “depth” of swaps on virtual qubits. + +* Fixed an oversight in the [`ECRGate`](qiskit.circuit.library.ECRGate "qiskit.circuit.library.ECRGate") that prevented setting an [`ECRGate.label`](qiskit.circuit.library.ECRGate#label "qiskit.circuit.library.ECRGate.label") attribute at object construction time. All other [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") classes and subclasses enable setting a `label` keyword argument in the constructor. + +* Fixed an oversight in the [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") (and standard-library subclasses) constructor where the [`duration`](qiskit.circuit.Gate#duration "qiskit.circuit.Gate.duration") and [`unit`](qiskit.circuit.Gate#unit "qiskit.circuit.Gate.unit") attributes could not be set as keyword arguments during construction. The parent class [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") supported setting this but [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") was previously not exposing this interface correctly. + +* Added support to allow `SparsePauliOp` default initialization passing an empty iterable to the static methods [`from_list()`](qiskit.quantum_info.SparsePauliOp#from_list "qiskit.quantum_info.SparsePauliOp.from_list") and [`from_sparse_list()`](qiskit.quantum_info.SparsePauliOp#from_sparse_list "qiskit.quantum_info.SparsePauliOp.from_sparse_list"). Fixed [#10159](https://github.com/Qiskit/qiskit-terra/issues/10159). + + + + + +### Other Notes + +* This version of Qiskit is explicitly pinned to the Numpy 1.x series, because it includes compiled extensions that are not yet compiled against the as-yet-unreleased Numpy 2.x series. We will release a new version of Qiskit with Numpy 2.x support as soon as feasible. + + We cannot prevent your package manager from resolving to older versions of Qiskit (which do not have the same pin but are still likely to be incompatible) if you forcibly try to install Qiskit alongside Numpy 2, before we have released a compatible version. + + + + + +## 0.25.0rc1 + + + +### New Features + +* Added two new options to `BlockCollector`. + + The first new options `split_layers` allows to split the collected block into sub-blocks over disjoint qubit subsets, i.e. into depth-1 sub-blocks. + + The second new option `collect_from_back` allows to greedily collect blocks starting from the outputs of the circuit. This is important in combination with ALAP-scheduling passes where we may prefer to put gates in the later rather than earlier blocks. + +* Added new options `split_layers` and `collect_from_back` to `CollectLinearFunctions` and `CollectCliffords` transpiler passes. + + When `split_layers` is True, the collected blocks are split into into sub-blocks over disjoint qubit subsets, i.e. into depth-1 sub-blocks. Consider the following example: + + ```python + from qiskit.circuit import QuantumCircuit + from qiskit.transpiler.passes import CollectLinearFunctions + + circuit = QuantumCircuit(5) + circuit.cx(0, 2) + circuit.cx(1, 4) + circuit.cx(2, 0) + circuit.cx(0, 3) + circuit.swap(3, 2) + circuit.swap(4, 1) + + # Collect all linear gates, without splitting into layers + qct = CollectLinearFunctions(split_blocks=False, min_block_size=1, split_layers=False)(circuit) + assert qct.count_ops()["linear_function"] == 1 + + # Collect all linear gates, with splitting into layers + qct = CollectLinearFunctions(split_blocks=False, min_block_size=1, split_layers=True)(circuit) + assert qct.count_ops()["linear_function"] == 4 + ``` + + The original circuit is linear. When collecting linear gates without splitting into layers, we should end up with a single linear function. However, when collecting linear gates and splitting into layers, we should end up with 4 linear functions. + + When `collect_from_back` is True, the blocks are greedily collected from the outputs towards the inputs of the circuit. Consider the following example: + + ```python + from qiskit.circuit import QuantumCircuit + from qiskit.transpiler.passes import CollectLinearFunctions + + circuit = QuantumCircuit(3) + circuit.cx(1, 2) + circuit.cx(1, 0) + circuit.h(2) + circuit.swap(1, 2) + + # This combines the CX(1, 2) and CX(1, 0) gates into a single linear function + qct = CollectLinearFunctions(collect_from_back=False)(circuit) + + # This combines the CX(1, 0) and SWAP(1, 2) gates into a single linear function + qct = CollectLinearFunctions(collect_from_back=True)(circuit) + ``` + + The original circuit contains a Hadamard gate, so that the CX(1, 0) gate can be combined either with CX(1, 2) or with SWAP(1, 2), but not with both. When `collect_from_back` is False, the linear blocks are greedily collected from the start of the circuit, and thus CX(1, 0) is combined with CX(1, 2). When `collect_from_back` is True, the linear blocks are greedily collected from the end of the circuit, and thus CX(1, 0) is combined with SWAP(1, 2). + +* Added [`DAGCircuit.classical_predecessors()`](qiskit.dagcircuit.DAGCircuit#classical_predecessors "qiskit.dagcircuit.DAGCircuit.classical_predecessors") and [`DAGCircuit.classical_successors()`](qiskit.dagcircuit.DAGCircuit#classical_successors "qiskit.dagcircuit.DAGCircuit.classical_successors"), an alternative to select the classical wires without having to go to the inner graph object directly of a node in the DAG. The following example illustrates the new functionality: + + ```python + from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister + from qiskit.converters import circuit_to_dag + from qiskit.circuit.library import RZGate + + q = QuantumRegister(3, 'q') + c = ClassicalRegister(3, 'c') + circ = QuantumCircuit(q, c) + circ.h(q[0]) + circ.cx(q[0], q[1]) + circ.measure(q[0], c[0]) + circ.rz(0.5, q[1]).c_if(c, 2) + circ.measure(q[1], c[0]) + dag = circuit_to_dag(circ) + + rz_node = dag.op_nodes(RZGate)[0] + # Contains the "measure" on clbit 0, and the "wire start" nodes for clbits 1 and 2. + classical_predecessors = list(dag.classical_predecessors(rz_node)) + # Contains the "measure" on clbit 0, and the "wire end" nodes for clbits 1 and 2. + classical_successors = list(dag.classical_successors(rz_node)) + ``` + +* Enabled performing the [`qiskit.transpiler.passes.CommutativeCancellation`](qiskit.transpiler.passes.CommutativeCancellation "qiskit.transpiler.passes.CommutativeCancellation") pass inside the blocks of [`qiskit.circuit.ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp"). This pass reorders some commuting gates and reduces resulting pairs of self-inverse gates. Previously, the blocks in control flow operations were skipped by this pass. The new feature operates recursively, that is, it will act on control flow operations inside blocks. + +* Enabled performing the [`ConsolidateBlocks`](qiskit.transpiler.passes.ConsolidateBlocks "qiskit.transpiler.passes.ConsolidateBlocks") pass inside the blocks of [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp"). This pass collects several sequences of gates and replaces each sequence with the equivalent numeric unitary gate. This new feature enables applying this pass recursively to the blocks in control flow operations. Note that the meaning of “block” in [`ConsolidateBlocks`](qiskit.transpiler.passes.ConsolidateBlocks "qiskit.transpiler.passes.ConsolidateBlocks") is unrelated to that in [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp"). + +* Added [`DAGCircuit.quantum_causal_cone()`](qiskit.dagcircuit.DAGCircuit#quantum_causal_cone "qiskit.dagcircuit.DAGCircuit.quantum_causal_cone") to obtain the causal cone of a qubit in a [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit"). The following example shows its correct usage: + + ```python + from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister + from qiskit.circuit.library import CXGate, CZGate + from qiskit.dagcircuit import DAGCircuit + + # Build a DAGCircuit + dag = DAGCircuit() + qreg = QuantumRegister(5) + creg = ClassicalRegister(5) + dag.add_qreg(qreg) + dag.add_creg(creg) + dag.apply_operation_back(CXGate(), qreg[[1, 2]], []) + dag.apply_operation_back(CXGate(), qreg[[0, 3]], []) + dag.apply_operation_back(CZGate(), qreg[[1, 4]], []) + dag.apply_operation_back(CZGate(), qreg[[2, 4]], []) + dag.apply_operation_back(CXGate(), qreg[[3, 4]], []) + + # Get the causal cone of qubit at index 0 + result = dag.quantum_causal_cone(qreg[0]) + ``` + +* Added a new function , `negativity()` that adds support for calculating entanglement measures negativity of an quantum state. An illustrative example for using the above function is given below: + +* A new method, `find_bit()`, has been added to the `DagCircuit` class. This is a method to get mapping of Qubit and Clbit to positional index. The method takes a Bit as input, checks whether it’s a Qubit or a Clbit, and then returns the corresponding BitLocations from the respective index dictionary (\_qubit\_indices or \_clbit\_indices). The BitLocations is a namedtuple which includes the positional index of the bit in the circuit and a list of registers containing the bit. If the bit cannot be found or is of an unknown type, it raises a DAGCircuitError. + +* The transpiler’s built-in [`EquivalenceLibrary`](qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") has been taught the circular Pauli relations $X = iYZ$, $Y = iZX$ and $Z = iXY$. This should make transpiling to constrained, and potentially incomplete, basis sets more reliable. See [#10293](https://github.com/Qiskit/qiskit-terra/issues/10293) for more detail. + +* Add `schmidt_decomposition` function to the `quantum_info` module. This function works with the `Statevector` and `DensityMatrix` classes for bipartite pure states. + +* Control-flow operations are now supported through the transpiler at all optimization levels, including levels 2 and 3 (e.g. calling [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") or [`generate_preset_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager "qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager") with keyword argument `optimization_level=3`). + +* Added a new synthesis algorithm `qiskit.synthesis.linear_phase.synth_cx_cz_depth_line_my()` of a CX circuit followed by a CZ circuit for linear nearest neighbor (LNN) connectivity in 2-qubit depth of at most 5n using CX and phase gates (S, Sdg or Z). The synthesis algorithm is based on the paper of Maslov and Yang ([https://arxiv.org/abs/2210.16195](https://arxiv.org/abs/2210.16195)). The algorithm accepts a binary invertible matrix `mat_x` representing the CX-circuit, a binary symmetric matrix `mat_z` representing the CZ-circuit, and returns a quantum circuit with 2-qubit depth of at most 5n computing the composition of the CX and CZ circuits. The following example illustrates the new functionality: + + ```python + import numpy as np + from qiskit.synthesis.linear_phase import synth_cx_cz_depth_line_my + mat_x = np.array([[0, 1], [1, 1]]) + mat_z = np.array([[0, 1], [1, 0]]) + qc = synth_cx_cz_depth_line_my(mat_x, mat_z) + ``` + + This algorithm is now used by default in the Clifford synthesis algorithm `qiskit.synthesis.clifford.synth_clifford_depth_lnn()` that optimizes 2-qubit depth for LNN connectivity, improving the 2-qubit depth from 9n+4 to 7n+2. The clifford synthesis algorithm can be used as follows: + + ```python + from qiskit.quantum_info import random_clifford + from qiskit.synthesis import synth_clifford_depth_lnn + + cliff = random_clifford(3) + qc = synth_clifford_depth_lnn(cliff) + ``` + + The above synthesis can be further improved as described in the paper by Maslov and Yang, using local optimization between 2-qubit layers. This improvement is left for follow-up work. + +* [`DAGCircuit.substitute_node()`](qiskit.dagcircuit.DAGCircuit#substitute_node "qiskit.dagcircuit.DAGCircuit.substitute_node") gained a `propagate_condition` keyword argument that is analogous to the same argument in [`substitute_node_with_dag()`](qiskit.dagcircuit.DAGCircuit#substitute_node_with_dag "qiskit.dagcircuit.DAGCircuit.substitute_node_with_dag"). Setting this to `False` opts out of the legacy behaviour of copying a condition on the `node` onto the new `op` that is replacing it. + + This option is ignored for general control-flow operations, which will never propagate their condition, nor accept a condition from another node. + +* Introduced a new method, [`separable_circuits()`](qiskit.dagcircuit.DAGCircuit#separable_circuits "qiskit.dagcircuit.DAGCircuit.separable_circuits"), which returns a list of [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") objects, one for each set of connected qubits which have no gates connecting them to another set. + + Each [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") instance returned by this method will contain the same number of clbits as `self`. This method will not return [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") instances consisting solely of clbits. + +* The `SymbolicPulse` library was extended. The new pulses in the library are: + + > * [`GaussianDeriv()`](qiskit.pulse.library.GaussianDeriv "qiskit.pulse.library.GaussianDeriv") + > * [`Sech()`](qiskit.pulse.library.Sech_fun.rst#qiskit.pulse.library.Sech "qiskit.pulse.library.Sech") + > * [`SechDeriv()`](qiskit.pulse.library.SechDeriv "qiskit.pulse.library.SechDeriv") + > * [`Square()`](qiskit.pulse.library.Square_fun.rst#qiskit.pulse.library.Square "qiskit.pulse.library.Square") + + The new functions return a `ScalableSymbolicPulse`, and match the functionality of the corresponding functions in the discrete pulse library, with the exception of Square() for which a phase of $2\\pi$ shifts by a full cycle (contrary to the discrete square() where such a shift was induced by a $\\pi$ phase). + +* In `MatplotlibDrawer`, operations built from [`ControlFlowOp`](qiskit.circuit.ControlFlowOp "qiskit.circuit.ControlFlowOp"), including `if`, `else`, `while`, `for`, and `switch/case`, whether directly instantiated or built using methods in [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"), will now fully display the circuits defined in the ControlFlowOps wrapped with boxes to delineate the circuits. + +* Added [`concurrent_measurements`](qiskit.transpiler.Target#concurrent_measurements "qiskit.transpiler.Target.concurrent_measurements") which represents a hardware constraint of qubits measured concurrently. This constraint is provided in the nested list form, in which each element represents qubit group to be measured together. In an example below, + + ```python + [[0, 1], [2, 3, 4]] + ``` + + qubits 0 and 1, and 2, 3 and 4 are measured together on the device. This constraint doesn’t block measuring an individual qubit, however, Qiskit scheduler must consider the alignment of measure operations for those qubits. + +* The performance of [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") and [`bind_parameters()`](qiskit.circuit.QuantumCircuit#bind_parameters "qiskit.circuit.QuantumCircuit.bind_parameters") has significantly increased for large circuits with structures typical of applications uses. This includes most circuits based on the [`NLocal`](qiskit.circuit.library.NLocal "qiskit.circuit.library.NLocal") structure, such as [`EfficientSU2`](qiskit.circuit.library.EfficientSU2 "qiskit.circuit.library.EfficientSU2"). See [#10282](https://github.com/Qiskit/qiskit-terra/issues/10282) for more detail. + +* The method [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") has gained two new keywords arguments: `flat_input` and `strict`. These are advanced options that can be used to speed up the method when passing the parameter bindings as a dictionary; `flat_input=True` is a guarantee that the dictionary keys contain only [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") instances (not [`ParameterVector`](qiskit.circuit.ParameterVector "qiskit.circuit.ParameterVector")s), and `strict=False` allows the dictionary to contain parameters that are not present in the circuit. Using these two options can reduce the overhead of input normalisation in this function. + +* The method `filter()` is activated in the [`ScheduleBlock`](qiskit.pulse.ScheduleBlock "qiskit.pulse.schedule.ScheduleBlock") class. This method enables users to retain only `Instruction` objects which pass through all the provided filters. As builtin filter conditions, pulse [`Channel`](pulse#qiskit.pulse.channels.Channel "qiskit.pulse.channels.Channel") subclass instance and [`Instruction`](pulse#qiskit.pulse.instructions.Instruction "qiskit.pulse.instructions.Instruction") subclass type can be specified. User-defined callbacks taking [`Instruction`](pulse#qiskit.pulse.instructions.Instruction "qiskit.pulse.instructions.Instruction") instance can be added to the filters, too. + +* The method `exclude()` is activated in the [`ScheduleBlock`](qiskit.pulse.ScheduleBlock "qiskit.pulse.schedule.ScheduleBlock") class. This method enables users to retain only `Instruction` objects which do not pass at least one of all the provided filters. As builtin filter conditions, pulse [`Channel`](pulse#qiskit.pulse.channels.Channel "qiskit.pulse.channels.Channel") subclass instance and [`Instruction`](pulse#qiskit.pulse.instructions.Instruction "qiskit.pulse.instructions.Instruction") subclass type can be specified. User-defined callbacks taking [`Instruction`](pulse#qiskit.pulse.instructions.Instruction "qiskit.pulse.instructions.Instruction") instance can be added to the filters, too. This method is the complement of `filter()`, so the following condition is always satisfied: `block.filter(*filters) + block.exclude(*filters) == block` in terms of instructions included, where `block` is a [`ScheduleBlock`](qiskit.pulse.ScheduleBlock "qiskit.pulse.schedule.ScheduleBlock") instance. + +* The transpiler pass `SetLayout` now is able to be constructed with a list of integers that represent the physical qubits on which the quantum circuit will be mapped on. That is, the first qubit in the circuit will be allocated in the physical qubit in the position zero of the list, and so on. + +* Added a new keyword argument `flatten` to the constructor for the following classes: + + > * [`EfficientSU2`](qiskit.circuit.library.EfficientSU2 "qiskit.circuit.library.EfficientSU2") + > * [`ExcitationPreserving`](qiskit.circuit.library.ExcitationPreserving "qiskit.circuit.library.ExcitationPreserving") + > * [`NLocal`](qiskit.circuit.library.NLocal "qiskit.circuit.library.NLocal") + > * [`RealAmplitudes`](qiskit.circuit.library.RealAmplitudes "qiskit.circuit.library.RealAmplitudes") + > * [`TwoLocal`](qiskit.circuit.library.TwoLocal "qiskit.circuit.library.TwoLocal") + > * [`EvolvedOperatorAnsatz`](qiskit.circuit.library.EvolvedOperatorAnsatz "qiskit.circuit.library.EvolvedOperatorAnsatz") + > * [`QAOAAnsatz`](qiskit.circuit.library.QAOAAnsatz "qiskit.circuit.library.QAOAAnsatz") + + If this argument is set to `True` the [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") subclass generated will not wrap the implementation into [`Gate`](qiskit.circuit.Gate "qiskit.circuit.Gate") or [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") objects. While this isn’t optimal for visualization it typically results in much better runtime performance, especially with [`QuantumCircuit.bind_parameters()`](qiskit.circuit.QuantumCircuit#bind_parameters "qiskit.circuit.QuantumCircuit.bind_parameters") and [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") which can see a substatial runtime improvement with a flattened output compared to the nested wrapped default output. + +* Add new `gaussian_square_echo()` pulse shape. This pulse is composed by three `GaussianSquare` pulses. The first two are echo pulses with duration half of the total duration and implement rotary tones. The third pulse is a cancellation tone that lasts the full duration of the pulse and implements correcting single qubit rotations. + +* A new lazy import tester, [`HAS_PYGMENTS`](utils#qiskit.utils.optionals.HAS_PYGMENTS "qiskit.utils.optionals.HAS_PYGMENTS"), is available for testing for the presence of [the Pygments syntax highlighting library](https://pygments.org/). + +* Allowing to construct a [`LinearFunction`](qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction") object from more general quantum circuits, that may contain: + + > * Barriers (of type `Barrier`) and delays ([`Delay`](qiskit.circuit.Delay "qiskit.circuit.Delay")), which are simply ignored + > * Permutations (of type [`PermutationGate`](qiskit.circuit.library.PermutationGate "qiskit.circuit.library.PermutationGate")) + > * Other linear functions + > * Cliffords (of type [`Clifford`](qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford")), when the Clifford represents a linear function (and a `CircuitError` exception is raised if not) + > * Nested quantum circuits of this form + +* Added `LinearFunction.__eq__()` method. Two objects of type [`LinearFunction`](qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction") are considered equal when their representations as binary invertible matrices are equal. + +* Added [`LinearFunction.extend_with_identity()`](qiskit.circuit.library.LinearFunction#extend_with_identity "qiskit.circuit.library.LinearFunction.extend_with_identity") method, which allows to extend a linear function over `k` qubits to a linear function over `n >= k` qubits, specifying the new positions of the original qubits and padding with identities on the remaining qubits. + +* Added two methods for pretty-printing [`LinearFunction`](qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction") objects: [`LinearFunction.mat_str()`](qiskit.circuit.library.LinearFunction#mat_str "qiskit.circuit.library.LinearFunction.mat_str"), which returns the string representation of the linear function viewed as a matrix with 0/1 entries, and [`LinearFunction.function_str()`](qiskit.circuit.library.LinearFunction#function_str "qiskit.circuit.library.LinearFunction.function_str"), which returns the string representation of the linear function viewed as a linear transformation. + +* The instructions [`StatePreparation`](qiskit.circuit.library.StatePreparation "qiskit.circuit.library.StatePreparation") and `Initialize`, and their associated circuit methods [`QuantumCircuit.prepare_state()`](qiskit.circuit.QuantumCircuit#prepare_state "qiskit.circuit.QuantumCircuit.prepare_state") and [`initialize()`](qiskit.circuit.QuantumCircuit#initialize "qiskit.circuit.QuantumCircuit.initialize"), gained a keyword argument `normalize`, which can be set to `True` to automatically normalize an array target. By default this is `False`, which retains the current behaviour of raising an exception when given non-normalized input. + +* Added utility function `qiskit.transpiler.passes.utils._block_to_matrix()` that can generate a matrix based on a block of operations between two qubits. This function can be used in transpiler passes that work on some decomposed circuits such as [`ConsolidateBlocks`](qiskit.transpiler.passes.ConsolidateBlocks "qiskit.transpiler.passes.ConsolidateBlocks"). + +* The transpiler’s built-in [`EquivalenceLibrary`](qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") has been taught more Pauli-rotation equivalences between the one-qubit $R_X$, $R_Y$ and $R_Z$ gates, and between the two-qubit $R_{XX}$, $R_{YY}$ and $R_{ZZ}$ gates. This should make simple basis translations more reliable, especially circuits that use $Y$ rotations. See [#7332](https://github.com/Qiskit/qiskit-terra/issues/7332). + +* The OpenQASM 3 exporters ([`qasm3.dump()`](qasm3#qiskit.qasm3.dump "qiskit.qasm3.dump"), [`dumps()`](qasm3#qiskit.qasm3.dumps "qiskit.qasm3.dumps") and [`Exporter`](qasm3#qiskit.qasm3.Exporter "qiskit.qasm3.Exporter")) have a new `allow_aliasing` argument, which will eventually replace the `alias_classical_registers` argument. This controls whether aliasing is permitted for either classical bits or qubits, rather than the option only being available for classical bits. + +* QPY supports the `Discriminator` and `Kernel` objects. This feature enables users to serialize and deserialize the [`Acquire`](qiskit.pulse.instructions.Acquire "qiskit.pulse.instructions.Acquire") instructions with these objects using QPY. + +* Some restrictions when using `wire_order` in the circuit drawers had been relaxed. Now, `wire_order` can list just qubits and, in that case, it can be used with `cregbundle=True`, since it will not affect the classical bits. + + ```python + from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister + + qr = QuantumRegister(4, "q") + cr = ClassicalRegister(4, "c") + cr2 = ClassicalRegister(2, "ca") + circuit = QuantumCircuit(qr, cr, cr2) + circuit.h(0) + circuit.h(3) + circuit.x(1) + circuit.x(3).c_if(cr, 10) + circuit.draw('text', wire_order=[2, 3, 0, 1], cregbundle=True) + ``` + + ```python + q_2: ──────────── + ┌───┐ ┌───┐ + q_3: ┤ H ├─┤ X ├─ + ├───┤ └─╥─┘ + q_0: ┤ H ├───╫─── + ├───┤ ║ + q_1: ┤ X ├───╫─── + └───┘┌──╨──┐ + c: 4/═════╡ 0xa ╞ + └─────┘ + ca: 2/════════════ + ``` + +* Control-flow operations are now supported by the Sabre family of transpiler passes, namely layout pass [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") and routing pass [`SabreSwap`](qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap"). Function [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") keyword arguments `layout_method` and `routing_method` now accept the option “sabre” for circuits with control flow, which was previously unsupported. + +* Adds support for multiplication of [`SparsePauliOp`](qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp") objects with [`Parameter`](qiskit.circuit.Parameter "qiskit.circuit.Parameter") objects by using the \* operator, for example: + + ```python + from qiskit.circuit import Parameter + from qiskit.quantum_info import SparsePauliOp + + param = Parameter("a") + op = SparsePauliOp("X") + param * op + ``` + +* Added the option to pass a callback to the [`UMDA`](qiskit.algorithms.optimizers.UMDA "qiskit.algorithms.optimizers.UMDA") optimizer, which allows to keep track of the number of function evaluations, the current parameters, and the best achieved function value. + + + + + +### Transpiler Features + +* A new [`qiskit.passmanager`](passmanager#module-qiskit.passmanager "qiskit.passmanager") module has been added to the Qiskit library. This module implements a generic pass manager and flow controllers, and provides infrastructure to manage execution of pass manager tasks. The module provides base classes for passes ([`GenericPass`](qiskit.passmanager.GenericPass "qiskit.passmanager.GenericPass")) and flow controllers ([`BaseController`](qiskit.passmanager.BaseController "qiskit.passmanager.BaseController")), as well as a new interface class, `passmanager.Task`, to manage the execution of the pass manager (see the `Task.execute()` method). These new classes follow the composite pattern, as flow controllers are collections of passes, and a controller can be recursively nested into the task pipeline. It must also be noted the base classes are not not aware of the input and output object types, and they must be subclassed for a particular program type to optimize. This unified design reduces the complexity of the conventional pass manager, and no longer requires the use of classes such as the `RunningPassManager` to handle the execution logic dispatch and task structure renormalization. The [`qiskit.transpiler`](transpiler#module-qiskit.transpiler "qiskit.transpiler") module has been reorganized to rebuild the existing pass managers based off of the generic pass manager. See upgrade notes for more details. + + + +### Known Issues + +* Added support for taking absolute values of [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression")s. For example, the following is now possible: + + ```python + from qiskit.circuit import QuantumCircuit, Parameter + + x = Parameter("x") + circuit = QuantumCircuit(1) + circuit.rx(abs(x), 0) + + bound = circuit.bind_parameters({x: -1}) + ``` + + + +### Upgrade Notes + +* Changed [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") to bind assigned integer and float values directly into the parameters of [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") instances in the circuit rather than binding the values wrapped within a [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression"). This change should have little user impact as `float(QuantumCircuit.data[i].operation.params[j])` still produces a `float` (and is the only way to access the value of a [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression")). Also, [`Instruction()`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") parameters could already be `float` as well as a [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression"), so code dealing with instruction parameters should already handle both cases. The most likely chance for user impact is in code that uses `isinstance` to check for [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") and behaves differently depending on the result. Additionally, qpy serializes the numeric value in a bound [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") at a different precision than a `float` (see also the related bug fix note about [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters")). + +* [`Clifford.from_circuit()`](qiskit.quantum_info.Clifford#from_circuit "qiskit.quantum_info.Clifford.from_circuit") will no longer attempt to resolve instructions whose [`definition`](qiskit.circuit.Instruction#definition "qiskit.circuit.Instruction.definition") fields are mutually recursive with some other object. Such recursive definitions are already a violation of the strictly hierarchical ordering that the [`definition`](qiskit.circuit.Instruction#definition "qiskit.circuit.Instruction.definition") field requires, and code should not rely on this being possible at all. If you want to define equivalences that are permitted to have (mutual) cycles, use an [`EquivalenceLibrary`](qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary"). + +* Qiskit Terra 0.25 has dropped support for Python 3.7 following deprecation warnings started in Qiskit Terra 0.23. This is consistent with Python 3.7’s end-of-life on the 27th of June, 2023. To continue using Qiskit, you must upgrade to a more recent version of Python. + +* The OpenQASM 2 constructor methods on [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") ([`from_qasm_str()`](qiskit.circuit.QuantumCircuit#from_qasm_str "qiskit.circuit.QuantumCircuit.from_qasm_str") and [`from_qasm_file()`](qiskit.circuit.QuantumCircuit#from_qasm_file "qiskit.circuit.QuantumCircuit.from_qasm_file")) have been switched to use the Rust-based parser added in Qiskit Terra 0.24. This should result in significantly faster parsing times (10 times or more is not uncommon) and massively reduced intermediate memory usage. + + The [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") methods are kept with the same interface for continuity; the preferred way to access the OpenQASM 2 importer is to use [`qasm2.load()`](qasm2#qiskit.qasm2.load "qiskit.qasm2.load") and [`qasm2.loads()`](qasm2#qiskit.qasm2.loads "qiskit.qasm2.loads"), which offer an expanded interface to control the parsing and construction. + +* The maximum number of trials evaluated when searching for the best layout using [`VF2Layout`](qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") and [`VF2PostLayout`](qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") is now limited in [`qiskit.transpiler.preset_passmanagers.level_1_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.level_1_pass_manager "qiskit.transpiler.preset_passmanagers.level_1_pass_manager"), [`qiskit.transpiler.preset_passmanagers.level_2_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.level_2_pass_manager "qiskit.transpiler.preset_passmanagers.level_2_pass_manager"), and [`qiskit.transpiler.preset_passmanagers.level_3_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.level_3_pass_manager "qiskit.transpiler.preset_passmanagers.level_3_pass_manager") to `2,500`, `25,000`, and `250,000`, respectively. Previously, all possible layouts were evaluated. This change was made to prevent transpilation from hanging during layout scoring for circuits with many connected components on larger devices, which scales combinatorially since each connected component must be evaluated in all possible positions on the device. To perform a full search as before, manually run [`VF2PostLayout`](qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") over the transpiled circuit in strict mode, specifying `0` for `max_trials`. + +* The OpenQASM 3 exporters ([`qasm3.dump()`](qasm3#qiskit.qasm3.dump "qiskit.qasm3.dump"), [`dumps()`](qasm3#qiskit.qasm3.dumps "qiskit.qasm3.dumps") and [`Exporter`](qasm3#qiskit.qasm3.Exporter "qiskit.qasm3.Exporter")) will now use fewer “register alias” definitions in its output. The circuit described will not change, but it will now preferentially export in terms of direct `bit`, `qubit` and `qubit[n]` types rather than producing a `_loose_bits` register and aliasing more registers off this. This is done to minimise the number of advanced OpenQASM 3 features in use, and to avoid introducing unnecessary array structure into programmes that do not require it. + +* The QPY format version emitted by `dump` has increased to 8. This new format version adds support for serializing the [`QuantumCircuit.layout`](qiskit.circuit.QuantumCircuit#layout "qiskit.circuit.QuantumCircuit.layout") attribute. + +* The deprecated `circuit_cregs` argument to the constructor for the [`InstructionSet`](qiskit.circuit.InstructionSet "qiskit.circuit.InstructionSet") class has been removed. It was deprecated in the 0.19.0 release. If you were using this argument and manually constructing an [`InstructionSet`](qiskit.circuit.InstructionSet "qiskit.circuit.InstructionSet") object (which should be quite uncommon as it’s mostly used internally) you should pass a callable to the `resource_requester` keyword argument instead. For example: + + ```python + from qiskit.circuit import Clbit, ClassicalRegister, InstructionSet + from qiskit.circuit.exceptions import CircuitError + + def my_requester(bits, registers): + bits_set = set(bits) + bits_flat = tuple(bits) + registers_set = set(registers) + + def requester(specifier): + if isinstance(specifer, Clbit) and specifier in bits_set: + return specifier + if isinstance(specifer, ClassicalRegster) and specifier in register_set: + return specifier + if isinstance(specifier, int) and 0 <= specifier < len(bits_flat): + return bits_flat[specifier] + raise CircuitError(f"Unknown resource: {specifier}") + + return requester + + my_bits = [Clbit() for _ in [None]*5] + my_registers = [ClassicalRegister(n) for n in range(3)] + + InstructionSet(resource_requester=my_requester(my_bits, my_registers)) + ``` + +* In the internal `qiskit.visualization.circuit.matplotlib.MatplotlibDrawer` object, the arguments `layout`, `global_phase`, `qregs` and `cregs` have been removed. They were originally deprecated in Qiskit Terra 0.20. These objects are simply inferred from the given `circuit` now. + + This is an internal worker class of the visualization routines. It is unlikely you will need to change any of your code. + +* Support for passing in lists of argument values to the [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") function is removed. This functionality was deprecated as part of the 0.23.0 release and is now being removed. You are still able to pass in a list of [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") objects for the first positional argument, what has been removed is the broadcasting lists of the other arguments to each circuit in that input list. Removing this functionality was necessary to greatly reduce the overhead for parallel execution for transpiling multiple circuits at once. If you’re using this functionality currently you can call [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") multiple times instead. For example if you were previously doing something like: + + ```python + from qiskit.transpiler import CouplingMap + from qiskit import QuantumCircuit + from qiskit import transpile + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0, 1) + qc.measure_all() + + cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)] + results = transpile([qc] * 6, coupling_map=cmaps) + ``` + + instead you should now run something like: + + ```python + from qiskit.transpiler import CouplingMap + from qiskit import QuantumCircuit + from qiskit import transpile + + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0, 1) + qc.measure_all() + + cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)] + results = [transpile(qc, coupling_map=cm) for cm in cmap] + ``` + + You can also leverage [`parallel_map()`](tools#qiskit.tools.parallel_map "qiskit.tools.parallel_map") or `multiprocessing` from the Python standard library if you want to run this in parallel. + +* The `qiskit.util` import location has been removed, as it had been deprecated since Qiskit Terra 0.17. Users should use the new import location, `qiskit.utils`. + +* The Sabre family of transpiler passes (namely [`SabreLayout`](qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") and [`SabreSwap`](qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap")) are now used by default for all circuits when invoking the transpiler at optimization level 1 (e.g. calling [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") or [`generate_preset_pass_manager()`](transpiler_preset#qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager "qiskit.transpiler.preset_passmanagers.generate_preset_pass_manager") with keyword argument `optimization_level=1`). Previously, circuits with control flow operations used [`DenseLayout`](qiskit.transpiler.passes.DenseLayout "qiskit.transpiler.passes.DenseLayout") and [`StochasticSwap`](qiskit.transpiler.passes.StochasticSwap "qiskit.transpiler.passes.StochasticSwap") with this profile. + +* The `map()` has been modified to use the new `rustworkx` version of `graph_token_swapper()` for performance reasons. Qiskit Terra 0.25 now requires versison 0.13.0 of `rustworkx`. + +* By default Qiskit builds its compiled extensions using the [Python Stable ABI](https://docs.python.org/3/c-api/stable.html) with support back to the oldest version of Python supported by Qiskit (currently 3.8). This means that moving forward there will be a single precompiled wheels that are shipped on release that works with all of Qiskit’s supported Python versions. There isn’t any expected runtime performance difference using the limited API so it is enabled by default for all builds now. Previously, the compiled extensions were built using the version specific API and would only work with a single Python version. This change was made to reduce the number of package files we need to build and publish in each release. When building Qiskit from source there should be no changes necessary to the build process except that the default tags in the output filenames will be different to reflect the use of the limited API. + + + + + +### Transpiler Upgrade Notes + +* As a consequence of the pass manager refactoring efforts, existing flow controllers: [`FlowControllerLinear`](qiskit.passmanager.FlowControllerLinear "qiskit.passmanager.FlowControllerLinear"), [`ConditionalController`](qiskit.passmanager.ConditionalController "qiskit.passmanager.ConditionalController"), and [`DoWhileController`](qiskit.passmanager.DoWhileController "qiskit.passmanager.DoWhileController") are now subclasses of the [`BaseController`](qiskit.passmanager.BaseController "qiskit.passmanager.BaseController"). Note that these controllers have dropped the implementation of the [`__iter__()`](https://docs.python.org/3/reference/datamodel.html#object.__iter__ "(in Python v3.12)") method. They are now only iterable in the context of a flow-controller execution, which threads the compilation state through after each inner task is executed. + +* The functionalitly of the `RunningPassManager` class has been superseded by the new pass manager framework ([`BasePassManager`](qiskit.passmanager.BasePassManager "qiskit.passmanager.BasePassManager") and [`BaseController`](qiskit.passmanager.BaseController "qiskit.passmanager.BaseController")). The running pass manager is now a stateless flow controller (essentially, an alias of [`FlowControllerLinear`](qiskit.passmanager.FlowControllerLinear "qiskit.passmanager.FlowControllerLinear")), as the pass manager is responsible for the construction of task pipeline, while the controller is responsible for the execution of associated tasks. Subclassing the `RunningPassManager` is no longer recommended, and this class will be completely replaced with the flow controller in future releases. + +* A new class, [`WorkflowStatus`](qiskit.passmanager.WorkflowStatus "qiskit.passmanager.WorkflowStatus"), has been introduced to track the status of the pass manager workflow. This portable object is created when the pass manager is run, and handed over to the underlying tasks. Such status was previously managed by the `RunningPassManager` with instance variables. + +* The transpiler-specific [`transpiler.PassManager`](qiskit.transpiler.PassManager "qiskit.transpiler.PassManager") (used in [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile")) is now a subclass of [`passmanager.BasePassManager`](qiskit.passmanager.BasePassManager "qiskit.passmanager.BasePassManager"). However, this class hierarchy change doesn’t introduce any breaking change to the public-facing API. + +* Exceptions raised during pass-manager execution now inherit from the newly introduced [`PassManagerError`](passmanager#qiskit.passmanager.PassManagerError "qiskit.passmanager.PassManagerError"). A generic failure of the pass-manager machinery will raise [`PassManagerError`](passmanager#qiskit.passmanager.PassManagerError "qiskit.passmanager.PassManagerError") for general pass managers, but the transpiler-specific `transpile.PassManager` will currently wrap this in its specific [`TranspilerError`](transpiler#qiskit.transpiler.TranspilerError "qiskit.transpiler.TranspilerError") for backwards compatibility. This wrapping will be removed in the future. + +* The use of `FencedObject` in the pass manager framework has been removed. This wrapper class cannot protect mutable object attributes from modification, and this should not be an issue for properly implemented code. Analysis passes should not modify an input IR, controllers should not update the property set, and so forth. It’s the pass manager developer’s responsibility to ensure that the pass is not modifying object attributes, + + + + + +### Misc. Upgrade Notes + +* The magic `%qiskit_version_table` from `qiskit.tools.jupyter` and the deprecated `qiskit.__qiskit_version__` do not include qiskit-terra anymore. Now that Qiskit Terra is called Qiskit, these entries are not needed anymore and you can just refer to the `qiskit` entry. + + + +### Deprecation Notes + +* The [`qiskit.algorithms`](algorithms#module-qiskit.algorithms "qiskit.algorithms") module has been deprecated and will be removed in a future release. It has been superseded by a new standalone library `qiskit-algorithms` which can be found on PyPi or on Github here: + + [https://github.com/qiskit-community/qiskit-algorithms](https://github.com/qiskit-community/qiskit-algorithms) + + The [`qiskit.algorithms`](algorithms#module-qiskit.algorithms "qiskit.algorithms") will continue to work as before and bug fixes will be made to module until its future removal, but active development of new features has moved to the new package. If you’re relying on [`qiskit.algorithms`](algorithms#module-qiskit.algorithms "qiskit.algorithms") you should update your requirements to also include `qiskit-algorithms` and update the imports from `qiskit.algorithms` to `qiskit_algorithms`. Please note that this new package does not include already deprecated algorithms code, including `opflow` and `QuantumInstance`-based algorithms. If you have not yet migrated from `QuantumInstance`-based to primitives-based algorithms, you should follow the migration guidelines in [https://qisk.it/algo\_migration](https://qisk.it/algo_migration). The decision to migrate the [`algorithms`](algorithms#module-qiskit.algorithms "qiskit.algorithms") module to a separate package was made to clarify the purpose Qiskit and make a distinction between the tools and libraries built on top of it. + +* The Jupyter magic `%circuit_library_info` and the objects in `qiskit.tools.jupyter.library` it calls in turn: + + * `circuit_data_table` + * `properties_widget` + * `qasm_widget` + * `circuit_digram_widget` + * `circuit_library_widget` + + are deprecated and will be removed in Terra 0.27. These objects were only intended for use in the documentation build. They are no longer used there, so are no longer supported or maintained. + +* Initializing a `ScalableSymbolicPulse` with complex amp value is now deprecated. This change also affects the following library pulses: + + > * [`Gaussian`](qiskit.pulse.library.Gaussian_class.rst#qiskit.pulse.library.Gaussian "qiskit.pulse.library.Gaussian") + > * [`GaussianSquare`](qiskit.pulse.library.GaussianSquare "qiskit.pulse.library.GaussianSquare") + > * [`Drag`](qiskit.pulse.library.Drag_class.rst#qiskit.pulse.library.Drag "qiskit.pulse.library.Drag") + > * [`Constant`](qiskit.pulse.library.Constant_class.rst#qiskit.pulse.library.Constant "qiskit.pulse.library.Constant") + + Initializing them with complex amp is now deprecated as well. + + Instead, one should use two floats for the amp and angle parameters, where amp represents the magnitude of the complex amplitude, and angle represents the angle of the complex amplitude. i.e. the complex amplitude is given by amp \* exp(1j \* angle). + +* The function `get_vf2_call_limit` available via the module `qiskit.transpiler.preset_passmanagers.common` has been deprecated. This will likely affect very few users since this function was neither explicitly exported nor documented. Its functionality has been replaced and extended by a function in the same module. + +* The method [`qasm()`](qiskit.circuit.Instruction#qasm "qiskit.circuit.Instruction.qasm") and all overriding methods of subclasses of :meth:\`\~qiskit.circuit.Instruction are deprecated. There is no replacement for generating an OpenQASM 2 string for an isolated instruction. + +* Extensions of the `qiskit` and `qiskit.providers` namespaces by external packages are now deprecated and the hook points enabling this will be removed in a future release. In the past, the Qiskit project was composed of elements that extended a shared namespace and these hook points enabled doing that. However, it was not intended for these interfaces to ever be used by other packages. Now that the overall Qiskit package is no longer using that packaging model, leaving the possibility for these extensions carry more risk than benefits and is therefore being deprecated for future removal. If you’re maintaining a package that extends the Qiskit namespace (i.e. your users import from `qiskit.x` or `qiskit.providers.y`) you should transition to using a standalone Python namespace for your package. No warning will be raised as part of this because there is no method to inject a warning at the packaging level that would be required to warn external packages of this change. + +* The [`Call`](qiskit.pulse.instructions.Call "qiskit.pulse.instructions.Call") has been deprecated and will be removed in a future release. Instead, use the [pulse builder](https://qiskit.org/documentation/tutorials/circuits_advanced/06_building_pulse_schedules.html) function [`call()`](pulse#qiskit.pulse.builder.call "qiskit.pulse.builder.call") within an active building context. + + + + + +### Transpiler Deprecations + +* The flow controller factory method [`FlowController.controller_factory()`](qiskit.passmanager.FlowController#controller_factory "qiskit.passmanager.FlowController.controller_factory") is deprecated along with [`FlowController.add_flow_controller()`](qiskit.passmanager.FlowController#add_flow_controller "qiskit.passmanager.FlowController.add_flow_controller") and [`FlowController.remove_flow_controller()`](qiskit.passmanager.FlowController#remove_flow_controller "qiskit.passmanager.FlowController.remove_flow_controller"). In the future, task construction with keyword arguments in the [`BasePassManager.append()`](qiskit.passmanager.BasePassManager#append "qiskit.passmanager.BasePassManager.append") method will also be deprecated. Controllers must be explicitly instantiated and appended to the pass manager. For example, the previously used conventional syntax + + ```python + pm.append([task1, task2], condition=lambda x: x["value1"] > 10) + ``` + + must be replaced with + + ```python + controller = ConditionalController([task1, task2], condition=lambda x: x["value1"] > 10) + pm.append(controller) + ``` + + The latter allows more precise control on the order of controllers especially when multiple keyword arguments are specified together, and allows for the construction of general flow controllers that may have more than one pipeline or do not take a single simple conditional function in their constructors. + +* The [`FlowControllerLinear.append()`](qiskit.passmanager.FlowControllerLinear#append "qiskit.passmanager.FlowControllerLinear.append"), [`DoWhileController.append()`](qiskit.passmanager.DoWhileController#append "qiskit.passmanager.DoWhileController.append"), and [`ConditionalController.append()`](qiskit.passmanager.ConditionalController#append "qiskit.passmanager.ConditionalController.append") methods are all deprecated immediately. The construction of the pass manager task pipeline is now the role of [`BasePassManager`](qiskit.passmanager.BasePassManager "qiskit.passmanager.BasePassManager"), and individual flow controllers do not need to this method. For a flow controller, all the passes should be specificed in one go directly to the constructor. + +* The general attribute and variable name `passes` is replaced with `tasks` all over the [`qiskit.passmanager`](passmanager#module-qiskit.passmanager "qiskit.passmanager") module. Note that a task must indicate a union of pass and controller, and the singular form pass conflicts with the Python keyword. In this sense, the use of tasks is much preferable. + + + + + +### Bug Fixes + +* Updated [`plot_gate_map()`](qiskit.visualization.plot_gate_map "qiskit.visualization.plot_gate_map"), [`plot_error_map()`](qiskit.visualization.plot_error_map "qiskit.visualization.plot_error_map"), and [`plot_circuit_layout()`](qiskit.visualization.plot_circuit_layout "qiskit.visualization.plot_circuit_layout") to support 433 qubit heavy-hex coupling maps. This allows coupling map visualizations for IBM’s `ibm_seattle`. + +* Fixed the deserialization of [`DiagonalGate`](qiskit.circuit.library.DiagonalGate "qiskit.circuit.library.DiagonalGate") instances through QPY. See [#10364](https://github.com/Qiskit/qiskit-terra/issues/10364). + +* Fixed an issue with [`FullAncillaAllocation`](qiskit.transpiler.passes.FullAncillaAllocation "qiskit.transpiler.passes.FullAncillaAllocation") so it can now function with [`Target`](qiskit.transpiler.Target "qiskit.transpiler.Target") objects that do not have a coupling map (typically because there are no 2 qubit gates in the [`Target`](qiskit.transpiler.Target "qiskit.transpiler.Target")). In this case [`FullAncillaAllocation`](qiskit.transpiler.passes.FullAncillaAllocation "qiskit.transpiler.passes.FullAncillaAllocation") will add ancilla qubits so that the number of qubits in the [`DAGCircuit`](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") matches the number [`Target.num_qubits`](qiskit.transpiler.Target#num_qubits "qiskit.transpiler.Target.num_qubits"). + +* Changed the binding of numeric values with [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") to avoid a mismatch between the values of circuit instruction parameters and corresponding parameter keys in the circuit’s calibration dictionary. Fixed [#9764](https://github.com/Qiskit/qiskit-terra/issues/9764) and [#10166](https://github.com/Qiskit/qiskit-terra/issues/10166). See also the related upgrade note regarding [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters"). + +* [`DAGCircuit.substitute_node()`](qiskit.dagcircuit.DAGCircuit#substitute_node "qiskit.dagcircuit.DAGCircuit.substitute_node") will no longer silently overwrite an existing condition on the given replacement `op`. If `propagate_condition` is set to `True` (the default), a [`DAGCircuitError`](dagcircuit#qiskit.dagcircuit.DAGCircuitError "qiskit.dagcircuit.DAGCircuitError") will be raised instead. + +* A parametrised circuit that contains a custom gate whose definition has a parametrised global phase can now successfully bind the parameter in the inner global phase. See [#10283](https://github.com/Qiskit/qiskit-terra/issues/10283) for more detail. + +* Construction of a [`Statevector`](qiskit.quantum_info.Statevector "qiskit.quantum_info.Statevector") from a [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") containing zero-qubit operations will no longer raise an error. These operations impart a global phase on the resulting statevector. + +* When `qs_decomposition()`, which does quantum Shannon decomposition, was called on trivial numeric unitaries that do not benefit from this decomposition, an unexpected error was raised. With this fix, such unitaries are detected and the equivalent circuit is returned without performing Shannon decomposition. + +* Fixes a typo where BasicSwap called `fake_run()` the attribute instead of `_fake_run()` the function. Refer to #10149 \ for more details. + +* Fixed an issue with copying circuits with new-style [`Clbit`](qiskit.circuit.Clbit "qiskit.circuit.Clbit")s and [`Qubit`](qiskit.circuit.Qubit "qiskit.circuit.Qubit")s (bits without registers) where references to these bits from the containing circuit could be broken, causing issues with serialization and circuit visualization. + +* The [`CheckMap`](qiskit.transpiler.passes.CheckMap "qiskit.transpiler.passes.CheckMap") transpiler pass will no longer spuriously error when dealing with nested conditional structures created by the control-flow builder interface. See [#10394](https://github.com/Qiskit/qiskit-terra/issues/10394). + +* Fixed a bug in `BlockCollapser` where classical bits were ignored when collapsing a block of nodes. + +* Fixed a bug in [`replace_block_with_op()`](qiskit.dagcircuit.DAGCircuit#replace_block_with_op "qiskit.dagcircuit.DAGCircuit.replace_block_with_op") and [`replace_block_with_op()`](qiskit.dagcircuit.DAGDependency#replace_block_with_op "qiskit.dagcircuit.DAGDependency.replace_block_with_op") that led to ignoring classical bits. + +* Fixed a bug in [`QuantumCircuit.compose()`](qiskit.circuit.QuantumCircuit#compose "qiskit.circuit.QuantumCircuit.compose") where the `SwitchCaseOp.target` attribute in the subcircuit would not get mapped to a register in the base circuit correctly. + +* The control-flow builder interface will now correctly include [`ClassicalRegister`](qiskit.circuit.ClassicalRegister "qiskit.circuit.ClassicalRegister") resources from nested switch statements in their containing circuit scopes. See [#10398](https://github.com/Qiskit/qiskit-terra/issues/10398). + +* Fixed an issue in the `QuantumCircuit.decompose()` method where passing a circuit name to the function that matched a composite gate name would not decompose the gate if it had a label assigned to it as well. Fixed [#9136](https://github.com/Qiskit/qiskit-terra/issues/9136) + +* Fixed an issue in tranpiler passes for padding delays, which did not respect target’s constraints and inserted delays even for qubits not supporting [`Delay`](qiskit.circuit.Delay "qiskit.circuit.Delay") instruction. [`PadDelay`](qiskit.transpiler.passes.PadDelay "qiskit.transpiler.passes.PadDelay") and [`PadDynamicalDecoupling`](qiskit.transpiler.passes.PadDynamicalDecoupling "qiskit.transpiler.passes.PadDynamicalDecoupling") are fixed so that they do not pad any idle time of qubits such that the target does not support `Delay` instructions for the qubits. Also legacy scheduling passes `ASAPSchedule` and `ALAPSchedule`, which pad delays internally, are fixed in the same way. In addition, `transpile()` is fixed to call `PadDelay` with a `target` object so that it works correctly when called with `scheduling_method` option. Fixed [#9993](https://github.com/Qiskit/qiskit-terra/issues/9993) + +* Fixed an failure of the pulse builder when the context is initialized with [`BackendV2`](qiskit.providers.BackendV2 "qiskit.providers.BackendV2"). + +* Fix a bug in [`RZXCalibrationBuilder`](qiskit.transpiler.passes.RZXCalibrationBuilder "qiskit.transpiler.passes.RZXCalibrationBuilder") where calling calibration with wrong parameters would crash instead of raising exception. + +* Fixed an issue with the [`BooleanExpression.from_dimacs_file()`](qiskit.circuit.classicalfunction.BooleanExpression#from_dimacs_file "qiskit.circuit.classicalfunction.BooleanExpression.from_dimacs_file") constructor method where the exception type raised when tweedledum wasn’t installed was not the expected `MissingOptionalLibrary`. Fixed [#10079](https://github.com/Qiskit/qiskit-terra/issues/10079) + +* Using `initial_layout` in calls to [`transpile()`](compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") will no longer error if the circuit contains qubits not in any registers, or qubits that exist in more than one register. See [#10125](https://github.com/Qiskit/qiskit-terra/issues/10125). + +* Fixed the gate decomposition of multi-controlled Z rotation gates added via [`QuantumCircuit.mcrz()`](qiskit.circuit.QuantumCircuit#mcrz "qiskit.circuit.QuantumCircuit.mcrz"). Previously, this method implemented a multi-controlled phase gate, which has a relative phase difference to the Z rotation. To obtain the previous .QuantumCircuit.mcrz behaviour, use .QuantumCircuit.mcp. + +* Fixed the output of pulse `measure()` and `measure_all()` when functions are called with the [`BackendV2`](qiskit.providers.BackendV2 "qiskit.providers.BackendV2") backend. + +* Fixed the dimensions of the output density matrix from [`DensityMatrix.partial_transpose()`](qiskit.quantum_info.DensityMatrix#partial_transpose "qiskit.quantum_info.DensityMatrix.partial_transpose") so they match the dimensions of the corresponding input density matrix. + +* Fixed plot legend error when your dataset has a zero value at first position. When one of your counts or distributions had a zero value at first position, the relative legend didn’t show up. See #10158 \<[https://github.com/Qiskit/qiskit-terra/issues/10158](https://github.com/Qiskit/qiskit-terra/issues/10158)> for more details. + +* Fixed an issue with the [`PassManagerConfig.from_backend()`](qiskit.transpiler.PassManagerConfig#from_backend "qiskit.transpiler.PassManagerConfig.from_backend") constructor when building a [`PassManagerConfig`](qiskit.transpiler.PassManagerConfig "qiskit.transpiler.PassManagerConfig") object from a [`BackendV1`](qiskit.providers.BackendV1 "qiskit.providers.BackendV1") instance that didn’t have a coupling map attribute defined. Previously, the constructor would incorrectly create a [`CouplingMap`](qiskit.transpiler.CouplingMap "qiskit.transpiler.CouplingMap") object with 0 qubits instead of using `None`. Fixed [#10171](https://github.com/Qiskit/qiskit-terra/issues/10171) + +* Importing [`qiskit.primitives`](primitives#module-qiskit.primitives "qiskit.primitives") will no longer cause deprecation warnings stemming from the deprecated [`qiskit.opflow`](opflow#module-qiskit.opflow "qiskit.opflow") module. These warnings would have been hidden to users by the default Python filters, but triggered the eager import of [`opflow`](opflow#module-qiskit.opflow "qiskit.opflow"), which meant that a subsequent import by a user would not trigger the warnings. + +* Fixed the OpenQASM 2 output of [`QuantumCircuit.qasm()`](qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm") when a custom gate object contained a gate with the same name. Ideally this shouldn’t happen for most gates, but complex algorithmic operations like the [`GroverOperator`](qiskit.circuit.library.GroverOperator "qiskit.circuit.library.GroverOperator") class could produce such structures accidentally. See [#10162](https://github.com/Qiskit/qiskit-terra/issues/10162). + +* Fixed a regression in the LaTeX drawer of [`QuantumCircuit.draw()`](qiskit.circuit.QuantumCircuit#draw "qiskit.circuit.QuantumCircuit.draw") when temporary files are placed on a separate filesystem to the working directory. See [#10211](https://github.com/Qiskit/qiskit-terra/issues/10211). + +* Fixes a bug introduced in Qiskit 0.24.0 where numeric rotation angles were no longer substituted for symbolic ones before preparing for two-qubit synthesis. This caused an exception to be raised because the synthesis routines require numberic matrices. + +* Fixed an issue with [`UnitarySynthesis`](qiskit.transpiler.passes.UnitarySynthesis "qiskit.transpiler.passes.UnitarySynthesis") when using the `target` parameter where circuits with control flow were not properly mapped to the target. + +* Fix a bug in which running [`Optimize1qGatesDecomposition`](qiskit.transpiler.passes.Optimize1qGatesDecomposition "qiskit.transpiler.passes.Optimize1qGatesDecomposition") in parallel would raise an error due to OneQubitGateErrorMap not being picklable. + +* Fixed an failure of [`Target.update_from_instruction_schedule_map()`](qiskit.transpiler.Target#update_from_instruction_schedule_map "qiskit.transpiler.Target.update_from_instruction_schedule_map") when the argument `inst_map` has schedule with unassigned duration. + +* Fix a bug in the [`VF2Layout`](qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") and [`VF2PostLayout`](qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") passes where the passes wer failing to account for the 1 qubit error component when evaluating a potential layout. + +* Fixed bug in [`VQD`](qiskit.algorithms.eigensolvers.VQD "qiskit.algorithms.eigensolvers.VQD") where `result.optimal_values` was a copy of `result.optimal_points`. It now returns the corresponding values. + +* When the parameter `conditional=True` is set in `qiskit.circuit.random.random_circuit`, the conditional operations will be preceded by a full mid-circuit measurment. Fixes [#9016](https://github.com/Qiskit/qiskit-terra/issues/9016) + +* Improve the type annotations on the [`QuantumCircuit.assign_parameters()`](qiskit.circuit.QuantumCircuit#assign_parameters "qiskit.circuit.QuantumCircuit.assign_parameters") method to reflect the change in return type depending on the `inplace` argument. + +* The OpenQASM 2 circuit-constructor methods ([`QuantumCircuit.from_qasm_str()`](qiskit.circuit.QuantumCircuit#from_qasm_str "qiskit.circuit.QuantumCircuit.from_qasm_str") and [`from_qasm_file()`](qiskit.circuit.QuantumCircuit#from_qasm_file "qiskit.circuit.QuantumCircuit.from_qasm_file")) will no longer error when encountering a `gate` definition that contains `U` or `CX` instructions. See [#5536](https://github.com/Qiskit/qiskit-terra/issues/5536). + +* Reduced overhead of the [`ConsolidateBlocks`](qiskit.transpiler.passes.ConsolidateBlocks "qiskit.transpiler.passes.ConsolidateBlocks") pass by performing matrix operations on all two-qubit blocks using `qiskit.transpiler.passes.utils._block_to_matrix()` instead of creating an instance of [`QuantumCircuit`](qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") and passing it to an [`Operator`](qiskit.quantum_info.Operator "qiskit.quantum_info.Operator"). The speedup will only be applicable when consolidating two-qubit blocks. Anything higher than that will still be handled by the [`Operator`](qiskit.quantum_info.Operator "qiskit.quantum_info.Operator") class. Check [#8779](https://github.com/Qiskit/qiskit-terra/issues/8779) for details. + +* Improved the error messages returned when an attempt to convert a fully bound [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") into a concrete `float` or `int` failed, for example because the expression was naturally a complex number. + +* Fixed `float` conversions for [`ParameterExpression`](qiskit.circuit.ParameterExpression "qiskit.circuit.ParameterExpression") values which had, at some point in their construction history, an imaginary component that had subsequently been cancelled. When using Sympy as a backend, these conversions would usually already have worked. When using Symengine as the backend, these conversions would often fail with type errors, despite the result having been symbolically evaluated to be real, and [`ParameterExpression.is_real()`](qiskit.circuit.ParameterExpression#is_real "qiskit.circuit.ParameterExpression.is_real") being true. + +* Fixed a potential performance scaling issue with layout scoring in preset pass managers, which could occur when transpiling circuits with many connected components on large devices. + +* The OpenQASM 3 exporter ([`qiskit.qasm3`](qasm3#module-qiskit.qasm3 "qiskit.qasm3")) will no longer output invalid OpenQASM 3 for non-unitary [`Instruction`](qiskit.circuit.Instruction "qiskit.circuit.Instruction") instances, but will instead raise a [`QASM3ExporterError`](qasm3#qiskit.qasm3.QASM3ExporterError "qiskit.qasm3.QASM3ExporterError") explaining that this are not yet supported. This feature will is slated for a later release of Qiskit, when there are more classical-processing facilities throughout the library. + +* Fixed the [`qpy`](qpy#module-qiskit.qpy "qiskit.qpy") serialization of [`QuantumCircuit.layout`](qiskit.circuit.QuantumCircuit#layout "qiskit.circuit.QuantumCircuit.layout") attribue. Previously, the [`layout`](qiskit.circuit.QuantumCircuit#layout "qiskit.circuit.QuantumCircuit.layout") attribute would have been dropped when serializing a circuit to QPY. Fixed [#10112](https://github.com/Qiskit/qiskit-terra/issues/10112) + +* Fixes issue #10185 \<[https://github.com/Qiskit/qiskit-terra/issues/10185](https://github.com/Qiskit/qiskit-terra/issues/10185)>. + +* The function `state_to_latex()` produced not valid LaTeX with unintended coefficient rounding, resulting in errors when calling `state_drawer()` is called. Fixed [#9297](https://github.com/Qiskit/qiskit-terra/issues/9297). + diff --git a/docs/api/qiskit/release-notes/index.md b/docs/api/qiskit/release-notes/index.md new file mode 100644 index 00000000000..3c5e2e6eca2 --- /dev/null +++ b/docs/api/qiskit/release-notes/index.md @@ -0,0 +1,52 @@ +--- +title: Qiskit release notes +description: New features, bug fixes, and other changes in previous versions of Qiskit. +--- + +# Qiskit release notes + +New features, bug fixes, and other changes in previous versions of Qiskit. + +## Release notes by version + +* [0.45](/api/qiskit/release-notes/0.45) +* [0.44](/api/qiskit/release-notes/0.44) +* [0.43](/api/qiskit/release-notes/0.43) +* [0.42](/api/qiskit/release-notes/0.42) +* [0.41](/api/qiskit/release-notes/0.41) +* [0.40](/api/qiskit/release-notes/0.40) +* [0.39](/api/qiskit/release-notes/0.39) +* [0.38](/api/qiskit/release-notes/0.38) +* [0.37](/api/qiskit/release-notes/0.37) +* [0.36](/api/qiskit/release-notes/0.36) +* [0.35](/api/qiskit/release-notes/0.35) +* [0.34](/api/qiskit/release-notes/0.34) +* [0.33](/api/qiskit/release-notes/0.33) +* [0.32](/api/qiskit/release-notes/0.32) +* [0.31](/api/qiskit/release-notes/0.31) +* [0.30](/api/qiskit/release-notes/0.30) +* [0.29](/api/qiskit/release-notes/0.29) +* [0.28](/api/qiskit/release-notes/0.28) +* [0.27](/api/qiskit/release-notes/0.27) +* [0.26](/api/qiskit/release-notes/0.26) +* [0.25](/api/qiskit/release-notes/0.25) +* [0.24](/api/qiskit/release-notes/0.24) +* [0.23](/api/qiskit/release-notes/0.23) +* [0.22](/api/qiskit/release-notes/0.22) +* [0.21](/api/qiskit/release-notes/0.21) +* [0.20](/api/qiskit/release-notes/0.20) +* [0.19](/api/qiskit/release-notes/0.19) +* [0.18](/api/qiskit/release-notes/0.18) +* [0.17](/api/qiskit/release-notes/0.17) +* [0.16](/api/qiskit/release-notes/0.16) +* [0.15](/api/qiskit/release-notes/0.15) +* [0.14](/api/qiskit/release-notes/0.14) +* [0.13](/api/qiskit/release-notes/0.13) +* [0.12](/api/qiskit/release-notes/0.12) +* [0.11](/api/qiskit/release-notes/0.11) +* [0.10](/api/qiskit/release-notes/0.10) +* [0.9](/api/qiskit/release-notes/0.9) +* [0.8](/api/qiskit/release-notes/0.8) +* [0.7](/api/qiskit/release-notes/0.7) +* [0.6](/api/qiskit/release-notes/0.6) +* [0.5](/api/qiskit/release-notes/0.5) diff --git a/scripts/commands/updateApiDocs.ts b/scripts/commands/updateApiDocs.ts index 7df18354845..f778f030f54 100644 --- a/scripts/commands/updateApiDocs.ts +++ b/scripts/commands/updateApiDocs.ts @@ -87,6 +87,7 @@ const PACKAGES: Pkg[] = [ githubSlug: "qiskit/qiskit", baseUrl: `https://qiskit.org/documentation`, initialUrls: [`https://qiskit.org/documentation/apidoc/index.html`], + hasSeparateReleaseNotes: true, tocOptions: { collapsed: true, nestModule(id: string) { @@ -122,7 +123,7 @@ const readArgs = (): Arguments => { const processLegacyReleaseNotes = async ( pkg: Pkg, ): Promise<{ title: string; url: string }[]> => { - if (!(pkg.name === "qiskit")) { + if (!pkg.hasSeparateReleaseNotes) { return []; } const legacyReleaseNoteVersions = ( @@ -131,6 +132,7 @@ const processLegacyReleaseNotes = async ( .trim() .split("\n") .map((x) => parse(x).name) + .filter((x) => x.match(/^\d/)) // remove index .sort((a: string, b: string) => { const aParts = a.split(".").map((x) => Number(x)); const bParts = b.split(".").map((x) => Number(x)); @@ -204,6 +206,7 @@ zxMain(async () => { pkg, args.version, legacyReleaseNoteEntries, + versionWithoutPatch, ); }); @@ -251,15 +254,20 @@ async function convertHtmlToMarkdown( baseSourceUrl: string, pkg: Pkg, version: string, - legacyReleaseNoteEntries: { title: string; url: string }[], + releaseNoteEntries: { title: string; url: string }[], + versionWithoutPatch: string, ) { - const globs = ["apidocs/**.html", "apidoc/**.html", "stubs/**.html"]; - if (pkg.name !== "qiskit") { - globs.push("release_notes.html"); - } - const files = await globby(globs, { - cwd: htmlPath, - }); + const files = await globby( + [ + "apidocs/**.html", + "apidoc/**.html", + "stubs/**.html", + "release_notes.html", + ], + { + cwd: htmlPath, + }, + ); const ignore = pkg.ignore ?? (() => false); @@ -271,6 +279,7 @@ async function convertHtmlToMarkdown( url: `${pkg.baseUrl}/${file}`, baseSourceUrl, imageDestination: `/images/api/${pkg.name}`, + releaseNotesTitle: `${pkg.title} ${versionWithoutPatch} release notes`, }); const { dir, name } = parse(`${markdownPath}/${file}`); let url = `/${relative(`${getRoot()}/docs`, dir)}/${name}`; @@ -278,6 +287,14 @@ async function convertHtmlToMarkdown( if (!result.meta.python_api_name || !ignore(result.meta.python_api_name)) { results.push({ ...result, url }); } + if (pkg.hasSeparateReleaseNotes && file.endsWith("release_notes.html")) { + if (releaseNoteEntries[0].title !== versionWithoutPatch) { + releaseNoteEntries.unshift({ + title: versionWithoutPatch, + url: `/api/${pkg.name}/release-notes/${versionWithoutPatch}`, + }); + } + } } const allImages = uniqBy( @@ -297,10 +314,16 @@ async function convertHtmlToMarkdown( renameUrls(results); await updateLinks(results, pkg.transformLink); await dedupeResultIds(results); - addFrontMatter(results, pkg); + addFrontMatter(results, pkg, versionWithoutPatch); for (const result of results) { - await writeFile(urlToPath(result.url), result.markdown); + let path = urlToPath(result.url); + if (pkg.hasSeparateReleaseNotes && path.endsWith("release-notes.md")) { + path = `${getRoot()}/docs/api/${ + pkg.name + }/release-notes/${versionWithoutPatch}.md`; + } + await writeFile(path, result.markdown); } console.log("Generating toc"); @@ -309,11 +332,8 @@ async function convertHtmlToMarkdown( title: pkg.title, name: pkg.name, version, - releaseNoteEntries: legacyReleaseNoteEntries, - releaseNotesUrl: - pkg.name !== "qiskit" - ? `/api/${pkg.name}/release-notes` - : "https://github.com/qiskit/qiskit/releases", + releaseNoteEntries, + releaseNotesUrl: `/api/${pkg.name}/release-notes`, tocOptions: pkg.tocOptions, }, results, @@ -323,6 +343,21 @@ async function convertHtmlToMarkdown( JSON.stringify(toc, null, 2) + "\n", ); + if (pkg.hasSeparateReleaseNotes) { + console.log("Generating release-notes/index"); + let markdown = "---\n"; + markdown += `title: ${pkg.title} release notes\n`; + markdown += `description: New features, bug fixes, and other changes in previous versions of ${pkg.title}.\n`; + markdown += "---\n\n"; + markdown += `# ${pkg.title} release notes\n\n`; + markdown += `New features, bug fixes, and other changes in previous versions of ${pkg.title}.\n\n`; + markdown += `## Release notes by version\n\n`; + for (const entry of releaseNoteEntries) { + markdown += `* [${entry.title}](${entry.url})\n`; + } + await writeFile(`${markdownPath}/release-notes/index.md`, markdown); + } + console.log("Generating version file"); const pkg_json = { name: pkg.name, version: version }; await writeFile( diff --git a/scripts/lib/sharedTypes.ts b/scripts/lib/sharedTypes.ts index bc6b17ad88d..4272d21200e 100644 --- a/scripts/lib/sharedTypes.ts +++ b/scripts/lib/sharedTypes.ts @@ -24,6 +24,7 @@ export type Pkg = { initialUrls: string[]; title: string; ignore?(id: string): boolean; + hasSeparateReleaseNotes?: boolean; tocOptions?: { collapsed?: boolean; nestModule?(id: string): boolean; diff --git a/scripts/lib/sphinx/addFrontMatter.ts b/scripts/lib/sphinx/addFrontMatter.ts index 1b2d57ca3ac..940fc80668d 100644 --- a/scripts/lib/sphinx/addFrontMatter.ts +++ b/scripts/lib/sphinx/addFrontMatter.ts @@ -14,7 +14,11 @@ import { getLastPartFromFullIdentifier } from "../stringUtils"; import { SphinxToMdResult } from "./SphinxToMdResult"; import { Pkg } from "../sharedTypes"; -export function addFrontMatter(results: SphinxToMdResult[], pkg: Pkg): void { +export function addFrontMatter( + results: T[], + pkg: Pkg, + versionWithoutPatch: string, +): void { for (let result of results) { let markdown = result.markdown; if (result.meta.python_api_name) { @@ -30,7 +34,9 @@ ${markdown} `; } else if (result.isReleaseNotes) { result.markdown = `--- -title: ${pkg.title} release notes +title: ${pkg.title}${ + pkg.hasSeparateReleaseNotes ? " " + versionWithoutPatch : "" + } release notes description: Changes made to ${pkg.title} in_page_toc_max_heading_level: 2 --- diff --git a/scripts/lib/sphinx/generateToc.test.ts b/scripts/lib/sphinx/generateToc.test.ts index afb73a6e6f1..ddda78cbd4c 100644 --- a/scripts/lib/sphinx/generateToc.test.ts +++ b/scripts/lib/sphinx/generateToc.test.ts @@ -304,6 +304,52 @@ describe("generateTocFromPythonApiFiles", () => { } `); }); + + test("TOC with nested release notes", () => { + const toc = generateToc({ + pkg: { + ...pkg, + releaseNoteEntries: [ + { title: "0.39", url: "/docs/runtime/release-notes/0.39" }, + { title: "0.38", url: "/docs/runtime/release-notes/0.38" }, + ], + }, + results: [ + { + meta: { + python_api_type: "module", + python_api_name: "qiskit_ibm_runtime", + }, + url: "/docs/runtime/qiskit_ibm_runtime", + }, + ], + }); + + expect(toc).toMatchInlineSnapshot(` + { + "children": [ + { + "title": "qiskit_ibm_runtime", + "url": "/docs/runtime/qiskit_ibm_runtime", + }, + { + "children": [ + { + "title": "0.39", + "url": "/docs/runtime/release-notes/0.39", + }, + { + "title": "0.38", + "url": "/docs/runtime/release-notes/0.38", + }, + ], + "title": "Release notes", + }, + ], + "title": "Qiskit Runtime IBM Client", + } + `); + }); }); const pkg = { diff --git a/scripts/lib/sphinx/generateToc.ts b/scripts/lib/sphinx/generateToc.ts index 7c73feb36f7..3280b412d2f 100644 --- a/scripts/lib/sphinx/generateToc.ts +++ b/scripts/lib/sphinx/generateToc.ts @@ -126,15 +126,15 @@ export function generateToc(options: { tocChildren.push(...orderEntriesByTitle(nestedTocModules)); } - const releaseNoteEntry: TocEntry = { + const releaseNotesEntry: TocEntry = { title: "Release notes", }; if (pkg.releaseNoteEntries.length) { - releaseNoteEntry.children = pkg.releaseNoteEntries; + releaseNotesEntry.children = pkg.releaseNoteEntries; } else { - releaseNoteEntry.url = pkg.releaseNotesUrl; + releaseNotesEntry.url = pkg.releaseNotesUrl; } - tocChildren.push(releaseNoteEntry); + tocChildren.push(releaseNotesEntry); const toc: Toc = { title: pkg.title, diff --git a/scripts/lib/sphinx/sphinxHtmlToMarkdown.ts b/scripts/lib/sphinx/sphinxHtmlToMarkdown.ts index cb93f83f703..ad07eda9a48 100644 --- a/scripts/lib/sphinx/sphinxHtmlToMarkdown.ts +++ b/scripts/lib/sphinx/sphinxHtmlToMarkdown.ts @@ -40,6 +40,7 @@ export async function sphinxHtmlToMarkdown(options: { // url links to a fixed version and ending in / // https://github.com/Qiskit/qiskit-ibm-runtime/tree/0.9.2/ baseSourceUrl?: string; + releaseNotesTitle?: string; }): Promise { const images: Array<{ src: string; dest: string }> = []; const { @@ -47,6 +48,7 @@ export async function sphinxHtmlToMarkdown(options: { url, imageDestination = "/images/api/", baseSourceUrl, + releaseNotesTitle, } = options; const meta: PythonObjectMeta = {}; const isReleaseNotes = url.endsWith("release_notes.html") ? true : false; @@ -64,6 +66,11 @@ export async function sphinxHtmlToMarkdown(options: { } }); + if (isReleaseNotes && releaseNotesTitle) { + // Replace heading with custom heading + $page("h1").html(releaseNotesTitle); + } + $main .find("img") .toArray()