1036 lines
106 KiB
Plaintext
1036 lines
106 KiB
Plaintext
---
|
||
title: Qiskit 0.40 release notes
|
||
description: Changes made in Qiskit 0.40
|
||
in_page_toc_max_heading_level: 4
|
||
---
|
||
|
||
# Qiskit 0.40 release notes
|
||
|
||
## 0.40.0
|
||
|
||
This release officially deprecates the Qiskit IBMQ provider project as part of the Qiskit metapackage. This means that in a future release, `pip install qiskit` will no longer automatically include `qiskit-ibmq-provider`. If you’re currently installing or listing `qiskit` as a dependency to get `qiskit-ibmq-provider`, you should update to explicitly include `qiskit-ibmq-provider` as well. This is being done as the Qiskit project moves towards a model where the `qiskit` package only contains the common core functionality for building and compiling quantum circuits, programs, and applications. Packages that build on that core or link Qiskit to hardware or simulators will be installable as separate packages.
|
||
|
||
<span id="terra-0-23-0" />
|
||
|
||
### Terra 0.23.0
|
||
|
||
<span id="release-notes-0-23-0-prelude" />
|
||
|
||
<span id="id64" />
|
||
|
||
#### Prelude
|
||
|
||
Qiskit Terra 0.23.0 is a major feature release that includes a multitude of new features and bugfixes. The highlights for this release are:
|
||
|
||
> * Support for importing OpenQASM 3 programs and creating [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") objects from the input program via two new functions [`qiskit.qasm3.load()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.load "qiskit.qasm3.load") and [`qiskit.qasm3.loads()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.loads "qiskit.qasm3.loads").
|
||
>
|
||
> * Improvements to the library of synthesis algorithms included in Qiskit. This includes the following new synthesis functions:
|
||
>
|
||
> > * Clifford Synthesis
|
||
> >
|
||
> > * [`synth_clifford_layers()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_clifford_layers "qiskit.synthesis.synth_clifford_layers")
|
||
> > * [`synth_clifford_greedy()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_clifford_greedy "qiskit.synthesis.synth_clifford_greedy")
|
||
> >
|
||
> > * Linear Function Synthesis:
|
||
> >
|
||
> > * [`synth_cnot_depth_line_kms()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_cnot_depth_line_kms "qiskit.synthesis.synth_cnot_depth_line_kms")
|
||
> > * [`synth_cnot_count_full_pmh()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_cnot_count_full_pmh "qiskit.synthesis.synth_cnot_count_full_pmh")
|
||
> >
|
||
> > * Permutation Synthesis:
|
||
> >
|
||
> > * [`synth_permutation_basic()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_permutation_basic "qiskit.synthesis.synth_permutation_basic")
|
||
> > * [`synth_permutation_acg()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_permutation_acg "qiskit.synthesis.synth_permutation_acg")
|
||
> > * [`synth_permutation_depth_lnn_kms()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_permutation_depth_lnn_kms "qiskit.synthesis.synth_permutation_depth_lnn_kms")
|
||
> >
|
||
> > * [`SolovayKitaevDecomposition`](/api/qiskit/0.45/qiskit.synthesis.SolovayKitaevDecomposition "qiskit.synthesis.SolovayKitaevDecomposition") detailed in: [https://arxiv.org/abs/quant-ph/0505030](https://arxiv.org/abs/quant-ph/0505030)
|
||
> >
|
||
> > * New plugins for [`HighLevelSynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis"):
|
||
> >
|
||
> > * `ACGSynthesisPermutation`
|
||
> > * `KMSSynthesisPermutation`
|
||
> > * `BasicSynthesisPermutation`
|
||
> >
|
||
> > * New plugin for [`UnitarySynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.UnitarySynthesis "qiskit.transpiler.passes.UnitarySynthesis")
|
||
> >
|
||
> > * [`SolovayKitaevSynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.SolovayKitaevSynthesis "qiskit.transpiler.passes.SolovayKitaevSynthesis")
|
||
>
|
||
> * Performance improvements to [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout"). The pass is now primarily written in Rust which can lead to a runtime improvement, however the bigger improvement is in the quality of the output (on average, fewer [`SwapGate`](/api/qiskit/0.45/qiskit.circuit.library.SwapGate "qiskit.circuit.library.SwapGate") gates introduced by [`SabreSwap`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap")). For example, running [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") and [`SabreSwap`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap") on Bernstein Vazirani circuits targeting the [`FakeSherbrooke`](/api/qiskit/0.45/qiskit.providers.fake_provider.FakeSherbrooke "qiskit.providers.fake_provider.FakeSherbrooke") backend yields the following results:
|
||
>
|
||
> 
|
||
|
||
This release also deprecates support for running with Python 3.7. A `DeprecationWarning` will now be emitted if you run Qiskit with Python 3.7. Support for Python 3.7 will be removed as part of the 0.25.0 release (currently planned for release in July 2023), at which point you will need Python 3.8 or newer to use Qiskit.
|
||
|
||
<span id="id65" />
|
||
|
||
#### New Features
|
||
|
||
* The pulses in [`qiskit.pulse.library`](/api/qiskit/0.45/pulse#module-qiskit.pulse.library "qiskit.pulse.library")
|
||
|
||
> * [`Gaussian`](/api/qiskit/0.45/qiskit.pulse.library.Gaussian_class.rst#qiskit.pulse.library.Gaussian "qiskit.pulse.library.Gaussian")
|
||
> * [`GaussianSquare`](/api/qiskit/0.45/qiskit.pulse.library.GaussianSquare "qiskit.pulse.library.GaussianSquare")
|
||
> * [`Drag`](/api/qiskit/0.45/qiskit.pulse.library.Drag_class.rst#qiskit.pulse.library.Drag "qiskit.pulse.library.Drag")
|
||
> * [`Constant`](/api/qiskit/0.45/qiskit.pulse.library.Constant_class.rst#qiskit.pulse.library.Constant "qiskit.pulse.library.Constant")
|
||
|
||
can be initialized with new parameter `angle`, such that two float parameters could be provided: `amp` and `angle`. Initialization with complex `amp` is still supported.
|
||
|
||
* The [`AdaptVQE`](/api/qiskit/0.45/qiskit.algorithms.minimum_eigensolvers.AdaptVQE "qiskit.algorithms.minimum_eigensolvers.AdaptVQE") class has a new attribute, [`eigenvalue_history`](/api/qiskit/0.45/qiskit.algorithms.minimum_eigensolvers.AdaptVQEResult#eigenvalue_history "qiskit.algorithms.minimum_eigensolvers.AdaptVQEResult.eigenvalue_history"), which is used to track the lowest achieved energy per iteration of the AdaptVQE. For example:
|
||
|
||
```python
|
||
from qiskit.algorithms.minimum_eigensolvers import VQE
|
||
from qiskit.algorithms.minimum_eigensolvers.adapt_vqe import AdaptVQE
|
||
from qiskit.algorithms.optimizers import SLSQP
|
||
from qiskit.circuit.library import EvolvedOperatorAnsatz
|
||
from qiskit.opflow import PauliSumOp
|
||
from qiskit.primitives import Estimator
|
||
from qiskit.quantum_info import SparsePauliOp
|
||
from qiskit.utils import algorithm_globals
|
||
|
||
excitation_pool = [
|
||
PauliSumOp(
|
||
SparsePauliOp(["IIIY", "IIZY"], coeffs=[0.5 + 0.0j, -0.5 + 0.0j]), coeff=1.0
|
||
),
|
||
PauliSumOp(
|
||
SparsePauliOp(["ZYII", "IYZI"], coeffs=[-0.5 + 0.0j, 0.5 + 0.0j]), coeff=1.0
|
||
),
|
||
PauliSumOp(
|
||
SparsePauliOp(
|
||
["ZXZY", "IXIY", "IYIX", "ZYZX", "IYZX", "ZYIX", "ZXIY", "IXZY"],
|
||
coeffs=[
|
||
-0.125 + 0.0j,
|
||
0.125 + 0.0j,
|
||
-0.125 + 0.0j,
|
||
0.125 + 0.0j,
|
||
0.125 + 0.0j,
|
||
-0.125 + 0.0j,
|
||
0.125 + 0.0j,
|
||
-0.125 + 0.0j,
|
||
],
|
||
),
|
||
coeff=1.0,
|
||
),
|
||
]
|
||
ansatz = EvolvedOperatorAnsatz(excitation_pool, initial_state=self.initial_state)
|
||
optimizer = SLSQP()
|
||
h2_op = PauliSumOp.from_list(
|
||
[
|
||
("IIII", -0.8105479805373266),
|
||
("ZZII", -0.2257534922240251),
|
||
("IIZI", +0.12091263261776641),
|
||
("ZIZI", +0.12091263261776641),
|
||
("IZZI", +0.17218393261915543),
|
||
("IIIZ", +0.17218393261915546),
|
||
("IZIZ", +0.1661454325638243),
|
||
("ZZIZ", +0.1661454325638243),
|
||
("IIZZ", -0.2257534922240251),
|
||
("IZZZ", +0.16892753870087926),
|
||
("ZZZZ", +0.17464343068300464),
|
||
("IXIX", +0.04523279994605788),
|
||
("ZXIX", +0.04523279994605788),
|
||
("IXZX", -0.04523279994605788),
|
||
("ZXZX", -0.04523279994605788),
|
||
]
|
||
)
|
||
|
||
algorithm_globals.random_seed = 42
|
||
calc = AdaptVQE(VQE(Estimator(), ansatz, self.optimizer))
|
||
res = calc.compute_minimum_eigenvalue(operator=h2_op)
|
||
|
||
print(calc.eigenvalue_history)
|
||
```
|
||
|
||
the returned value of `calc.history` should be roughly `[-1.85727503]` as there is a single iteration.
|
||
|
||
* The runtime logging when running the [`AdaptVQE`](/api/qiskit/0.45/qiskit.algorithms.minimum_eigensolvers.AdaptVQE "qiskit.algorithms.minimum_eigensolvers.AdaptVQE") has been improved. When running the class now, `DEBUG` and `INFO` level log messages will be emitted as the class runs.
|
||
|
||
* Added a new transpiler pass, `CollectAndCollapse`, to collect and to consolidate blocks of nodes in a circuit. This pass is designed to be a general base class for combined block collection and consolidation. To be completely general, the work of collecting and collapsing the blocks is done via functions provided during instantiating the pass. For example, the [`CollectLinearFunctions`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectLinearFunctions "qiskit.transpiler.passes.CollectLinearFunctions") has been updated to inherit from `CollectAndCollapse` and collects blocks of [`CXGate`](/api/qiskit/0.45/qiskit.circuit.library.CXGate "qiskit.circuit.library.CXGate") and [`SwapGate`](/api/qiskit/0.45/qiskit.circuit.library.SwapGate "qiskit.circuit.library.SwapGate") gates, and replaces each block with a [`LinearFunction`](/api/qiskit/0.45/qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction"). The [`CollectCliffords`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectCliffords "qiskit.transpiler.passes.CollectCliffords") which is also now based on `CollectAndCollapse`, collects blocks of “Clifford” gates and replaces each block with a [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford").
|
||
|
||
The interface also supports the option `do_commutative_analysis`, which allows to exploit commutativity between gates in order to collect larger blocks of nodes. For example, collecting blocks of CX gates in the following circuit:
|
||
|
||
```python
|
||
qc = QuantumCircuit(2)
|
||
qc.cx(0, 1)
|
||
qc.z(0)
|
||
qc.cx(1, 0)
|
||
```
|
||
|
||
using `do_commutative_analysis` enables consolidating the two CX gates, as the first CX gate and the Z gate commute.
|
||
|
||
* Added a new class `BlockCollector` that implements various collection strategies, and a new class `BlockCollapser` that implements various collapsing strategies. Currently `BlockCollector` includes the strategy to greedily collect all gates adhering to a given filter function (for example, collecting all Clifford gates), and `BlockCollapser` includes the strategy to consolidate all gates in a block to a single object (or example, a block of Clifford gates can be consolidated to a single [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford")).
|
||
|
||
* Added a new [`CollectCliffords`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectCliffords "qiskit.transpiler.passes.CollectCliffords") transpiler pass that collects blocks of Clifford gates and consolidates these blocks into [`qiskit.quantum_info.Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") objects. This pass inherits from `CollectAndCollapse` and in particular supports the option `do_commutative_analysis`. It also supports two additional options `split_blocks` and `min_block_size`. See the release notes for `CollectAndCollapse` and [`CollectLinearFunctions`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectLinearFunctions "qiskit.transpiler.passes.CollectLinearFunctions") for additional details.
|
||
|
||
* The [`CollectLinearFunctions`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectLinearFunctions "qiskit.transpiler.passes.CollectLinearFunctions") transpiler pass has several new arguments on its constructor:
|
||
|
||
> * `do_commutative_analysis`: enables exploiting commutativity between gates in order to collect larger blocks of nodes.
|
||
>
|
||
> * `split_blocks`: enables spliting collected blocks into sub-blocks over disjoint subsets of qubits. For example, in the following circuit:
|
||
>
|
||
> ```python
|
||
> qc = QuantumCircuit(4)
|
||
> qc.cx(0, 2)
|
||
> qc.cx(1, 3)
|
||
> qc.cx(2, 0)
|
||
> qc.cx(3, 1)
|
||
> qc.cx(1, 3)
|
||
> ```
|
||
>
|
||
> the single block of CX gates over qubits `{0, 1, 2, 3}` can be split into two disjoint sub-blocks, one over qubits `{0, 2}` and the other over qubits `{1, 3}`.
|
||
>
|
||
> * `min_block_size`: allows to specify the minimum size of the block to be consolidated, blocks with fewer gates will not be modified. For example, in the following circuit:
|
||
>
|
||
> ```python
|
||
> qc = QuantumCircuit(4)
|
||
> qc.cx(1, 2)
|
||
> qc.cx(2, 1)
|
||
> ```
|
||
>
|
||
> the two CX gates will be consolidated when `min_block_size` is 1 or 2, and will remain unchanged when `min_block_size` is 3 or larger.
|
||
|
||
* Added a depth-efficient synthesis algorithm [`synth_cnot_depth_line_kms()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_cnot_depth_line_kms "qiskit.synthesis.synth_cnot_depth_line_kms") for linear reversible circuits [`LinearFunction`](/api/qiskit/0.45/qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction") over the linear nearest-neighbor architecture, following the paper: [https://arxiv.org/abs/quant-ph/0701194](https://arxiv.org/abs/quant-ph/0701194).
|
||
|
||
* The [`DAGCircuit.replace_block_with_op()`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit#replace_block_with_op "qiskit.dagcircuit.DAGCircuit.replace_block_with_op") method will now return the new [`DAGOpNode`](/api/qiskit/0.45/qiskit.dagcircuit.DAGOpNode "qiskit.dagcircuit.DAGOpNode") that is created when the block is replaced. Previously, calling this method would not return anything.
|
||
|
||
* Added a depth-efficient synthesis algorithm [`synth_permutation_depth_lnn_kms()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_permutation_depth_lnn_kms "qiskit.synthesis.synth_permutation_depth_lnn_kms") for [`Permutation`](/api/qiskit/0.45/qiskit.circuit.library.Permutation "qiskit.circuit.library.Permutation") over the linear nearest-neighbor architecture, following the paper: [https://arxiv.org/abs/quant-ph/0701194](https://arxiv.org/abs/quant-ph/0701194)
|
||
|
||
* Added a new class [`PermutationGate`](/api/qiskit/0.45/qiskit.circuit.library.PermutationGate "qiskit.circuit.library.PermutationGate") for representing permutation logic as a circuit element. Unlike the existing [`Permutation`](/api/qiskit/0.45/qiskit.circuit.library.Permutation "qiskit.circuit.library.Permutation") circuit library element which had a static definition this new class avoids synthesizing a permutation circuit when it is declared. This delays the actual synthesis to the transpiler. It also allows enables using several different algorithms for synthesizing permutations, which are available as high-level-synthesis permutation plugins.
|
||
|
||
Another key feature of the [`PermutationGate`](/api/qiskit/0.45/qiskit.circuit.library.PermutationGate "qiskit.circuit.library.PermutationGate") is that implements the `__array__` interface for efficiently returning a unitary matrix for a permutation.
|
||
|
||
* Added several high-level-synthesis plugins for synthesizing permutations:
|
||
|
||
> * `BasicSynthesisPermutation`: applies to fully-connected architectures and is based on sorting. This is the previously used algorithm for constructing quantum circuits for permutations.
|
||
> * `ACGSynthesisPermutation`: applies to fully-connected architectures but is based on the Alon, Chung, Graham method. It synthesizes any permutation in depth 2 (measured in terms of SWAPs).
|
||
> * `KMSSynthesisPermutation`: applies to linear nearest-neighbor architectures and corresponds to the recently added Kutin, Moulton, Smithline method.
|
||
|
||
For example:
|
||
|
||
```python
|
||
from qiskit.circuit import QuantumCircuit
|
||
from qiskit.circuit.library import PermutationGate
|
||
from qiskit.transpiler import PassManager
|
||
from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis
|
||
from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPluginManager
|
||
|
||
# Create a permutation and add it to a quantum circuit
|
||
perm = PermutationGate([4, 6, 3, 7, 1, 2, 0, 5])
|
||
qc = QuantumCircuit(8)
|
||
qc.append(perm, range(8))
|
||
|
||
# Print available plugin names for synthesizing permutations
|
||
# Returns ['acg', 'basic', 'default', 'kms']
|
||
print(HighLevelSynthesisPluginManager().method_names("permutation"))
|
||
|
||
# Default plugin for permutations
|
||
# Returns a quantum circuit with size 6 and depth 3
|
||
qct = PassManager(HighLevelSynthesis()).run(qc)
|
||
print(f"Default: {qct.size() = }, {qct.depth() = }")
|
||
|
||
# KMSSynthesisPermutation plugin for permutations
|
||
# Returns a quantum circuit with size 18 and depth 6
|
||
# but adhering to the linear nearest-neighbor architecture.
|
||
qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("kms", {})]))).run(qc)
|
||
print(f"kms: {qct.size() = }, {qct.depth() = }")
|
||
|
||
# BasicSynthesisPermutation plugin for permutations
|
||
# Returns a quantum circuit with size 6 and depth 3
|
||
qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("basic", {})]))).run(qc)
|
||
print(f"basic: {qct.size() = }, {qct.depth() = }")
|
||
|
||
# ACGSynthesisPermutation plugin for permutations
|
||
# Returns a quantum circuit with size 6 and depth 2
|
||
qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("acg", {})]))).run(qc)
|
||
print(f"acg: {qct.size() = }, {qct.depth() = }")
|
||
```
|
||
|
||
* Added new classes for Quantum Fisher Information (QFI) and Quantum Geometric Tensor (QGT) algorithms using [`primitives`](/api/qiskit/0.45/primitives#module-qiskit.primitives "qiskit.primitives"), [`qiskit.algorithms.gradients.QFI`](/api/qiskit/0.45/qiskit.algorithms.gradients.QFI "qiskit.algorithms.gradients.QFI") and [`qiskit.algorithms.gradients.LinCombQGT`](/api/qiskit/0.45/qiskit.algorithms.gradients.LinCombQGT "qiskit.algorithms.gradients.LinCombQGT"), to the gradients module: [`qiskit.algorithms.gradients`](/api/qiskit/0.45/qiskit.algorithms.gradients#module-qiskit.algorithms.gradients "qiskit.algorithms.gradients"). For example:
|
||
|
||
```python
|
||
from qiskit.circuit import QuantumCircuit, Parameter
|
||
from qiskit.algorithms.gradients import LinCombQGT, QFI
|
||
|
||
estimator = Estimator()
|
||
a, b = Parameter("a"), Parameter("b")
|
||
qc = QuantumCircuit(1)
|
||
qc.h(0)
|
||
qc.rz(a, 0)
|
||
qc.rx(b, 0)
|
||
|
||
parameter_value = [[np.pi / 4, 0]]
|
||
|
||
qgt = LinCombQGT(estimator)
|
||
qgt_result = qgt.run([qc], parameter_value).result()
|
||
|
||
qfi = QFI(qgt)
|
||
qfi_result = qfi.run([qc], parameter_value).result()
|
||
```
|
||
|
||
* Added a new keyword argument, `derivative_type`, to the constructor for the [`LinCombEstimatorGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.LinCombEstimatorGradient "qiskit.algorithms.gradients.LinCombEstimatorGradient"). This argument takes a `DerivativeType` enum that enables specifying to compute only the real or imaginary parts of the gradient.
|
||
|
||
* Added a new option `circuit_reverse_bits` to the user config file. This allows users to set a boolean for their preferred default behavior of the `reverse_bits` argument of the circuit drawers [`QuantumCircuit.draw()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#draw "qiskit.circuit.QuantumCircuit.draw") and [`circuit_drawer()`](/api/qiskit/0.45/qiskit.visualization.circuit_drawer "qiskit.visualization.circuit_drawer"). For example, adding a section to the user config file in the default location `~/.qiskit/settings.conf` with:
|
||
|
||
```python
|
||
[default]
|
||
circuit_reverse_bits = True
|
||
```
|
||
|
||
will change the default to display the bits in reverse order.
|
||
|
||
* Added a new class [`Z2Symmetries`](/api/qiskit/0.45/qiskit.quantum_info.Z2Symmetries "qiskit.quantum_info.Z2Symmetries") to [`qiskit.quantum_info`](/api/qiskit/0.45/quantum_info#module-qiskit.quantum_info "qiskit.quantum_info") which is used to identify any $Z_2$ symmetries from an input [`SparsePauliOp`](/api/qiskit/0.45/qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp").
|
||
|
||
* Added a new pulse directive [`TimeBlockade`](/api/qiskit/0.45/qiskit.pulse.instructions.TimeBlockade "qiskit.pulse.instructions.TimeBlockade"). This directive behaves almost identically to the delay instruction, but will be removed before execution. This directive is intended to be used internally within the pulse builder and helps [`ScheduleBlock`](/api/qiskit/0.45/qiskit.pulse.ScheduleBlock "qiskit.pulse.ScheduleBlock") represent instructions with absolute time intervals. This allows the pulse builder to convert `Schedule` into `ScheduleBlock`, rather than wrapping with [`Call`](/api/qiskit/0.45/qiskit.pulse.instructions.Call "qiskit.pulse.instructions.Call") instructions.
|
||
|
||
* Added primitive-enabled algorithms for Variational Quantum Time Evolution that implement the interface for Quantum Time Evolution. The [`qiskit.algorithms.VarQRTE`](/api/qiskit/0.45/qiskit.algorithms.VarQRTE "qiskit.algorithms.VarQRTE") class is used for real and the [`qiskit.algorithms.VarQITE`](/api/qiskit/0.45/qiskit.algorithms.VarQITE "qiskit.algorithms.VarQITE") class is used for imaginary quantum time evolution according to a variational principle passed.
|
||
|
||
Each algorithm accepts a variational principle which implements the [`ImaginaryVariationalPrinciple`](/api/qiskit/0.45/qiskit.algorithms.time_evolvers.variational.ImaginaryVariationalPrinciple "qiskit.algorithms.time_evolvers.variational.ImaginaryVariationalPrinciple") abstract interface. The following implementations are included:
|
||
|
||
> * [`ImaginaryMcLachlanPrinciple`](/api/qiskit/0.45/qiskit.algorithms.time_evolvers.variational.ImaginaryMcLachlanPrinciple "qiskit.algorithms.time_evolvers.variational.ImaginaryMcLachlanPrinciple")
|
||
> * [`RealMcLachlanPrinciple`](/api/qiskit/0.45/qiskit.algorithms.time_evolvers.variational.RealMcLachlanPrinciple "qiskit.algorithms.time_evolvers.variational.RealMcLachlanPrinciple")
|
||
|
||
For example:
|
||
|
||
```python
|
||
from qiskit.algorithms import TimeEvolutionProblem, VarQITE
|
||
from qiskit.algorithms.time_evolvers.variational import ImaginaryMcLachlanPrinciple
|
||
from qiskit.circuit.library import EfficientSU2
|
||
from qiskit.quantum_info import SparsePauliOp
|
||
import numpy as np
|
||
|
||
observable = SparsePauliOp.from_list(
|
||
[
|
||
("II", 0.2252),
|
||
("ZZ", 0.5716),
|
||
("IZ", 0.3435),
|
||
("ZI", -0.4347),
|
||
("YY", 0.091),
|
||
("XX", 0.091),
|
||
]
|
||
)
|
||
|
||
ansatz = EfficientSU2(observable.num_qubits, reps=1)
|
||
init_param_values = np.zeros(len(ansatz.parameters))
|
||
for i in range(len(ansatz.parameters)):
|
||
init_param_values[i] = np.pi / 2
|
||
var_principle = ImaginaryMcLachlanPrinciple()
|
||
time = 1
|
||
evolution_problem = TimeEvolutionProblem(observable, time)
|
||
var_qite = VarQITE(ansatz, var_principle, init_param_values)
|
||
evolution_result = var_qite.evolve(evolution_problem)
|
||
```
|
||
|
||
* Added rules for converting [`XXPlusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXPlusYYGate "qiskit.circuit.library.XXPlusYYGate") and [`XXMinusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXMinusYYGate "qiskit.circuit.library.XXMinusYYGate") to other gates to the `SessionEquivalenceLibrary`. This enables running [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") targeting a backend or [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target") that uses these gates.
|
||
|
||
* Added two new fake backends, [`FakePrague`](/api/qiskit/0.45/qiskit.providers.fake_provider.FakePrague "qiskit.providers.fake_provider.FakePrague") and [`FakeSherbrooke`](/api/qiskit/0.45/qiskit.providers.fake_provider.FakeSherbrooke "qiskit.providers.fake_provider.FakeSherbrooke") to the [`qiskit.providers.fake_provider`](/api/qiskit/0.45/providers_fake_provider#module-qiskit.providers.fake_provider "qiskit.providers.fake_provider") module. [`FakePrague`](/api/qiskit/0.45/qiskit.providers.fake_provider.FakePrague "qiskit.providers.fake_provider.FakePrague") provides a backend with a snapshot of the properties from the IBM Prague Egret R1 backend and [`FakeSherbrooke`](/api/qiskit/0.45/qiskit.providers.fake_provider.FakeSherbrooke "qiskit.providers.fake_provider.FakeSherbrooke") provides a backend with a snapshot of the properties from the IBM Sherbrooke Eagle R3 backend.
|
||
|
||
* Added a new keyword argument, `allow_unknown_parameters`, to the [`ParameterExpression.bind()`](/api/qiskit/0.45/qiskit.circuit.ParameterExpression#bind "qiskit.circuit.ParameterExpression.bind") and [`ParameterExpression.subs()`](/api/qiskit/0.45/qiskit.circuit.ParameterExpression#subs "qiskit.circuit.ParameterExpression.subs") methods. When set this new argument enables passing a dictionary containing unknown parameters to these methods without causing an error to be raised. Previously, this would always raise an error without any way to disable that behavior.
|
||
|
||
* The [`BaseEstimator.run()`](/api/qiskit/0.45/qiskit.primitives.BaseEstimator#run "qiskit.primitives.BaseEstimator.run") method’s `observables` argument now accepts a `str` or sequence of `str` input type in addition to the other types already accepted. When used the input string format should match the Pauli string representation accepted by the constructor for [`Pauli`](/api/qiskit/0.45/qiskit.quantum_info.Pauli "qiskit.quantum_info.Pauli") objects.
|
||
|
||
* Added a new constructor method [`QuantumCircuit.from_instructions()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#from_instructions "qiskit.circuit.QuantumCircuit.from_instructions") that enables creating a [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") object from an iterable of instructions. For example:
|
||
|
||
```python
|
||
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
|
||
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
|
||
from qiskit.circuit import Measure
|
||
from qiskit.circuit.library import HGate, CXGate
|
||
|
||
|
||
qr = QuantumRegister(2)
|
||
cr = ClassicalRegister(2)
|
||
instructions = [
|
||
CircuitInstruction(HGate(), [qr[0]], []),
|
||
CircuitInstruction(CXGate(), [qr[0], qr[1]], []),
|
||
CircuitInstruction(Measure(), [qr[0]], [cr[0]]),
|
||
CircuitInstruction(Measure(), [qr[1]], [cr[1]]),
|
||
]
|
||
circuit = QuantumCircuit.from_instructions(instructions)
|
||
circuit.draw("mpl")
|
||
```
|
||
|
||

|
||
|
||
* The [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") class now takes an optional `copy` keyword argument in its constructor. If set to `False`, then a `StabilizerTable` provided as input will not be copied, but will be used directly. This can have performance benefits, if the data in the table will never be mutated by any other means.
|
||
|
||
* The performance of [`Clifford.compose()`](/api/qiskit/0.45/qiskit.quantum_info.Clifford#compose "qiskit.quantum_info.Clifford.compose") has been greatly improved for all numbers of qubits. For operators of 20 qubits, the speedup is on the order of 100 times.
|
||
|
||
* Added a new synthesis function [`synth_clifford_layers()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_clifford_layers "qiskit.synthesis.synth_clifford_layers"), for synthesizing a [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") into layers. The algorithm is based on S. Bravyi, D. Maslov, Hadamard-free circuits expose the structure of the Clifford group, [arxiv:2003.09412](https://arxiv.org/abs/2003.09412). This decomposes the Clifford into 8 layers of gates including two layers of CZ gates, and one layer of CX gates. For example, a 5-qubit Clifford circuit is decomposed into the following layers:
|
||
|
||
```python
|
||
┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐
|
||
q_0: ┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├
|
||
│ ││ ││ ││ ││ ││ ││ ││ │
|
||
q_1: ┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├
|
||
│ ││ ││ ││ ││ ││ ││ ││ │
|
||
q_2: ┤2 S2 ├┤2 CZ ├┤2 CX_dg ├┤2 H2 ├┤2 S1 ├┤2 CZ ├┤2 H1 ├┤2 Pauli ├
|
||
│ ││ ││ ││ ││ ││ ││ ││ │
|
||
q_3: ┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├
|
||
│ ││ ││ ││ ││ ││ ││ ││ │
|
||
q_4: ┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├
|
||
└─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘
|
||
```
|
||
|
||
This method will allow to decompose a [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") in 2-qubit depth $7n+2$ for linear nearest neighbor (LNN) connectivity.
|
||
|
||
* The return types for the [`power()`](/api/qiskit/0.45/qiskit.circuit.Gate#power "qiskit.circuit.Gate.power") methods on several standard library gate classes have been updated to return more specific gate objects that result in a less lossy and more efficient output. For example, running [`power()`](/api/qiskit/0.45/qiskit.circuit.library.IGate#power "qiskit.circuit.library.IGate.power") now returns an [`IGate`](/api/qiskit/0.45/qiskit.circuit.library.IGate "qiskit.circuit.library.IGate") instance instead of [`UnitaryGate`](/api/qiskit/0.45/qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.UnitaryGate") as was done previously.
|
||
|
||
The full list of output types that have been improved are:
|
||
|
||
| Gate Class | Output Class from [`power()`](/api/qiskit/0.45/qiskit.circuit.Gate#power "qiskit.circuit.Gate.power") |
|
||
| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||
| [`CPhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.CPhaseGate "qiskit.circuit.library.CPhaseGate") | [`CPhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.CPhaseGate "qiskit.circuit.library.CPhaseGate") |
|
||
| [`CSGate`](/api/qiskit/0.45/qiskit.circuit.library.CSGate "qiskit.circuit.library.CSGate") | [`CPhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.CPhaseGate "qiskit.circuit.library.CPhaseGate") |
|
||
| [`CSdgGate`](/api/qiskit/0.45/qiskit.circuit.library.CSdgGate "qiskit.circuit.library.CSdgGate") | [`CPhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.CPhaseGate "qiskit.circuit.library.CPhaseGate") |
|
||
| [`IGate`](/api/qiskit/0.45/qiskit.circuit.library.IGate "qiskit.circuit.library.IGate") | [`IGate`](/api/qiskit/0.45/qiskit.circuit.library.IGate "qiskit.circuit.library.IGate"). |
|
||
| [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`RGate`](/api/qiskit/0.45/qiskit.circuit.library.RGate "qiskit.circuit.library.RGate") | [`RGate`](/api/qiskit/0.45/qiskit.circuit.library.RGate "qiskit.circuit.library.RGate") |
|
||
| [`RXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") | [`RXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXGate "qiskit.circuit.library.RXGate") |
|
||
| [`RXXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXXGate "qiskit.circuit.library.RXXGate") | [`RXXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXXGate "qiskit.circuit.library.RXXGate") |
|
||
| [`RYGate`](/api/qiskit/0.45/qiskit.circuit.library.RYGate "qiskit.circuit.library.RYGate") | [`RYGate`](/api/qiskit/0.45/qiskit.circuit.library.RYGate "qiskit.circuit.library.RYGate") |
|
||
| [`RYYGate`](/api/qiskit/0.45/qiskit.circuit.library.RYYGate "qiskit.circuit.library.RYYGate") | [`RYYGate`](/api/qiskit/0.45/qiskit.circuit.library.RYYGate "qiskit.circuit.library.RYYGate") |
|
||
| [`RZGate`](/api/qiskit/0.45/qiskit.circuit.library.RZGate "qiskit.circuit.library.RZGate") | [`RZGate`](/api/qiskit/0.45/qiskit.circuit.library.RZGate "qiskit.circuit.library.RZGate") |
|
||
| [`RZXGate`](/api/qiskit/0.45/qiskit.circuit.library.RZXGate "qiskit.circuit.library.RZXGate") | [`RZXGate`](/api/qiskit/0.45/qiskit.circuit.library.RZXGate "qiskit.circuit.library.RZXGate") |
|
||
| [`RZZGate`](/api/qiskit/0.45/qiskit.circuit.library.RZZGate "qiskit.circuit.library.RZZGate") | [`RZZGate`](/api/qiskit/0.45/qiskit.circuit.library.RZZGate "qiskit.circuit.library.RZZGate") |
|
||
| [`SdgGate`](/api/qiskit/0.45/qiskit.circuit.library.SdgGate "qiskit.circuit.library.SdgGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`SGate`](/api/qiskit/0.45/qiskit.circuit.library.SGate "qiskit.circuit.library.SGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`TdgGate`](/api/qiskit/0.45/qiskit.circuit.library.TdgGate "qiskit.circuit.library.TdgGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`TGate`](/api/qiskit/0.45/qiskit.circuit.library.TGate "qiskit.circuit.library.TGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`XXMinusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXMinusYYGate "qiskit.circuit.library.XXMinusYYGate") | [`XXMinusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXMinusYYGate "qiskit.circuit.library.XXMinusYYGate") |
|
||
| [`XXPlusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXPlusYYGate "qiskit.circuit.library.XXPlusYYGate") | [`XXPlusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXPlusYYGate "qiskit.circuit.library.XXPlusYYGate") |
|
||
| [`ZGate`](/api/qiskit/0.45/qiskit.circuit.library.ZGate "qiskit.circuit.library.ZGate") | [`PhaseGate`](/api/qiskit/0.45/qiskit.circuit.library.PhaseGate "qiskit.circuit.library.PhaseGate") |
|
||
| [`iSwapGate`](/api/qiskit/0.45/qiskit.circuit.library.iSwapGate "qiskit.circuit.library.iSwapGate") | [`XXPlusYYGate`](/api/qiskit/0.45/qiskit.circuit.library.XXPlusYYGate "qiskit.circuit.library.XXPlusYYGate") |
|
||
|
||
* The [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") is now represented internally as a `PyDiGraph`, this underlying graph object can be accesed from the new [`graph`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary#graph "qiskit.circuit.EquivalenceLibrary.graph") attribute. This attribute is intended for use internally in Qiskit and therefore should always be copied before being modified by the user to prevent possible corruption of the internal equivalence graph.
|
||
|
||
* The [`Operator.from_circuit()`](/api/qiskit/0.45/qiskit.quantum_info.Operator#from_circuit "qiskit.quantum_info.Operator.from_circuit") constructor method now will reverse the output permutation caused by the routing/swap mapping stage of the transpiler. By default if a transpiled circuit had Swap gates inserted the output matrix will have that permutation reversed so the returned matrix will be equivalent to the original un-transpiled circuit. If you’d like to disable this default behavior the `ignore_set_layout` keyword argument can be set to `True` to do this (in addition to previous behavior of ignoring the initial layout from transpilation). If you’d like to manually set a final layout you can use the new `final_layout` keyword argument to pass in a [`Layout`](/api/qiskit/0.45/qiskit.transpiler.Layout "qiskit.transpiler.Layout") object to use for the output permutation.
|
||
|
||
* Added support to the [`GateDirection`](/api/qiskit/0.45/qiskit.transpiler.passes.GateDirection "qiskit.transpiler.passes.GateDirection") transpiler pass to handle the the symmetric [`RXXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXXGate "qiskit.circuit.library.RXXGate"), [`RYYGate`](/api/qiskit/0.45/qiskit.circuit.library.RYYGate "qiskit.circuit.library.RYYGate"), and [`RZZGate`](/api/qiskit/0.45/qiskit.circuit.library.RZZGate "qiskit.circuit.library.RZZGate") gates. The pass will now correctly handle these gates and simply reverse the qargs order in place without any other modifications.
|
||
|
||
* Added support for using the Python exponentiation operator, `**`, with [`Gate`](/api/qiskit/0.45/qiskit.circuit.Gate "qiskit.circuit.Gate") objects is now supported. It is equivalent to running the [`Gate.power()`](/api/qiskit/0.45/qiskit.circuit.Gate#power "qiskit.circuit.Gate.power") method on the object.
|
||
|
||
For example:
|
||
|
||
```python
|
||
from qiskit.circuit.library import XGate
|
||
|
||
sx = XGate() ** 0.5
|
||
```
|
||
|
||
* Added new `GaussianSquareDrag` pulse shape to the [`qiskit.pulse.library`](/api/qiskit/0.45/pulse#module-qiskit.pulse.library "qiskit.pulse.library") module. This pulse shape is similar to [`GaussianSquare`](/api/qiskit/0.45/qiskit.pulse.library.GaussianSquare "qiskit.pulse.library.GaussianSquare") but uses the [`Drag`](/api/qiskit/0.45/qiskit.pulse.library.Drag_class.rst#qiskit.pulse.library.Drag "qiskit.pulse.library.Drag") shape during its rise and fall. The correction from the DRAG pulse shape can suppress part of the frequency spectrum of the rise and fall of the pulse which can help avoid exciting spectator qubits when they are close in frequency to the drive frequency of the pulse.
|
||
|
||
* Added a new keyword argument, `method`, to the constructors for the [`FiniteDiffEstimatorGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.FiniteDiffEstimatorGradient "qiskit.algorithms.gradients.FiniteDiffEstimatorGradient") and [`FiniteDiffSamplerGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.FiniteDiffSamplerGradient "qiskit.algorithms.gradients.FiniteDiffSamplerGradient") classes. The `method` argument accepts a string to indicate the computation method to use for the gradient. There are three methods, available `"central"`, `"forward"`, and `"backward"`. The definition of the methods are:
|
||
|
||
| Method | Computation |
|
||
| ------------ | -------------------------- |
|
||
| `"central"` | $\frac{f(x+e)-f(x-e)}{2e}$ |
|
||
| `"forward"` | $\frac{f(x+e) - f(x)}{e}$ |
|
||
| `"backward"` | $\frac{f(x)-f(x-e)}{e}$ |
|
||
|
||
where $e$ is the offset epsilon.
|
||
|
||
* All gradient classes in [`qiskit.algorithms.gradients`](/api/qiskit/0.45/qiskit.algorithms.gradients#module-qiskit.algorithms.gradients "qiskit.algorithms.gradients") now preserve unparameterized operations instead of attempting to unroll them. This allows to evaluate gradients on custom, opaque gates that individual primitives can handle and keeps a higher level of abstraction for optimized synthesis and compilation after the gradient circuits have been constructed.
|
||
|
||
* Added a [`TranslateParameterizedGates`](/api/qiskit/0.45/qiskit.transpiler.passes.TranslateParameterizedGates "qiskit.transpiler.passes.TranslateParameterizedGates") pass to map only parameterized gates in a circuit to a specified basis, but leave unparameterized gates untouched. The pass first attempts unrolling and finally translates if a parameterized gate cannot be further unrolled.
|
||
|
||
* The [`CollectCliffords`](/api/qiskit/0.45/qiskit.transpiler.passes.CollectCliffords "qiskit.transpiler.passes.CollectCliffords") transpiler pass has been expanded to collect and combine blocks of “clifford gates” into [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") objects, where “clifford gates” may now also include objects of type [`LinearFunction`](/api/qiskit/0.45/qiskit.circuit.library.LinearFunction "qiskit.circuit.library.LinearFunction"), [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford"), and [`PauliGate`](/api/qiskit/0.45/qiskit.circuit.library.PauliGate "qiskit.circuit.library.PauliGate"). For example:
|
||
|
||
```python
|
||
from qiskit.circuit import QuantumCircuit
|
||
from qiskit.circuit.library import LinearFunction, PauliGate
|
||
from qiskit.quantum_info.operators import Clifford
|
||
from qiskit.transpiler.passes import CollectCliffords
|
||
from qiskit.transpiler import PassManager
|
||
|
||
# Create a Clifford
|
||
cliff_circuit = QuantumCircuit(2)
|
||
cliff_circuit.cx(0, 1)
|
||
cliff_circuit.h(0)
|
||
cliff = Clifford(cliff_circuit)
|
||
|
||
# Create a linear function
|
||
lf = LinearFunction([[0, 1], [1, 0]])
|
||
|
||
# Create a pauli gate
|
||
pauli_gate = PauliGate("XYZ")
|
||
|
||
# Create a quantum circuit with the above and also simple clifford gates.
|
||
qc = QuantumCircuit(4)
|
||
qc.cz(0, 1)
|
||
qc.append(cliff, [0, 1])
|
||
qc.h(0)
|
||
qc.append(lf, [0, 2])
|
||
qc.append(pauli_gate, [0, 2, 1])
|
||
qc.x(2)
|
||
|
||
# Run CollectCliffords transpiler pass
|
||
qct = PassManager(CollectCliffords()).run(qc)
|
||
```
|
||
|
||
All the gates will be collected and combined into a single [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford"). Thus the final circuit consists of a single [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") object.
|
||
|
||
* [`CouplingMap`](/api/qiskit/0.45/qiskit.transpiler.CouplingMap "qiskit.transpiler.CouplingMap") is now implicitly iterable, with the iteration being identical to iterating through the output of [`CouplingMap.get_edges()`](/api/qiskit/0.45/qiskit.transpiler.CouplingMap#get_edges "qiskit.transpiler.CouplingMap.get_edges"). In other words,
|
||
|
||
```python
|
||
from qiskit.transpiler import CouplingMap
|
||
coupling = CouplingMap.from_line(3)
|
||
list(coupling) == list(coupling.get_edges())
|
||
```
|
||
|
||
will now function as expected, as will other iterations. This is purely a syntactic convenience.
|
||
|
||
* Added a new function [`synth_cnot_count_full_pmh()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_cnot_count_full_pmh "qiskit.synthesis.synth_cnot_count_full_pmh") which is used to synthesize linear reversible circuits for all-to-all architectures using the Patel, Markov and Hayes method. This function is identical to the available `qiskit.transpiler.synthesis.cnot_synth()` function but has a more descriptive name and is more logically placed in the package tree. This new function supersedes the legacy function which will likely be deprecated in a future release.
|
||
|
||
* [`InstructionScheduleMap`](/api/qiskit/0.45/qiskit.pulse.InstructionScheduleMap "qiskit.pulse.InstructionScheduleMap") has been updated to store backend calibration data in the format of PulseQobj JSON and invokes conversion when the data is accessed for the first time, i.e. lazy conversion. This internal logic update drastically improves the performance of loading backend especially with many calibration entries.
|
||
|
||
* New module `qiskit.pulse.calibration_entries` has been added. This contains several wrapper classes for different pulse schedule representations.
|
||
|
||
* `ScheduleDef`
|
||
* `CallableDef`
|
||
* `PulseQobjDef`
|
||
|
||
These classes implement the `get_schedule()` and `get_signature()` methods that returns pulse schedule and parameter names to assign, respectively. These classes are internally managed by the [`InstructionScheduleMap`](/api/qiskit/0.45/qiskit.pulse.InstructionScheduleMap "qiskit.pulse.InstructionScheduleMap") or backend [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target"), and thus they will not appear in a typical user programs.
|
||
|
||
* Introduced a new subclass `ScalableSymbolicPulse`, as a subclass of [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse"). The new subclass behaves the same as [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse"), except that it assumes that the envelope of the pulse includes a complex amplitude pre-factor of the form $\text{amp} * e^{i \times \text{angle}}$. This envelope shape matches many common pulses, including all of the pulses in the Qiskit Pulse library (which were also converted to `amp`, `angle` representation in this release).
|
||
|
||
The new subclass removes the non-unique nature of the `amp`, `angle` representation, and correctly compares pulses according to their complex amplitude.
|
||
|
||
* Added a new keyword argument, `dtype`, to the [`PauliSumOp.from_list()`](/api/qiskit/0.45/qiskit.opflow.primitive_ops.PauliSumOp#from_list "qiskit.opflow.primitive_ops.PauliSumOp.from_list") method. When specified this argument can be used to specify the `dtype` of the numpy array allocated for the [`SparsePauliOp`](/api/qiskit/0.45/qiskit.quantum_info.SparsePauliOp "qiskit.quantum_info.SparsePauliOp") used internally by the constructed [`PauliSumOp`](/api/qiskit/0.45/qiskit.opflow.primitive_ops.PauliSumOp "qiskit.opflow.primitive_ops.PauliSumOp").
|
||
|
||
* Support for importing OpenQASM 3 programs into Qiskit has been added. This can most easily be accessed using the functions [`qasm3.loads()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.loads "qiskit.qasm3.loads") and [`qasm3.load()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.load "qiskit.qasm3.load"), to load a program directly from a string and indirectly from a filename, respectively. For example, one can now do:
|
||
|
||
```python
|
||
from qiskit import qasm3
|
||
|
||
circuit = qasm3.loads("""
|
||
OPENQASM 3.0;
|
||
include "stdgates.inc";
|
||
|
||
qubit q;
|
||
qubit[5] qr;
|
||
bit c;
|
||
bit[5] cr;
|
||
|
||
h q;
|
||
c = measure q;
|
||
|
||
if (c) {
|
||
h qr[0];
|
||
cx qr[0], qr[1];
|
||
cx qr[0], qr[2];
|
||
cx qr[0], qr[3];
|
||
cx qr[0], qr[4];
|
||
} else {
|
||
h qr[4];
|
||
cx qr[4], qr[3];
|
||
cx qr[4], qr[2];
|
||
cx qr[4], qr[1];
|
||
cx qr[4], qr[0];
|
||
}
|
||
cr = measure qr;
|
||
""")
|
||
```
|
||
|
||
This will load the program into a [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") instance in the variable `circuit`.
|
||
|
||
Not all OpenQASM 3 features are supported at first, because Qiskit does not yet have a way to represent advanced classical data processing. The capabilities of the importer will increase along with the capabilities of the rest of Qiskit. The initial feature set of the importer is approximately the same set of features that would be output by the exporter ([`qasm3.dump()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.dump "qiskit.qasm3.dump") and [`qasm3.dumps()`](/api/qiskit/0.45/qasm3#qiskit.qasm3.dumps "qiskit.qasm3.dumps")).
|
||
|
||
Note that Qiskit’s support of OpenQASM 3 is not meant to provide a totally lossless representation of [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit")s. For that, consider using [`qiskit.qpy`](/api/qiskit/0.45/qpy#module-qiskit.qpy "qiskit.qpy").
|
||
|
||
* The [`primitives`](/api/qiskit/0.45/primitives#module-qiskit.primitives "qiskit.primitives")-based gradient classes defined by the [`BaseEstimatorGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.BaseEstimatorGradient "qiskit.algorithms.gradients.BaseEstimatorGradient") and [`BaseSamplerGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.BaseSamplerGradient "qiskit.algorithms.gradients.BaseSamplerGradient") abstract classes have been updated to simplify extending the base interface. There are three new internal overridable methods, `_preprocess()`, `_postprocess()`, and `_run_unique()`. `_preprocess()` enables a subclass to customize the input gradient circuits and parameters, `_postprocess` enables to customize the output result, and `_run_unique` enables calculating the gradient of a circuit with unique parameters.
|
||
|
||
* The [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") transpiler pass has greatly improved performance as it has been re-written in Rust. As part of this rewrite the pass has been transformed from an analysis pass to a transformation pass that will run both layout and routing. This was done to not only improve the runtime performance but also improve the quality of the results. The previous functionality of the pass as an analysis pass can be retained by manually setting the `routing_pass` argument or using the new `skip_routing` argument.
|
||
|
||
* The [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") transpiler pass has a new constructor argument `layout_trials`. This argument is used to control how many random number generator seeds will be attempted to run [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") with. When set the SABRE layout algorithm is run `layout_trials` number of times and the best quality output (measured in the lowest number of swap gates added) is selected. These seed trials are executed in parallel using multithreading to minimize the potential performance overhead of running layout multiple times. By default if this is not specified the [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") pass will default to using the number of physical CPUs are available on the local system.
|
||
|
||
* Added two new classes [`SciPyRealEvolver`](/api/qiskit/0.45/qiskit.algorithms.SciPyRealEvolver "qiskit.algorithms.SciPyRealEvolver") and [`SciPyImaginaryEvolver`](/api/qiskit/0.45/qiskit.algorithms.SciPyImaginaryEvolver "qiskit.algorithms.SciPyImaginaryEvolver") that implement integration methods for time evolution of a quantum state. The value and standard deviation of observables as well as the times they are evaluated at can be queried as [`TimeEvolutionResult.observables`](/api/qiskit/0.45/qiskit.algorithms.TimeEvolutionResult#observables "qiskit.algorithms.TimeEvolutionResult.observables") and [`TimeEvolutionResult.times`](/api/qiskit/0.45/qiskit.algorithms.TimeEvolutionResult#times "qiskit.algorithms.TimeEvolutionResult.times"). For example:
|
||
|
||
```python
|
||
from qiskit.algorithms.time_evolvers.time_evolution_problem import TimeEvolutionProblem
|
||
from qiskit.quantum_info import SparsePauliOp
|
||
from qiskit.quantum_info.states.statevector import Statevector
|
||
from qiskit.algorithms import SciPyImaginaryEvolver
|
||
|
||
initial_state = Statevector.from_label("+++++")
|
||
hamiltonian = SparsePauliOp("ZZZZZ")
|
||
evolution_problem = TimeEvolutionProblem(hamiltonian, 100, initial_state, {"Energy":hamiltonian})
|
||
classic_evolver = SciPyImaginaryEvolver(num_timesteps=300)
|
||
result = classic_evolver.evolve(evolution_problem)
|
||
print(result.observables)
|
||
```
|
||
|
||
* Added the [`SolovayKitaev`](/api/qiskit/0.45/qiskit.transpiler.passes.SolovayKitaev "qiskit.transpiler.passes.SolovayKitaev") transpiler pass to run the Solovay-Kitaev algorithm for approximating single-qubit unitaries using a discrete gate set. In combination with the basis translator, this allows to convert any unitary circuit to a universal discrete gate set, which could be implemented fault-tolerantly.
|
||
|
||
This pass can e.g. be used after compiling to U and CX gates:
|
||
|
||
```python
|
||
from qiskit import transpile
|
||
from qiskit.circuit.library import QFT
|
||
from qiskit.transpiler.passes.synthesis import SolovayKitaev
|
||
|
||
qft = QFT(3)
|
||
|
||
# optimize to general 1-qubit unitaries and CX
|
||
transpiled = transpile(qft, basis_gates=["u", "cx"], optimization_level=1)
|
||
|
||
skd = SolovayKitaev() # uses T Tdg and H as default basis
|
||
discretized = skd(transpiled)
|
||
|
||
print(discretized.count_ops())
|
||
```
|
||
|
||
The decomposition can also be used with the unitary synthesis plugin, as the “sk” method on the [`UnitarySynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.UnitarySynthesis "qiskit.transpiler.passes.UnitarySynthesis") transpiler pass:
|
||
|
||
```python
|
||
from qiskit import QuantumCircuit
|
||
from qiskit.quantum_info import Operator
|
||
from qiskit.transpiler.passes import UnitarySynthesis
|
||
|
||
circuit = QuantumCircuit(1)
|
||
circuit.rx(0.8, 0)
|
||
unitary = Operator(circuit).data
|
||
|
||
unitary_circ = QuantumCircuit(1)
|
||
unitary_circ.unitary(unitary, [0])
|
||
|
||
synth = UnitarySynthesis(basis_gates=["h", "s"], method="sk")
|
||
out = synth(unitary_circ)
|
||
|
||
out.draw('mpl')
|
||
```
|
||
|
||

|
||
|
||
* Random-circuit generation with [`qiskit.circuit.random.random_circuit()`](/api/qiskit/0.45/circuit#qiskit.circuit.random.random_circuit "qiskit.circuit.random.random_circuit") is now significantly faster for large circuits.
|
||
|
||
* Random-circuit generation with [`qiskit.circuit.random.random_circuit()`](/api/qiskit/0.45/circuit#qiskit.circuit.random.random_circuit "qiskit.circuit.random.random_circuit") will now output all “standard” gates in Qiskit’s circuit library ([`qiskit.circuit.library`](/api/qiskit/0.45/circuit_library#module-qiskit.circuit.library "qiskit.circuit.library")). This includes two 4-qubit gates [`C3SXGate`](/api/qiskit/0.45/qiskit.circuit.library.C3SXGate "qiskit.circuit.library.C3SXGate") and [`RC3XGate`](/api/qiskit/0.45/qiskit.circuit.library.RC3XGate "qiskit.circuit.library.RC3XGate"), and the allowed values of `max_operands` have been expanded accordingly.
|
||
|
||
* The [`Optimize1qGatesDecomposition`](/api/qiskit/0.45/qiskit.transpiler.passes.Optimize1qGatesDecomposition "qiskit.transpiler.passes.Optimize1qGatesDecomposition") transpiler pass has a new keyword argument, `target`, on its constructor. This argument can be used to specify a [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target") object that represnts the compilation target. If used it superscedes the `basis` argument to determine if an instruction in the circuit is present on the target backend.
|
||
|
||
* The [`UnrollCustomDefinitions`](/api/qiskit/0.45/qiskit.transpiler.passes.UnrollCustomDefinitions "qiskit.transpiler.passes.UnrollCustomDefinitions") transpiler pass has a new keyword argument, `target`, on its constructor. This argument can be used to specify a [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target") object that represnts the compilation target. If used it superscedes the `basis_gates` argument to determine if an instruction in the circuit is present on the target backend.
|
||
|
||
* Added the [`ReverseEstimatorGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.ReverseEstimatorGradient "qiskit.algorithms.gradients.ReverseEstimatorGradient") class for a classical, fast evaluation of expectation value gradients based on backpropagation or reverse-mode gradients. This class uses statevectors and thus provides exact gradients but scales exponentially in system size. It is designed for fast reference calculation of smaller system sizes. It can for example be used as:
|
||
|
||
```python
|
||
from qiskit.circuit.library import EfficientSU2
|
||
from qiskit.quantum_info import SparsePauliOp
|
||
from qiskit.algorithms.gradients import ReverseEstimatorGradient
|
||
|
||
observable = SparsePauliOp.from_sparse_list([("ZZ", [0, 1], 1)], num_qubits=10)
|
||
circuit = EfficientSU2(num_qubits=10)
|
||
values = [i / 100 for i in range(circuit.num_parameters)]
|
||
gradient = ReverseEstimatorGradient()
|
||
|
||
result = gradient.run([circuit], [observable], [values]).result()
|
||
```
|
||
|
||
* Added a new keyword argument, `use_dag` to the constructor for the [`OneQubitEulerDecomposer`](/api/qiskit/0.45/qiskit.quantum_info.OneQubitEulerDecomposer "qiskit.quantum_info.OneQubitEulerDecomposer") class. When `use_dag` is set to `True` the output from the decomposer will be a [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") object instead of [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") object. This is useful for transpiler passes that use [`OneQubitEulerDecomposer`](/api/qiskit/0.45/qiskit.quantum_info.OneQubitEulerDecomposer "qiskit.quantum_info.OneQubitEulerDecomposer") (such as [`Optimize1qGatesDecomposition`](/api/qiskit/0.45/qiskit.transpiler.passes.Optimize1qGatesDecomposition "qiskit.transpiler.passes.Optimize1qGatesDecomposition")) as working directly with a [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") avoids the overhead of converting between [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") and [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit").
|
||
|
||
* Added the ability for analysis passes to set custom heuristic weights for the [`VF2Layout`](/api/qiskit/0.45/qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") and [`VF2PostLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") transpiler passes. If an analysis pass sets the `vf2_avg_error_map` key in the property set, its value is used for the error weights instead of the error rates from the backend’s [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target") (or [`BackendProperties`](/api/qiskit/0.45/qiskit.providers.models.BackendProperties "qiskit.providers.models.BackendProperties") for [`BackendV1`](/api/qiskit/0.45/qiskit.providers.BackendV1 "qiskit.providers.BackendV1")). The value should be an `ErrorMap` instance, where each value represents the avg error rate for all 1 or 2 qubit operation on those qubits. If a value is `NaN`, the corresponding edge is treated as an ideal edge (or qubit for 1q operations). For example, an error map created as:
|
||
|
||
```python
|
||
from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
|
||
|
||
error_map = ErrorMap(3)
|
||
error_map.add_error((0, 0), 0.0024)
|
||
error_map.add_error((0, 1), 0.01)
|
||
error_map.add_error((1, 1), 0.0032)
|
||
```
|
||
|
||
describes a 2 qubit target, where the avg 1q error rate is `0.0024` on qubit 0 and `0.0032` on qubit 1, the avg 2q error rate for gates that operate on (0, 1) is 0.01, and (1, 0) is not supported by the target. This will be used for scoring if it’s set for the `vf2_avg_error_map` key in the property set when [`VF2Layout`](/api/qiskit/0.45/qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") and [`VF2PostLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.VF2PostLayout "qiskit.transpiler.passes.VF2PostLayout") are run. For example:
|
||
|
||
```python
|
||
from qiskit.transpiler import AnalysisPass, PassManager, Target
|
||
from qiskit.transpiler.passes import VF2Layout
|
||
from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
|
||
from qiskit.circuit.library import CZGate, UGate
|
||
from qiskit.circuit import Parameter
|
||
|
||
class CustomVF2Scoring(AnalysisPass):
|
||
"""Set custom score for vf2."""
|
||
|
||
def run(self, dag):
|
||
error_map = ErrorMap(3)
|
||
error_map.add_error((0, 0), 0.0024)
|
||
error_map.add_error((0, 1), 0.01)
|
||
error_map.add_error((1, 1), 0.0032)
|
||
self.property_set["vf2_avg_error_map"] = error_map
|
||
|
||
|
||
target = Target(num_qubits=2)
|
||
target.add_instruction(
|
||
UGate(Parameter('theta'), Parameter('phi'), Parameter('lam')),
|
||
{(0,): None, (1,): None}
|
||
)
|
||
target.add_instruction(
|
||
CZGate(), {(0, 1): None}
|
||
)
|
||
|
||
vf2_pass = VF2Layout(target=target, seed=1234568942)
|
||
pm = PassManager([CustomVF2Scoring(), vf2_pass])
|
||
```
|
||
|
||
That will run [`VF2Layout`](/api/qiskit/0.45/qiskit.transpiler.passes.VF2Layout "qiskit.transpiler.passes.VF2Layout") with the custom scoring from `error_map` for a 2 qubit [`Target`](/api/qiskit/0.45/qiskit.transpiler.Target "qiskit.transpiler.Target") that doesn’t contain any error rates.
|
||
|
||
<span id="release-notes-0-23-0-upgrade-notes" />
|
||
|
||
<span id="id66" />
|
||
|
||
#### Upgrade Notes
|
||
|
||
* When initializing any of the pulse classes in [`qiskit.pulse.library`](/api/qiskit/0.45/pulse#module-qiskit.pulse.library "qiskit.pulse.library"):
|
||
|
||
> * [`Gaussian`](/api/qiskit/0.45/qiskit.pulse.library.Gaussian_class.rst#qiskit.pulse.library.Gaussian "qiskit.pulse.library.Gaussian")
|
||
> * [`GaussianSquare`](/api/qiskit/0.45/qiskit.pulse.library.GaussianSquare "qiskit.pulse.library.GaussianSquare")
|
||
> * [`Drag`](/api/qiskit/0.45/qiskit.pulse.library.Drag_class.rst#qiskit.pulse.library.Drag "qiskit.pulse.library.Drag")
|
||
> * [`Constant`](/api/qiskit/0.45/qiskit.pulse.library.Constant_class.rst#qiskit.pulse.library.Constant "qiskit.pulse.library.Constant")
|
||
|
||
providing a complex `amp` argument with a finite `angle` will result in [`PulseError`](/api/qiskit/0.45/pulse#qiskit.pulse.PulseError "qiskit.pulse.PulseError") now. For example, instead of calling `Gaussian(duration=100,sigma=20,amp=0.5j)` one should use `Gaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2)` instead now. The pulse envelope which used to be defined as `amp * ...` is in turn defined as `amp * exp(1j * angle) * ...`. This change was made to better support [Qiskit Experiments](https://qiskit.org/documentation/experiments/) where the amplitude and angle of pulses are calibrated in separate experiments.
|
||
|
||
* For Python 3.7 [singledispatchmethod](https://pypi.org/project/singledispatchmethod/) is now a dependency. This was added to enable leveraging the method dispatch mechanism in the standard library of newer versions of Python. If you’re on Python >= 3.8 there is no extra dependency required.
|
||
|
||
* The previously deprecated `MSBasisDecomposer` transpiler pass available via the [`qiskit.transpiler.passes`](/api/qiskit/0.45/transpiler_passes#module-qiskit.transpiler.passes "qiskit.transpiler.passes") module has been removed. It was originally deprecated as part of the Qiskit Terra 0.16.0 release (10-16-2020). Instead the [`BasisTranslator`](/api/qiskit/0.45/qiskit.transpiler.passes.BasisTranslator "qiskit.transpiler.passes.BasisTranslator") transpiler pass should be used instead to translate a circuit into an appropriate basis with a [`RXXGate`](/api/qiskit/0.45/qiskit.circuit.library.RXXGate "qiskit.circuit.library.RXXGate")
|
||
|
||
* [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") objects that are initialized with the `base` attribute will no long have a shared reference with the [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") passed in. In earlier releases if you mutated `base` after it was used to create a new [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") instance both instances would reflect that change. This no longer is the case and updates to `base` will no longer be reflected in the new [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary"). For example, if you created an equivalence library with:
|
||
|
||
```python
|
||
import math
|
||
|
||
from qiskit.circuit import QuantumCircuit
|
||
from qiskit.circuit.library import XGate
|
||
from qiskit.circuit.equivalence import EquivalenceLibrary
|
||
|
||
original_lib = EquivalenceLibrary()
|
||
qc = QuantumCircuit(1)
|
||
qc.rx(math.pi, 0)
|
||
original_lib.add_equivalence(XGate(), qc)
|
||
new_lib = EquivalenceLibrary(base=original_lib)
|
||
```
|
||
|
||
if you modified `original_lib` with:
|
||
|
||
```python
|
||
import from qiskit.circuit.library import SXGate
|
||
|
||
qc = QuantumCircuit(1)
|
||
qc.rx(math.pi / 2, 0)
|
||
original_lib.add_equivalence(SXGate(), qc)
|
||
```
|
||
|
||
in previous releases `new_lib` would also include the definition of `SXGate` after it was added to `original_lib`, but in this release this no longer will be the case. This change was made because of the change in internal data structure to be a graph, which improved performance of the [`EquivalenceLibrary`](/api/qiskit/0.45/qiskit.circuit.EquivalenceLibrary "qiskit.circuit.EquivalenceLibrary") class, especially when there are multiple runs of the [`BasisTranslator`](/api/qiskit/0.45/qiskit.transpiler.passes.BasisTranslator "qiskit.transpiler.passes.BasisTranslator") transpiler pass.
|
||
|
||
* The `initial_state` argument for the constructor of the [`NLocal`](/api/qiskit/0.45/qiskit.circuit.library.NLocal "qiskit.circuit.library.NLocal") class along with assigning directly to the `NLocal.initial_state` atrribute must be a [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") now. Support for using other types for this argument and attribute is no longer supported. Support for other types was deprecated as part of the Qiskit Terra 0.18.0 release (July 2021).
|
||
|
||
* The LaTeX array drawers (e.g. `array_to_latex`, `Statevector.draw('latex')`) now use the same sympy function as the ket-convention drawer. This means it may render some numbers differently to previous releases, but will provide a more consistent experience. For example, it may identify new factors, or rationalize denominators where it did not previously. The default `precision` has been changed from 5 to 10.
|
||
|
||
* The QPY version format version emitted by [`dump()`](/api/qiskit/0.45/qpy#qiskit.qpy.dump "qiskit.qpy.dump") has been increased to version 6. This new format version is incompatible with the previous versions and will result in an error when trying to load it with a deserializer that isn’t able to handle QPY version 6. This change was necessary to support the introduction of `ScalableSymbolicPulse` which was handled by adding a `class_name_size` attribute to the header of the dumped [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse") objects.
|
||
|
||
* The `__hash__` method for the [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse") was removed. This was done to reflect the mutable nature (via parameter assignment) of this class which could result in errors when using [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse") in situtations where a hashable object was required. This means the builtin `hash()` method and using [`SymbolicPulse`](/api/qiskit/0.45/qiskit.pulse.library.SymbolicPulse "qiskit.pulse.library.SymbolicPulse") as keys in dictionaries or set members will no longer work.
|
||
|
||
* The names of [`Register`](/api/qiskit/0.45/qiskit.circuit.Register "qiskit.circuit.Register") instances (which includes instances of [`QuantumRegister`](/api/qiskit/0.45/qiskit.circuit.QuantumRegister "qiskit.circuit.QuantumRegister") and `ClassicalRegigster`) are no longer constrained to be valid OpenQASM 2 identifiers. This is being done as the restriction is overly strict as Qiskit becomes more decoupled from OpenQASM 2, and even the OpenQASM 3 specification is not so restrictive. If you were relying on registers having valid OpenQASM 2 identifier names, you will need to begin escaping the names. A simplistic version of this could be done, for example, by:
|
||
|
||
```python
|
||
import re
|
||
import string
|
||
|
||
def escape(name: str) -> str:
|
||
out = re.sub(r"\W", "_", name, flags=re.ASCII)
|
||
if not out or out[0] not in string.ascii_lowercase:
|
||
return "reg_" + out
|
||
return out
|
||
```
|
||
|
||
* The [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") methods `u1`, `u2`, `u3`, and their controlled variants `cu1`, `cu3` and `mcu1` have been removed following their deprecation in Qiskit Terra 0.16.0. This was to remove gate names that were usually IBM-specific, in favour of the more general methods [`p()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#p "qiskit.circuit.QuantumCircuit.p"), [`u()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#u "qiskit.circuit.QuantumCircuit.u"), [`cp()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#cp "qiskit.circuit.QuantumCircuit.cp") and [`cu()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#cu "qiskit.circuit.QuantumCircuit.cu"). The gate classes [`U1Gate`](/api/qiskit/0.45/qiskit.circuit.library.U1Gate "qiskit.circuit.library.U1Gate"), [`U2Gate`](/api/qiskit/0.45/qiskit.circuit.library.U2Gate "qiskit.circuit.library.U2Gate") and [`U3Gate`](/api/qiskit/0.45/qiskit.circuit.library.U3Gate "qiskit.circuit.library.U3Gate") are still available for use with [`QuantumCircuit.append()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#append "qiskit.circuit.QuantumCircuit.append"), so backends can still support bases with these gates explicitly given.
|
||
|
||
* The [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") methods `combine` and `extend` have been removed following their deprecation in Qiskit Terra 0.17.0. This was done because these functions were simply less powerful versions of [`QuantumCircuit.compose()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#compose "qiskit.circuit.QuantumCircuit.compose"), which should be used instead.
|
||
|
||
The removal of `extend` also means that the `+` and `+=` operators are no longer defined for [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit"). Instead, you can use the `&` and `&=` operators respectively, which use [`QuantumCircuit.compose()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#compose "qiskit.circuit.QuantumCircuit.compose").
|
||
|
||
* The previously deprecated functions: `qiskit.circuit.measure.measure()` and `qiskit.circuit.reset.reset()` have been removed. These functions were deprecated in the Qiskit Terra 0.19.0 release (December, 2021). Instead you should use the [`QuantumCircuit.measure()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#measure "qiskit.circuit.QuantumCircuit.measure") and [`QuantumCircuit.reset()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#reset "qiskit.circuit.QuantumCircuit.reset") methods of the [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") object you wish to append a [`Measure`](/api/qiskit/0.45/qiskit.circuit.library.Measure "qiskit.circuit.library.Measure") or [`Reset`](/api/qiskit/0.45/qiskit.circuit.library.Reset "qiskit.circuit.library.Reset") operation to.
|
||
|
||
* The previously deprecated `ParameterView` methods which were inherited from `set` have been removed from `ParameterView`, the type returned by [`QuantumCircuit.parameters`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#parameters "qiskit.circuit.QuantumCircuit.parameters"). The specific methods which have been removed are:
|
||
|
||
> * `add()`
|
||
> * `difference()`
|
||
> * `difference_update()`
|
||
> * `discard()`
|
||
> * `intersection()`
|
||
> * `intersection_update()`
|
||
> * `issubset()`
|
||
> * `issuperset()`
|
||
> * `symmetric_difference()`
|
||
> * `symmetric_difference_update()`
|
||
> * `union()`
|
||
> * `update()`
|
||
|
||
along with support for the Python operators:
|
||
|
||
> * `ixor`: `^=`
|
||
> * `isub`: `-=`
|
||
> * `ior`: `|=`
|
||
|
||
These were deprecated in the Qiskit Terra 0.17.0 release (April, 2021). The `ParameterView` type is now a general sequence view type and doesn’t support these `set` operations any longer.
|
||
|
||
* The previously deprecated [NetworkX](https://networkx.org/) converter methods for the [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") and [`DAGDependency`](/api/qiskit/0.45/qiskit.dagcircuit.DAGDependency "qiskit.dagcircuit.DAGDependency") classes: `DAGCircuit.to_networkx()`, `DAGCircuit.from_networkx()`, and `DAGDependency.to_networkx()` have been removed. These methods were originally deprecated as part of the Qiskit Terra 0.21.0 release (June, 2022). Qiskit has been using [rustworkx](https://qiskit.org/documentation/rustworkx/) as its graph library since the qiskit-terra 0.12.0 release and since then the NetworkX converter function have been a lossy process. They were originally added so that users could leverage NetworkX’s algorithms library to leverage functionality not present in [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") and/or rustworkx. However, since that time both [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") and rustworkx has matured and offers more functionality and the [`DAGCircuit`](/api/qiskit/0.45/qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit") is tightly coupled to rustworkx for its operation and having these converter methods provided limited functionality and therefore have been removed.
|
||
|
||
* `tweedledum` has been removed as a core requirement of Qiskit Terra. The functionality provided ([`qiskit.circuit.classicalfunction`](/api/qiskit/0.45/classicalfunction#module-qiskit.circuit.classicalfunction "qiskit.circuit.classicalfunction")) is still available, if `tweedledum` is installed manually, such as by:
|
||
|
||
```python
|
||
pip install tweedledum
|
||
```
|
||
|
||
This change was made because `tweedledum` development has slowed to the point of not keeping up with new Python and OS releases, and was blocking some Qiskit users from installing Qiskit.
|
||
|
||
* The lazy optional checkers [`HAS_MATPLOTLIB`](/api/qiskit/0.45/utils#external-python-libraries "qiskit.utils.optionals.HAS_MATPLOTLIB"), [`HAS_PIL`](/api/qiskit/0.45/utils#external-python-libraries "qiskit.utils.optionals.HAS_PIL"), [`HAS_PYLATEX`](/api/qiskit/0.45/utils#external-python-libraries "qiskit.utils.optionals.HAS_PYLATEX") and [`HAS_PDFTOCAIRO`](/api/qiskit/0.45/utils#external-command-line-tools "qiskit.utils.optionals.HAS_PDFTOCAIRO") are no longer exposed from [`qiskit.visualization`](/api/qiskit/0.45/visualization#module-qiskit.visualization "qiskit.visualization"), having been deprecated in Qiskit Terra 0.21. The canonical location for these (and many other lazy checkers) is [`qiskit.utils.optionals`](/api/qiskit/0.45/utils#module-qiskit.utils.optionals "qiskit.utils.optionals"), and all four objects can be found there.
|
||
|
||
* The previously deprecated `gate` argument to the constructor of the [`Decompose`](/api/qiskit/0.45/qiskit.transpiler.passes.Decompose "qiskit.transpiler.passes.Decompose") transpiler pass, along with its matching attribute `Decompose.gate` have been removed. The argument and attribute were deprecated as part of the Qiskit Terra 0.19.0 release (December, 2021). Instead the `gates_to_decompose` argument for the constructor along with the `Decompose.gates_to_decompose` attribute should be used instead. The `gates_to_decompose` argument and attribute should function the same, but has a more explicit name and also enables specifying lists of gates instead of only supporting a single gate.
|
||
|
||
* The previously deprecated `label` argument for the constructor of the [`MCMT`](/api/qiskit/0.45/qiskit.circuit.library.MCMT "qiskit.circuit.library.MCMT") and [`MCMTVChain`](/api/qiskit/0.45/qiskit.circuit.library.MCMTVChain "qiskit.circuit.library.MCMTVChain") classes has been removed. It was deprecated as of the Qiskit Terra 0.19.0 release (Decemeber, 2021). Using the `label` argument on these classes was undefined behavior as they are subclasses of [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") instead of [`Instruction`](/api/qiskit/0.45/qiskit.circuit.Instruction "qiskit.circuit.Instruction"). This would result in the assigned label generally being ignored. If you need to assign a `label` to an instance of [`MCMT`](/api/qiskit/0.45/qiskit.circuit.library.MCMT "qiskit.circuit.library.MCMT") or [`MCMTVChain`](/api/qiskit/0.45/qiskit.circuit.library.MCMTVChain "qiskit.circuit.library.MCMTVChain") you should convert them to an [`Gate`](/api/qiskit/0.45/qiskit.circuit.Gate "qiskit.circuit.Gate") instance with [`to_gate()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#to_gate "qiskit.circuit.QuantumCircuit.to_gate") and then assign the desired label to [`label`](/api/qiskit/0.45/qiskit.circuit.Gate#label "qiskit.circuit.Gate.label") attribute. For example:
|
||
|
||
```python
|
||
from qiskit.circuit.library import MCMT, XGate
|
||
|
||
mcmt_circuit = MCMT(XGate(), 3, 2)
|
||
mcmt_gate = mcmt_circuit.to_gate()
|
||
mcmt_gate.label = "Custom MCMT X"
|
||
```
|
||
|
||
* The `retworkx` dependency for Qiskit has been removed and replaced by `rustworkx` library. These are the same packages, but `rustworkx` is the new name for `retworkx` which was renamed as part of their combined 0.12.0 release. If you were previously using retworkx 0.12.0 with Qiskit then you already installed rustworkx (retworkx 0.12.0 was just a redirect shim for backwards compatibility). This change was made to migrate to the new package name which will be the only supported package in the future.
|
||
|
||
* The default behavior of the [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") compiler pass has changed. The pass is no longer an [`AnalysisPass`](/api/qiskit/0.45/qiskit.transpiler.AnalysisPass "qiskit.transpiler.AnalysisPass") and by default will compute the initital layout, apply it to the circuit, and will also run [`SabreSwap`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap") internally and apply the swap mapping and set the `final_layout` property set with the permutation caused by swap insertions. This means for users running [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") as part of a custom [`PassManager`](/api/qiskit/0.45/qiskit.transpiler.PassManager "qiskit.transpiler.PassManager") will need to adjust the pass manager to account for this (unless they were setting the `routing_pass` argument for [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout")). This change was made in the interest of improving the quality output, the layout and routing quality are highly coupled and [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") will now run multiple parallel seed trials and to calculate which seed provides the best results it needs to perform both the layout and routing together. There are three ways you can adjust the usage in your custom pass manager. The first is to avoid using embedding in your preset pass manager. If you were previously running something like:
|
||
|
||
```python
|
||
from qiskit.transpiler import PassManager
|
||
from qiskit.transpiler.preset_passmanagers import common
|
||
from qiskit.transpiler.passes.SabreLayout
|
||
|
||
pm = PassManager()
|
||
pm.append(SabreLayout(coupling_map)
|
||
pm += common.generate_embed_passmanager(coupling_map)
|
||
```
|
||
|
||
to compute the layout and then apply it (which was typically followed by routing) you can adjust the usage to just simply be:
|
||
|
||
```python
|
||
from qiskit.transpiler import PassManager
|
||
from qiskit.transpiler.preset_passmanagers import common
|
||
from qiskit.transpiler.passes.SabreLayout
|
||
|
||
pm = PassManager()
|
||
pm.append(SabreLayout(coupling_map)
|
||
```
|
||
|
||
as [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") will apply the layout and you no longer need the embedding stage. Alternatively, you can specify the `routing_pass` argument which will revert [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") to its previous behavior. For example, if you want to run [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") as it was run in previous releases you can do something like:
|
||
|
||
```python
|
||
from qiskit.transpiler.passes import SabreSwap, SabreLayout
|
||
routing_pass = SabreSwap(
|
||
coupling_map, "decay", seed=seed, fake_run=True
|
||
)
|
||
layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)
|
||
```
|
||
|
||
which will have [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") run as an analysis pass and just set the `layout` property set. The final approach is to leverage the `skip_routing` argument on `SabreLayout`, when this argument is set to `True` it will skip applying the found layout and inserting the swap gates from routing. However, doing this has a runtime penalty as `SabreLayout` will still be computing the routing and just does not use this data. The first two approaches outlined do not have additional overhead associated with them.
|
||
|
||
* The layouts computed by the [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") pass (when run without the `routing_pass` argument) with a fixed seed value may change from previous releases. This is caused by a new random number generator being used as part of the rewrite of the [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") pass in Rust which significantly improved the performance. If you rely on having consistent output you can run the pass in an earlier version of Qiskit and leverage [`qiskit.qpy`](/api/qiskit/0.45/qpy#module-qiskit.qpy "qiskit.qpy") to save the circuit and then load it using the current version. Alternatively you can explicitly set the `routing_pass` argument to an instance of [`SabreSwap`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap") to mirror the previous behavior of [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout"):
|
||
|
||
```python
|
||
from qiskit.transpiler.passes import SabreSwap, SabreLayout
|
||
|
||
|
||
routing_pass = SabreSwap(
|
||
coupling_map, "decay", seed=seed, fake_run=True
|
||
)
|
||
layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)
|
||
```
|
||
|
||
which will mirror the behavior of the pass in the previous release. Note, that if you were using the `swap_trials` argument on [`SabreLayout`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreLayout "qiskit.transpiler.passes.SabreLayout") in previous releases when adjusting the usage to this form that you will need to set `trials` argument on the [`SabreSwap`](/api/qiskit/0.45/qiskit.transpiler.passes.SabreSwap "qiskit.transpiler.passes.SabreSwap") constructor if you want to retain the previous output with a fixed seed.
|
||
|
||
* The exact circuit returned by `qiskit.circuit.random.random_circuit` for a given seed has changed. This is due to efficiency improvements in the internal random-number generation for the function.
|
||
|
||
* The version requirement for the optional feature package `qiskit-toqm`, installable via `pip install qiskit-terra[toqm]`, has been upgraded from version `0.0.4` to `0.1.0`. To use the `toqm` routing method with [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") you must now use qiskit-toqm version `0.1.0` or newer. Older versions are no longer discoverable by the transpiler.
|
||
|
||
* The output [`QuasiDistribution`](/api/qiskit/0.45/qiskit.result.QuasiDistribution "qiskit.result.QuasiDistribution") from the `Sampler.run` method has been updated to filter out any states with a probability of zero. Now if a valid state is missing from the dictionary output it can be assumed to have a 0 probability. Previously, all possible outcomes for a given number of bits (e.g. for a 3 bit result `000`, `001`, `010`, `011`, `100`, `101`, `110`, and `111`) even if the probability of a given state was 0. This change was made to reduce the size of the output as for larger number of bits the output size could be quite large. Also, filtering the zero probability results makes the output consistent with other implementations of [`BaseSampler`](/api/qiskit/0.45/qiskit.primitives.BaseSampler "qiskit.primitives.BaseSampler").
|
||
|
||
* The behavior of the pulse builder when a [`Schedule`](/api/qiskit/0.45/qiskit.pulse.Schedule "qiskit.pulse.Schedule") is called has been upgraded. Called schedules are internally converted into [`ScheduleBlock`](/api/qiskit/0.45/qiskit.pulse.ScheduleBlock "qiskit.pulse.ScheduleBlock") representation and now reference mechanism is always applied rather than appending the schedules wrapped by the [`Call`](/api/qiskit/0.45/qiskit.pulse.instructions.Call "qiskit.pulse.instructions.Call") instruction. Note that the converted block doesn’t necessary recover the original alignment context. This is simply an ASAP aligned sequence of pulse instructions with absolute time intervals. This is an upgrade of internal representation of called pulse programs and thus no API changes. However the [`Call`](/api/qiskit/0.45/qiskit.pulse.instructions.Call "qiskit.pulse.instructions.Call") instruction and [`Schedule`](/api/qiskit/0.45/qiskit.pulse.Schedule "qiskit.pulse.Schedule") no longer appear in the builder’s pulse program. This change guarantees the generated schedule blocks are always QPY compatible. If you are filtering the output schedule instructions by [`Call`](/api/qiskit/0.45/qiskit.pulse.instructions.Call "qiskit.pulse.instructions.Call"), you can access to the [`ScheduleBlock.references`](/api/qiskit/0.45/qiskit.pulse.ScheduleBlock#references "qiskit.pulse.ScheduleBlock.references") instead to retrieve the called program.
|
||
|
||
* [`RZXCalibrationBuilder`](/api/qiskit/0.45/qiskit.transpiler.passes.RZXCalibrationBuilder "qiskit.transpiler.passes.RZXCalibrationBuilder") and [`RZXCalibrationBuilderNoEcho`](/api/qiskit/0.45/qiskit.transpiler.passes.RZXCalibrationBuilderNoEcho "qiskit.transpiler.passes.RZXCalibrationBuilderNoEcho") transpiler pass have been upgraded to generate [`ScheduleBlock`](/api/qiskit/0.45/qiskit.pulse.ScheduleBlock "qiskit.pulse.ScheduleBlock"). This change guarantees the transpiled circuits are always QPY compatible. If you are directly using [`rescale_cr_inst()`](/api/qiskit/0.45/qiskit.transpiler.passes.RZXCalibrationBuilder#rescale_cr_inst "qiskit.transpiler.passes.RZXCalibrationBuilder.rescale_cr_inst"), method from another program or a pass subclass to rescale cross resonance pulse of the device, now this method is turned into a pulse builder macro, and you need to use this method within the pulse builder context to adopts to new release. The method call injects a play instruction to the context pulse program, instead of returning a [`Play`](/api/qiskit/0.45/qiskit.pulse.instructions.Play "qiskit.pulse.instructions.Play") instruction with the stretched pulse.
|
||
|
||
<span id="release-notes-0-23-0-deprecation-notes" />
|
||
|
||
<span id="id67" />
|
||
|
||
#### Deprecation Notes
|
||
|
||
* Support for running Qiskit with Python 3.7 support has been deprecated and will be removed in the qiskit-terra 0.25.0 release. This means starting in the 0.25.0 release you will need to upgrade the Python version you’re using to Python 3.8 or above.
|
||
|
||
* The class [`LinearFunctionsSynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.LinearFunctionsSynthesis "qiskit.transpiler.passes.LinearFunctionsSynthesis") class is now deprecated and will be removed in a future release. It has been superseded by the more general [`HighLevelSynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") class which should be used instead. For example, you can instantiate an instance of [`HighLevelSynthesis`](/api/qiskit/0.45/qiskit.transpiler.passes.HighLevelSynthesis "qiskit.transpiler.passes.HighLevelSynthesis") that will behave the same way as `LinearFunctionSynthesis` with:
|
||
|
||
```python
|
||
from qiskit.transpiler.passes import HighLevelSynthesis
|
||
from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
|
||
|
||
HighLevelSynthesis(
|
||
HLSConfig(
|
||
linear_function=[("default", {})],
|
||
use_default_on_unspecified=False,
|
||
)
|
||
)
|
||
```
|
||
|
||
* Support for passing in lists of argument values to the [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") function is deprecated and will be removed in the 0.25.0 release. This is being done to facilitate greatly reducing the overhead for parallel execution for transpiling multiple circuits at once. If you’re using this functionality currently you can call [`transpile()`](/api/qiskit/0.45/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 run something like:
|
||
|
||
```python
|
||
from itertools import cycle
|
||
from qiskit.transpiler import CouplingMap
|
||
from qiskit import QuantumCircuit
|
||
from qiskit import transpile
|
||
|
||
qc = QuantumCircuit(2)
|
||
qc.h(0)
|
||
qc.cx(0, 1)
|
||
qc.measure_all()
|
||
cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
|
||
|
||
results = []
|
||
for qc, cmap in zip(cycle([qc]), cmaps):
|
||
results.append(transpile(qc, coupling_map=cmap))
|
||
```
|
||
|
||
You can also leverage [`parallel_map()`](/api/qiskit/0.45/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 legacy version of the pulse drawer present in the `qiskit.visualization.pulse` has been deprecated and will be removed in a future release. This includes the `ScheduleDrawer` and :class\`WaveformDrawer\` classes. This module has been superseded by the `qiskit.visualization.pulse_v2` drawer and the typical user API [`pulse_drawer()`](/api/qiskit/0.45/qiskit.visualization.pulse_drawer "qiskit.visualization.pulse_drawer") and `PulseBlock.draw()` are already updated internally to use `qiskit.visualization.pulse_v2`.
|
||
|
||
* The `pulse.Instruction.draw()` method has been deprecated and will removed in a future release. The need for this method has been superseded by the `qiskit.visualization.pulse_v2` drawer which doesn’t require `Instrucion` objects to have their own draw method. If you need to draw a pulse instruction you should leverage the [`pulse_drawer()`](/api/qiskit/0.45/qiskit.visualization.pulse_drawer "qiskit.visualization.pulse_drawer") instead.
|
||
|
||
* The import `qiskit.circuit.qpy_serialization` is deprecated, as QPY has been promoted to the top level. You should import the same objects from [`qiskit.qpy`](/api/qiskit/0.45/qpy#module-qiskit.qpy "qiskit.qpy") instead. The old path will be removed in a future of Qiskit Terra.
|
||
|
||
* The `qiskit.IBMQ` object is deprecated. This alias object lazily redirects attribute access to `qiskit.providers.ibmq.IBMQ`. As the `qiskit-ibmq-provider` package has been supersceded by `qiskit-ibm-provider` package which maintains its own namespace maintaining this alias is no longer relevant with the new package. If you were relying on the `qiskit.IBMQ` alias you should update your usage to use `qiskit.providers.ibmq.IBMQ` directly instead (and also consider migrating to `qiskit-ibm-provider`, see the [migration guide](https://qiskit.org/documentation/partners/qiskit_ibm_provider/tutorials/Migration_Guide_from_qiskit-ibmq-provider.html) for more details).
|
||
|
||
* Several public methods of pulse Qobj converters have been deprecated and in a future release they will no longer be directly callable. The list of methods is:
|
||
|
||
In `InstructionToQobjConverter`,
|
||
|
||
* `convert_acquire()`
|
||
* `convert_bundled_acquires()`
|
||
* `convert_set_frequency()`
|
||
* `convert_shift_frequency()`
|
||
* `convert_set_phase()`
|
||
* `convert_shift_phase()`
|
||
* `convert_delay()`
|
||
* `convert_play()`
|
||
* `convert_snapshot()`
|
||
|
||
In `QobjToInstructionConverter`,
|
||
|
||
* `convert_acquire()`
|
||
* `convert_set_phase()`
|
||
* `convert_shift_phase()`
|
||
* `convert_set_frequency()`
|
||
* `convert_shift_frequency()`
|
||
* `convert_delay()`
|
||
* `bind_pulse()`
|
||
* `convert_parametric()`
|
||
* `convert_snapshot()`
|
||
|
||
Instead of calling any of these methods directly they will be implicitly selected when a converter instance is directly called. For example:
|
||
|
||
```python
|
||
converter = QobjToInstructionConverter()
|
||
converter(pulse_qobj)
|
||
```
|
||
|
||
* The `qiskit.visualization.state_visualization.num_to_latex_ket()` and `qiskit.visualization.state_visualization.num_to_latex_terms()` functions have been deprecated and will be removed in a future release. These function were primarily used internally by the LaTeX output from [`Statevector.draw()`](/api/qiskit/0.45/qiskit.quantum_info.Statevector#draw "qiskit.quantum_info.Statevector.draw") and [`DensityMatrix.draw()`](/api/qiskit/0.45/qiskit.quantum_info.DensityMatrix#draw "qiskit.quantum_info.DensityMatrix.draw") which no longer are using these function and are leverging [sympy](https://pypi.org/project/sympy/) for this instead. If you were using these functions you should cosinder using Sympy’s [nsimplify()](https://docs.sympy.org/latest/modules/simplify/simplify.html) [latex()](https://docs.sympy.org/latest/modules/printing.html) functions.
|
||
|
||
* The method `Register.qasm()` is deprecated and will be removed in a future release. This method is found on the subclasses [`QuantumRegister`](/api/qiskit/0.45/qiskit.circuit.QuantumRegister "qiskit.circuit.QuantumRegister") and [`ClassicalRegister`](/api/qiskit/0.45/qiskit.circuit.ClassicalRegister "qiskit.circuit.ClassicalRegister"). The deprecation is because the `qasm()` method promotes a false view of the responsible party for safe conversion to OpenQASM 2; a single object alone does not have the context to provide a safe conversion, such as whether its name clashes after escaping it to produce a valid identifier.
|
||
|
||
* The class-variable regular expression [`Register.name_format`](/api/qiskit/0.45/qiskit.circuit.Register#name_format "qiskit.circuit.Register.name_format") is deprecated and wil be removed in a future release. The names of registers are now permitted to be any valid Python string, so the regular expression has no use any longer.
|
||
|
||
* The functions `qiskit.quantum_info.synthesis.decompose_clifford()` and `qiskit.quantum_info.synthesis.decompose_cnot_dihedral()` are deprecated and will be removed in a future release. They are replaced by the two functions [`qiskit.synthesis.synth_clifford_full()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_clifford_full "qiskit.synthesis.synth_clifford_full") and [`qiskit.synthesis.synth_cnotdihedral_full()`](/api/qiskit/0.45/synthesis#qiskit.synthesis.synth_cnotdihedral_full "qiskit.synthesis.synth_cnotdihedral_full") respectively.
|
||
|
||
<span id="release-notes-0-23-0-bug-fixes" />
|
||
|
||
<span id="id68" />
|
||
|
||
#### Bug Fixes
|
||
|
||
* Fixed an issue in the [`PauliOp.adjoint()`](/api/qiskit/0.45/qiskit.opflow.primitive_ops.PauliOp#adjoint "qiskit.opflow.primitive_ops.PauliOp.adjoint") method where it would return the correct value for Paulis with complex coefficients, for example: `PauliOp(Pauli("iX"))`. Fixed [#9433](https://github.com/Qiskit/qiskit/issues/9433).
|
||
|
||
* Fixed an issue with the amplitude estimation algorithms in the `qiskit.algorithms.amplitude_estimators` module (see `amplitude_estimators`) for the usage with primitives built from the abstract [`BaseSampler`](/api/qiskit/0.45/qiskit.primitives.BaseSampler "qiskit.primitives.BaseSampler") primitive (such as [`Sampler`](/api/qiskit/0.45/qiskit.primitives.Sampler "qiskit.primitives.Sampler") and [`BackendSampler`](/api/qiskit/0.45/qiskit.primitives.BackendSampler "qiskit.primitives.BackendSampler")). Previously, the measurement results were expanded to more bits than actually measured which for oracles with more than one qubit led to potential errors in the detection of the “good” quantum states for oracles.
|
||
|
||
* Fixed an issue where the `QuantumCircuit.add_calibrations()` and `DAGCircuit.add_calibrations()` methods had a mismatch in their behavior of parameter-formatting logic. Previously `DAGCircuit.add_calibrations()` tried to cast every parameter into `float`, `QuantumCircuit.add_calibrations()` used given parameters as-is. This would potentially cause an error when running [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") on a [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") with pulse gates as the parameters of the calibrations could be kept as `ParameterExpresion` objects.
|
||
|
||
* Fixed a deserialization issue in QPY’s ([`qiskit.qpy`](/api/qiskit/0.45/qpy#module-qiskit.qpy "qiskit.qpy")) [`load()`](/api/qiskit/0.45/qpy#qiskit.qpy.load "qiskit.qpy.load") function where circuits containing gates of class [`MCXGate`](/api/qiskit/0.45/qiskit.circuit.library.MCXGate "qiskit.circuit.library.MCXGate"), [`MCXGrayCode`](/api/qiskit/0.45/qiskit.circuit.library.MCXGrayCode "qiskit.circuit.library.MCXGrayCode"), [`MCXRecursive`](/api/qiskit/0.45/qiskit.circuit.library.MCXRecursive "qiskit.circuit.library.MCXRecursive"), and [`MCXVChain`](/api/qiskit/0.45/qiskit.circuit.library.MCXVChain "qiskit.circuit.library.MCXVChain") would fail to deserialize. Fixed [#9390](https://github.com/Qiskit/qiskit/issues/9390).
|
||
|
||
* Fixed an issue in [`TensoredOp.to_matrix()`](/api/qiskit/0.45/qiskit.opflow.list_ops.TensoredOp#to_matrix "qiskit.opflow.list_ops.TensoredOp.to_matrix") where the global coefficient of the operator was multiplied to the final matrix more than once. Now, the global coefficient is correctly applied, independent of the number of tensored operators or states. Fixed [#9398](https://github.com/Qiskit/qiskit/issues/9398).
|
||
|
||
* The output from the [`run()`](/api/qiskit/0.45/qiskit.primitives.BackendSampler#run "qiskit.primitives.BackendSampler.run") method of the the [`BackendSampler`](/api/qiskit/0.45/qiskit.primitives.BackendSampler "qiskit.primitives.BackendSampler") class now sets the `shots` and `stddev_upper_bound` attributes of the returned [`QuasiDistribution`](/api/qiskit/0.45/qiskit.result.QuasiDistribution "qiskit.result.QuasiDistribution"). Previously these attributes were missing which prevent some post-processing using the output. Fixed [#9311](https://github.com/Qiskit/qiskit/issues/9311)
|
||
|
||
* The OpenQASM 2 exporter method [`QuantumCircuit.qasm()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm") will now emit higher precision floating point numbers for gate parameters by default. In addition, a tighter bound ($1e-12$ instead of $1e-6$) is used for checking whether a given parameter is close to a fraction/power of $\pi$. Fixed [#7166](https://github.com/Qiskit/qiskit/issues/7166).
|
||
|
||
* Fixed support in the [`primitives`](/api/qiskit/0.45/primitives#module-qiskit.primitives "qiskit.primitives") module for running [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") objects with control flow instructions (e.g. [`IfElseOp`](/api/qiskit/0.45/qiskit.circuit.IfElseOp "qiskit.circuit.IfElseOp")). Previously, the `BaseSampler` and `BaseEstimator` base classes could not correctly normalize such circuits. However, executing these circuits is dependent on the particular implementation of the primitive supporting control flow instructions. This just fixed support to enable a particular implementation of `BaseSampler` or `BaseEstimator` to use control flow instructions.
|
||
|
||
* Fixed an issue with the `PauliOp.matmul()` method where it would return incorrect results with `iI`. Fixed [#8680](https://github.com/Qiskit/qiskit/issues/8680).
|
||
|
||
* Fixed an issue with the Approximate Quantum Compiler ([`AQC`](/api/qiskit/0.45/qiskit.transpiler.synthesis.aqc.AQC "qiskit.transpiler.synthesis.aqc.AQC")) class which caused it to return an incorrect circuit when the input unitary had a determinant of -1. Fixed [#9327](https://github.com/Qiskit/qiskit/issues/9327)
|
||
|
||
* Fixed an issue with the [`QuantumCircuit.compose()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#compose "qiskit.circuit.QuantumCircuit.compose") method where it would incorrectly reject valid qubit or clbit specifiers. This has been fixed so that the method now accepts the same set of qubit and clbit specifiers as other [`QuantumCircuit`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit "qiskit.circuit.QuantumCircuit") methods, such as [`append()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#append "qiskit.circuit.QuantumCircuit.append"). Fixed [#8691](https://github.com/Qiskit/qiskit/issues/8691).
|
||
|
||
* Fixed an issue with the [`QuantumCircuit.compose()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#compose "qiskit.circuit.QuantumCircuit.compose") method where it would incorrectly map registers in conditions on the given circuit to complete registers on the base. Previously, the mapping was very imprecise; the bits used within each condition were not subject to the mapping, and instead an inaccurate attempt was made to find a corresponding register. This could also result in a condition on a smaller register being expanded to be on a larger register, which is not a valid transformation. Now, a condition on a single bit or a register will be composed to be on precisely the bits as defined by the `clbits` argument. A new aliasing register will be added to the base circuit to facilitate this, if necessary. Fixed [#6583](https://github.com/Qiskit/qiskit/issues/6583).
|
||
|
||
* Fixed an issue with the [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") function when run with `optimization_level` set to `1`, `2`, or `3` and no `backend`, `basis_gates`, or `target` argument specified. If the input circuit had runs of single qubit gates which could be simplified the output circuit would not be as optimized as possible as those runs of single qubit gates would not have been removed. This could have been corrected previously by specifying either the `backend`, `basis_gates`, or `target` arguments on the [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed [#9217](https://github.com/Qiskit/qiskit/issues/9217)
|
||
|
||
* Fixed an issue with the [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") function when run with `optimization_level=3` and no `backend`, `basis_gates`, or `target` argument specified. If the input circuit contained any 2 qubit blocks which were equivalent to an identity matrix the output circuit would not be as optimized as possible and and would still contain that identity block. This could have been corrected previously by specifying either the `backend`, `basis_gates`, or `target` arguments on the [`transpile()`](/api/qiskit/0.45/compiler#qiskit.compiler.transpile "qiskit.compiler.transpile") call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed [#9217](https://github.com/Qiskit/qiskit/issues/9217)
|
||
|
||
* Fixed an issue with [`LinCombSamplerGradient`](/api/qiskit/0.45/qiskit.algorithms.gradients.LinCombSamplerGradient "qiskit.algorithms.gradients.LinCombSamplerGradient") where it would potentially raise an error when run with the [`Sampler`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Sampler.html#qiskit_aer.primitives.Sampler "(in Qiskit Aer v0.13.0)") class from `qiskit-aer`.
|
||
|
||
* Fixed an issue with [`NumPyEigensolver`](/api/qiskit/0.45/qiskit.algorithms.eigensolvers.NumPyEigensolver "qiskit.algorithms.eigensolvers.NumPyEigensolver") and by extension [`NumPyMinimumEigensolver`](/api/qiskit/0.45/qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver "qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver") where solving for `BaseOperator` subclasses other than `Operator` would cause an error.
|
||
|
||
* Fixed an issue in the metadata output from [`primitives`](/api/qiskit/0.45/primitives#module-qiskit.primitives "qiskit.primitives") where the list made copies by reference and all elements were updated with the same value at every iteration.
|
||
|
||
* Fixed an issue with the `QobjToInstructionConverter` when multiple backends are called and they accidentally have the same pulse name in the pulse library. This was an edge case that could only be caused when a converter instance was reused across multiple backends (this was not a typical usage pattern).
|
||
|
||
* Fixed an issue with the [`PVQD`](/api/qiskit/0.45/qiskit.algorithms.PVQD "qiskit.algorithms.PVQD") class where the loss function was incorrecly squaring the fidelity. This has been fixed so that the loss function matches the definition in the original algorithm definition.
|
||
|
||
* Fixed a bug in QPY ([`qiskit.qpy`](/api/qiskit/0.45/qpy#module-qiskit.qpy "qiskit.qpy")) where circuits containing registers whose bits occurred in the circuit after loose bits would fail to deserialize. See [#9094](https://github.com/Qiskit/qiskit/issues/9094).
|
||
|
||
* The class `TwoQubitWeylDecomposition` is now compatible with the `pickle` protocol. Previously, it would fail to deserialize and would raise a `TypeError`. See [#7312](https://github.com/Qiskit/qiskit/issues/7312).
|
||
|
||
* Fixed an issue with the [`LocalReadoutMitigator.quasi_probabilities()`](/api/qiskit/0.45/qiskit.result.LocalReadoutMitigator#quasi_probabilities "qiskit.result.LocalReadoutMitigator.quasi_probabilities") method where the `shots` argument was not used. It is now used to set the number of shots in the return object.
|
||
|
||
* Fixed a regression in the construction of [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") objects from `QuantumCircuits` that contain other [`Clifford`](/api/qiskit/0.45/qiskit.quantum_info.Clifford "qiskit.quantum_info.Clifford") objects.
|
||
|
||
* Fixed an issue with the `TwoQubitWeylDecomposition` class (and its subclasses) to enable the Python standard library `pickle` to serialize these classes. This partially fixed [#7312](https://github.com/Qiskit/qiskit/issues/7312)
|
||
|
||
* [`QuantumCircuit.qasm()`](/api/qiskit/0.45/qiskit.circuit.QuantumCircuit#qasm "qiskit.circuit.QuantumCircuit.qasm") will now correctly escape gate and register names that collide with reserved OpenQASM 2 keywords. Fixes [#5043](https://github.com/Qiskit/qiskit/issues/5043).
|
||
|
||
* Fixed an issue in the [`RZXCalibrationBuilder`](/api/qiskit/0.45/qiskit.transpiler.passes.RZXCalibrationBuilder "qiskit.transpiler.passes.RZXCalibrationBuilder") where the ECR pulse sequence was misaligned. Fixed [#9013](https://github.com/Qiskit/qiskit/issues/9013).
|
||
|
||
* Fixed an issue with the [`pulse_drawer()`](/api/qiskit/0.45/qiskit.visualization.pulse_drawer "qiskit.visualization.pulse_drawer") where in some cases the output visualization would omit some of the channels in a schedule. Fixed [#8981](https://github.com/Qiskit/qiskit/issues/8981).
|
||
|
||
<span id="id69" />
|
||
|
||
### Aer 0.11.2
|
||
|
||
No change
|
||
|
||
<span id="ibm-q-provider-0-19-2" />
|
||
|
||
### IBM Q Provider 0.19.2
|
||
|
||
No change
|
||
|
||
<span id="qiskit-0-39-5" />
|