Qiskit 0.33 release notes
0.33.1
Terra 0.19.1
Prelude
Qiskit Terra 0.19.1 is a bugfix release, solving some issues in 0.19.0 concerning circuits constructed by the control-flow builder interface, conditional gates and QPY serialisation of newer Terra objects.
Deprecation Notes
-
The loose functions
qiskit.circuit.measure.measure()
andqiskit.circuit.reset.reset()
are deprecated, and will be removed in a future release. Instead, you should access these as methods onQuantumCircuit
:from qiskit import QuantumCircuit circuit = QuantumCircuit(1, 1) # Replace this deprecated form ... from qiskit.circuit.measure import measure measure(circuit, 0, 0) # ... with either of the next two lines: circuit.measure(0, 0) QuantumCircuit.measure(circuit, 0, 0)
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. Previously, the number of bits necessary for the created gate or instruction would be calculated incorrectly, often causing an exception during the conversion. -
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()
-
The control-flow builder interface now supports using
ClassicalRegister
s as conditions in nested control-flow scopes. Previously, doing this would not raise an error immediately, but the internal circuit blocks would not have the correct registers defined, and so later logic that worked with the inner blocks would fail.For example, previously the drawers would fail when trying to draw an inner block conditioned on a classical register, whereas now it will succeed, such as in this example:
from qiskit import QuantumCircuit from qiskit.circuit import QuantumRegister, ClassicalRegister qreg = QuantumRegister(4) creg = ClassicalRegister(1) circ = QuantumCircuit(qreg, creg) with circ.for_loop(range(10)) as a: circ.ry(a, 0) with circ.if_test((creg, 1)): circ.break_loop() print(circ.draw(cregbundle=False)) print(circ.data[0][0].blocks[0].draw(cregbundle=False))
-
Fixed
qpy_serialization
support for serializingQuantumCircuit
objects that are usingParameterVector
orParameterVectorElement
as parameters. Previously, aParameterVectorElement
parameter was just treated as aParameter
for QPY serialization which meant theParameterVector
context was lost in QPY and the output order ofparameters
could be incorrect.To fix this issue a new QPY format version, Version 3, was required. This new format version includes a representation of the
ParameterVectorElement
class which is described in theqpy_serialization
documentation at PARAMETER_VECTOR_ELEMENT. -
Fixed the
qpy_serialization
support for serializing aPauliEvolutionGate
object. Previously, thePauliEvolutionGate
was treated as a custom gate for serialization and would be deserialized as aGate
object that had the same definition and name as the originalPauliEvolutionGate
. However, this would lose the original state from thePauliEvolutionGate
. This has been fixed so that starting in this release aPauliEvolutionGate
in the circuit will be preserved 1:1 across QPY serialization now. The only limitation with this is that it does not support customEvolutionSynthesis
classes. Only the classes available fromqiskit.synthesis
can be used with aPauliEvolutionGate
for qpy serialization.To fix this issue a new QPY format version, Version 3, was required. This new format version includes a representation of the
PauliEvolutionGate
class which is described in theqpy_serialization
documentation at PAULI_EVOLUTION. -
Two loose functions
qiskit.circuit.measure.measure()
andqiskit.circuit.reset.reset()
were accidentally removed without a deprecation period. They have been reinstated, but are marked as deprecated in favour of the methodsQuantumCircuit.measure()
andQuantumCircuit.reset()
, respectively, and will be removed in a future release.
Other Notes
-
The new control-flow builder interface uses various context managers and helper objects to do its work. These should not be considered part of the public API, and are liable to be changed and removed without warning. The usage of the builder interface has stability guarantees, in the sense that the behaviour described by
QuantumCircuit.for_loop()
,while_loop()
andif_test()
for the builder interface are subject to the standard deprecation policies, but the actual objects used to effect this are not. You should not rely on the objects (such asIfContext
orControlFlowBuilderBlock
) existing in their current locations, or having any methods or attributes attached to them.This was not previously clear in the 0.19.0 release. All such objects now have a warning in their documentation strings making this explicit. It is likely in the future that their locations and backing implementations will become quite different.
Aer 0.9.1
No change
Ignis 0.7.0
No change
IBM Q Provider 0.18.2
Bug Fixes
- Fix delivered in #1065 for the issue where job kept crashing when
Parameter
was passed in circuit metadata. - Fix delivered in #1094 for the issue wherein
qiskit.providers.ibmq.runtime.RuntimeEncoder
does an extra decompose() if the circuit being serialized is aBlueprintCircuit
.
0.33.0
This release officially marks the end of support for the Qiskit Aqua project in Qiskit. It was originally deprecated in the 0.25.0 release and as was documented in that release the qiskit-aqua
package has been removed from the Qiskit metapackage, which means pip install qiskit
will no longer include qiskit-aqua
. However, because of limitations in python packaging we cannot automatically remove a pre-existing install of qiskit-aqua
when upgrading a previous version of Qiskit to this release (or a future release) with pip install -U qiskit
. If you are upgrading from a previous version it’s recommended that you manually uninstall Qiskit Aqua with pip uninstall qiskit-aqua
or install in a fresh python environment.
The application modules that were provided by qiskit-aqua
have been split into several new packages: qiskit-optimization
, qiskit-nature
, qiskit-machine-learning
, and qiskit-finance
. These packages can be installed by themselves (via the standard pip install command, e.g. pip install qiskit-nature
) or with the rest of the Qiskit metapackage as optional extras (e.g. pip install 'qiskit[finance,optimization]'
or pip install 'qiskit[all]'
). The core algorithms and the operator flow now exist as part of Qiskit Terra at qiskit.algorithms
and qiskit.opflow
. Depending on your existing usage of Aqua you should either use the application packages or the new modules in Qiskit Terra. For more details on how to migrate from Qiskit Aqua you can refer to the Aqua Migration Guide.
This release also officially deprecates the Qiskit Ignis project. Accordingly, in a future release the qiskit-ignis
package will be removed from the Qiskit metapackage, which means in that future release pip install qiskit
will no longer include qiskit-ignis
. Qiskit Ignis has been supersceded by the Qiskit Experiments project and active development has ceased. While deprecated, critical bug fixes and compatibility fixes will continue to be made to provide users a sufficient opportunity to migrate off of Ignis. After the deprecation period (which will be no shorter than 3 months from this release) the project will be retired and archived. You can refer to the migration guide for details on how to switch from Qiskit Ignis to Qiskit Experiments.
Terra 0.19.0
Prelude
The Qiskit Terra 0.19 release highlights are:
- A new version of the abstract Qiskit/hardware interface, in the form of
BackendV2
, which comes with a new data structureTarget
to allow backends to better model their constraints for the transpiler. - An extensible plugin interface to the
UnitarySynthesis
transpiler pass, allowing users or other packages to extend Qiskit Terra’s synthesis routines with new methods. - Control-flow instructions, for representing
for
andwhile
loops andif
/else
statements inQuantumCircuit
. The simulators in Qiskit Aer will soon be able to work with these new instructions, allowing you to write more dynamic quantum programs. - Preliminary support for the evolving OpenQASM 3 specification. You can use the new
qiskit.qasm3
module to serialize yourQuantumCircuit
s into OpenQASM 3, including the new control-flow constructs.
This release marks the end of support for Python 3.6 in Qiskit. This release of Qiskit Terra, and any subsequent bugfix releases in the 0.19.x series, will be the last to work with Python 3.6. Starting from the next minor release (0.20.0) of Qiskit Terra, the minimum required Python version will be 3.7.
As always, there are many more features and fixes in this release as well, which you can read about below.
New Features
-
QuantumCircuit.decompose()
and its corresponding transpiler passDecompose
now optionally accept a parameter containing a collection of gate names. If this parameter is given, then only gates with matching names will be decomposed. This supports Unix-shell-style wildcard matches. For example:qc.decompose(["h", "r[xz]"])
will decompose any
h
,rx
orrz
gates, but leave (for example)x
gates untouched. -
Added the
termination_checker
argument to theSPSA
optimizer. This allows the user to implement a custom termination criterion.import numpy as np from qiskit.algorithms.optimizers import SPSA def objective(x): return np.linalg.norm(x) + .04*np.random.rand(1) class TerminationChecker: def __init__(self, N : int): """ Callback to terminate optimization when the average decrease over the last N data points is smaller than the specified tolerance. """ self.N = N self.values = [] def __call__(self, nfev, parameters, value, stepsize, accepted) -> bool: """ Returns: True if the optimization loop should be terminated. """ self.values.append(value) if len(self.values) > self.N: last_values = self.values[-self.N:] pp = np.polyfit(range(self.N), last_values, 1) slope = pp[0] / self.N if slope > 0: return True return False maxiter = 400 spsa = SPSA(maxiter=maxiter, termination_checker=TerminationChecker(10)) parameters, value, niter = spsa.optimize(2, objective, initial_point=np.array([0.5, 0.5]))
-
Added a new version of the
Backend
interface,BackendV2
. This new version is a large change from the previous version,BackendV1
and changes both the user access pattern for properties of the backend (like number of qubits, etc) and how the backend represents its constraints to the transpiler. The execution of circuits (via therun()
method) remains unchanged. With aBackendV2
backend instead of having a separateconfiguration()
,properties()
, anddefaults()
methods that constructBackendConfiguration
,BackendProperties
, andPulseDefaults
objects respectively, like in theBackendV1
interface, the attributes contained in those output objects are accessible directly as attributes of theBackendV2
object. For example, to get the number of qubits for a backend withBackendV1
you would do:num_qubits = backend.configuration().n_qubits
while with
BackendV2
it is:num_qubits = backend.num_qubits
The other change around this is that the number of attributes exposed in the abstract
BackendV2
class is designed to be a hardware/vendor agnostic set of the required or optional fields that the rest of Qiskit can use today with any backend. Subclasses of the abstractBackendV2
class can add support for additional attributes and methods beyond those defined inBackendV2
, but these will not be supported universally throughout Qiskit.The other critical change that is primarily important for provider authors is how a
BackendV2
exposes the properties of a particular backend to the transpiler. WithBackendV2
this is done via aTarget
object. TheTarget
, which is exposed via thetarget
attribute, is used to represent the set of constraints for running circuits on a particular backend. It contains the subset of information previously exposed by theBackendConfiguration
,BackendProperties
, andPulseDefaults
classes which the transpiler can actively use. When migrating a provider to useBackendV2
(or when creating a new provider package) the construction of backend objects will primarily be around creating aTarget
object for the backend. -
Added a new
Target
class to thetranspiler
module. TheTarget
class is designed to represent the constraints of backend to the compiler. TheTarget
class is intended to be used with aBackendV2
backend and is how backends will model their constraints for the transpiler moving forward. It combines the previously distinct fields used for controlling thetranspile()
target device (e.g.basis_gates
,coupling_map
,instruction_durations
, etc) into a single data structure. It also adds additional functionality on top of what was available previously such as representing heterogeneous gate sets, multi-qubit gate connectivity, and tuned variants of the same gates. Currently the transpiler doesn’t factor in all these constraints, but over time it will grow to leverage the extra functionality. -
The
Options
class now has optional support for specifying validators. This enablesBackend
authors to optionally specify basic validation on the user supplied values for fields in theOptions
object. For example, if you had anOptions
object defined with:from qiskit.providers.Options options = Options(shots=1024)
you can set a validator on shots for it to be between 1 and 4096 with:
options.set_validator('shots', (1, 4096))
With the validator set any call to the
update_options()
method will check that ifshots
is being updated the proposed new value is within the valid range. -
Added a new transpiler analysis pass,
ContainsInstruction
, to theqiskit.transpiler.passes
module. This pass is used to determine if a circuit contains a specific instruction. It takes in a single parameter at initialization, the name of the instruction to check for and set a boolean in the property set whether the circuit contains that instruction or not. For example:from qiskit.transpiler.passes import ContainsInstruction from qiskit.circuit import QuantumCircuit circuit = QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.measure_all() property_set = {} # Contains Hadamard contains_h = ContainsInstruction("h") contains_h(circuit, property_set) assert property_set["contains_h"] == True # Not contains SX contains_sx = ContainsInstruction("sx") contains_sx(circuit, property_set) assert property_set["contains_sx"] == False
-
Added a utility function
qiskit.utils.detach_prefix()
that is a counterpart ofapply_prefix()
. The new function returns a tuple of scaled value and prefix from a given float value. For example, a value1.3e8
will be converted into(130, "M")
that can be used to display a value in the user friendly format, such as130 MHz
. -
The values
"gate_error"
and"balanced"
are now available for theobjective
option in the construction of theBIPMapping
object, and"balanced"
is now the default.The
"gate_error"
objective requires passing aBackendProperties
instance in thebackend_prop
kwarg, which contains the 2q-gate gate errors used in the computation of the objectives. The"balanced"
objective will use theBackendProperties
instance if it is given, but otherwise will assume a CX error rate as given in the new parameterdefault_cx_error_rate
. The relative weights of the gate-error and depth components of the balanced objective can be controlled with the newdepth_obj_weight
parameter. -
Every attribute of the
VQE
class that is set at the initialization is now accessible with getters and setters. Further, the default values of the VQE attributesansatz
andoptimizer
can be reset by assigningNone
to them:vqe = VQE(my_ansatz, my_optimizer) vqe.ansatz = None # reset to default: RealAmplitudes ansatz vqe.optimizer = None # reset to default: SLSQP optimizer
-
Added a new method
PauliList.group_qubit_wise_commuting()
that partitions aPauliList
into sets of mutually qubit-wise commutingPauli
operators. For example:from qiskit.quantum_info import PauliList, Pauli pauli_list = PauliList([Pauli("IY"), Pauli("XX"), Pauli("YY"), Pauli("YX")]) pauli_list.group_qubit_wise_commuting()
-
Added a new coupling-map constructor method
CouplingMap.from_hexagonal_lattice()
for constructing a hexagonal lattice coupling map. For example, to construct a 2x2 hexagonal lattice coupling map:from qiskit.transpiler import CouplingMap cmap = CouplingMap.from_hexagonal_lattice(2, 2) cmap.draw()
-
New fake backend classes are available under
qiskit.test.mock
. These include mocked versions ofibmq_brooklyn
,ibmq_manila
,ibmq_jakarta
, andibmq_lagos
. As with the other fake backends, these include snapshots of calibration data (i.e.backend.defaults()
) and error data (i.e.backend.properties()
) taken from the real system, and can be used for local testing, compilation and simulation. -
Added the
OperatorBase.is_hermitian()
method to check whether the operator is Hermitian or not.NumPyEigensolver
andNumPyMinimumEigensolver
useeigh
oreigsh
to solve the eigenvalue problem when the operator is Hermitian. -
Added a new constructor method
PassManagerConfig.from_backend()
. It constructs aPassManagerConfig
object with user options and the configuration of a backend. With this feature, a preset passmanager can be built easier. For example:from qiskit.transpiler.passmanager_config import PassManagerConfig from qiskit.transpiler.preset_passmanagers import level_1_pass_manager from qiskit.test.mock import FakeMelbourne pass_manager = level_1_pass_manager( PassManagerConfig.from_backend(FakeMelbourne(), seed_transpiler=42) )
-
A new transpiler pass,
PulseGates
, was added, which automatically extracts user-provided calibrations from the instruction schedule map and attaches the gate schedule to the given (transpiled) quantum circuit as a pulse gate.The
PulseGates
transpiler pass is applied to all optimization levels from 0 to 3. No gate implementation is updated unless the end-user explicitly overrides thebackend.defaults().instruction_schedule_map
. This pass saves users from individually callingQuantumCircuit.add_calibration()
for every circuit run on the hardware.To supplement this new pass, a schedule was added to
InstructionScheduleMap
and is implicitly updated with a metadata field"publisher"
. Backend-calibrated gate schedules have a special publisher kind to avoid overriding circuits with calibrations of already known schedules. Usually, end-users don’t need to take care of this metadata as it is applied automatically. You can callInstructionScheduleMap.has_custom_gate()
to check if the map has custom gate calibration.See the below code example to learn how to apply custom gate implementation for all circuits under execution.
from qiskit.test.mock import FakeGuadalupe from qiskit import pulse, circuit, transpile backend = FakeGuadalupe() with pulse.build(backend, name="x") as x_q0: pulse.play(pulse.Constant(160, 0.1), pulse.drive_channel(0)) backend.defaults().instruction_schedule_map.add("x", (0,), x_q0) circs = [] for _ in range(100): circ = circuit.QuantumCircuit(1) circ.sx(0) circ.rz(1.57, 0) circ.x(0) circ.measure_active() circs.append(circ) circs = transpile(circs, backend) circs[0].calibrations # This returns calibration only for x gate
Note that the instruction schedule map is a mutable object. If you override one of the entries and use that backend for other experiments, you may accidentally update the gate definition.
backend = FakeGuadalupe() instmap = backend.defaults().instruction_schedule_map instmap.add("x", (0, ), my_x_gate_schedule) qc = QuantumCircuit(1, 1) qc.x(0) qc.measure(0, 0) qc = transpile(qc, backend) # This backend uses custom X gate
If you want to update the gate definitions of a specific experiment, you need to first deepcopy the instruction schedule map and directly pass it to the transpiler.
-
Introduced a new option
qubit_subset
to the constructor ofBIPMapping
. The option enables us to specify physical qubits to be used (incoupling_map
of the device) during the mapping in one line:mapped_circ = BIPMapping( coupling_map=CouplingMap([[0, 1], [1, 2], [1, 3], [3, 4]]), qubit_subset=[1, 3, 4] )(circ)
Previously, to do the same thing, we had to supply a reduced
coupling_map
which contains only the qubits to be used, embed the resulting circuit onto the originalcoupling_map
and update theQuantumCircuit._layout
accordingly:reduced_coupling = coupling_map.reduce(qubit_to_use) mapped = BIPMapping(reduced_coupling)(circ) # skip the definition of fill_with_ancilla() # recover circuit on original coupling map layout = Layout({q: qubit_to_use[i] for i, q in enumerate(mapped.qubits)}) for reg in mapped.qregs: layout.add_register(reg) property_set = {"layout": fill_with_ancilla(layout)} recovered = ApplyLayout()(mapped, property_set) # recover layout overall_layout = Layout({v: qubit_to_use[q] for v, q in mapped._layout.get_virtual_bits().items()}) for reg in mapped.qregs: overall_layout.add_register(reg) recovered._layout = fill_with_ancilla(overall_layout)
-
Added the
ignore_pauli_phase
andcopy
arguments to the constructor ofSparsePauliOp
.ignore_pauli_phase
prevents thephase
attribute of an inputPauliList
from being read, which is more performant if thePauliList
is already known to have all phases as zero in the internal ZX convention.copy
allows users to avoid the copy of the input data when they explicitly setcopy=False
. -
Improved performance of the following
SparsePauliOp
operations:simplify()
(see #7122)compose()
(see #7126)_add()
(see #7138)from_list()
and__init__()
(see other discussion in #7138).
-
Added the
SparsePauliOp.sum()
method to add together manySparsePauliOp
s. This method has significantly better performance than adding the instances together in a loop. For example, the previous way to add severalSparsePauliOp
s together would be to do:from qiskit.quantum_info import SparsePauliOp, random_pauli_list sparse_ops = [SparsePauliOp(random_pauli_list(10, 10)) for _ in [None]*1000] total = sparse_ops[0] for op in sparse_ops[1:]: total += op
This can now be done far more efficiently (in both speed and typing!) as:
SparsePauliOp.sum(sparse_ops)
-
Added an argument
limit_amplitude
to the constructor ofParametricPulse
, which is the base class ofGaussian
,GaussianSquare
,Drag
andConstant
, to allowing disabling the amplitude limit of 1 on a pulse-by-pulse basis. Withlimit_amplitude=False
, individual pulses may have an amplitude exceeding unity without raising aPulseError
. See #6544 for more detail. -
Using
QuantumCircuit.draw()
orcircuit_drawer()
with thelatex
drawer will now generate a file in an image format inferred from the filename extension, for example:import qiskit circuit = qiskit.QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.draw('latex', filename='./file.jpg')
This will save the circuit drawing in the JPEG format. Previously, the image always be in PNG format. Refer to #6448 for more details.
Now, if it encounters a filename extension which is not supported, for example:
circuit.draw('latex', filename='./file.spooky')
it will raise a
ValueError
to change the filename extension to a supported image format. -
Added the parameter
filename
toplot_gate_map()
andplot_coupling_map()
, which allows saving the resulting images to a file. -
Introduced an approximate quantum compiler and a corresponding unitary synthesis plugin implementation. The main AQC class is
AQC
for a standalone version that compiles a unitary matrix into an approximate circuit. The plugin may be invoked bytranspile()
when theunitary_synthesis_method
argument is set to'aqc'
. Seeqiskit.transpiler.synthesis.aqc
for full details. -
Added a
filter_function
argument toQuantumCircuit.depth()
andQuantumCircuit.size()
in order to analyze circuit operations according to some criteria.For example, to get the number of two-qubit gates, you can do:
circuit.size(lambda x: x[0].num_qubits == 2)
Or to get the depth of T gates acting on the zeroth qubit:
circuit.depth(lambda x: x[0].name == 't' and circuit.qubits[0] in x[1])
-
Added a new transpiler pass,
CollectMultiQBlocks
, to theqiskit.transpiler.passes
module. This pass is used to collect sequences of uninterrupted gates acting on groups of qubits. It provides a similar function to the existingCollect2qBlocks
pass, but while that pass is designed and optimized to find 2 qubit blocks this new pass will work to find blocks of any size. -
There is a builder interface for the new control-flow operations on
QuantumCircuit
, such as the newForLoopOp
,IfElseOp
, andWhileLoopOp
. The interface uses the same circuit methods, i.e.QuantumCircuit.for_loop()
,QuantumCircuit.if_test()
andQuantumCircuit.while_loop()
, which are overloaded so that if thebody
parameter is not given, they return a context manager. Entering one of these context managers pushes a scope into the circuit, and captures all gate calls (and other scopes) and the resources these use, and builds up the relevant operation at the end. For example, you can now do:qc = QuantumCircuit(2, 2) with qc.for_loop(range(5)) as i: qc.rx(i * math.pi / 4, 0)
This will produce a
ForLoopOp
onqc
, which knows that qubit 0 is the only resource used within the loop body. These context managers can be nested, and will correctly determine their widths. You can useQuantumCircuit.break_loop()
andQuantumCircuit.continue_loop()
within a context, and it will expand to be the correct width for its containing loop, even if it is nested in furtherQuantumCircuit.if_test()
blocks.The
if_test()
context manager provides a chained manager which, if desired, can be used to create anelse
block, such as by:qreg = QuantumRegister(2) creg = ClassicalRegister(2) qc = QuantumCircuit(qreg, creg) qc.h(0) qc.cx(0, 1) qc.measure(0, 0) with qc.if_test((creg, 0)) as else_: qc.x(1) with else_: qc.z(1)
The manager will ensure that the
if
andelse
bodies are defined over the same set of resources. -
Introduced a new transpiler pass
InverseCancellation
that generalizes theCXCancellation
pass to cancel any self-inverse gates or gate-inverse pairs. It can be used by initializingInverseCancellation
and passing a gate to cancel, for example:from qiskit.transpiler.passes import InverseCancellation from qiskit import QuantumCircuit from qiskit.circuit.library import HGate from qiskit.transpiler import PassManager qc = QuantumCircuit(2, 2) qc.h(0) qc.h(0) pass_ = InverseCancellation([HGate()]) pm = PassManager(pass_) new_circ = pm.run(qc)
-
The constructor of
RZXCalibrationBuilder
has two new kwargsinstruction_schedule_map
andqubit_channel_mapping
which take aInstructionScheduleMap
and list of channel name lists for each qubit respectively. These new arguments are used to directly specify the information needed from a backend target. They should be used instead of passing aBaseBackend
orBackendV1
object directly to the pass with thebackend
argument. -
The
Statevector
s of states comprised only of qubits can now be drawn in LaTeX in ket notation. In ket notation the entries of the statevector are processed such that exact factors like fractions or square roots of two are drawn as such. The particular convention can be chosen by passing theconvention
keyword argument as either"ket"
or"vector"
as appropriate:import math from qiskit.quantum_info import Statevector sv = Statevector([math.sqrt(0.5), 0, 0, -math.sqrt(0.5)]) sv.draw("latex", convention="ket") sv.draw("latex", convention="vector")
-
Added a new transpiler pass
EchoRZXWeylDecomposition
that allows users to decompose an arbitrary two-qubit gate in terms of echoed RZX-gates by leveraging Cartan’s decomposition. In combination with other transpiler passes, this can be used to transpile arbitrary circuits to RZX-gate-based and pulse-efficient circuits that implement the same unitary. -
The
SPSA
andQNSPSA
optimizer classes are now capable of batching as many circuit evaluations as possible for both the iterations and the initial calibrations. This can be leveraged by setting themax_evals_grouped
kwarg on the constructor forVQE
when using eitherSPSA
orQNSPSA
as theoptimizer
parameter. For example:from qiskit.circuit.library import TwoLocal from qiskit.algorithms import VQE from qiskit.algorithms.optimizers import QNSPSA from qiskit.test.mock import FakeMontreal backend = FakeMontreal() ansatz = TwoLocal(2, rotation_blocks=["ry", "rz"], entanglement_blocks="cz") qnspsa = QNSPSA(fidelity, maxiter=5) vqe = VQE( ansatz=ansatz, optimizer=qnspsa, max_evals_grouped=100, quantum_instance=backend, )
-
This release introduces a decomposition method for two-qubit gates which targets user-defined sets of RZX gates. Transpiler users can enable decomposition for {
RZX(pi/2)
,RZX(pi/4)
, andRZX(pi/6)
} specifically by including'rzx'
in theirbasis_gates
list when callingtranspile()
. Quantum information package users can find the method itself under theXXDecomposer
class. -
Added a transpiler pass
Optimize1qGatesSimpleCommutation
, which optimizes a circuit according to a strategy of commuting single-qubit gates around to discover resynthesis opportunities. -
Added a
max_job_tries
parameter toQuantumInstance
, to limit the number of times a job will attempt to be executed on a backend. Previously the submission and fetching of results would be attempted infinitely, even if the job was cancelled or errored on the backend. The default is now 50, and the previous behaviour can be achieved by settingmax_job_tries=-1
. Fixes #6872 and #6821. -
The
latex
output method for thecircuit_drawer()
function and theQuantumCircuit.draw()
method can now draw circuits that contain gates with single bit condition. This was added for compatibility of latex drawer with the new feature of supporting classical conditioning of gates on single classical bits. -
The
"mpl"
output method for thecircuit_drawer()
function and theQuantumCircuit.draw()
method can now draw circuits that contain gates with single bit condition. This was added for compatibility of the"mpl"
drawer with the new feature of supporting classical conditioning of gates on single classical bits. -
The
text
output method for thecircuit_drawer()
function and theQuantumCircuit.draw()
method can now draw circuits that contain gates with single bit condition. This was added for compatibility of text drawer with the new feature of supporting classical conditioning of gates on single classical bits. -
A new analysis transpiler pass,
GatesInBasis
, was added toqiskit.transpiler.passes
. This pass is used to check if theDAGCircuit
being transpiled has all the gates in the configured basis set or not. It will set the attribute"all_gates_in_basis"
in the property set toTrue
if all the gates in theDAGCircuit
are in the configured basis set orFalse
if they are not. For example:from qiskit.circuit import QuantumCircuit from qiskit.transpiler.passes import GatesInBasis # Instatiate Pass basis_gates = ["cx", "h"] basis_check_pass = GatesInBasis(basis_gates) # Build circuit circuit = QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.measure_all() # Run pass on circuit property_set = {} basis_check_pass(circuit, property_set=property_set) assert property_set["all_gates_in_basis"]
-
Added two new constructor methods,
from_heavy_hex()
andfrom_heavy_square()
, to theCouplingMap
class. These constructor methods are used to create aCouplingMap
that are a heavy hex or heavy square graph as described in Chamberland et al., 2020.For example:
from qiskit.transpiler import CouplingMap cmap = CouplingMap.from_heavy_hex(5) cmap.draw()
from qiskit.transpiler import CouplingMap cmap = CouplingMap.from_heavy_square(5) cmap.draw()
-
The
HHL
algorithm can now find solutions when its matrix has negative eigenvalues. To enable this, the algorithm now adds an extra qubit to represent the sign of the value, and the helper algorithmExactReciprocal
was updated to process this new information. See #6971 for more details. -
Added two new classes,
CompleteMeasFitter
andTensoredMeasFitter
to theqiskit.utils.mitigation
module. These classes are for use only as values for themeasurement_error_mitigation_cls
kwarg of theQuantumInstance
class. The instantiation and usage of these classes (or anything else inqiskit.utils.mitigation
) outside of themeasurement_error_mitigation_cls
kwarg should be treated as an internal private API and not relied upon. -
The
ListOp
class inqiskit.opflow
now has acoeffs
attribute, which returns a list of the coefficients of the operator list, with the overall coefficient (ListOp.coeff
) distributed multiplicatively into the list. Note thatListOp
objects may be nested (contained inoplist
of aListOp
object), and in these cases an exception is raised if the coeffs method is called. TheListOp.coeffs
method conveniently duck-types against thecoeffs
property method of the non-nestingPauliSumOp
class. -
The
Statevector
class is now subscriptable. User can now retrieve the nth coefficient in aStatevector
by index asstatevec[n]
. -
Added the
Statevector.inner
method to calculate inner products ofStatevector
instances. For example:statevec_inner_other = statevec.inner(other)
will return the inner product of
statevec
withother
. Whilestatevec
must be aStatevector
,other
can be anything that can be constructed into aStatevector
, such as a Numpy array. -
Added a new parameter,
add_bits
, toQuantumCircuit.measure_all()
. By default it is set toTrue
to maintain the previous behaviour of adding a newClassicalRegister
of the same size as the number of qubits to store the measurements. If set toFalse
, the measurements will be stored in the already existing classical bits. For example, if you created a circuit with existing classical bits like:from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister qr = QuantumRegister(2) cr = ClassicalRegister(2, "meas") circuit = QuantumCircuit(qr, cr)
calling
circuit.measure_all(add_bits=False)
will use the existing classical registercr
as the output target of theMeasurement
objects added to the circuit. -
ParameterExpression
now delegates its numeric conversions to the underlying symbolic library, even if there are potentially unbound parameters. This allows conversions of expressions such as:>>> from qiskit.circuit import Parameter >>> x = Parameter('x') >>> float(x - x + 2.3) 2.3
where the underlying expression has a fixed value, but the parameter
x
is not yet bound. -
Added an
Optimizer.minimize()
method to all optimizers:Optimizer
and derived classes. This method mimics the signature of SciPy’sminimize()
function and returns anOptimizerResult
.For example
import numpy as np from qiskit.algorithms.optimizers import COBYLA def loss(x): return -(x[0] - 1) ** 2 - (x[1] + 1) ** 3 initial_point = np.array([0, 0]) optimizer = COBYLA() result = optimizer.minimize(loss, initial_point) optimal_parameters = result.x minimum_value = result.fun num_function_evals = result.nfev
-
Added a
PauliEvolutionGate
to the circuit library (qiskit.circuit.library
) which defines a gate performing time evolution of (sums or sums-of-sums of)Pauli
s. The synthesis of this gate is performed byEvolutionSynthesis
and is decoupled from the gate itself. Currently available synthesis methods are:LieTrotter
: first order TrotterizationSuzukiTrotter
: higher order TrotterizationMatrixExponential
: exact, matrix-based evolution
For example:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import PauliEvolutionGate from qiskit.quantum_info import SparsePauliOp from qiskit.synthesis import SuzukiTrotter operator = SparsePauliOp.from_list([ ("XIZ", 0.5), ("ZZX", 0.5), ("IYY", -1) ]) time = 0.12 # evolution time synth = SuzukiTrotter(order=4, reps=2) evo = PauliEvolutionGate(operator, time=time, synthesis=synth) circuit = QuantumCircuit(3) circuit.append(evo, range(3))
-
A new function
plot_coupling_map()
has been introduced, which extends the functionality of the existing functionplot_gate_map()
, by accepting three parameters:num_qubit
,qubit_coordinates
, andcoupling_map
(instead ofbackend
), to allow an arbitrary qubit coupling map to be plotted. -
Qiskit Terra now has initial support for serializing
QuantumCircuit
s to OpenQASM 3:from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit import qasm3 qc = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) print(qasm3.dumps(qc))
This initial release has limited support for named registers, basic built-in instructions (such as measure, barrier and reset), user-defined gates, user-defined instructions (as subroutines), and the new control-flow constructs also introduced in this release:
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit import qasm3 import math composite_circ_qreg = QuantumRegister(2) composite_circ = QuantumCircuit(composite_circ_qreg, name="composite_circ") composite_circ.h(0) composite_circ.x(1) composite_circ.cx(0, 1) composite_circ_gate = composite_circ.to_gate() qr = QuantumRegister(2, "qr") cr = ClassicalRegister(2, "cr") qc = QuantumCircuit(qr, cr) with qc.for_loop(range(4)) as i: qc.rx(i * math.pi / 4, 0) qc.cx(0, 1) qc.barrier() qc.append(composite_circ_gate, [0, 1]) qc.measure([0, 1], [0, 1]) print(qasm3.dumps(qc))
-
The
QDrift
class was reformulated as a synthesis method forPauliEvolutionGate
, deriving fromTrotterizationBase
.from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import PauliEvolutionGate from qiskit.synthesis import QDrift from qiskit.opflow import X, Y, Z qdrift = QDrift(reps=2) operator = (X ^ 3) + (Y ^ 3) + (Z ^ 3) time = 2.345 # evolution time evolution_gate = PauliEvolutionGate(operator, time, synthesis=qdrift) circuit = QuantumCircuit(3) circuit.append(evolution_gate, range(3))
-
QPY serialization is now capable of representing
global_phase
attributes of aQuantumCircuit
object that are anint
,Parameter
object, orParameterExpression
object. Previous versions of QPY would only accept aglobal_phase
that was afloat
.This requires the QPY format Version 2 which was introduced in this release to represent the additional types.
-
A new
find_bit()
method has been added to theQuantumCircuit
class, which allows lookups of the index and registers of a providedBit
on the given circuit. The method returns a two-elementnamedtuple
containing 0) the index of theBit
in eitherqubits
(for aQubit
) orclbits
(for aClbit
) and 1) a list of length-2 tuples containing each circuitRegister
which contains theBit
, and the index in thatRegister
at which theBit
can be found.For example:
from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit reg1 = QuantumRegister(3, 'foo') qubit = Qubit() reg2 = QuantumRegister(2, 'bar') qc = QuantumCircuit(reg1, [qubit], reg2) print(qc.find_bit(reg1[2])) print(qc.find_bit(qubit))
would generate:
BitLocations(index=2, registers=[(QuantumRegister(3, 'foo'), 2)]) BitLocations(index=3, registers=[])
-
Three new
Instruction
subclasses have been added to support control flow operations in dynamic circuits:WhileLoopOp
,ForLoopOp
, andIfElseOp
. Additionally, two subclasses,BreakLoopOp
, andContinueLoopOp
, have been added to support breaking from and continuing to the next iteration of a loop context, respectively.These can be created as stand-alone
Instruction
s, or appended to an existingQuantumCircuit
instance via their respective methods,QuantumCircuit.while_loop()
,for_loop()
,if_test()
,if_else()
,break_loop()
, andcontinue_loop()
. -
Added the
BaseReadoutMitigator
abstract base class for implementing classical measurement error mitigators. These objects are intended for mitigation measurement errors inCounts
objects returned from execution of circuits on backends with measurement errors.Readout mitigator classes have two main methods:
expectation_value()
which computes an mitigated expectation value and standard error of a diagonal operator from a noisyCounts
object.quasi_probabilities()
that computes an error mitigatedQuasiDistribution
, including standard error, from a noisy counts object.
Note that currently the
qiskit.algorithms
module and theQuantumInstance
class still use the legacy mitigators migrated from Qiskit Ignis inqiskit.utils.mitigation
. It is planned to upgrade the module to use the new mitigator classes and deprecate the legacy mitgation code in a future release. -
Added the
LocalReadoutMitigator
class for performing measurement readout error mitigation of local measurement errors. Local measuerment errors are those that are described by a tensor-product of single-qubit measurement errors.This class can be initialized with a list of single-qubit of measurement error assignment matrices or from a backend using the readout error information in the backend properties.
Mitigation is implemented using local assignment-matrix inversion which has complexity of for -qubit mitigation of
QuasiDistribution
and expectation values. -
Added the
CorrelatedReadoutMitigator
class for performing measurement readout error mitigation of correlated measurement errors. This class can be initialized with a single measurement error assignment matrix that descirbes the error probabilities. Mitigation is implemented via inversion of assigment matrix which has mitigation complexity of ofQuasiDistribution
and expectation values. -
Added a
QuasiDistribution.stddev_upper_bound
attribute and a kwarg to the constructor of theQuasiDistribution
class, which is used for storing standard errors in quasi-probability estimates. This is used byBaseReadoutMitigator
classes to store the standard error in mitigated quasi probabilities. -
Added a
shots()
method toqiskit.result.Counts
to return the sum of all outcomes in the counts. -
When running the
Grover
algorithm class if the optimal power is known and only a single circuit is run, theAmplificationProblem.is_good_state
callback function is no longer required to be set and the Grover search will return the most likely bitstring. Generally, if the optimal power of the Grover operator is not known, theGrover
algorithm checks different powers (i.e. iterations) and applies theis_good_state
function to check whether a good bitstring has been measured. For example, you are now able to run something like:from qiskit.algorithms import Grover, AmplificationProblem from qiskit.providers.aer import AerSimulator from qiskit.quantum_info import Statevector # Fixed Grover power: 2. grover = Grover(iterations=2, quantum_instance=AerSimulator()) # The ``is_good_state`` argument not required here since Grover search # will be run only once, with a power of 2. problem = AmplificationProblem(Statevector.from_label("111")) # Run Grover search and print the best measurement result = grover.amplify(problem) print(result.top_measurement) # should print 111
-
Added method
remove_cregs()
to classDAGCircuit
to support classical register removal. -
Added method
remove_clbits()
to classDAGCircuit
to support the removal of idle classical bits. Any classical registers referencing a removed bit are also removed. -
Added a new method,
replace_block_with_op()
, to theDAGCircuit
class. This method is used to replace a block of nodes in the DAG with a single operation. The canonical example is for theConsolidateBlocks
pass which replaces blocks of nodes with equivalentUnitaryGate
nodes. -
Added a new analysis transpiler pass,
Collect1qRuns
, to theqiskit.transpiler.passes
module. This pass is used to find sequences of uninterrupted gates acting on a single qubit. It is similar to theCollect2qBlocks
andCollectMultiQBlocks
but optimized for single qubit runs instead of multiple qubit blocks. -
Various transpilation internals now use new features in retworkx 0.10 when operating on the internal circuit representation. This can often result in speedups in calls to
transpile
of around 10-40%, with greater effects at higher optimization levels. See #6302 for more details. -
The
UnitarySynthesis
transpiler pass inqiskit.transpiler.passes
has a new kwarg in the constructor,min_qubits
. When specified this can be set to anint
value which is the minimum sizeUnitaryGate
object to run the unitary synthesis on. If aUnitaryGate
in aQuantumCircuit
uses fewer qubits it will be skipped by that instance of the pass. -
The
Eigensolver
andMinimumEigensolver
interfaces now support the typeDict[str, Optional[OperatorBase]]
for theaux_operators
parameter in their respectivecompute_eigenvalues()
andcompute_minimum_eigenvalue()
methods. In this case, the auxiliary eigenvalues are also stored in a dictionary under the same keys provided by theaux_operators
dictionary. Keys that correspond to an operator that does not commute with the main operator are dropped. -
The
BasisTranslator
,GateDirection
, andCheckGateDirection
transpiler passes have a newtarget
kwarg in their constructors, which can be used to set aTarget
object as the target for the pass. If it is set it will be used instead of thetarget_basis
(in the case of theBasisTranslator
pass) orcoupling_map
(in the case of theGateDirection
andCheckGateDirection
passes) arguments. -
Allow two transpiler stages in the
QuantumInstance
, one for parameterized circuits and a second one for bound circuits (i.e. no free parameters) only. If a quantum instance with passes for unbound and bound circuits is passed into aCircuitSampler
, the sampler will attempt to apply the unbound pass once on the parameterized circuit, cache it, and only apply the bound pass for all future evaluations.This enables variational algorithms like the
VQE
to run a custom pass manager for parameterized circuits once and, additionally, another the transpiler again with a different custom pass manager on the bound circuits in each iteration. Being able to run different pass managers is important because not all passes support parameterized circuits (for exampleOptimize1qGatesDecomposition
only works with bound circuit parameters).For example, this feature allows using the pulse-efficient CX decomposition in the VQE, as
from qiskit.algorithms import VQE from qiskit.opflow import Z from qiskit.circuit.library.standard_gates.equivalence_library import StandardEquivalenceLibrary as std_eqlib from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap from qiskit.transpiler.preset_passmanagers import level_1_pass_manager from qiskit.transpiler.passes import ( Collect2qBlocks, ConsolidateBlocks, Optimize1qGatesDecomposition, RZXCalibrationBuilderNoEcho, UnrollCustomDefinitions, BasisTranslator ) from qiskit.transpiler.passes.optimization.echo_rzx_weyl_decomposition import EchoRZXWeylDecomposition from qiskit.test.mock import FakeBelem from qiskit.utils import QuantumInstance # Replace by a real backend! If not ensure qiskit-aer is installed to simulate the backend backend = FakeBelem() # Build the pass manager for the parameterized circuit rzx_basis = ['rzx', 'rz', 'x', 'sx'] coupling_map = CouplingMap(backend.configuration().coupling_map) config = PassManagerConfig(basis_gates=rzx_basis, coupling_map=coupling_map) pre = level_1_pass_manager(config) # Build a pass manager for the CX decomposition (works only on bound circuits) post = PassManager([ # Consolidate consecutive two-qubit operations. Collect2qBlocks(), ConsolidateBlocks(basis_gates=['rz', 'sx', 'x', 'rxx']), # Rewrite circuit in terms of Weyl-decomposed echoed RZX gates. EchoRZXWeylDecomposition(backend), # Attach scaled CR pulse schedules to the RZX gates. RZXCalibrationBuilderNoEcho(backend), # Simplify single-qubit gates. UnrollCustomDefinitions(std_eqlib, rzx_basis), BasisTranslator(std_eqlib, rzx_basis), Optimize1qGatesDecomposition(rzx_basis), ]) quantum_instance = QuantumInstance(backend, pass_manager=pre, bound_pass_manager=post) vqe = VQE(quantum_instance=quantum_instance) result = vqe.compute_minimum_eigenvalue(Z ^ Z)
-
Introduced a new unitary synthesis plugin interface which is used to enable using alternative synthesis techniques included in external packages seamlessly with the
UnitarySynthesis
transpiler pass. Users can select a plugin to use when callingtranspile()
by setting theunitary_synthesis_method
kwarg to the plugin’s name. A full list of installed plugins can be found using theqiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names()
function. For example, if you installed a package that includes a synthesis plugin namedspecial_synth
you could use it with:from qiskit import transpile transpile(qc, unitary_synthesis_method='special_synth', optimization_level=3)
This will replace all uses of the
UnitarySynthesis
with the method included in the external package that exports thespecial_synth
plugin.The plugin interface is built around setuptools entry points which enable packages external to Qiskit to advertise they include a synthesis plugin. For details on writing a new plugin refer to the
qiskit.transpiler.passes.synthesis.plugin
module documentation. -
Added a new transpiler pass,
VF2Layout
. This pass models the layout allocation problem as a subgraph isomorphism problem and uses the VF2 algorithm implementation in rustworkx to find a perfect layout (a layout which would not require additional routing) if one exists. The functionality exposed by this new pass is very similar to exisitingCSPLayout
butVF2Layout
is significantly faster.
Known Issues
-
The
"ket"
convention in the"latex"
drawer ofStatevector.draw()
is only valid for states comprising purely of qubits. If you are using states with some spaces of dimension greater than two, you should either passconvention="vector"
, or use a different drawer. -
The OpenQASM 3 export capabilities are in a beta state, and some features of Qiskit Terra’s
QuantumCircuit
are not yet supported. In particular, you may see errors if you try to export custom subroutines with classical parameters, and there is no provision yet for exporting pulse-calibrated operations into OpenPulse. -
When running the
BasisTranslator
in isolation with thetarget
argument set to aTarget
object, where some single-qubit gates can only apply to non-overlapping sets of qubits, the output circuit might incorrectly include operations on a qubit that are not allowed by theTarget
. For example, if you ran:from qiskit.circuit import QuantumCircuit, Parameter from qiskit.circuit.library import UGate, RZGate, XGate, SXGate, CXGate from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel from qiskit.transpiler import PassManager, Target, InstructionProperties from qiskit.transpiler.passes import BasisTranslator gmap = Target() # U gate in qubit 0. theta = Parameter('theta') phi = Parameter('phi') lam = Parameter('lambda') u_props = { (0,): InstructionProperties(duration=5.23e-8, error=0.00038115), } gmap.add_instruction(UGate(theta, phi, lam), u_props) # Rz gate in qubit 1. phi = Parameter("phi") rz_props = { (1,): InstructionProperties(duration=0.0, error=0), } gmap.add_instruction(RZGate(phi), rz_props) # X gate in qubit 1. x_props = { (1,): InstructionProperties( duration=3.5555555555555554e-08, error=0.00020056469709026198 ), } gmap.add_instruction(XGate(), x_props) # SX gate in qubit 1. sx_props = { (1,): InstructionProperties( duration=3.5555555555555554e-08, error=0.00020056469709026198 ), } gmap.add_instruction(SXGate(), sx_props) cx_props = { (0, 1): InstructionProperties(duration=5.23e-7, error=0.00098115), (1, 0): InstructionProperties(duration=4.52e-7, error=0.00132115), } gmap.add_instruction(CXGate(), cx_props) bt_pass = BasisTranslator(sel, target_basis=None, target=gmap) qc = QuantumCircuit(2) qc.iswap(0, 1) output = bt_pass(qc)
output
will haveRZGate
andSXGate
on qubit 0, even though this is forbidden. To correct this you can normally run the basis translator a second time (i.e.output = bt_pass(output)
in the above example) to correct this. This should not affect the output of running thetranspile()
function and is only an issue if you run the pass by itself.
Upgrade Notes
-
Starting with this version,
from qiskit import *
will not import submodules, but only a selected list of objects. This might break existing code usingfrom qiskit import *
and referring to objects that are not part of the current namespace. As a reminder,import *
is considered bad practice and it should not be used in production code. Qiskit sets__all__
inqiskit/__init__.py
as a way to mitigate the effects of said bad practice. If your code raisesname '<something>' is not defined
, addfrom qiskit import <something>
and try again. -
The preset pass managers for optimization levels 0, 1, 2, and 3 which are generated by
level_0_pass_manager()
,level_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
respectively will no longer unconditionally run theTimeUnitConversion
. Previously, the preset pass managers would always run this pass regardless of the inputs to the transpiler and the circuit. Now this pass will only be run if ascheduling_method
parameter is set or the circuit contains aDelay
instruction and theinstruction_durations
parameter is set. This change was made in the interest of runtime performance as in some cases runningtranspile()
on circuits with a large number of gates and no delays, timing, or scheduling being used theTimeUnitConversion
could be the largest bottleneck in the transpilation. -
The default method for
BIPMapping
is nowbalanced
rather thandepth
. This new objective generally achieves a better result, as it factors in both the circuit depth and the gate error. -
The
sort_parameters_by_name
of theVQE
class has been removed, following its deprecation in Qiskit Terra 0.18. There is no alternative provided, as the new ordering of parameters is the more natural sort order. -
The circuit drawers
QuantumCircuit.draw()
andcircuit_drawer()
with thelatex
option will now save their images in a format determined the file extension (if a file name is provided). Previously, they would always save in PNG format. They now raiseValueError
if the image format is not known. This was done to make it easier to save the image in different formats. -
The core dependency
retworkx
had its version requirement bumped to 0.10.1, up from 0.9. This enables several performance improvements across different transpilation passes. -
The previously deprecated
condition
kwarg, which was deprecated as part of the 0.15.0 release, has been removed fromDAGCircuit.apply_operation_back()
andDAGCircuit.apply_operation_front()
. Instead set thecondition
attribute on theInstruction
instances being added to theDAGCircuit
usingInstruction.c_if()
. -
The
DAGCircuit.extend_back()
method has been removed. It was originally deprecated in the 0.13.0 release. Instead you can use theDAGCircuit.compose()
method which is more general and provides the same functionality. -
The
DAGCircuit.compose_back()
method has been removed. It was originally deprecated in the 0.13.0 release. Instead you can use theDAGCircuit.compose()
method which is more general and provides the same functionality. -
The
edge_map
kwarg of theDAGCircuit
methodcompose()
has been removed. It was originally deprecated in the 0.14.0 release. The method takes aqubits
andclbits
kwargs to specify the positional order of bits to compose onto instead of using a dictionary mapping thatedge_map
previously provided. -
The
DAGCircuit.twoQ_gates()
method has been removed. It was originally deprecated in the 0.13.0 release. Instead,DAGCircuit.two_qubit_ops()
should be used. -
The
DAGCircuit.threeQ_or_more_gates()
method has been removed. It was originally deprecated in the 0.13.0 release. Instead,DAGCircuit.multi_qubit_ops()
method should be used. -
Named access for the first positional argument for the constructor of the
SingleQubitUnitary
class withu
has been removed. It was originally deprecated in the 0.14.0 release. Instead, the first positional argument can be set using the nameunitary_matrix
(or just set it positionally instead of by name). -
Named access for the first positional argument for the
QuantumCircuit
methodsqu
withu
has been removed. It was originally deprecated in the 0.14.0 release. Instead the first positional argument can be set using the nameunitary_matrix
(or just set it positionally instead of by name). -
The unused
proc
andnested_scope
kwargs for theqasm()
method of the QASM node classes in theqiskit.qasm.node
module have been removed. They were originally deprecated in the 0.15.0 release. -
The unused
proc
andnested_scope
kwargs for thelatex()
method of the QASM node classes in theqiskit.qasm.node
module have been removed. They were originally deprecated in the 0.15.0 release. -
The unused
proc
andnested_scope
kwargs for thereal()
method of the QASM node classes in theqiskit.qasm.node
module have been removed. They were originally deprecated in the 0.15.0 release. -
The output of
Statevector.draw()
when using"latex"
output is now the new"ket"
convention if plotting a state comprised purely of qubits. This was changed to make reading the output clearer, especially in educational contexts, because it shows the ket labels, and only displays the nonzero elements. -
When running
execute()
with aBackendV1
backend the default values for the kwargsshots
,max_credits
,meas_level
,meas_return
andmemory_slot_size
will now be whatever the set default is on the target backend’soptions
attribute. Previously these defaults were set to match the default values when callingexecute()
with a legacyBaseBackend
backend. For example:from qiskit.test.mock import FakeMumbai from qiskit import QuantumCircuit, execute circuit = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) qc.measure_all() backend = FakeMumbai() backend.set_options(shots=4096) execute(qc, backend)
will now run with
4096
shots. While in previous releases it would run with1024
. -
The minimum supported version of Matplotlib has been raised from 2.1.0 to 3.3.0. You will now need to have Matplotlib 3.3.0 installed if you’re using Matplotlib-based visualization functions such as the
'mpl'
backend for thecircuit_drawer()
function or theplot_bloch_vector()
function. This was done for two reasons, the first is because recent versions of Matplotlib have deprecated the use of APIs around 3D visualizations that were compatible with older releases and second installing older versions of Matplotlib was becoming increasingly difficult as matplotlib’s upstream dependencies have caused incompatiblities that made testing moving forward more difficult. -
The internal use of the random number generator in
random_circuit()
was adjusted, which will change the output from previous versions, even with a fixed seed. This was done to greatly improve the runtime scaling with the number of qubits being used. If you were depending on an identical output from a previous version it is recommended that you useqpy_serialization.dump()
to save the random circuit generated with a previous version and instead of re-generating it with the new release, and instead just useqpy_serialization.load()
to load that saved circuit. -
The use of
*
(__mul__
) for thedot()
method and@
(__matmul__
) for thecompose()
method ofBaseOperator
(which is the parent of all the operator classes inqiskit.quantum_info
including classes likeOperator
andPauli
) is no longer supported. The use of these operators were previously deprecated in 0.17.0 release. Instead you should use thedot()
andcompose()
methods directly, or the&
operator (__and__
) can be used forcompose()
. For example, if you were previously using the operator like:from qiskit.quantum_info import random_hermitian op_a = random_hermitian(4) op_b = random_hermitian(4) new_op = op_a @ op_b
this should be changed to be:
from qiskit.quantum_info import random_hermitian op_a = random_hermitian(4) op_b = random_hermitian(4) new_op = op_a.compose(op_b)
or:
new_op = op_a & op_b
-
Various methods of assigning parameters to operands of pulse program instructions have been removed, having been deprecated in Qiskit Terra 0.17. These include:
- the
assign()
method ofpulse.Instruction
. - the
assign()
method ofChannel
, which is the base ofAcquireChannel
,SnapshotChannel
,MemorySlot
andRegisterSlot
. - the
assign()
andassign_parameters()
methods ofParametricPulse
, which is the base ofpulse.Gaussian
,pulse.GaussianSquare
,pulse.Drag
andpulse.Constant
.
These parameters should be assigned from the pulse program (
pulse.Schedule
andpulse.ScheduleBlock
) rather than operands of the pulse program instruction. - the
-
The
flatten()
method ofpulse.Instruction
andqiskit.pulse.Schedule
has been removed and no longer exists as per the deprecation notice from Qiskit Terra 0.17. This transformation is defined as a standalone function inqiskit.pulse.transforms.canonicalization.flatten()
. -
qiskit.pulse.interfaces.ScheduleComponent
has been removed and no longer exists as per the deprecation notice from Qiskit Terra 0.15. No alternative class will be provided. -
Legacy pulse drawer arguments have been removed from
pulse.Waveform.draw()
,Schedule.draw()
andScheduleBlock.draw()
and no longer exist as per the deprecation notice from Qiskit Terra 0.16. Now these draw methods support only V2 pulse drawer arguments. See method documentations for details. -
The
qiskit.pulse.reschedule
module has been removed and this import path no longer exist as per the deprecation notice from Qiskit Terra 0.14. Useqiskit.pulse.transforms
instead. -
A protected method
Schedule._children()
has been removed and replaced by a protected instance variable as per the deprecation notice from Qiskit Terra 0.17. This is now provided as a public attributeSchedule.children
. -
Timeslot relevant methods and properties have been removed and no longer exist in
ScheduleBlock
as per the deprecation notice from Qiskit Terra 0.17. Since this representation doesn’t have notion of instruction timet0
, the timeslot information will be available after it is transformed to aSchedule
. Corresponding attributes have been provided after this conversion, but they are no longer supported. The following attributes are removed:timeslots
start_time
stop_time
ch_start_time
ch_stop_time
shift
insert
-
Alignment pulse schedule transforms have been removed and no longer exist as per the deprecation notice from Qiskit Terra 0.17. These transforms are integrated and implemented in the
AlignmentKind
context of the schedule block. The following explicit transform functions are removed:qiskit.pulse.transforms.align_equispaced
qiskit.pulse.transforms.align_func
qiskit.pulse.transforms.align_left
qiskit.pulse.transforms.align_right
qiskit.pulse.transforms.align_sequential
-
Redundant pulse builder commands have been removed and no longer exist as per the deprecation notice from Qiskit Terra 0.17.
pulse.builder.call_schedule
andpulse.builder.call_circuit
have been integrated intopulse.builder.call()
. -
An internal filter override that caused all Qiskit deprecation warnings to be displayed has been removed. This means that the behaviour will now revert to the standard Python behaviour for deprecations; you should only see a
DeprecationWarning
if it was triggered by code in the main script file, interpreter session or Jupyter notebook. The user will no longer be blamed with a warning if internal Qiskit functions call deprecated behaviour. If you write libraries, you should occasionally run with the default warning filters disabled, or have tests which always run with them disabled. See the Python documentation on warnings, and in particular the section on testing for deprecations for more information on how to do this. -
Certain warnings used to be only issued once, even if triggered from multiple places. This behaviour has been removed, so it is possible that if you call deprecated functions, you may see more warnings than you did before. You should change any deprecated function calls to the suggested versions, because the deprecated forms will be removed in future Qiskit releases.
-
The deprecated
qiskit.schemas
module and theqiskit.validation
module which build jsonschema validator from the schemas have been removed. This was deprecated in the 0.17.0 release and has been replaced with a dedicated repository for the IBM Quantum API payload schemas.If you were relying on the schema files previously packaged in
qiskit.schemas
or the validators built on them you should use that repository and create validators from the schema files it contains. -
The functions
qiskit.qobj.validate_qobj_against_schema
andqiskit.qobj.common.validator
along with thevalidate
kwarg of the methodsQasmQobj.to_dict()
,PulseQobj.to_dict()
, andQobj.to_dict()
have been removed. These were deprecated in the 0.17.0 release. If you were using these function you will have to manually build jsonschema validation functions forQobj
objects using the jsonschema files from the dedicated repository for the IBM Quantum API payload schemas. -
The
fastjsonschema
andjsonschema
packages are no longer in the requirements list for qiskit-terra. The internal use of jsonschema has been removed and they are no longer required to use qiskit-terra. -
The exception raised by the
assemble()
function when invalid parameters are passed in for constructing aPulseQobj
have changed from aSchemaValidationError
to aQiskitError
. This was necessary because theSchemaValidationError
class was removed along with the rest of the deprecatedqiskit.schemas
andqiskit.validation
. This also makes it more consistent with other error conditions fromassemble()
which were already raising aQiskitError
. -
The default routing pass and layout pass for transpiler optimization level 3 has changed to use
SabreSwap
andSabreLayout
respectively. This was done to improve the quality of the output result, as using the sabre passes produces better results than usingStochasticSwap
andDenseLayout
, which were used as the defaults in prior releases. This change will improve the quality of the results when runningtranspile()
orexecute()
functions with theoptimization_level
kwarg set to3
. While this is generally an improvement, if you need to retain the previous behavior for any reason you can do this by explicitly setting therouting_method="stochastic"
andlayout_method="dense"
when callingtranspile()
withoptimization_level=3
. -
The return type of
pauli_basis()
will change fromPauliTable
toPauliList
in a future release of Qiskit Terra. To immediately swap to the new behaviour, pass the keyword argumentpauli_list=True
. -
The
name
attribute of theSingleQubitUnitary
gate class has been changed fromunitary
tosqu
. This was necessary to avoid a conflict with theUnitaryGate
class’s name which was alsounitary
since the 2 gates are not the same and don’t have the same implementation (and can’t be used interchangeably). -
The minimum version of Symengine required for installing has been increased to 0.8.0. This was necessary to fix some issues with the handling of
numpy.float16
andnumpy.float32
values when runningbind()
to bind parameters in aParameterExpression
. -
A new dependency stevedore has been added to the requirements list. This is required by qiskit-terra as it is used to build the unitary synthesis plugin interface.
Deprecation Notes
-
The
gate
attribute and initialization parameter ofqiskit.transpiler.passes.Decompose
is deprecated, and will be removed in a future release. Instead of this single gate, you should pass a list of gate names to the new parametergates_to_decompose
. This was done as the new form allows you to select more than one gate as a decomposition target, which is more flexible, and does not need to re-run the pass several times to decompose a set of gates. -
There has been a significant transpiler pass reorganization regarding calibrations. The import paths:
from qiskit.transpiler.passes.scheduling.calibration_creators import RZXCalibrationBuilder from qiskit.transpiler.passes.scheduling.calibration_creators import RZXCalibrationBuilderNoEcho
are deprecated, and will be removed in a future release. The import path:
from qiskit.transpiler.passes.scheduling.rzx_templates import rzx_templates
is also deprecated, and will be removed in a future release. You should use the new import paths:
from qiskit.transpiler.passes import RZXCalibrationBuilder from qiskit.transpiler.passes import RZXCalibrationBuilderNoEcho from qiskit.transpiler.passes.calibration.rzx_templates import rzx_templates
-
The
DAGNode
class is being deprecated as a standalone class and will be used in the future only as the parent class forDAGOpNode
,DAGInNode
, andDAGOutNode
. As part of this deprecation, the following kwargs and associated attributes inDAGNode
are also being deprecated:type
,op
, andwire
. -
For the constructor of the
RZXCalibrationBuilder
passing a backend either as the first positional argument or with the namedbackend
kwarg is deprecated and will no longer work in a future release. Instead aInstructionScheduleMap
should be passed directly to theinstruction_schedule_map
kwarg and a list of channel name lists for each qubit should be passed directly toqubit_channel_mapping
. For example, if you were calling the pass like:from qiskit.transpiler.passes import RZXCalibrationBuilder from qiskit.test.mock import FakeMumbai backend = FakeMumbai() cal_pass = RZXCalibrationBuilder(backend)
instead you should call it like:
from qiskit.transpiler.passes import RZXCalibrationBuilder from qiskit.test.mock import FakeMumbai backend = FakeMumbai() inst_map = backend.defaults().instruction_schedule_map channel_map = self.backend.configuration().qubit_channel_mapping cal_pass = RZXCalibrationBuilder( instruction_schedule_map=inst_map, qubit_channel_mapping=channel_map, )
This change is necessary because as a general rule backend objects are not pickle serializable and it would break when it was used with multiple processes inside of
transpile()
when compiling multiple circuits at once. -
The
label
property of classMCMT
and subclassMCMTVChain
has been deprecated and will be removed in a future release. Consequently, thelabel
kwarg on the constructor for both classes is also deprecated, along with thelabel
kwarg of methodMCMT.control()
. Currently, thelabel
property is used to name the controlled target when it is comprised of more than one target qubit, however, this was never intended to be user-specifiable, and can result in an incorrect MCMT gate if the name of a well-known operation is used. After deprecation, thelabel
property will no longer be user-specifiable. However, you can get the generated name of the controlled target viaMCMT.data[0][0].base_gate.name
-
The
subgraph()
method of theCouplingMap
class is deprecated and will be removed in a future release. Instead thereduce()
method should be used, which does the same thing except it preserves the node list order for the outputCouplingMap
(whilesubgraph()
did not preserve list order). -
Creating an instance of
InstructionSet
with thecircuit_cregs
keyword argument is deprecated. In general, these classes never need to be constructed by users (but are used internally), but should you need to, you should pass a callable as theresource_requester
keyword argument. For example:from qiskit.circuit import Clbit, ClassicalRegister, InstructionSet from qiskit.circuit.exceptions import CircuitError def my_requester(bits, registers): bits_set = set(bits) bits_flat = tuple(bits) registers_set = set(registers) def requester(specifier): if isinstance(specifer, Clbit) and specifier in bits_set: return specifier if isinstance(specifer, ClassicalRegster) and specifier in register_set: return specifier if isinstance(specifier, int) and 0 <= specifier < len(bits_flat): return bits_flat[specifier] raise CircuitError(f"Unknown resource: {specifier}") return requester my_bits = [Clbit() for _ in [None]*5] my_registers = [ClassicalRegister(n) for n in range(3)] InstructionSet(resource_requester=my_requester(my_bits, my_registers))
-
The use of the measurement mitigation classes
qiskit.ignis.mitigation.CompleteMeasFitter
andqiskit.ignis.mitigation.TensoredMeasFitter
fromqiskit-ignis
as values for themeasurement_error_mitigation_cls
kwarg of the constructor for theQuantumInstance
class is deprecated and will be removed in a future release. Instead the equivalent classes fromqiskit.utils.mitigation
,CompleteMeasFitter
andTensoredMeasFitter
should be used. This was necessary as theqiskit-ignis
project is now deprecated and will no longer be supported in the near future. It’s worth noting that unlike the equivalent classes fromqiskit-ignis
the versions fromqiskit.utils.mitigation
are supported only in their use withQuantumInstance
(i.e. as a class not an instance with themeasurement_error_mitigation_cls
kwarg) and not intended for standalone use. -
The
Optimizer.optimize()
method for all the optimizers (Optimizer
and derived classes) is now deprecated and will be removed in a future release. Instead, theOptimizer.minimize()
method should be used which mimics the signature of SciPy’sminimize()
function.To replace the current optimize call with minimize you can replace
xopt, fopt, nfev = optimizer.optimize( num_vars, objective_function, gradient_function, variable_bounds, initial_point, )
with
result = optimizer.minimize( fun=objective_function, x0=initial_point, jac=gradient_function, bounds=variable_bounds, ) xopt, fopt, nfev = result.x, result.fun, result.nfev
-
Importing the
qiskit.util
module will now issue aDeprecationWarning
. Users should instead import all the same functionality fromqiskit.utils
. Theutil
module has been deprecated since Terra 0.17, but previously did not issue a warning. It will be removed in Terra 0.20. -
The property
table
is deprecated, and will be removed in a future release. This is becauseSparsePauliOp
has been updated to internally usePauliList
instead ofPauliTable
. This is in order to significantly improve performance. You should now access thePauliList
data by using theSparsePauliOp.paulis
attribute.
Bug Fixes
-
Fixed a bug where many layout methods would ignore 3-or-more qubit gates, resulting in unexpected layout-allocation decisions. The transpiler pass
Unroll3qOrMore
is now being executed before the layout pass in all the preset pass managers whentranspile()
is called. Fixed #7156. -
Disassembled circuits now inherit calibrations from assembled
QasmQobj
and experiments. Fixes #5348. -
Fixed setting the
ansatz
oroptimizer
attributes of aVQE
instance toNone
resulting in a buggy behavior. See #7093 for details. -
Fixed addition of
PauliList
s withqargs
. The method used to raise a runtime error if the operands had different numbers of qubits. -
Fixed an issue causing an error when trying to compute a gradient with the
CircuitGradient
class for a gate that was not a supported gate. This bugfix transpiles a given gate to the set of supported gates for a requested gradient method. Fixes #6918. -
Removed calibration results when using error mitigation with the
execute()
method ofQuantumInstance
. Fixes #7129. -
Fixed a deprecation warning emitted when running
QuantumCircuit.draw()
orcircuit_drawer()
with Sympy 1.9 installed, mentioning the Sympy functionexpr_free_symbols()
. The circuit drawers previously made use of this method when finding instances of symbolic constants. -
Fixed an issue where the
ax
kwarg and thefigwidth
option in thestyle
kwarg for thempl
circuit drawer did not scale properly. Users can now pass anax
from a Matplotlib subplot to thempl
circuit drawer and the circuit will be drawn within the boundaries of that subplot. Alternatively, users can set thefigwidth
in inches in thestyle
dict kwarg and the drawing will scale to the width in inches that was set. Fixed #6367. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. When displaying ameasure
instruction targeted on a classical bit instead of a register, using thelatex
drawer option, the drawer would fail. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. With any of the 3 drawer options,mpl
,latex
, ortext
, if a gate with a classical condition was encountered that was conditioned on a classical bit without a register, the drawer would fail. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. With any of the 3 drawer options,mpl
,latex
, ortext
, if a gate with a classical condition was conditioned on the same classical bit as ameasure
and the bit that the measure targeted did not have a register, the drawer would fail. -
C3SXGate
now has a correct decomposition and matrix representation. Previously it was equivalent toSdgXGate().control(3)
, rather than the intendedSXGate().control(3)
. -
The member
name
ofqiskit.test.mock.utils.ConfigurableFakeBackend
has been changed tobackend_name
. This was done to avoid a conflict with thename()
method inherited from the parent abstractBackendV1
class. This makesConfigurableFakeBackend
compatible with anything expecting aBackendV1
object. However, if you were using thename
attribute directly before you will now need to either call it as a method or access thebackend_name
attribute instead. -
Fixed an issue where calling
QuantumCircuit.decompose()
on a circuit containing anInstruction
whosedefinition
attribute was empty would leave the instruction in place, instead of decomposing it into zero operations. For example, with a circuit:from qiskit.circuit import QuantumCircuit empty = QuantumCircuit(1, name="decompose me!") circuit = QuantumCircuit(1) circuit.append(empty.to_gate(), [0])
Previously, calling
circuit.decompose()
would not change the circuit. Now, the decomposition will correct decomposeempty
into zero instructions. See #6997 for more. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. When displaying ameasure
instruction containing a classicalcondition
using thempl
orlatex
options, thecondition
information would sometimes overwrite themeasure
display. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. Thempl
drawer used hex notation to display thecondition
value, whereas thetext
andlatex
drawers used decimal notation. Now all three drawers use hex notation. -
Fixed a bug in the Hoare optimizer transpilation pass where it could attempt to remove a gate twice if it could be separately combined with both its predecessor and its successor to form the identity. Refer to #7271 for more details.
-
Making an instruction conditional with the standard
InstructionSet.c_if()
method with integer indices is now consistent with the numbering scheme used by theQuantumCircuit
the instructions are part of. Previously, if there were twoClassicalRegister
s with overlappingClbit
s, the numbering would be incorrect. See #7246 for more detail. -
Making an instruction conditional with the standard
InstructionSet.c_if()
method will now succeed, even if there are noClassicalRegister
s in the circuit. See #7250 for more detail. -
Making an instruction conditional with the standard
InstructionSet.c_if()
method when using aClbit
that is contained in aClassicalRegister
of size one will now correctly create a condition on the bit, not the register. See #7255 for more detail. -
Trying to make an instruction conditional with the standard
InstructionSet.c_if()
method will now correctly raise an error if the classical resource is not present in the circuit. See #7255 for more detail. -
Fixed a compatibility issue with Matplotlib 3.5, where the Bloch sphere would fail to render if it had any vectors attached, such as by using
plot_bloch_vector
. See #7272 for more detail. -
Fixed an issue with the
NLocal.add_layer()
method incorrectly appending layers if theNLocal
object had already been built. -
Fixed an issue with pickling
InstructionScheduleMap
object when using Python 3.6. See #6944 for details. -
Complex valued pulse parameter assignment with symengine has been fixed. For example,
from qiskit import circuit, pulse import numpy as np amp = circuit.Parameter("amp") phase = circuit.Parameter("phase") with pulse.build() as sched: pulse.play(pulse.Gaussian(160, amp * np.exp(1j * phase), 40), pulse.DriveChannel(0)) sched.assign_parameters({amp: 0.1, phase: 1.57}, inplace=True)
The assigned amplitude has been shown as
ParameterExpression(0.1*exp(1.57*I))
after the use ofsymengine
was introduced in the 0.18.0 release. This is now correctly evaluated and shown as7.96327e-05 + 0.0999999683j
. -
Fixed an issue where
QAOA.construct_circuit()
with different operators with same number of qubits would generate the same circuit each time. See #7223 for more detail. -
Fixed an issue where
QAOAAnsatz
had an incorrect number of parameters if identities ofPauliSumOp
were given, e.g.,PauliSumOp.from_list([("III", 1)])
. See #7225 for more detail. -
Fixed a bug where the
QuantumCircuit.qasm()
method could return OpenQASM 2 instructions with invalid identifiers. The same bug was fixed forUnitaryGate
. -
Fixed an issue where trying to display registerless bits would cause a failure of the
mpl
and thelatex
circuit drawers. A leading_
has been removed from the display of registerless bits’ numbers in thetext
drawer. Fixed #6732. -
For one-bit registers, all of the circuit drawers now display only the register name and no longer show the
0
subscript. Fixed #5784. -
Fixed naming collisions of implicit registers in
QuantumCircuit.qasm
when dealing with registerless qubits and clbits. Previously, registerless qubits and clbits were put into correspondingqreg
andcreg
both calledregless
, despite the collision. They will now have separate, deterministically generated names, which will not clash with any user-defined register names in the circuit. -
Fixed an issue in scheduling of circuits with clbits operations, e.g. measurements, conditional gates, updating
ASAPSchedule
,ALAPSchedule
, andAlignMeasures
. The updated schedulers assume all clbits I/O operations take no time,measure
writes the measured value to a clbit at the end, andc_if
reads the conditional value in clbit(s) at the beginning. Fixed #7006. -
Calling
transpile
on an empty list will now correctly return an empty list without issuing a warning. Fixed #7287. -
Fixed an issue in
PiecewiseChebyshev
when the function to be approximated was constant. In these cases, you should now pass the constant directly as thef_x
argument, rather than using a function, such as:from qiskit.circuit.library.arithmetic import PiecewiseChebyshev PiecewiseChebyshev(1.0, degree=3)
See #6707 for more details.
-
If an
HHL
algorithm instance was constructed without aQuantumInstance
(the default), attempts to use the getter and setter properties to read or set an instance later would fail. The getters and setters now work as expected. -
The
QuantumCircuit.qasm()
method now edits the names of copies of the instructions present in the circuit, not the original instructions that live incircuit.data
. Refer to #6952 for more details. -
Fixed a bug in
PauliSumOp.permute()
causing the error:QiskitError: 'Pauli string label "" is not valid.'
if the permutation had the same number of Pauli terms. Calling
permute([2, 1, 0])
onX ^ Y ^ Z
no longer raises an error, and now returnsZ ^ Y ^ X
. -
Fixed a bug where the parameter bounds for the mixer parameters in the
QAOAAnsatz
were not been set. -
Fixed determination of final operations (barriers and measures) in pass
RemoveFinalMeasurements
and in methodremove_final_measurements()
of classQuantumCircuit
which previously considered only nodes immediately preceding an output node. -
Fixed determination of final operations in pass
RemoveFinalMeasurements
and in methodremove_final_measurements()
of classQuantumCircuit
which could wrongly consider a barrier to be final, even if other circuit operations followed it. -
Fixed multi-bit classical register removal in pass
RemoveFinalMeasurements
and in methodremove_final_measurements()
of classQuantumCircuit
where classical registers were not removed even if other bits were idle, unless a final measure was done into each and every bit. Now, classical registers that become idle as a result of removing final measurements and barriers are always removed. Classical bits are removed if they are referenced only by removed registers or are not referenced at all and became idle due to the removal. This fix also adds proper handling of registers with shared underlying bits. -
Fixed an issue with
RemoveFinalMeasurements
which could cause the resultingDAGCircuit
to become invalid. See #7196 for more details. -
Fixed an issue with method
remove_final_measurements()
of classQuantumCircuit
that causedQuantumCircuit.clbits
to be incorrect after invocation. Refer to #7089 for details. -
When tapering an empty zero operator in
qiskit.opflow
, the code, on detecting it was zero, logged a warning and returned the original operator. Such operators are commonly found in the auxiliary operators, when using Qiskit Nature, and the above behavior causedVQE
to throw an exception as tapered non-zero operators were a different number of qubits from the tapered zero operators (since taper has returned the input operator unchanged). The code will now correctly taper a zero operator such that the number of qubits is reduced as expected and matches to tapered non-zero operators e.g`0*"IIII"`
when we are tapering by 3 qubits will become0*"I"
. -
Fixed an issue with the
draw()
method andcircuit_drawer()
function, where a custom style set via the user config file (i.e.settings.conf
) would ignore the set value of thecircuit_mpl_style
field if thestyle
kwarg on the function/method was not set.
Other Notes
-
The string cast for
qiskit.circuit.ParameterExpression
does not have full precision anymore. This removes the trailing 0s when printing parameters that are bound to floats. This has consequences for QASM serialization and the circuit text drawer:>>> from qiskit.circuit import Parameter >>> x = Parameter('x') >>> str(x.bind({x:0.5})) '0.5' # instead of '0.500000000000000'
-
The
QAOAAnsatz
has been updated to use the parameter symbolγ
for the cost operator andβ
for the mixer operator, as is the standard notation in QAOA literature.
Aer 0.9.1
No change
Ignis 0.7.0
Prelude
This release deprecates the Qiskit Ignis project, it has been supersceded by the Qiskit Experiments project and active development has ceased. While deprecated, critical bug fixes and compatibility fixes will continue to be made to provide users a sufficient opportunity to migrate off of Ignis. After the deprecation period (which will be no shorter than 3 months from this release) the project will be retired and archived.
New Features
-
Updated the accreditation protocol to use fitting routine from https://arxiv.org/abs/2103.06603.
AccreditationFitter
now has methods FullAccreditation (previous protocol) and MeanAccreditation (new protocol). In addtition data entry has been changed to either use the result object AppendResult or a list of strings AppendStrings.qiskit.ignis.verification.QOTPCorrectString()
was also added. -
Added the option for the fast analytical generation of syndrome graphs. The
RepetitionCode
now has a new bool argumentbrute
, which allows to still use the brute force method. Helper classRepetitionCodeSyndromeGenerator
added to facilitate this. -
The
RepetitionCode
now has keyword argumentsresets
anddelay
. The former determines whether reset gates are inserted after measurement. The latter allows a time (in dt) to be specificed for a delay after each measurement (and reset, if applicable).The
syndrome_measurement()
method ofRepetitionCode
now has keyword argumentsfinal
anddelay
. The former determines whether to add reset gates according to the globalresets
, or to overwrite it with appropriate behavior for the final round of syndrome measurements. The latter allows a time (in dt) to be specificed for a delay after each measurement (and reset, if applicable). -
The
RepetitionCode
class now supports encoding with x basis states. This can be used by setting thexbasis
keyword argument when constructing aRepetitionCode
object.
Upgrade Notes
-
The keyword argument
reset
has been removed from the thesyndrome_measurement()
method ofRepetitionCode
. This is replaced by the globalresets
keyword argument for the class as well as the keyword argumentfinal
forsyndrome_measurement
. In cases where one would previously add the final measurement round usingreset=False
to avoid the final reset gates, one should now usefinal=True
. -
Remove
ParametrizedSchedule
fromupdate_u_gates()
.ParametrizedSchedule
was deprecated as a part of Qiskit-terra 0.17.0 and will be removed in next release. The function now updates u gates withSchedule
programs involving unassignedParameter
objects.
Deprecation Notes
-
Deprecating methods in
AccreditationFitter
namely bound_variation_distance and single_protocol_run -
The Qiskit Ignis project as a whole has been deprecated and the project will be retired and archived in the future. While deprecated only compatibility fixes and fixes for critical bugs will be made to the proejct. Instead of using Qiskit Ignis you should migrate to use Qiskit Experiments instead. You can refer to the migration guide:
https://github.com/qiskit-community/qiskit-ignis#migration-guide