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.
Terra 0.23.0
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
QuantumCircuitobjects from the input program via two new functionsqiskit.qasm3.load()andqiskit.qasm3.loads().Improvements to the library of synthesis algorithms included in Qiskit. This includes the following new synthesis functions:
Clifford Synthesis
Linear Function Synthesis:
Permutation Synthesis:
SolovayKitaevDecompositiondetailed in: https://arxiv.org/abs/quant-ph/0505030New plugins for
HighLevelSynthesis:
ACGSynthesisPermutationKMSSynthesisPermutationBasicSynthesisPermutationNew plugin for
UnitarySynthesisPerformance improvements to
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, fewerSwapGategates introduced bySabreSwap). For example, runningSabreLayoutandSabreSwapon Bernstein Vazirani circuits targeting theFakeSherbrookebackend 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.
New Features
-
The pulses in
qiskit.pulse.librarycan be initialized with new parameter
angle, such that two float parameters could be provided:ampandangle. Initialization with complexampis still supported. -
The
AdaptVQEclass has a new attribute,eigenvalue_history, which is used to track the lowest achieved energy per iteration of the AdaptVQE. For example: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.historyshould be roughly[-1.85727503]as there is a single iteration. -
The runtime logging when running the
AdaptVQEhas been improved. When running the class now,DEBUGandINFOlevel 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, theCollectLinearFunctionshas been updated to inherit fromCollectAndCollapseand collects blocks ofCXGateandSwapGategates, and replaces each block with aLinearFunction. TheCollectCliffordswhich is also now based onCollectAndCollapse, collects blocks of “Clifford” gates and replaces each block with aClifford.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:qc = QuantumCircuit(2) qc.cx(0, 1) qc.z(0) qc.cx(1, 0)using
do_commutative_analysisenables consolidating the two CX gates, as the first CX gate and the Z gate commute. -
Added a new class
BlockCollectorthat implements various collection strategies, and a new classBlockCollapserthat implements various collapsing strategies. CurrentlyBlockCollectorincludes the strategy to greedily collect all gates adhering to a given filter function (for example, collecting all Clifford gates), andBlockCollapserincludes 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 singleClifford). -
Added a new
CollectCliffordstranspiler pass that collects blocks of Clifford gates and consolidates these blocks intoqiskit.quantum_info.Cliffordobjects. This pass inherits fromCollectAndCollapseand in particular supports the optiondo_commutative_analysis. It also supports two additional optionssplit_blocksandmin_block_size. See the release notes forCollectAndCollapseandCollectLinearFunctionsfor additional details. -
The
CollectLinearFunctionstranspiler 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: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:qc = QuantumCircuit(4) qc.cx(1, 2) qc.cx(2, 1)the two CX gates will be consolidated when
min_block_sizeis 1 or 2, and will remain unchanged whenmin_block_sizeis 3 or larger.
-
-
Added a depth-efficient synthesis algorithm
synth_cnot_depth_line_kms()for linear reversible circuitsLinearFunctionover the linear nearest-neighbor architecture, following the paper: https://arxiv.org/abs/quant-ph/0701194. -
The
DAGCircuit.replace_block_with_op()method will now return the newDAGOpNodethat 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()forPermutationover the linear nearest-neighbor architecture, following the paper: https://arxiv.org/abs/quant-ph/0701194 -
Added a new class
PermutationGatefor representing permutation logic as a circuit element. Unlike the existingPermutationcircuit 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
PermutationGateis 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:
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,qiskit.algorithms.gradients.QFIandqiskit.algorithms.gradients.LinCombQGT, to the gradients module:qiskit.algorithms.gradients. For example: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 theLinCombEstimatorGradient. This argument takes aDerivativeTypeenum that enables specifying to compute only the real or imaginary parts of the gradient. -
Added a new option
circuit_reverse_bitsto the user config file. This allows users to set a boolean for their preferred default behavior of thereverse_bitsargument of the circuit drawersQuantumCircuit.draw()andcircuit_drawer(). For example, adding a section to the user config file in the default location~/.qiskit/settings.confwith:[default] circuit_reverse_bits = Truewill change the default to display the bits in reverse order.
-
Added a new class
Z2Symmetriestoqiskit.quantum_infowhich is used to identify any symmetries from an inputSparsePauliOp. -
Added a new pulse directive
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 helpsScheduleBlockrepresent instructions with absolute time intervals. This allows the pulse builder to convertScheduleintoScheduleBlock, rather than wrapping withCallinstructions. -
Added primitive-enabled algorithms for Variational Quantum Time Evolution that implement the interface for Quantum Time Evolution. The
qiskit.algorithms.VarQRTEclass is used for real and theqiskit.algorithms.VarQITEclass is used for imaginary quantum time evolution according to a variational principle passed.Each algorithm accepts a variational principle which implements the
ImaginaryVariationalPrincipleabstract interface. The following implementations are included:For example:
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
XXPlusYYGateandXXMinusYYGateto other gates to theSessionEquivalenceLibrary. This enables runningtranspile()targeting a backend orTargetthat uses these gates. -
Added two new fake backends,
FakePragueandFakeSherbrooketo theqiskit.providers.fake_providermodule.FakePragueprovides a backend with a snapshot of the properties from the IBM Prague Egret R1 backend andFakeSherbrookeprovides a backend with a snapshot of the properties from the IBM Sherbrooke Eagle R3 backend. -
Added a new keyword argument,
allow_unknown_parameters, to theParameterExpression.bind()andParameterExpression.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()method’sobservablesargument now accepts astror sequence ofstrinput 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 forPauliobjects. -
Added a new constructor method
QuantumCircuit.from_instructions()that enables creating aQuantumCircuitobject from an iterable of instructions. For example: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
Cliffordclass now takes an optionalcopykeyword argument in its constructor. If set toFalse, then aStabilizerTableprovided 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()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(), for synthesizing aCliffordinto layers. The algorithm is based on S. Bravyi, D. Maslov, Hadamard-free circuits expose the structure of the Clifford group, arxiv: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:┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐ 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
Cliffordin 2-qubit depth for linear nearest neighbor (LNN) connectivity. -
The return types for the
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, runningpower()now returns anIGateinstance instead ofUnitaryGateas was done previously.The full list of output types that have been improved are:
-
The
EquivalenceLibraryis now represented internally as aPyDiGraph, this underlying graph object can be accesed from the newgraphattribute. 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()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 theignore_set_layoutkeyword argument can be set toTrueto 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 newfinal_layoutkeyword argument to pass in aLayoutobject to use for the output permutation. -
Added support to the
GateDirectiontranspiler pass to handle the the symmetricRXXGate,RYYGate, andRZZGategates. 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,
**, withGateobjects is now supported. It is equivalent to running theGate.power()method on the object.For example:
from qiskit.circuit.library import XGate sx = XGate() ** 0.5 -
Added new
GaussianSquareDragpulse shape to theqiskit.pulse.librarymodule. This pulse shape is similar toGaussianSquarebut uses theDragshape 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 theFiniteDiffEstimatorGradientandFiniteDiffSamplerGradientclasses. Themethodargument 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""forward""backward"where is the offset epsilon.
-
All gradient classes in
qiskit.algorithms.gradientsnow 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
TranslateParameterizedGatespass 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
CollectCliffordstranspiler pass has been expanded to collect and combine blocks of “clifford gates” intoCliffordobjects, where “clifford gates” may now also include objects of typeLinearFunction,Clifford, andPauliGate. For example: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. Thus the final circuit consists of a singleCliffordobject. -
CouplingMapis now implicitly iterable, with the iteration being identical to iterating through the output ofCouplingMap.get_edges(). In other words,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()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 availableqiskit.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. -
InstructionScheduleMaphas 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_entrieshas been added. This contains several wrapper classes for different pulse schedule representations.ScheduleDefCallableDefPulseQobjDef
These classes implement the
get_schedule()andget_signature()methods that returns pulse schedule and parameter names to assign, respectively. These classes are internally managed by theInstructionScheduleMapor backendTarget, and thus they will not appear in a typical user programs. -
Introduced a new subclass
ScalableSymbolicPulse, as a subclass ofSymbolicPulse. The new subclass behaves the same asSymbolicPulse, except that it assumes that the envelope of the pulse includes a complex amplitude pre-factor of the form . This envelope shape matches many common pulses, including all of the pulses in the Qiskit Pulse library (which were also converted toamp,anglerepresentation in this release).The new subclass removes the non-unique nature of the
amp,anglerepresentation, and correctly compares pulses according to their complex amplitude. -
Added a new keyword argument,
dtype, to thePauliSumOp.from_list()method. When specified this argument can be used to specify thedtypeof the numpy array allocated for theSparsePauliOpused internally by the constructedPauliSumOp. -
Support for importing OpenQASM 3 programs into Qiskit has been added. This can most easily be accessed using the functions
qasm3.loads()andqasm3.load(), to load a program directly from a string and indirectly from a filename, respectively. For example, one can now do: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
QuantumCircuitinstance in the variablecircuit.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()andqasm3.dumps()).Note that Qiskit’s support of OpenQASM 3 is not meant to provide a totally lossless representation of
QuantumCircuits. For that, consider usingqiskit.qpy. -
The
primitives-based gradient classes defined by theBaseEstimatorGradientandBaseSamplerGradientabstract 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,_postprocessenables to customize the output result, and_run_uniqueenables calculating the gradient of a circuit with unique parameters. -
The
SabreLayouttranspiler 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 therouting_passargument or using the newskip_routingargument. -
The
SabreLayouttranspiler pass has a new constructor argumentlayout_trials. This argument is used to control how many random number generator seeds will be attempted to runSabreLayoutwith. When set the SABRE layout algorithm is runlayout_trialsnumber 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 theSabreLayoutpass will default to using the number of physical CPUs are available on the local system. -
Added two new classes
SciPyRealEvolverandSciPyImaginaryEvolverthat 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 asTimeEvolutionResult.observablesandTimeEvolutionResult.times. For example: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
SolovayKitaevtranspiler 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:
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
UnitarySynthesistranspiler pass: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()is now significantly faster for large circuits. -
Random-circuit generation with
qiskit.circuit.random.random_circuit()will now output all “standard” gates in Qiskit’s circuit library (qiskit.circuit.library). This includes two 4-qubit gatesC3SXGateandRC3XGate, and the allowed values ofmax_operandshave been expanded accordingly. -
The
Optimize1qGatesDecompositiontranspiler pass has a new keyword argument,target, on its constructor. This argument can be used to specify aTargetobject that represnts the compilation target. If used it superscedes thebasisargument to determine if an instruction in the circuit is present on the target backend. -
The
UnrollCustomDefinitionstranspiler pass has a new keyword argument,target, on its constructor. This argument can be used to specify aTargetobject that represnts the compilation target. If used it superscedes thebasis_gatesargument to determine if an instruction in the circuit is present on the target backend. -
Added the
ReverseEstimatorGradientclass 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: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_dagto the constructor for theOneQubitEulerDecomposerclass. Whenuse_dagis set toTruethe output from the decomposer will be aDAGCircuitobject instead ofQuantumCircuitobject. This is useful for transpiler passes that useOneQubitEulerDecomposer(such asOptimize1qGatesDecomposition) as working directly with aDAGCircuitavoids the overhead of converting betweenQuantumCircuitandDAGCircuit. -
Added the ability for analysis passes to set custom heuristic weights for the
VF2LayoutandVF2PostLayouttranspiler passes. If an analysis pass sets thevf2_avg_error_mapkey in the property set, its value is used for the error weights instead of the error rates from the backend’sTarget(orBackendPropertiesforBackendV1). The value should be anErrorMapinstance, where each value represents the avg error rate for all 1 or 2 qubit operation on those qubits. If a value isNaN, the corresponding edge is treated as an ideal edge (or qubit for 1q operations). For example, an error map created as: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.0024on qubit 0 and0.0032on 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 thevf2_avg_error_mapkey in the property set whenVF2LayoutandVF2PostLayoutare run. For example: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
VF2Layoutwith the custom scoring fromerror_mapfor a 2 qubitTargetthat doesn’t contain any error rates.
Upgrade Notes
-
When initializing any of the pulse classes in
qiskit.pulse.library:providing a complex
ampargument with a finiteanglewill result inPulseErrornow. For example, instead of callingGaussian(duration=100,sigma=20,amp=0.5j)one should useGaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2)instead now. The pulse envelope which used to be defined asamp * ...is in turn defined asamp * exp(1j * angle) * .... This change was made to better support Qiskit Experiments where the amplitude and angle of pulses are calibrated in separate experiments. -
For Python 3.7 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
MSBasisDecomposertranspiler pass available via theqiskit.transpiler.passesmodule has been removed. It was originally deprecated as part of the Qiskit Terra 0.16.0 release (10-16-2020). Instead theBasisTranslatortranspiler pass should be used instead to translate a circuit into an appropriate basis with aRXXGate -
EquivalenceLibraryobjects that are initialized with thebaseattribute will no long have a shared reference with theEquivalenceLibrarypassed in. In earlier releases if you mutatedbaseafter it was used to create a newEquivalenceLibraryinstance both instances would reflect that change. This no longer is the case and updates tobasewill no longer be reflected in the newEquivalenceLibrary. For example, if you created an equivalence library with: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_libwith: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_libwould also include the definition ofSXGateafter it was added tooriginal_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 theEquivalenceLibraryclass, especially when there are multiple runs of theBasisTranslatortranspiler pass. -
The
initial_stateargument for the constructor of theNLocalclass along with assigning directly to theNLocal.initial_stateatrribute must be aQuantumCircuitnow. 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 defaultprecisionhas been changed from 5 to 10. -
The QPY version format version emitted by
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 ofScalableSymbolicPulsewhich was handled by adding aclass_name_sizeattribute to the header of the dumpedSymbolicPulseobjects. -
The
__hash__method for theSymbolicPulsewas removed. This was done to reflect the mutable nature (via parameter assignment) of this class which could result in errors when usingSymbolicPulsein situtations where a hashable object was required. This means the builtinhash()method and usingSymbolicPulseas keys in dictionaries or set members will no longer work. -
The names of
Registerinstances (which includes instances ofQuantumRegisterandClassicalRegigster) 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: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
QuantumCircuitmethodsu1,u2,u3, and their controlled variantscu1,cu3andmcu1have 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 methodsp(),u(),cp()andcu(). The gate classesU1Gate,U2GateandU3Gateare still available for use withQuantumCircuit.append(), so backends can still support bases with these gates explicitly given. -
The
QuantumCircuitmethodscombineandextendhave been removed following their deprecation in Qiskit Terra 0.17.0. This was done because these functions were simply less powerful versions ofQuantumCircuit.compose(), which should be used instead.The removal of
extendalso means that the+and+=operators are no longer defined forQuantumCircuit. Instead, you can use the&and&=operators respectively, which useQuantumCircuit.compose(). -
The previously deprecated functions:
qiskit.circuit.measure.measure()andqiskit.circuit.reset.reset()have been removed. These functions were deprecated in the Qiskit Terra 0.19.0 release (December, 2021). Instead you should use theQuantumCircuit.measure()andQuantumCircuit.reset()methods of theQuantumCircuitobject you wish to append aMeasureorResetoperation to. -
The previously deprecated
ParameterViewmethods which were inherited fromsethave been removed fromParameterView, the type returned byQuantumCircuit.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
ParameterViewtype is now a general sequence view type and doesn’t support thesesetoperations any longer. -
The previously deprecated NetworkX converter methods for the
DAGCircuitandDAGDependencyclasses:DAGCircuit.to_networkx(),DAGCircuit.from_networkx(), andDAGDependency.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 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 inDAGCircuitand/or rustworkx. However, since that time bothDAGCircuitand rustworkx has matured and offers more functionality and theDAGCircuitis tightly coupled to rustworkx for its operation and having these converter methods provided limited functionality and therefore have been removed. -
tweedledumhas been removed as a core requirement of Qiskit Terra. The functionality provided (qiskit.circuit.classicalfunction) is still available, iftweedledumis installed manually, such as by:pip install tweedledumThis change was made because
tweedledumdevelopment 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,HAS_PIL,HAS_PYLATEXandHAS_PDFTOCAIROare no longer exposed fromqiskit.visualization, having been deprecated in Qiskit Terra 0.21. The canonical location for these (and many other lazy checkers) isqiskit.utils.optionals, and all four objects can be found there. -
The previously deprecated
gateargument to the constructor of theDecomposetranspiler pass, along with its matching attributeDecompose.gatehave been removed. The argument and attribute were deprecated as part of the Qiskit Terra 0.19.0 release (December, 2021). Instead thegates_to_decomposeargument for the constructor along with theDecompose.gates_to_decomposeattribute should be used instead. Thegates_to_decomposeargument 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
labelargument for the constructor of theMCMTandMCMTVChainclasses has been removed. It was deprecated as of the Qiskit Terra 0.19.0 release (Decemeber, 2021). Using thelabelargument on these classes was undefined behavior as they are subclasses ofQuantumCircuitinstead ofInstruction. This would result in the assigned label generally being ignored. If you need to assign alabelto an instance ofMCMTorMCMTVChainyou should convert them to anGateinstance withto_gate()and then assign the desired label tolabelattribute. For example: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
retworkxdependency for Qiskit has been removed and replaced byrustworkxlibrary. These are the same packages, butrustworkxis the new name forretworkxwhich 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
SabreLayoutcompiler pass has changed. The pass is no longer anAnalysisPassand by default will compute the initital layout, apply it to the circuit, and will also runSabreSwapinternally and apply the swap mapping and set thefinal_layoutproperty set with the permutation caused by swap insertions. This means for users runningSabreLayoutas part of a customPassManagerwill need to adjust the pass manager to account for this (unless they were setting therouting_passargument forSabreLayout). This change was made in the interest of improving the quality output, the layout and routing quality are highly coupled andSabreLayoutwill 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: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:
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
SabreLayoutwill apply the layout and you no longer need the embedding stage. Alternatively, you can specify therouting_passargument which will revertSabreLayoutto its previous behavior. For example, if you want to runSabreLayoutas it was run in previous releases you can do something like: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
SabreLayoutrun as an analysis pass and just set thelayoutproperty set. The final approach is to leverage theskip_routingargument onSabreLayout, when this argument is set toTrueit will skip applying the found layout and inserting the swap gates from routing. However, doing this has a runtime penalty asSabreLayoutwill 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
SabreLayoutpass (when run without therouting_passargument) 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 theSabreLayoutpass 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 leverageqiskit.qpyto save the circuit and then load it using the current version. Alternatively you can explicitly set therouting_passargument to an instance ofSabreSwapto mirror the previous behavior ofSabreLayout: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_trialsargument onSabreLayoutin previous releases when adjusting the usage to this form that you will need to settrialsargument on theSabreSwapconstructor if you want to retain the previous output with a fixed seed. -
The exact circuit returned by
qiskit.circuit.random.random_circuitfor 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 viapip install qiskit-terra[toqm], has been upgraded from version0.0.4to0.1.0. To use thetoqmrouting method withtranspile()you must now use qiskit-toqm version0.1.0or newer. Older versions are no longer discoverable by the transpiler. -
The output
QuasiDistributionfrom theSampler.runmethod 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 result000,001,010,011,100,101,110, and111) 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 ofBaseSampler. -
The behavior of the pulse builder when a
Scheduleis called has been upgraded. Called schedules are internally converted intoScheduleBlockrepresentation and now reference mechanism is always applied rather than appending the schedules wrapped by theCallinstruction. 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 theCallinstruction andScheduleno 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 byCall, you can access to theScheduleBlock.referencesinstead to retrieve the called program. -
RZXCalibrationBuilderandRZXCalibrationBuilderNoEchotranspiler pass have been upgraded to generateScheduleBlock. This change guarantees the transpiled circuits are always QPY compatible. If you are directly usingrescale_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 aPlayinstruction with the stretched pulse.
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
LinearFunctionsSynthesisclass is now deprecated and will be removed in a future release. It has been superseded by the more generalHighLevelSynthesisclass which should be used instead. For example, you can instantiate an instance ofHighLevelSynthesisthat will behave the same way asLinearFunctionSynthesiswith: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()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 calltranspile()multiple times instead. For example if you were previously doing something like: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:
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()ormultiprocessingfrom the Python standard library if you want to run this in parallel. -
The legacy version of the pulse drawer present in the
qiskit.visualization.pulsehas been deprecated and will be removed in a future release. This includes theScheduleDrawerand :class`WaveformDrawer` classes. This module has been superseded by theqiskit.visualization.pulse_v2drawer and the typical user APIpulse_drawer()andPulseBlock.draw()are already updated internally to useqiskit.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 theqiskit.visualization.pulse_v2drawer which doesn’t requireInstrucionobjects to have their own draw method. If you need to draw a pulse instruction you should leverage thepulse_drawer()instead. -
The import
qiskit.circuit.qpy_serializationis deprecated, as QPY has been promoted to the top level. You should import the same objects fromqiskit.qpyinstead. The old path will be removed in a future of Qiskit Terra. -
The
qiskit.IBMQobject is deprecated. This alias object lazily redirects attribute access toqiskit.providers.ibmq.IBMQ. As theqiskit-ibmq-providerpackage has been supersceded byqiskit-ibm-providerpackage which maintains its own namespace maintaining this alias is no longer relevant with the new package. If you were relying on theqiskit.IBMQalias you should update your usage to useqiskit.providers.ibmq.IBMQdirectly instead (and also consider migrating toqiskit-ibm-provider, see the migration guide 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:
converter = QobjToInstructionConverter() converter(pulse_qobj) -
The
qiskit.visualization.state_visualization.num_to_latex_ket()andqiskit.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 fromStatevector.draw()andDensityMatrix.draw()which no longer are using these function and are leverging sympy for this instead. If you were using these functions you should cosinder using Sympy’s nsimplify() latex() functions. -
The method
Register.qasm()is deprecated and will be removed in a future release. This method is found on the subclassesQuantumRegisterandClassicalRegister. The deprecation is because theqasm()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_formatis 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()andqiskit.quantum_info.synthesis.decompose_cnot_dihedral()are deprecated and will be removed in a future release. They are replaced by the two functionsqiskit.synthesis.synth_clifford_full()andqiskit.synthesis.synth_cnotdihedral_full()respectively.
Bug Fixes
-
Fixed an issue in the
PauliOp.adjoint()method where it would return the correct value for Paulis with complex coefficients, for example:PauliOp(Pauli("iX")). Fixed #9433. -
Fixed an issue with the amplitude estimation algorithms in the
qiskit.algorithms.amplitude_estimatorsmodule (seeamplitude_estimators) for the usage with primitives built from the abstractBaseSamplerprimitive (such asSamplerandBackendSampler). 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()andDAGCircuit.add_calibrations()methods had a mismatch in their behavior of parameter-formatting logic. PreviouslyDAGCircuit.add_calibrations()tried to cast every parameter intofloat,QuantumCircuit.add_calibrations()used given parameters as-is. This would potentially cause an error when runningtranspile()on aQuantumCircuitwith pulse gates as the parameters of the calibrations could be kept asParameterExpresionobjects. -
Fixed a deserialization issue in QPY’s (
qiskit.qpy)load()function where circuits containing gates of classMCXGate,MCXGrayCode,MCXRecursive, andMCXVChainwould fail to deserialize. Fixed #9390. -
Fixed an issue in
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. -
The output from the
run()method of the theBackendSamplerclass now sets theshotsandstddev_upper_boundattributes of the returnedQuasiDistribution. Previously these attributes were missing which prevent some post-processing using the output. Fixed #9311 -
The OpenQASM 2 exporter method
QuantumCircuit.qasm()will now emit higher precision floating point numbers for gate parameters by default. In addition, a tighter bound ( instead of ) is used for checking whether a given parameter is close to a fraction/power of . Fixed #7166. -
Fixed support in the
primitivesmodule for runningQuantumCircuitobjects with control flow instructions (e.g.IfElseOp). Previously, theBaseSamplerandBaseEstimatorbase 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 ofBaseSamplerorBaseEstimatorto use control flow instructions. -
Fixed an issue with the
PauliOp.matmul()method where it would return incorrect results withiI. Fixed #8680. -
Fixed an issue with the Approximate Quantum Compiler (
AQC) class which caused it to return an incorrect circuit when the input unitary had a determinant of -1. Fixed #9327 -
Fixed an issue with the
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 otherQuantumCircuitmethods, such asappend(). Fixed #8691. -
Fixed an issue with the
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 theclbitsargument. A new aliasing register will be added to the base circuit to facilitate this, if necessary. Fixed #6583. -
Fixed an issue with the
transpile()function when run withoptimization_levelset to1,2, or3and nobackend,basis_gates, ortargetargument 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 thebackend,basis_gates, ortargetarguments on thetranspile()call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed #9217 -
Fixed an issue with the
transpile()function when run withoptimization_level=3and nobackend,basis_gates, ortargetargument 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 thebackend,basis_gates, ortargetarguments on thetranspile()call, but now the output will be as simplified as it can be without knowing the target gates allowed. Fixed #9217 -
Fixed an issue with
LinCombSamplerGradientwhere it would potentially raise an error when run with theSamplerclass fromqiskit-aer. -
Fixed an issue with
NumPyEigensolverand by extensionNumPyMinimumEigensolverwhere solving forBaseOperatorsubclasses other thanOperatorwould cause an error. -
Fixed an issue in the metadata output from
primitiveswhere the list made copies by reference and all elements were updated with the same value at every iteration. -
Fixed an issue with the
QobjToInstructionConverterwhen 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
PVQDclass 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) where circuits containing registers whose bits occurred in the circuit after loose bits would fail to deserialize. See #9094. -
The class
TwoQubitWeylDecompositionis now compatible with thepickleprotocol. Previously, it would fail to deserialize and would raise aTypeError. See #7312. -
Fixed an issue with the
LocalReadoutMitigator.quasi_probabilities()method where theshotsargument was not used. It is now used to set the number of shots in the return object. -
Fixed a regression in the construction of
Cliffordobjects fromQuantumCircuitsthat contain otherCliffordobjects. -
Fixed an issue with the
TwoQubitWeylDecompositionclass (and its subclasses) to enable the Python standard librarypickleto serialize these classes. This partially fixed #7312 -
QuantumCircuit.qasm()will now correctly escape gate and register names that collide with reserved OpenQASM 2 keywords. Fixes #5043. -
Fixed an issue in the
RZXCalibrationBuilderwhere the ECR pulse sequence was misaligned. Fixed #9013. -
Fixed an issue with the
pulse_drawer()where in some cases the output visualization would omit some of the channels in a schedule. Fixed #8981.
Aer 0.11.2
No change
IBM Q Provider 0.19.2
No change