Qiskit 0.35 release notes
0.35.0
Terra 0.20.0
Prelude
The Qiskit Terra 0.20.0 release highlights are:
- The introduction of multithreaded modules written in Rust to accelerate the performance of certain portions of Qiskit Terra and improve scaling with larger numbers of qubits. However, when building Qiskit from source a Rust compiler is now required.
- More native support for working with a
Targetin the transpiler. Several passes now support working directly with aTargetobject which makes the transpiler robust in the types of backends it can target. - The introduction of the
qiskit.primitivesmodule. These APIs provide different abstraction levels for computing outputs of interest fromQuantumCircuitand using backends. For example, theBaseEstimatordefines an abstract interface for estimating an expectation value of an observable. This can then be used to construct higher level algorithms and applications that are built using the estimation of expectation values without having to worry about the implementation of computing the expectation value. This decoupling allows the implementation to improve in speed and quality while adhering to the defined abstract interface. Likewise, theBaseSamplercomputes quasi-probability distributions from circuit measurements. Other primitives will be introduced in the future.
This release no longer has support for Python 3.6. With this release, Python 3.7 through Python 3.10 are required.
New Features
-
Added a new constructor method for the
Operatorclass,Operator.from_circuit()for creating a newOperatorobject from aQuantumCircuit. While this was possible normally using the default constructor, theOperator.from_circuit()method provides additional options to adjust how the operator is created. Primarily this lets you permute the qubit order based on a setLayout. For, example:from qiskit.circuit import QuantumCircuit from qiskit import transpile from qiskit.transpiler import CouplingMap from qiskit.quantum_info import Operator circuit = QuantumCircuit(3) circuit.h(0) circuit.cx(0, 1) circuit.cx(1, 2) cmap = CouplingMap.from_line(3) out_circuit = transpile(circuit, initial_layout=[2, 1, 0], coupling_map=cmap) operator = Operator.from_circuit(out_circuit)the
operatorvariable will have the qubits permuted based on the layout so that it is identical to what is returned byOperator(circuit)before transpilation. -
Added a new method
DAGCircuit.copy_empty_like()to theDAGCircuitclass. This method is used to create a new copy of an existingDAGCircuitobject with the same structure but empty of any instructions. This method is the same as the private method_copy_circuit_metadata(), but instead is now part of the public API of the class. -
The fake backend and fake provider classes which were previously available in
qiskit.test.mockare now also accessible in a new module:qiskit.providers.fake_provider. This new module supersedes the previous moduleqiskit.test.mockwhich will be deprecated in Qiskit 0.21.0. -
Added a new gate class,
LinearFunction, that efficiently encodes a linear function (i.e. a function that can be represented by a sequence ofCXGateandSwapGategates). -
Added a new transpiler pass
CollectLinearFunctionsthat collects blocks of consecutiveCXGateandSwapGategates in a circuit, and replaces each block with aLinearFunctiongate. -
Added a new transpiler pass
LinearFunctionsSynthesisthat synthesizes anyLinearFunctiongates in using the Patel-Markov-Hayes algorithm. When combined with theCollectLinearFunctionstranspiler pass this enables to collect blocks of consecutiveCXGateandSwapGategates in a circuit, and re-synthesize them using the Patel-Markov-Hayes algorithm. -
Added a new transpiler pass
LinearFunctionsToPermutationsthat replaces aLinearFunctiongate by aPermutationcircuit whenever possible. -
FlowControllerclasses (such asConditionalController) can now be nested inside aPassManagerinstance when using thePassManager.append()method. This enables the use of nested logic to control the execution of passes in thePassManager. For example:from qiskit.transpiler import ConditionalController, PassManager from qiskit.transpiler.passes import ( BasisTranslator, GatesInBasis, Optimize1qGatesDecomposition, FixedPoint, Depth ) from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel pm = PassManager() def opt_control(property_set): return not property_set["depth_fixed_point"] def unroll_condition(property_set): return not property_set["all_gates_in_basis"] depth_check = [Depth(), FixedPoint("depth")] opt = [Optimize1qGatesDecomposition(['rx', 'ry', 'rz', 'rxx'])] unroll = [BasisTranslator(sel, ['rx', 'ry', 'rz', 'rxx'])] unroll_check = [GatesInBasis(['rx', 'ry', 'rz', 'rxx'])] flow_unroll = [ConditionalController(unroll, condition=unroll_condition)] pm.append(depth_check + opt + unroll_check + flow_unroll, do_while=opt_control)The
pmPassManagerobject will only execute theBasisTranslatorpass (in theunrollstep) in each loop iteration if theunroll_conditionis met. -
The constructors for the
ZFeatureMapandZZFeatureMapclasses have a new keyword argumentparameter_prefix. This new argument is used to set the prefix of parameters of the data encoding circuit. For example:from qiskit.circuit.library import ZFeatureMap feature_map = ZFeatureMap(feature_dimension=4, parameter_prefix="my_prefix") feature_map.decompose().draw('mpl')the generated
ZFeatureMapcircuit has prefixed all its internal parameters with the prefix"my_prefix". -
The
TemplateOptimizationtranspiler pass can now work withGateobjects that haveParameterExpressionparameters. An illustrative example of usingParameters withTemplateOptimizationis the following:from qiskit import QuantumCircuit, transpile, schedule from qiskit.circuit import Parameter from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TemplateOptimization # New contributions to the template optimization from qiskit.transpiler.passes.calibration import RZXCalibrationBuilder, rzx_templates from qiskit.test.mock import FakeCasablanca backend = FakeCasablanca() phi = Parameter('φ') qc = QuantumCircuit(2) qc.cx(0,1) qc.p(2*phi, 1) qc.cx(0,1) print('Original circuit:') print(qc) pass_ = TemplateOptimization(**rzx_templates.rzx_templates(['zz2'])) qc_cz = PassManager(pass_).run(qc) print('ZX based circuit:') print(qc_cz) # Add the calibrations pass_ = RZXCalibrationBuilder(backend) cal_qc = PassManager(pass_).run(qc_cz.bind_parameters({phi: 0.12})) # Transpile to the backend basis gates cal_qct = transpile(cal_qc, backend) qct = transpile(qc.bind_parameters({phi: 0.12}), backend) # Compare the schedule durations print('Duration of schedule with the calibration:') print(schedule(cal_qct, backend).duration) print('Duration of standard with two CNOT gates:') print(schedule(qct, backend).duration)outputs
Original circuit: q_0: ──■──────────────■── ┌─┴─┐┌────────┐┌─┴─┐ q_1: ┤ X ├┤ P(2*φ) ├┤ X ├ └───┘└────────┘└───┘ ZX based circuit: ┌─────────────┐ » q_0: ────────────────────────────────────┤0 ├────────────» ┌──────────┐┌──────────┐┌──────────┐│ Rzx(2.0*φ) │┌──────────┐» q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤1 ├┤ Rx(-2*φ) ├» └──────────┘└──────────┘└──────────┘└─────────────┘└──────────┘» « «q_0: ──────────────────────────────────────────────── « ┌──────────┐┌──────────┐┌──────────┐┌──────────┐ «q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤ P(2.0*φ) ├ « └──────────┘└──────────┘└──────────┘└──────────┘ Duration of schedule with the calibration: 1600 Duration of standard with two CNOT gates: 6848 -
The
DAGOpNode,DAGInNodeandDAGOutNodeclasses now define a custom__repr__method which outputs a representation. Per the Python documentation the output is a string representation that is roughly equivalent to the Python string used to create an equivalent object. -
The performance of the
SparsePauliOp.simplify()method has greatly improved by replacing the use ofnumpy.uniqueto compute unique elements of an array by a new similar function implemented in Rust that doesn’t pre-sort the array. -
Added a new method
equiv()to theSparsePauliOpclass for testing the equivalence of aSparsePauliOpwith anotherSparsePauliOpobject. Unlike the==operator which compares operators element-wise,equiv()compares whether two operators are equivalent or not. For example:op = SparsePauliOp.from_list([("X", 1), ("Y", 1)]) op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)]) op3 = SparsePauliOp.from_list([("Y", 1), ("X", 1)]) print(op == op2) # False print(op == op3) # False print(op.equiv(op2)) # True print(op.equiv(op3)) # True -
Added new fake backend classes from snapshots of the IBM Quantum systems based on the
BackendV2interface and provided aTargetfor each backend.BackendV2based versions of all the existing backends are added except for three old backendsFakeRueschlikon,FakeTenerifeandFakeTokyoas they do not have snapshots files available which are required for creating a new fake backend class based onBackendV2.These new V2 fake backends will enable testing and development of new features introduced by
BackendV2andTargetsuch as improving the transpiler. -
Added a new gate class
XXMinusYYGateto the circuit library (qiskit.circuit.library) for the XX-YY interaction. This gate can be used to implement the bSwap gate and its powers. It also arises in the simulation of superconducting fermionic models. -
Added new gate class,
XXPlusYYGate, to the circuit library (qiskit.circuit.library). This gate is a 2-qubit parameterized XX+YY interaction, also known as an XY gate, and is based on the gate described in https://arxiv.org/abs/1912.04424. -
The
FakeBogota,FakeManila,FakeRome, andFakeSantiagofake backends which can be found in theqiskit.providers.fake_providermodule can now be used as backends in Pulse experiments as they now include aPulseDefaultscreated from a snapshot of the equivalent IBM Quantum machine’s properties. -
The
ConsolidateBlockspass has a new keyword argument on its constructor,target. This argument is used to specify aTargetobject representing the compilation target for the pass. If it is specified it supersedes thebasis_gateskwarg. If a target is specified, the pass will respect the gates and qubits for the instructions defined in theTargetwhen deciding which gates to consolidate into a unitary. -
The
Targetclass has a new method,instruction_supported()which is used to query the target to see if an instruction (the combination of an operation and the qubit(s) it is executed on) is supported on the backend modelled by theTarget. -
Added a new kwarg,
metadata_serializer, to theqpy.dump()function for specifying a customJSONEncodersubclass for use when serializing theQuantumCircuit.metadataattribute and a dual kwargmetadata_deserializerto theqpy.load()function for specifying aJSONDecodersubclass. By default thedump()andload()functions will attempt to JSON serialize and deserialize with the stdlib default json encoder and decoder. SinceQuantumCircuit.metadatacan contain any Python dictionary, even those with contents not JSON serializable by the default encoder, will lead to circuits that can’t be serialized. The newmetadata_serializerargument fordump()enables users to specify a customJSONEncoderthat will be used with the internaljson.dump()call for serializing theQuantumCircuit.metadatadictionary. This can then be paired with the newmetadata_deserializerargument of theqpy.load()function to decode those custom JSON encodings. Ifmetadata_serializeris specified ondump()butmetadata_deserializeris not specified onload()calls the QPY will be loaded, but the circuit metadata may not be reconstructed fully.For example if you wanted to define a custom serialization for metadata and then load it you can do something like:
from qiskit.qpy import dump, load from qiskit.circuit import QuantumCircuit, Parameter import json import io class CustomObject: """Custom string container object.""" def __init__(self, string): self.string = string def __eq__(self, other): return self.string == other.string class CustomSerializer(json.JSONEncoder): """Custom json encoder to handle CustomObject.""" def default(self, o): if isinstance(o, CustomObject): return {"__type__": "Custom", "value": o.string} return json.JSONEncoder.default(self, o) class CustomDeserializer(json.JSONDecoder): """Custom json decoder to handle CustomObject.""" def __init__(self, *args, **kwargs): super().__init__(*args, object_hook=self.object_hook, **kwargs) def object_hook(self, o): """Hook to override default decoder.""" if "__type__" in o: obj_type = o["__type__"] if obj_type == "Custom": return CustomObject(o["value"]) return o theta = Parameter("theta") qc = QuantumCircuit(2, global_phase=theta) qc.h(0) qc.cx(0, 1) qc.measure_all() circuits = [qc, qc.copy()] circuits[0].metadata = {"key": CustomObject("Circuit 1")} circuits[1].metadata = {"key": CustomObject("Circuit 2")} with io.BytesIO() as qpy_buf: dump(circuits, qpy_buf, metadata_serializer=CustomSerializer) qpy_buf.seek(0) new_circuits = load(qpy_buf, metadata_deserializer=CustomDeserializer) -
The
DenseLayoutpass has a new keyword argument on its constructor,target. This argument is used to specify aTargetobject representing the compilation target for the pass. If it is specified it supersedes the other arguments on the constructor,coupling_mapandbackend_prop. -
The
Targetclass has a new method,operation_names_for_qargs(). This method is used to get the operation names (i.e. lookup key in the target) for the operations on a givenqargstuple. -
A new pass
DynamicalDecouplingPaddinghas been added to theqiskit.transpiler.passesmodule. This new pass supersedes the existingDynamicalDecouplingpass to work with the new scheduling workflow in the transpiler. It is a subclass of theBasePaddingpass and depends on having scheduling and alignment analysis passes run prior to it in aPassManager. This new pass can take apulse_alignmentargument which represents a hardware constraint for waveform start timing. The spacing between gates comprising a dynamical decoupling sequence is now adjusted to satisfy this constraint so that the circuit can be executed on hardware with the constraint. This value is usually found inBackendConfiguration.timing_constraints. Additionally the pass also has anextra_slack_distributionoption has been to control how to distribute the extra slack when the duration of the created dynamical decoupling sequence is shorter than the idle time of your circuit that you want to fill with the sequence. This defaults tomiddlewhich is identical to conventional behavior. The new strategysplit_edgesevenly divide the extra slack into the beginning and end of the sequence, rather than adding it to the interval in the middle of the sequence. This might result in better noise cancellation especially whenpulse_alignment> 1. -
The
Z2Symmetriesclass now exposes the threshold tolerances used to chop small real and imaginary parts of coefficients. With this one can control how the coefficients of the tapered operator are simplified. For example:from qiskit.opflow import Z2Symmetries from qiskit.quantum_info import Pauli z2_symmetries = Z2Symmetries( symmetries=[Pauli("IIZI"), Pauli("IZIZ"), Pauli("ZIII")], sq_paulis=[Pauli("IIXI"), Pauli("IIIX"), Pauli("XIII")], sq_list=[1, 0, 3], tapering_values=[1, -1, -1], tol=1e-10, )By default, coefficients are chopped with a tolerance of
tol=1e-14. -
Added a
chop()method to theSparsePauliOpclass that truncates real and imaginary parts of coefficients individually. This is different from theSparsePauliOp.simplify()method which removes a coefficient only if the absolute value is close to 0. For example:>>> from qiskit.quantum_info import SparsePauliOp >>> op = SparsePauliOp(["X", "Y", "Z"], coeffs=[1+1e-17j, 1e-17+1j, 1e-17]) >>> op.simplify() SparsePauliOp(['X', 'Y'], coeffs=[1.e+00+1.e-17j, 1.e-17+1.e+00j]) >>> op.chop() SparsePauliOp(['X', 'Y'], coeffs=[1.+0.j, 0.+1.j])Note that the chop method does not accumulate the coefficents of the same Paulis, e.g.
>>> op = SparsePauliOp(["X", "X"], coeffs=[1+1e-17j, 1e-17+1j) >>> op.chop() SparsePauliOp(['X', 'X'], coeffs=[1.+0.j, 0.+1.j]) -
Added a new kwarg,
target, to the constructor for theGatesInBasistranspiler pass. This new argument can be used to optionally specify aTargetobject that represents the backend. When set thisTargetwill be used for determining whether aDAGCircuitcontains gates outside the basis set and thebasis_gatesargument will not be used. -
Added partial support for running on ppc64le and s390x Linux platforms. This release will start publishing pre-compiled binaries for ppc64le and s390x Linux platforms on all Python versions. However, unlike other supported platforms not all of Qiskit’s upstream dependencies support these platforms yet. So a C/C++ compiler may be required to build and install these dependencies and a simple
pip install qiskit-terrawith just a working Python environment will not be sufficient to install Qiskit. Additionally, these same constraints prevent us from testing the pre-compiled wheels before publishing them, so the same guarantees around platform support that exist for the other platforms don’t apply here. -
The
GradientandQFIclasses can now calculate the imaginary part of expectation value gradients. When using a different measurement basis, i.e.-Yinstead ofZ, we can measure the imaginary part of gradients The measurement basis can be set with theaux_meas_opargument.For the gradients,
aux_meas_op = Zcomputes0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]andaux_meas_op = -Ycomputes0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. For the QFIs,aux_meas_op = Zcomputes4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]andaux_meas_op = -Ycomputes4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]. For example:from qiskit import QuantumRegister, QuantumCircuit from qiskit.opflow import CircuitStateFn, Y from qiskit.opflow.gradients.circuit_gradients import LinComb from qiskit.circuit import Parameter a = Parameter("a") b = Parameter("b") params = [a, b] q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(params[0], q[0]) qc.rx(params[1], q[0]) op = CircuitStateFn(primitive=qc, coeff=1.0) aux_meas_op = -Y prob_grad = LinComb(aux_meas_op=aux_meas_op).convert(operator=op, params=params) -
The
InstructionDurationsclass now has support for working with parameters of an instruction. Each entry in anInstructionDurationsobject now consists of a tuple of(inst_name, qubits, duration, parameters, unit). This enables anInstructionDurationsto define durations for an instruction given a certain parameter value to account for different durations with different parameter values on an instruction that takes a numeric parameter. -
Added a new value for the
stylekeyword argument on the circuit drawer functioncircuit_drawer()andQuantumCircuit.draw()method,iqx_dark. Whenstyleis set toiqx_darkwith thempldrawer backend, the output visualization will use a color scheme similar to the the dark mode color scheme used by the IBM Quantum composer. For example:from qiskit.circuit import QuantumCircuit from matplotlib.pyplot import show circuit = QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.p(0.2, 1) circuit.draw("mpl", style="iqx-dark") -
Several lazy dependency checkers have been added to the new module
qiskit.utils.optionals, which can be used to query if certain Qiskit functionality is available. For example, you can ask if Qiskit has detected the presence ofmatplotlibby askingif qiskit.utils.optionals.HAS_MATPLOTLIB. These objects only attempt to import their dependencies when they are queried, so you can use them in runtime code without affecting import time. -
Import time for
qiskithas been significantly improved, especially for those with many of Qiskit Terra’s optional dependencies installed. -
The
marginal_counts()function now supports marginalizing thememoryfield of an inputResultobject. For example, if the inputresultargument is a qiskitResultobject obtained from a 4-qubit measurement we can marginalize onto the first qubit with:print(result.results[0].data.memory) marginal_result = marginal_counts(result, [0]) print(marginal_result.results[0].data.memory)The output is:
['0x0', '0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'] ['0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1'] -
The internals of the
StochasticSwapalgorithm have been reimplemented to be multithreaded and are now written in the Rust programming language instead of Cython. This significantly increases the run time performance of the compiler pass and by extensiontranspile()when run withoptimization_level0, 1, and 2. By default the pass will use up to the number of logical CPUs on your local system but you can control the number of threads used by the pass by setting theRAYON_NUM_THREADSenvironment variable to an integer value. For example, settingRAYON_NUM_THREADS=4will run theStochasticSwapwith 4 threads. -
A new environment variable
QISKIT_FORCE_THREADSis available for users to directly control whether potentially multithreaded portions of Qiskit’s code will run in multiple threads. Currently this is only used by theStochasticSwaptranspiler pass but it likely will be used other parts of Qiskit in the future. When this env variable is set toTRUEany multithreaded code in Qiskit Terra will always use multiple threads regardless of any other runtime conditions that might have otherwise caused the function to use a single threaded variant. For example, inStochasticSwapif the pass is being run as part of atranspile()call with > 1 circuit that is being executed in parallel withmultiprocessingviaparallel_map()theStochasticSwapwill not use multiple threads to avoid potentially oversubscribing CPU resources. However, if you’d like to use multiple threads in the pass along with multiple processes you can setQISKIT_FORCE_THREADS=TRUE. -
New fake backend classes are available under
qiskit.providers.fake_provider. These include mocked versions ofibm_cairo,ibm_hanoi,ibmq_kolkata,ibm_nairobi, andibm_washington. As with the other fake backends, these include snapshots of calibration and error data taken from the real system, and can be used for local testing, compilation and simulation. -
Introduced a new class
StatePreparation. This class allows users to prepare a desired state in the same fashion asInitializewithout the reset being automatically applied.For example, to prepare a qubit in the state :
import numpy as np from qiskit import QuantumCircuit circuit = QuantumCircuit(1) circuit.prepare_state([1/np.sqrt(2), -1/np.sqrt(2)], 0) circuit.draw()The output is as:
┌─────────────────────────────────────┐ q_0: ┤ State Preparation(0.70711,-0.70711) ├ └─────────────────────────────────────┘ -
The
Optimize1qGatestranspiler pass now has support for optimizingU1Gate,U2Gate, andPhaseGategates with unbound parameters in a circuit. Previously, if these gates had unbound parameters the pass would not use them. For example:from qiskit import QuantumCircuit from qiskit.circuit import Parameter from qiskit.transpiler import PassManager from qiskit.transpiler.passes import Optimize1qGates, Unroller phi = Parameter('φ') alpha = Parameter('α') qc = QuantumCircuit(1) qc.u1(2*phi, 0) qc.u1(alpha, 0) qc.u1(0.1, 0) qc.u1(0.2, 0) pm = PassManager([Unroller(['u1', 'cx']), Optimize1qGates()]) nqc = pm.run(qc)will be combined to the circuit with only one single-qubit gate:
qc = QuantumCircuit(1) qc.u1(2*phi + alpha + 0.3, 0) -
The methods
Pauli.evolve()andPauliList.evolve()now have a new keyword argument,frame, which is used to perform an evolution of a Pauli by a Clifford. Ifframe='h'(default) then it does the Heisenberg picture evolution of a Pauli by a Clifford (), and ifframe='s'then it does the Schrödinger picture evolution of a Pauli by a Clifford (). The latter option yields a faster calculation, and is also useful in certain cases. This new option makes the calculation of the greedy Clifford decomposition method indecompose_cliffordsignificantly faster. -
Added a new module to Qiskit:
qiskit.primitives. The primitives module is where APIs are defined which provide different abstractions around computing certain common functions fromQuantumCircuitwhich abstracts away the details of the underlying execution on aBackend. This enables higher level algorithms and applications to concentrate on performing the computation and not need to worry about the execution and processing of results and have a standardized interface for common computations. For example, estimating an expectation value of a quantum circuit and observable can be performed by any class implementing theBaseEstimatorclass and consumed in a standardized manner regardless of the underlying implementation. Applications can then be written using the primitive interface directly.To start the module contains two types of primitives, the
Sampler(seeBaseSamplerfor the abstract class definition) andEstimator(seeBaseEstimatorfor the abstract class definition). Reference implementations are included in theqiskit.primitivesmodule and are built using theqiskit.quantum_infomodule which perform ideal simulation of primitive operation. The expectation is that provider packages will offer their own implementations of these interfaces for providers which can efficiently implement the protocol natively (typically using a classical runtime). Additionally, in the future for providers which do not offer a native implementation of the primitives a method will be provided which will enable constructing primitive objects from aBackend. -
Added a new module,
qiskit.qpy, which contains the functionality previously exposed inqiskit.circuit.qpy_serialization. The public functions previously exposed atqiskit.circuit.qpy_serialization,dump()andload()are now available from this new module (although they are still accessible fromqiskit.circuit.qpy_serializationbut this will be deprecated in a future release). This new module was added in the interest of the future direction of the QPY file format, which in future versions will support representingpulseScheduleandScheduleBlockobjects in addition to theQuantumCircuitobjects it supports today. -
Added a new attribute,
qubit_propertiesto theTargetclass. This attribute contains a list ofQubitPropertiesobjects for each qubit in the target. For example:target.qubit_properties[2]will contain the
QubitPropertiesfor qubit number 2 in the target.For
BackendV2authors, if you were previously definingQubitPropertiesdirectly on yourBackendV2implementation by overridingBackendV2.qubit_properties()this will still work fine. However, if you do move the definition to the underlyingTargetobject and remove the specializedBackendV2.qubit_properties()implementation which will enable using qubit properties in the transpiler and also maintain API compatibility with your previous implementation. -
Added a new function,
qiskit.algorithms.eval_observables(), which is used to evaluate observables given a boundQuantumCircuit. It originates from a private method,_eval_aux_ops(), of theqiskit.algorithms.VQEclass but the neweval_observables()function is now more general so that it can be used in other algorithms, for example time evolution algorithms. -
The basis search strategy in
BasisTranslatortranspiler pass has been modified into a variant of Dijkstra search which greatly improves the runtime performance of the pass when attempting to target an unreachable basis. -
The
DenseLayouttranspiler pass is now multithreaded, which greatly improves the runtime performance of the pass. By default, it will use the number of logical CPUs on your local system, but you can control the number of threads used by the pass by setting theRAYON_NUM_THREADSenvironment variable to an integer value. For example, settingRAYON_NUM_THREADS=4will run theDenseLayoutpass with 4 threads. -
The internal computations of
Statevector.expectation_value()andDensityMatrix.expectation_value()methods have been reimplemented in the Rust programming language. This new implementation is multithreaded and by default for aStatevectororDensityMatrix>= 19 qubits will spawn a thread pool with the number of logical CPUs available on the local system. You can you can control the number of threads used by setting theRAYON_NUM_THREADSenvironment variable to an integer value. For example, settingRAYON_NUM_THREADS=4will only use 4 threads in the thread pool. -
Added a new
SparsePauliOp.from_sparse_list()constructor that takes an iterable, where the elements represent Pauli terms that are themselves sparse, so that"XIIIIIIIIIIIIIIIX"can now be written as("XX", [0, 16]). For example, the operatorcan now be constructed as
op = SparsePauliOp.from_sparse_list([("XZ", [0, 3], 1), ("YY", [1, 4], 2)], num_qubits=5) # or equivalently, as previously op = SparsePauliOp.from_list([("IZIIX", 1), ("YIIYI", 2)])This facilitates the construction of very sparse operators on many qubits, as is often the case for Ising Hamiltonians.
-
The
UnitarySynthesistranspiler pass has a new keyword argument on its constructor,target. This can be used to optionally specify aTargetobject which represents the compilation target for the pass. When it’s specified it will supersede the values set forbasis_gates,coupling_map, andbackend_props. -
The
UnitarySynthesisPluginabstract plugin class has a new optional attribute implementations can add,supports_target. If a plugin has this attribute set toTrueaTargetobject will be passed in theoptionspayload under thetargetfield. The expectation is that thisTargetobject will be used in place ofcoupling_map,gate_lengths,basis_gates, andgate_errors. -
Introduced a new transpiler pass workflow for building
PassManagerobjects for schedulingQuantumCircuitobjects in the transpiler. In the new workflow scheduling and alignment passes are allAnalysisPassobjects that only update the property set of the pass manager, specifically new property set itemnode_start_time, which holds the absolute start time of each opnode. A separateTransformationPasssuch asPadDelayis subsequently used to apply scheduling to the DAG. This new workflow is both more efficient and can correct for additional timing constraints exposed by a backend.Previously, the pass chain would have been implemented as
scheduling -> alignmentwhich were both transform passes thus there were multipleDAGCircuitinstances recreated during each pass. In addition, scheduling occured in each pass to obtain instruction start time. Now the required pass chain becomesscheduling -> alignment -> paddingwhere theDAGCircuitupdate only occurs at the end with thepaddingpass.For those who are creating custom
PassManagerobjects that involve circuit scheduling you will need to adjust yourPassManagerto insert one of theBasePaddingpasses (currently eitherPadDelayorPadDynamicalDecouplingcan be used) at the end of the scheduling pass chain. Without the padding pass the scheduling passes will not be reflected in the output circuit of therun()method of your customPassManager.For example, if you were previously building your
PassManagerwith something like:from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TimeUnitConversion, ALAPSchedule, ValidatePulseGates, AlignMeasures pm = PassManager() scheduling = [ ALAPSchedule(instruction_durations), PadDelay()), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), AlignMeasures(alignment=timing_constraints.acquire_alignment), ] pm.append(scheduling)you can instead use:
from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay pm = PassManager() scheduling = [ ALAPScheduleAnalysis(instruction_durations), PadDelay()), ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), PadDelay() ] pm.append(scheduling)which will both be more efficient and also align instructions based on any hardware constraints.
-
Added a new transpiler pass
ConstrainedReschedulepass. TheConstrainedReschedulepass considers both hardware alignment constraints that can be definied in aBackendConfigurationobject,pulse_alignmentandacquire_alignment. This new class supersedes the previosuly existingAlignMeasuresas it performs the same alignment (via the property set) for measurement instructions in addition to general instruction alignment. By setting theacquire_alignmentconstraint argument for theConstrainedReschedulepass it is a drop-in replacement ofAlignMeasureswhen paired with a newBasePaddingpass. -
Added two new transpiler passes
ALAPScheduleAnalysisandASAPScheduleAnalysiswhich superscede theALAPScheduleandASAPScheduleas part of the reworked transpiler workflow for schedling. The new passes perform the same scheduling but in the property set and relying on aBasePaddingpass to adjust the circuit based on all the scheduling alignment analysis.The standard behavior of these passes also aligns timing ordering with the topological ordering of the DAG nodes. This change may affect the scheduling outcome if it includes conditional operations, or simultaneously measuring two qubits with the same classical register (edge-case). To reproduce conventional behavior, set
clbit_write_latencyidentical to the measurement instruction length.For example, consider scheduling an input circuit like:
┌───┐┌─┐ q_0: ┤ X ├┤M├────────────── └───┘└╥┘ ┌───┐ q_1: ──────╫────┤ X ├────── ║ └─╥─┘ ┌─┐ q_2: ──────╫──────╫─────┤M├ ║ ┌────╨────┐└╥┘ c: 1/══════╩═╡ c_0=0x1 ╞═╩═ 0 └─────────┘ 0from qiskit import QuantumCircuit from qiskit.transpiler import InstructionDurations, PassManager from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay, SetIOLatency from qiskit.visualization.timeline import draw circuit = QuantumCircuit(3, 1) circuit.x(0) circuit.measure(0, 0) circuit.x(1).c_if(0, 1) circuit.measure(2, 0) durations = InstructionDurations([("x", None, 160), ("measure", None, 800)]) pm = PassManager( [ SetIOLatency(clbit_write_latency=800, conditional_latency=0), ALAPScheduleAnalysis(durations), PadDelay(), ] ) draw(pm.run(circuit))As you can see in the timeline view, the measurement on
q_2starts before the conditional X gate on theq_1, which seems to be opposite to the topological ordering of the node. This is also expected behavior because clbit write-access happens at the end edge of the measure instruction, and the read-access of the conditional gate happens the begin edge of the instruction. Thus topological ordering is preserved on the timeslot of the classical register, which is not captured by the timeline view. However, this assumes a paticular microarchitecture design, and the circuit is not necessary scheduled like this.By using the default configuration of passes, the circuit is schedule like below.
from qiskit import QuantumCircuit from qiskit.transpiler import InstructionDurations, PassManager from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay from qiskit.visualization.timeline import draw circuit = QuantumCircuit(3, 1) circuit.x(0) circuit.measure(0, 0) circuit.x(1).c_if(0, 1) circuit.measure(2, 0) durations = InstructionDurations([("x", None, 160), ("measure", None, 800)]) pm = PassManager([ALAPScheduleAnalysis(durations), PadDelay()]) draw(pm.run(circuit))Note that clbit is locked throughout the measurement instruction interval. This behavior is designed based on the Qiskit Pulse, in which the acquire instruction takes
AcquireChannelandMemorySlotwhich are not allowed to overlap with other instructions, i.e. simultaneous memory access from the different instructions is prohibited. This also always aligns the timing ordering with the topological node ordering. -
Added a new transpiler pass
PadDynamicalDecouplingwhich supersedes theDynamicalDecouplingpass as part of the reworked transpiler workflow for scheduling. This new pass will insert dynamical decoupling sequences into the circuit per any scheduling and alignment analysis that occured in earlier passes. -
The
plot_gate_map()visualization function and the functions built on top of it,plot_error_map()andplot_circuit_layout(), have a new keyword argument,qubit_coordinates. This argument takes a sequence of 2D coordinates to use for plotting each qubit in the backend being visualized. If specified this sequence must have a length equal to the number of qubits on the backend and it will be used instead of the default behavior. -
The
plot_gate_map()visualization function and the functions built on top of it,plot_error_map()andplot_circuit_layout(), now are able to plot any backend not just those with the number of qubits equal to one of the IBM backends. This relies on the retworkxspring_layout()function to generate the layout for the visualization. If the default layout doesn’t work with a backend’s particular coupling graph you can use thequbit_coordinatesfunction to set a custom layout. -
The
plot_gate_map()visualization function and the functions built on top of it,plot_error_map()andplot_circuit_layout(), are now able to function with aBackendV2based backend. Previously, these functions only worked withBaseBackendorBackendV1based backends. -
Added a new transpiler pass,
SetIOLatency. This pass takes two argumentsclbit_write_latencyandconditional_latencyto define the I/O latency for classical bits and classical conditions on a backend. This pass will then define these values on the pass manager’s property set to enable subsequent scheduling and alignment passes to correct for these latencies and provide a more presice scheduling output of a dynamic circuit. -
A new transpiler pass
PadDelayhas been added. This pass fills idle time on the qubit wires withDelayinstructions. This pass is part of the new workflow for scheduling passes in the transpiler and depends on a scheduling analysis pass (such asALAPScheduleAnalysisorASAPScheduleAnalysis) and any alignment passes (such asConstrainedReschedule) to be run prior toPadDelay. -
The
VF2Layouttranspiler pass has a new keyword argument,targetwhich is used to provide aTargetobject for the pass. When specified, theTargetwill be used by the pass for all information about the target device. If it is specified, thetargetoption will take priority over thecoupling_mapandpropertiesarguments. -
Allow callables as optimizers in
VQEandQAOA. Now, the optimizer can either be one of Qiskit’s optimizers, such asSPSAor a callable with the following signature:from qiskit.algorithms.optimizers import OptimizerResult def my_optimizer(fun, x0, jac=None, bounds=None) -> OptimizerResult: # Args: # fun (callable): the function to minimize # x0 (np.ndarray): the initial point for the optimization # jac (callable, optional): the gradient of the objective function # bounds (list, optional): a list of tuples specifying the parameter bounds result = OptimizerResult() result.x = # optimal parameters result.fun = # optimal function value return resultThe above signature also allows to directly pass any SciPy minimizer, for instance as
from functools import partial from scipy.optimize import minimize optimizer = partial(minimize, method="L-BFGS-B")
Known Issues
- When running
parallel_map()(which is done internally by performance sensitive functions such astranspile()andassemble()) in a subprocess launched outside ofparallel_map(), it is possible that the parallel dispatch performed insideparallel_map()will hang and never return. This is due to upstream issues in CPython around the default method to launch subprocesses on Linux and macOS with Python 3.7 (see https://bugs.python.org/issue40379 for more details). If you encounter this, you have two options: you can either remove the nested parallel processes, as callingparallel_map()from a main process should work fine; or you can manually call the CPython standard librarymultiprocessingmodule to perform similar parallel dispatch from a subprocess, but use the"spawn"or"forkserver"launch methods to avoid the potential to have things get stuck and never return.
Upgrade Notes
-
The classes
Qubit,ClbitandAncillaQubitnow have the__slots__attribute. This is to reduce their memory usage. As a side effect, they can no longer have arbitrary data attached as attributes to them. This is very unlikely to have any effect on downstream code other than performance benefits. -
The core dependency
retworkxhad its version requirement bumped to 0.11.0, up from 0.10.1. This improves the performance of transpilation passConsolidateBlocks. -
The minimum supported version of
symengineis now 0.9.0. This was necessary to improve compatibility with Python’spicklemodule which is used internally as part of parallel dispatch withparallel_map(). -
The default value of
QISKIT_PARALLELwhen running with Python 3.9 on Linux is now set toTRUE. This means when runningparallel_map()or functions that call it internally, such astranspile()andassemble(), the function will be executed in multiple processes and should have better run time performance. This change was made because the issues with reliability of parallel dispatch appear to have been resolved (see #6188 for more details). If you still encounter issues because of this you can disable multiprocessing and revert to the previous default behavior by setting theQISKIT_PARALLELenvironment variable toFALSE, or setting theparalleloption toFalsein your user config file (also please file an issue so we can track any issues related to multiprocessing). -
The previously deprecated
MSGategate class previously found inqiskit.circuit.libraryhas been removed. It was originally deprecated in the 0.16.0 release. Instead theGMSclass should be used, as this allows you to create an equivalent 2 qubit MS gate in addition to anMSGatefor any number of qubits. -
The previously deprecated
mirror()method of theInstructionclass has been removed. It was originally deprecated in 0.15.0 release. Instead you should useInstruction.reverse_ops(). -
The previously deprecated
num_ancilla_qubits()method of theqiskit.circuit.library.PiecewiseLinearPauliRotationsandqiskit.circuit.library.WeightedAdderclasses has been removed. It was originally deprecated in the 0.16.0 release. Instead thePiecewiseLinearPauliRotations.num_ancillas()andWeightedAdder.num_ancillas()methods should be used. -
The previously deprecated
reverseargument on the constructor for thePolynomialPauliRotationsclass has been removed. It was originally deprecated in the 0.15.0 release. Instead you should use theQuantumCircuit.reverse_bits()method to reverse thePolynomialPauliRotationscircuit if needed. -
The previously deprecated
angleargument on the constructors for theC3SXGateandC3XGategate classes has been removed. It was originally deprecated in the 0.17.0 release. Instead for fractional 3-controlled X gates you can use theC3XGate.power()method. -
Support for using
np.ndarrayobjects as part of theparamsattribute of aGateobject has been removed. This has been deprecated since Qiskit Terra 0.16.0 and now will no longer work. Instead one should create a new subclass ofGateand explicitly allow anp.ndarrayinput by overloading thevalidate_parameter()method. -
A new extra
csp-layout-passhas been added to the install target forpip install qiskit-terra, and is also included in theallextra. This has no effect in Qiskit Terra 0.20, but starting from Qiskit Terra 0.21, the dependencies needed only for theCSPLayouttranspiler pass will be downgraded from requirements to optionals, and installed by this extra. You can prepare a package that depends on this pass by setting its requirements (orpip installcommand) to targetqiskit-terra[csp-layout-pass]. -
Support for running with Python 3.6 has been removed. To run Qiskit you need a minimum Python version of 3.7.
-
The
AmplitudeEstimatornow inherits from theABCclass from the Python standard library. This requires any subclass to implement theestimate()method when previously it wasn’t required. This was done because the original intent of the class was to always be a child class ofABC, as theestimate()is required for the operation of anAmplitudeEstimatorobject. However, if you were previously defining anAmplitudeEstimatorsubclass that didn’t implementestimate()this will now result in an error. -
The error raised by
HoareOptimizerif the optional dependencyz3is not available has changed fromTranspilerErrortoMissingOptionalLibraryError(which is both aQiskitErrorand anImportError). This was done to be consistent with the other optional dependencies. -
On Linux, the minimum library support has been raised from the manylinux2010 VM to manylinux2014. This mirrors similar changes in Numpy and Scipy. There should be no meaningful effect for most users, unless your system still contains a very old version of
glibc. -
The
marginal_counts()function when called with aResultobject input, will now marginalize thememoryfield of experiment data if it’s set in the inputResult. Previously, thememoryfield in the the input was not marginalized. This change was made because the previous behavior would result in thecountsfield not matching thememoryfield aftermarginal_counts()was called. If the previous behavior is desired it can be restored by settingmarginalize_memory=Noneas an argument tomarginal_counts()which will not marginalize thememoryfield. -
The
StochasticSwaptranspiler pass may return different results with the same seed value set. This is due to the internal rewrite of the transpiler pass to improve runtime performance. However, this means that if you rantranspile()withoptimization_level0, 1 (the default), or 2 with a value set forseed_transpileryou may get an output with different swap mapping present after upgrading to Qiskit Terra 0.20.0. -
To build Qiskit Terra from source a Rust compiler is now needed. This is due to the internal rewrite of the
StochasticSwaptranspiler pass which greatly improves the runtime performance of the transpiler. The rust compiler can easily be installed using rustup, which can be found here: https://rustup.rs/ -
The
nameattribute of thePauliEvolutionGateclass has been changed to always be"PauliEvolution". This change was made to be consistent with other gates in Qiskit and enables other parts of Qiskit to quickly identify when a particular operation in a circuit is aPauliEvolutionGate. For example, it enables the unrolling to Pauli evolution gates.Previously, the name contained the operators which are evolved, which is now available via the
PauliEvolutionGate.labelattribute. If a circuit with aPauliEvolutionGateis drawn, the gate will still show the same information, which gates are being evolved. -
The previously deprecated methods:
qiskit.algorithms.VQE.get_optimal_costqiskit.algorithms.VQE.get_optimal_circuitqiskit.algorithms.VQE.get_optimal_vectorqiskit.algorithms.VQE.optimal_paramsqiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phaseqiskit.algorithms.PhaseEstimationResult.most_likely_phase
which were originally deprecated in the Qiskit Terra 0.18.0 release have been removed and will no longer work.
-
The
qiskit.algorithms.VariationalAlgorithmclass is now defined as an abstract base class (ABC) which will require classes that inherit from it to define both aVariationalAlgorithm.initial_pointgetter and setter method. -
The
pass_managerkwarg for thetranspile()function has been removed. It was originally deprecated in the 0.13.0 release. The preferred way to transpile a circuit with a customPassManagerobject is to use therun()method of thePassManagerobject. -
The previously deprecated
ParametrizedScheduleclass has been removed and no longer exists. This class was deprecated as a part of the 0.17.0 release. Instead of using this class you can directly parametrizeScheduleorScheduleBlockobjects by specifying aParameterobject to the parametric pulse argument. -
The module
qiskit.circuit.library.probability_distributionshas been removed and no longer exists as per the deprecation notice from qiskit-terra 0.17.0 (released Apr 1, 2021). The affected classes areUniformDistribution,NormalDistribution, andLogNormalDistribution. They are all moved to the qiskit-finance library, into its circuit library module:qiskit_finance.circuit.library.probability_distributions. -
The previous
qiskit.test.mock.fake_mumbai_v2.FakeMumbaiV2class has been renamed toFakeMumbaiFractionalCXto differentiate it from theBackendV2based fake backend for the IBM Mumbai device,qiskit.test.mock.backends.FakeMumbaiV2. If you were previously relying on theFakeMumbaiV2class to get a fake backend that had fractional applications ofCXGatedefined in its target you need to useFakeMumbaiFractionalCXclass as theFakeMumbaiV2will no longer have those extra gate definitions in itsTarget. -
The resolver used by
QuantumCircuit.append()(and consequently all methods that add an instruction onto aQuantumCircuit) to convert bit specifiers has changed to make it faster and more reliable. Certain constructs like:import numpy as np from qiskit import QuantumCircuit qc = QuantumCircuit(1, 1) qc.measure(np.array([0]), np.array([0]))will now work where they previously would incorrectly raise an error, but certain pathological inputs such as:
from sympy import E, I, pi qc.x(E ** (I * pi))will now raise errors where they may have occasionally (erroneously) succeeded before. For almost all correct uses, there should be no noticeable change except for a general speed-up.
-
The semi-public internal method
QuantumCircuit._append()no longer checks the types of its inputs, and assumes that there are no invalid duplicates in its argument lists. This function is used by certain internal parts of Qiskit and other libraries to build upQuantumCircuitinstances as quickly as possible by skipping the error checking when the data is already known to be correct. In general, users or functions taking in user data should use the publicQuantumCircuit.append()method, which resolves integer bit specifiers, broadcasts its arguments and checks the inputs for correctness. -
Cython is no longer a build dependency of Qiskit Terra and is no longer required to be installed when building Qiskit Terra from source.
-
The preset passmanagers in
qiskit.transpiler.preset_passmanagersfor all optimization levels 2 and 3 as generated bylevel_2_pass_manager()andlevel_3_pass_manager()have been changed to run theVF2Layoutby default prior to the layout pass. TheVF2Layoutpass will quickly check if a perfect layout can be found and supersedes what was previously done for optimization levels 2 and 3 which were using a combination ofTrivialLayoutandCSPLayoutto try and find a perfect layout. This will result in potentially different behavior whentranspile()is called by default as it removes a default path for all optimization levels >=2 of using a trivial layout (wherecircuit.qubits[0]is mapped to physical qubit 0,circuit.qubits[1]is mapped to physical qubit 1, etc) assuming the trivial layout is perfect. If your use case was dependent on the trivial layout you can explictly request it when transpiling by specifyinglayout_method="trivial"when callingtranspile(). -
The preset pass manager for optimization level 1 (when calling
transpile()withoptimization_level=1or when nooptimization_levelargument is set) as generated bylevel_1_pass_manager()has been changed so thatVF2Layoutis called by default to quickly check if a a perfect layout can be found prior to theDenseLayout. However, unlike with optimization level 2 and 3 a trivial layout is still attempted prior to runningVF2Layoutand if it’s a perfect mapping the output fromVF2Layoutwill be used.
Deprecation Notes
-
The
max_creditsargument toexecute(), and all of theQobjconfigurations (e.g.QasmQobjConfigandPulseQobjConfig), is deprecated and will be removed in a future release. The credit system has not been in use on IBM Quantum backends for two years, and the option has no effect. No alternative is necessary. For example, if you were callingexecute()as:job = execute(qc, backend, shots=4321, max_credits=10)you can simply omit the
max_creditsargument:job = execute(qc, backend, shots=4321) -
Using an odd integer for the
orderargument on the constructor of theSuzukiTrotterclass is deprecated and will no longer work in a future release. The product formulae used by theSuzukiTrotterare only defined when the order is even as the Suzuki product formulae is symmetric. -
The
qregs,cregs,layout, andglobal_phasekwargs to theMatplotlibDrawer,TextDrawing, andQCircuitImageclasses, and thecalibrationskwarg to theMatplotlibDrawerclass, are now deprecated and will be removed in a subsequent release.
Bug Fixes
-
Fixed an error in the circuit conversion functions
circuit_to_gate()andcircuit_to_instruction()(and their associated circuit methodsQuantumCircuit.to_gate()andQuantumCircuit.to_instruction()) when acting on a circuit with registerless bits, or bits in more than one register. -
Fixed an issue where calling
QuantumCircuit.copy()on the “body” circuits of a control-flow operation created with the builder interface would raise an error. For example, this was previously an error, but will now return successfully:from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister qreg = QuantumRegister(4) creg = ClassicalRegister(1) circ = QuantumCircuit(qreg, creg) with circ.if_test((creg, 0)): circ.h(0) if_else_instruction, _, _ = circ.data[0] true_body = if_else_instruction.params[0] true_body.copy() -
Added a missing entry from the standard session equivalence library between
CXGateandCPhaseGateas well as betweenCXGateandCRZGate. -
Fixed an issue where running the
==operator between twoSparsePauliOpobjects would raise an error when the two operators had different numbers of coefficients. For example:op = SparsePauliOp.from_list([("X", 1), ("Y", 1)]) op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)]) print(op == op2)This would previously raise a
ValueErrorinstead of returningFalse. -
Fixed support in
transpile()for passing aInstructionScheduleMapobject to the underlyingPassManagerbased on theTargetforBackendV2based backends. Previously, thetranspile()function would not do this processing and any transpiler passes which do not support working with aTargetobject yet would not have access to the default pulse calibrations for the instructions from aBackendV2backend. -
The
AmplitudeAmplifieris now correctly available from the rootqiskit.algorithmsmodule directly. Previously it was not included in the re-exported classes off the root module and was only accessible fromqiskit.algorithms.amplitude_amplifiers. Fixed #7751. -
Fixed an issue with the
mplbackend for the circuit drawer functioncircuit_drawer()and theQuantumCircuit.draw()method where gates with conditions would not display properly when a sufficient number of gates caused the drawer to fold over to a second row. Fixed: #7752. -
Fixed an issue where the
HHL.construct_circuit()method under certain conditions would not return a correctQuantumCircuit. Previously, the function had a rounding error in calculating how many qubits were necessary to represent the eigenvalues which would cause an incorrect circuit output. -
Fixed an endianness bug in
BaseReadoutMitigator.expectation_value()when a stringdiagonalwas passed. It will now correctly be interpreted as little endian in the same manner as the rest of Qiskit Terra, instead of big endian. -
Fixed an issue with the
quantum_info.partial_trace()when the function was asked to trace out no subsystems, it will now correctly return theDensityMatrixof the input state with all dimensions remaining rather than throwing an error. Fixed #7613 -
Fixed an issue with the
textbackend for the circuit drawer functioncircuit_drawer()and theQuantumCircuit.draw()method when gates that use side text, such as theCPhaseGateandRZZGategate classes, with classical conditions set would not display properly. Fixed #7532. -
Fixed an issue with the
circuit_drawer()function anddraw()method ofQuantumCircuit. When using thereverse_bitsoption with thempl,latex, ortextoptions, bits without registers did not display in the correct order. Fixed #7303. -
Fixed an issue in the
LocalReadoutMitigator.assignment_matrix()method where it would previously reject an input value for thequbitsargument that wasn’t a trivial sequence of qubits in the form:[0, 1, 2, ..., n-1]. This has been corrected so that now any list of qubit indices to be measured are accepted by the method. -
Fixed an issue in the
StabilizerState.expectation_value()method’s expectation value calculation, where the output expectation value would be incorrect if the inputPaulioperator for theoperargument had a non-trivial phase. Fixed #7441. -
An opflow expression containing the Pauli identity
opflow.Ino longer produces anIGatewhen converted to a circuit. This change fixes a difference in expectation; the identity gate in the circuit indicates a delay however in opflow we expect a mathematical identity – meaning no operation at all. -
The
PauliGateno longer inserts anIGatefor Paulis with the label"I". -
PauliSumOpequality tests now handle the case when one of the compared items is a singlePauliOp. For example,0 * X + I == Inow evaluates to True, whereas it was False prior to this release. -
Fixed an issue with the
ALAPScheduleandASAPScheduletranspiler passes when working with instructions that had custom pulse calibrations (i.e. pulse gates) set. Previously, the scheduling passes would not use the duration from the custom pulse calibration for thse instructions which would result in the an incorrect scheduling being generated for the circuit. This has been fixed so that now the scheduling passes will use the duration of the custom pulse calibration for any instruction in the circuit which has a custom calibration. -
Fixed support for using
ParameterExpressioninstruction paramaters in theRZXCalibrationBuildertranspiler pass. Previously, if an instruction parameter included a boundParameterExpressionthe pass would not be able to handle this correctly. -
Stopped the parser in
QuantumCircuit.from_qasm_str()andfrom_qasm_file()from accepting OpenQASM programs that identified themselves as being from a language version other than 2.0. This parser is only for OpenQASM 2.0; support for imported circuits from OpenQASM 3.0 will be added in an upcoming release. -
The OpenQASM 3 exporter,
qasm3.Exporter, will now escape register and parameter names that clash with reserved OpenQASM 3 keywords by generating a new unique name. Registers and parameters with the same name will no longer have naming clashes in the code output from the OpenQASM 3 exporter. Fixed #7742.
Aer 0.10.3
No change
Ignis 0.7.0
No change
IBM Q Provider 0.18.3
No change