Qiskit 0.28 release notes
0.28.0
Terra 0.18.0
Prelude
This release includes many new features and bug fixes. The highlights of this release are the introduction of two new transpiler passes, BIPMapping
and DynamicalDecoupling
, which when combined with the new pulse_optimize
kwarg on the UnitarySynthesis
pass enables recreating the Quantum Volume 64 results using the techniques described in: https://arxiv.org/abs/2008.08571. These new transpiler passes and options and are also generally applicable to optimizing any circuit.
New Features
-
The
measurement_error_mitgation
kwarg for theQuantumInstance
constructor can now be set to theTensoredMeasFitter
class from qiskit-ignis in addition toCompleteMeasFitter
that was already supported. If you useTensoredMeasFitter
you will also be able to set the newmit_pattern
kwarg to specify the qubits on which to useTensoredMeasFitter
You can refer to the documentation formit_pattern
in theTensoredMeasFitter
documentation for the expected format. -
The decomposition methods for single-qubit gates, specified via the
basis
kwarg, inOneQubitEulerDecomposer
has been expanded to now also include the'ZSXX'
basis, for making use of direct gate as well as gate. -
Added two new passes
AlignMeasures
andValidatePulseGates
to theqiskit.transpiler.passes
module. These passes are a hardware-aware optimization, and a validation routine that are used to manage alignment restrictions on time allocation of instructions for a backend.If a backend has a restriction on the alignment of
Measure
instructions (in terms of quantization in time), theAlignMeasures
pass is used to adjust delays in a scheduled circuit to ensure that anyMeasure
instructions in the circuit are aligned given the constraints of the backend. TheValidatePulseGates
pass is used to check if any custom pulse gates (gates that have a custom pulse definition in thecalibrations
attribute of aQuantumCircuit
object) are valid given an alignment constraint for the target backend.In the built-in
preset_passmangers
used by thetranspile()
function, these passes get automatically triggered if the alignment constraint, either via the dedicatedtiming_constraints
kwarg ontranspile()
or has antiming_constraints
attribute in theBackendConfiguration
object of the backend being targetted.The backends from IBM Quantum Services (accessible via the qiskit-ibmq-provider package) will provide the alignment information in the near future.
For example:
from qiskit import circuit, transpile from qiskit.test.mock import FakeArmonk backend = FakeArmonk() qc = circuit.QuantumCircuit(1, 1) qc.x(0) qc.delay(110, 0, unit="dt") qc.measure(0, 0) qc.draw('mpl')
qct = transpile(qc, backend, scheduling_method='alap', timing_constraints={'acquire_alignment': 16}) qct.draw('mpl')
-
A new transpiler pass class
qiskit.transpiler.passes.BIPMapping
that tries to find the best layout and routing at once by solving a BIP (binary integer programming) problem as described in arXiv:2106.06446 has been added.The
BIPMapping
pass (named “mapping” to refer to “layout and routing”) represents the mapping problem as a BIP (binary integer programming) problem and relies on CPLEX (cplex
) to solve the BIP problem. The dependent libraries including CPLEX can be installed along with qiskit-terra:pip install qiskit-terra[bip-mapper]
Since the free version of CPLEX can solve only small BIP problems, i.e. mapping of circuits with less than about 5 qubits, the paid version of CPLEX may be needed to map larger circuits.
The BIP mapper scales badly with respect to the number of qubits or gates. For example, it would not work with
coupling_map
beyond 10 qubits because the BIP solver (CPLEX) could not find any solution within the default time limit.Note that, if you want to fix physical qubits to be used in the mapping (e.g. running Quantum Volume (QV) circuits), you need to specify
coupling_map
which contains only the qubits to be used.Here is a minimal example code to build pass manager to transpile a QV circuit:
num_qubits = 4 # QV16 circ = QuantumVolume(num_qubits=num_qubits) backend = ... basis_gates = backend.configuration().basis_gates coupling_map = CouplingMap.from_line(num_qubits) # supply your own coupling map def _not_mapped(property_set): return not property_set["is_swap_mapped"] def _opt_control(property_set): return not property_set["depth_fixed_point"] from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel pm = PassManager() # preparation pm.append([ Unroll3qOrMore(), TrivialLayout(coupling_map), FullAncillaAllocation(coupling_map), EnlargeWithAncilla(), BarrierBeforeFinalMeasurements() ]) # mapping pm.append(BIPMapping(coupling_map)) pm.append(CheckMap(coupling_map)) pm.append(Error(msg="BIP mapper failed to map", action="raise"), condition=_not_mapped) # post optimization pm.append([ Depth(), FixedPoint("depth"), Collect2qBlocks(), ConsolidateBlocks(basis_gates=basis_gates), UnitarySynthesis(basis_gates), Optimize1qGatesDecomposition(basis_gates), CommutativeCancellation(), UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates) ], do_while=_opt_control) transpile_circ = pm.run(circ)
-
A new constructor method
initialize_from()
was added to theSchedule
andScheduleBlock
classes. This method initializes a new empty schedule which takes the attributes from other schedule. For example:sched = Schedule(name='my_sched') new_sched = Schedule.initialize_from(sched) assert sched.name == new_sched.name
-
A new kwarg,
line_discipline
, has been added to thejob_monitor()
function. This kwarg enables changing the carriage return characters used in thejob_monitor
output. Theline_discipline
kwarg defaults to'\r'
, which is what was in use before. -
The abstract
Pulse
class (which is the parent class for classes such asWaveform
,Constant
, andGaussian
now has a new kwarg on the constructor,limit_amplitude
, which can be set toFalse
to disable the previously hard coded amplitude limit of1
. This can also be set as a class attribute directly to change the global default for a Pulse class. For example:from qiskit.pulse.library import Waveform # Change the default value of limit_amplitude to False Waveform.limit_amplitude = False wave = Waveform(2.0 * np.exp(1j * 2 * np.pi * np.linspace(0, 1, 1000)))
-
A new class,
PauliList
, has been added to theqiskit.quantum_info
module. This class is used to efficiently represent a list ofPauli
operators. This new class inherets from the same parent class as the existingPauliTable
(and therefore can be mostly used interchangeably), however it differs from thePauliTable
because theqiskit.quantum_info.PauliList
class can handle Z4 phases. -
Added a new transpiler pass,
RemoveBarriers
, toqiskit.transpiler.passes
. This pass is used to remove all barriers in a circuit. -
Add a new optimizer class,
SciPyOptimizer
, to theqiskit.algorithms.optimizers
module. This class is a simple wrapper class of thescipy.optimize.minimize
function (documentation) which enables the use of all optimization solvers and all parameters (e.g. callback) which are supported byscipy.optimize.minimize
. For example:from qiskit.algorithms.optimizers import SciPyOptimizer values = [] def callback(x): values.append(x) optimizer = SciPyOptimizer("BFGS", options={"maxiter": 1000}, callback=callback)
-
The
HoareOptimizer
pass has been improved so that it can now replace aControlledGate
in a circuit with with the base gate if all the control qubits are in the state. -
Added two new methods,
is_successor()
andis_predecessor()
, to theDAGCircuit
class. These functions are used to check if a node is either a successor or predecessor of another node on theDAGCircuit
. -
A new transpiler pass,
RZXCalibrationBuilderNoEcho
, was added to theqiskit.transpiler.passes
module. This pass is similar to the existingRZXCalibrationBuilder
in that it creates calibrations for anRZXGate(theta)
, howeverRZXCalibrationBuilderNoEcho
does this without inserting the echo pulses in the pulse schedule. This enables exposing the echo in the cross-resonance sequence as gates so that the transpiler can simplify them. TheRZXCalibrationBuilderNoEcho
pass only supports the hardware-native direction of theCXGate
. -
A new kwarg,
wrap
, has been added to thecompose()
method ofQuantumCircuit
. This enables choosing whether composed circuits should be wrapped into an instruction or not. By default this isFalse
, i.e. no wrapping. For example:from qiskit import QuantumCircuit circuit = QuantumCircuit(2) circuit.h([0, 1]) other = QuantumCircuit(2) other.x([0, 1]) print(circuit.compose(other, wrap=True)) # wrapped print(circuit.compose(other, wrap=False)) # not wrapped
-
A new attribute,
control_channels
, has been added to thePulseBackendConfiguration
class. This attribute represents the control channels on a backend as a mapping of qubits to a list ofControlChannel
objects. -
A new kwarg,
epsilon
, has been added to the constructor for theIsometry
class and the correspondingQuantumCircuit
methodisometry()
. This kwarg enables optionally setting the epsilon tolerance used by anIsometry
gate. For example:import numpy as np from qiskit import QuantumRegister, QuantumCircuit tolerance = 1e-8 iso = np.eye(2,2) num_q_output = int(np.log2(iso.shape[0])) num_q_input = int(np.log2(iso.shape[1])) q = QuantumRegister(num_q_output) qc = QuantumCircuit(q) qc.isometry(iso, q[:num_q_input], q[num_q_input:], epsilon=tolerance)
-
Added a transpiler pass,
DynamicalDecoupling
, toqiskit.transpiler.passes
for inserting dynamical decoupling sequences in idle periods of a circuit (after mapping to physical qubits and scheduling). The pass allows control over the sequence of DD gates, the spacing between them, and the qubits to apply on. For example:from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import XGate from qiskit.transpiler import PassManager, InstructionDurations from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling from qiskit.visualization import timeline_drawer circ = QuantumCircuit(4) circ.h(0) circ.cx(0, 1) circ.cx(1, 2) circ.cx(2, 3) circ.measure_all() durations = InstructionDurations( [("h", 0, 50), ("cx", [0, 1], 700), ("reset", None, 10), ("cx", [1, 2], 200), ("cx", [2, 3], 300), ("x", None, 50), ("measure", None, 1000)] ) dd_sequence = [XGate(), XGate()] pm = PassManager([ALAPSchedule(durations), DynamicalDecoupling(durations, dd_sequence)]) circ_dd = pm.run(circ) timeline_drawer(circ_dd)
-
The
QuantumCircuit
methodqasm()
has a new kwarg,encoding
, which can be used to optionally set the character encoding of an output QASM file generated by the function. This can be set to any valid codec or alias string from the Python standard library’s codec module. -
Added a new class,
EvolvedOperatorAnsatz
, to theqiskit.circuit.library
module. This library circuit, which had previously been located in Qiskit Nature , can be used to construct ansatz circuits that consist of time-evolved operators, where the evolution time is a variational parameter. Examples of such ansatz circuits includeUCCSD
class in thechemistry
module of Qiskit Nature or theQAOAAnsatz
class. -
A new fake backend class is available under
qiskit.test.mock
for theibmq_guadalupe
backend. As with the other fake backends, this includes a snapshot 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. -
A new method
children()
for theSchedule
class has been added. This method is used to return the child schedule components of theSchedule
object as a tuple. It returns nested schedules without flattening. This method is equivalent to the private_children()
method but has a public and stable interface. -
A new optimizer class,
GradientDescent
, has been added to theqiskit.algorithms.optimizers
module. This optimizer class implements a standard gradient descent optimization algorithm for use with quantum variational algorithms, such asVQE
. For a detailed description and examples on how to use this class, please refer to theGradientDescent
class documentation. -
A new optimizer class,
QNSPSA
, has been added to theqiskit.algorithms.optimizers
module. This class implements the Quantum Natural SPSA (QN-SPSA) algorithm, a generalization of the 2-SPSA algorithm, and estimates the Quantum Fisher Information Matrix instead of the Hessian to obtain a stochastic estimate of the Quantum Natural Gradient. For examples on how to use this new optimizer refer to theQNSPSA
class documentation. -
A new kwarg,
second_order
, has been added to the constructor of theSPSA
class in theqiskit.algorithms.optimizers
module. When set toTrue
this enables using second-order SPSA. Second order SPSA, or 2-SPSA, is an extension of the ordinary SPSA algorithm that enables estimating the Hessian alongside the gradient, which is used to precondition the gradient before the parameter update step. As a second-order method, this tries to improve convergence of SPSA. For examples on how to use this option refer to theSPSA
class documentation. -
When using the
latex
orlatex_source
output mode ofcircuit_drawer()
or thedraw()
ofQuantumCircuit
thestyle
kwarg can now be used just as with thempl
output formatting. However, unlike thempl
output mode only thedisplaytext
field will be used when using thelatex
orlatex_source
output modes (because neither supports color). -
When using the
mpl
orlatex
output methods for thecircuit_drawer()
function or thedraw()
ofQuantumCircuit
, you can now use math mode formatting for text and set color formatting (mpl
only) by setting thestyle
kwarg as a dict with a user-generated name or label. For example, to add subscripts and to change a gate color:from qiskit import QuantumCircuit from qiskit.circuit.library import HGate qc = QuantumCircuit(3) qc.append(HGate(label='h1'), [0]) qc.append(HGate(label='h2'), [1]) qc.append(HGate(label='h3'), [2]) qc.draw('mpl', style={'displaytext': {'h1': 'H_1', 'h2': 'H_2', 'h3': 'H_3'}, 'displaycolor': {'h2': ('#EEDD00', '#FF0000')}})
-
Added three new classes,
CDKMRippleCarryAdder
,ClassicalAdder
andDraperQFTAdder
, to theqiskit.circuit.library
module. These new circuit classes are used to perform classical addition of two equally-sized qubit registers. For two registers and on qubits, the three new classes perform the operation:For example:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import CDKMRippleCarryAdder from qiskit.quantum_info import Statevector # a encodes |01> = 1 a = QuantumCircuit(2) a.x(0) # b encodes |10> = 2 b = QuantumCircuit(2) b.x(1) # adder on 2-bit numbers adder = CDKMRippleCarryAdder(2) # add the state preparations to the front of the circuit adder.compose(a, [0, 1], inplace=True, front=True) adder.compose(b, [2, 3], inplace=True, front=True) # simulate and get the state of all qubits sv = Statevector(adder) counts = sv.probabilities_dict() state = list(counts.keys())[0] # we only have a single state # skip the input carry (first bit) and the register |a> (last two bits) result = state[1:-2] print(result) # '011' = 3 = 1 + 2
-
Added two new classes,
RGQFTMultiplier
andHRSCumulativeMultiplier
, to theqiskit.circuit.library
module. These classes are used to perform classical multiplication of two equally-sized qubit registers. For two registers and on qubits, the two new classes perform the operationFor example:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import RGQFTMultiplier from qiskit.quantum_info import Statevector num_state_qubits = 2 # a encodes |11> = 3 a = QuantumCircuit(num_state_qubits) a.x(range(num_state_qubits)) # b encodes |11> = 3 b = QuantumCircuit(num_state_qubits) b.x(range(num_state_qubits)) # multiplier on 2-bit numbers multiplier = RGQFTMultiplier(num_state_qubits) # add the state preparations to the front of the circuit multiplier.compose(a, [0, 1], inplace=True, front=True) multiplier.compose(b, [2, 3], inplace=True, front=True) # simulate and get the state of all qubits sv = Statevector(multiplier) counts = sv.probabilities_dict(decimals=10) state = list(counts.keys())[0] # we only have a single state # skip both input registers result = state[:-2*num_state_qubits] print(result) # '1001' = 9 = 3 * 3
-
The
Delay
class now can accept aParameterExpression
orParameter
value for theduration
kwarg on its constructor and for itsduration
attribute.For example:
idle_dur = Parameter('t') qc = QuantumCircuit(1, 1) qc.x(0) qc.delay(idle_dur, 0, 'us') qc.measure(0, 0) print(qc) # parameterized delay in us (micro seconds) # assign before transpilation assigned = qc.assign_parameters({idle_dur: 0.1}) print(assigned) # delay in us transpiled = transpile(assigned, some_backend_with_dt) print(transpiled) # delay in dt # assign after transpilation transpiled = transpile(qc, some_backend_with_dt) print(transpiled) # parameterized delay in dt assigned = transpiled.assign_parameters({idle_dur: 0.1}) print(assigned) # delay in dt
-
A new binary serialization format, QPY, has been introduced. It is designed to be a fast binary serialization format that is backwards compatible (QPY files generated with older versions of Qiskit can be loaded by newer versions of Qiskit) that is native to Qiskit. The QPY serialization tooling is available via the
qiskit.circuit.qpy_serialization
module. For example, to generate a QPY file:from datetime import datetime from qiskit.circuit import QuantumCircuit from qiskit.circuit import qpy_serialization qc = QuantumCircuit( 2, metadata={'created_at': datetime.utcnow().isoformat()} ) qc.h(0) qc.cx(0, 1) qc.measure_all() circuits = [qc] * 5 with open('five_bells.qpy', 'wb') as qpy_file: qpy_serialization.dump(circuits, qpy_file)
Then the five circuits saved in the QPY file can be loaded with:
from qiskit.circuit.qpy_serialization with open('five_bells.qpy', 'rb') as qpy_file: circuits = qpy_serialization.load(qpy_file)
The QPY file format specification is available in the module documentation.
-
The
TwoQubitBasisDecomposer
class has been updated to perform pulse optimal decompositions for a basis with CX, √X, and virtual Rz gates as described in https://arxiv.org/pdf/2008.08571. Pulse optimal here means that the duration of gates between the CX gates of the decomposition is reduced in exchange for possibly more local gates before or after all the CX gates such that, when composed into a circuit, there is the possibility of single qubit compression with neighboring gates reducing the overall sequence duration.A new keyword argument,
`pulse_optimize
, has been added to the constructor forTwoQubitBasisDecomposer
to control this:None
: Attempt pulse optimal decomposition. If a pulse optimal decomposition is unknown for the basis of the decomposer, drop back to the standard decomposition without warning. This is the default setting.True
: Attempt pulse optimal decomposition. If a pulse optimal decomposition is unknown for the basis of the decomposer, raise QiskitError.False
: Do not attempt pulse optimal decomposition.
For example:
from qiskit.quantum_info import TwoQubitBasisDecomposer from qiskit.circuit.library import CXGate from qiskit.quantum_info import random_unitary unitary_matrix = random_unitary(4) decomposer = TwoQubitBasisDecomposer(CXGate(), euler_basis="ZSX", pulse_optimize=True) circuit = decomposer(unitary_matrix)
-
The transpiler pass
UnitarySynthesis
located inqiskit.transpiler.passes
has been updated to support performing pulse optimal decomposition. This is done primarily with the thepulse_optimize
keyword argument which was added to the constructor and used to control whether pulse optimal synthesis is performed. The behavior of this kwarg mirrors thepulse_optimize
kwarg in theTwoQubitBasisDecomposer
class’s constructor. Additionally, the constructor has another new keyword argument,synth_gates
, which is used to specify the list of gate names over which synthesis should be attempted. IfNone
andpulse_optimize
isFalse
orNone
, use"unitary"
. If None and pulse_optimize isTrue
, use"unitary"
and"swap"
. Since the direction of the CX gate in the synthesis is arbitrary, another keyword argument,natural_direction
, is added to consider first a coupling map and thenCXGate
durations in choosing for which direction of CX to generate the synthesis.from qiskit.circuit import QuantumCircuit from qiskit.transpiler import PassManager, CouplingMap from qiskit.transpiler.passes import TrivialLayout, UnitarySynthesis from qiskit.test.mock import FakeVigo from qiskit.quantum_info.random import random_unitary backend = FakeVigo() conf = backend.configuration() coupling_map = CouplingMap(conf.coupling_map) triv_layout_pass = TrivialLayout(coupling_map) circ = QuantumCircuit(2) circ.unitary(random_unitary(4), [0, 1]) unisynth_pass = UnitarySynthesis( basis_gates=conf.basis_gates, coupling_map=None, backend_props=backend.properties(), pulse_optimize=True, natural_direction=True, synth_gates=['unitary']) pm = PassManager([triv_layout_pass, unisynth_pass]) optimal_circ = pm.run(circ)
-
A new basis option,
'XZX'
, was added for thebasis
argumentOneQubitEulerDecomposer
class. -
Added a new method,
get_instructions()
, was added to theQuantumCircuit
class. This method is used to return allInstruction
objects in the circuit which have aname
that matches the providedname
argument along with its associatedqargs
andcargs
lists ofQubit
andClbit
objects. -
A new optional extra
all
has been added to the qiskit-terra package. This enables installing all the optional requirements with a single extra, for example:pip install 'qiskit-terra[all]'
, Previously, it was necessary to list all the extras individually to install all the optional dependencies simultaneously. -
Added two new classes
ProbDistribution
andQuasiDistribution
for dealing with probability distributions and quasiprobability distributions respectively. These objects both are dictionary subclasses that add additional methods for working with probability and quasiprobability distributions. -
Added a new
settings
property to theOptimizer
abstract base class that all the optimizer classes in theqiskit.algorithms.optimizers
module are based on. This property will return a Python dictionary of the settings for the optimizer that can be used to instantiate another instance of the same optimizer class. For example:from qiskit.algorithms.optimizers import GradientDescent optimizer = GradientDescent(maxiter=10, learning_rate=0.01) settings = optimizer.settings new_optimizer = GradientDescent(**settings)
The
settings
dictionary is also potentially useful for serializing optimizer objects using JSON or another serialization format. -
A new function,
set_config()
, has been added to theqiskit.user_config
module. This function enables setting values in a user config from the Qiskit API. For example:from qiskit.user_config import set_config set_config("circuit_drawer", "mpl", section="default", file="settings.conf")
which will result in adding a value of
circuit_drawer = mpl
to thedefault
section in thesettings.conf
file.If no
file_path
argument is specified, the currently used path to the user config file (either the value of theQISKIT_SETTINGS
environment variable if set or the default location~/.qiskit/settings.conf
) will be updated. However, changes to the existing config file will not be reflected in the current session since the config file is parsed at import time. -
Added a new state class,
StabilizerState
, to theqiskit.quantum_info
module. This class represents a stabilizer simulator state using the convention from Aaronson and Gottesman (2004). -
Two new options,
'value'
and'value_desc'
were added to thesort
kwarg of theqiskit.visualization.plot_histogram()
function. Whensort
is set to either of these options the output visualization will sort the x axis based on the maximum probability for each bitstring. For example:from qiskit.visualization import plot_histogram counts = { '000': 5, '001': 25, '010': 125, '011': 625, '100': 3125, '101': 15625, '110': 78125, '111': 390625, } plot_histogram(counts, sort='value')
Known Issues
- When running
parallel_map()
(and functions that internally callparallel_map()
such astranspile()
andassemble()
) on Python 3.9 withQISKIT_PARALLEL
set to True in some scenarios it is possible for the program to deadlock and never finish running. To avoid this from happening the default for Python 3.9 was changed to not run in parallel, but ifQISKIT_PARALLEL
is explicitly enabled then this can still occur.
Upgrade Notes
-
The minimum version of the retworkx dependency was increased to version 0.9.0. This was done to use new APIs introduced in that release which improved the performance of some transpiler passes.
-
The default value for
QISKIT_PARALLEL
on Python 3.9 environments has changed toFalse
, this means that when running on Python 3.9 by default multiprocessing will not be used. This was done to avoid a potential deadlock/hanging issue that can occur when running multiprocessing on Python 3.9 (see the known issues section for more detail). It is still possible to manual enable it by explicitly setting theQISKIT_PARALLEL
environment variable toTRUE
. -
The existing fake backend classes in
qiskit.test.mock
now strictly implement theBackendV1
interface. This means that if you were manually constructingQasmQobj
orPulseQobj
object for use with therun()
method this will no longer work. Therun()
method only acceptsQuantumCircuit
orSchedule
objects now. This was necessary to enable testing of new backends implemented without qobj which previously did not have any testing inside qiskit terra. If you need to leverage the fake backends withQasmQobj
orPulseQobj
new fake legacy backend objects were added to explicitly test the legacy providers interface. This will be removed after the legacy interface is deprecated and removed. Moving forward new fake backends will only implement theBackendV1
interface and will not add new legacy backend classes for new fake backends. -
When creating a
Pauli
object with an invalid string label, aQiskitError
is now raised. This is a change from previous releases which would raise anAttributeError
on an invalid string label. This change was made to ensure the error message is more informative and distinct from a genericAttributeError
. -
The output program representation from the pulse builder (
qiskit.pulse.builder.build()
) has changed from aSchedule
to aScheduleBlock
. This new representation disables some timing related operations such as shift and insert. However, this enables parameterized instruction durations within the builder context. For example:from qiskit import pulse from qiskit.circuit import Parameter dur = Parameter('duration') with pulse.build() as sched: with pulse.align_sequential(): pulse.delay(dur, pulse.DriveChannel(1)) pulse.play(pulse.Gaussian(dur, 0.1, dur/4), pulse.DriveChannel(0)) assigned0 = sched.assign_parameters({dur: 100}) assigned1 = sched.assign_parameters({dur: 200})
You can directly pass the duration-assigned schedules to the assembler (or backend), or you can attach them to your quantum circuit as pulse gates.
-
The tweedledum library which was previously an optional dependency has been made a requirement. This was done because of the wide use of the
PhaseOracle
(which depends on having tweedledum installed) with several algorithms fromqiskit.algorithms
. -
The optional extra
full-featured-simulators
which could previously used to installqiskit-aer
with something likepip install qiskit-terra[full-featured-simulators]
has been removed from the qiskit-terra package. If this was being used to installqiskit-aer
withqiskit-terra
instead you should rely on the qiskit metapackage or just install qiskit-terra and qiskit-aer together withpip install qiskit-terra qiskit-aer
. -
A new requirement symengine has been added for Linux (on x86_64, aarch64, and ppc64le) and macOS users (x86_64 and arm64). It is an optional dependency on Windows (and available on PyPi as a precompiled package for 64bit Windows) and other architectures. If it is installed it provides significantly improved performance for the evaluation of
Parameter
andParameterExpression
objects. -
All library circuit classes, i.e. all
QuantumCircuit
derived classes inqiskit.circuit.library
, are now wrapped in aInstruction
(orGate
, if they are unitary). For example, importing and drawing theQFT
circuit:before looked like
┌───┐ q_0: ────────────────────■────────■───────┤ H ├─X─ ┌───┐ │ │P(π/2) └───┘ │ q_1: ──────■───────┤ H ├─┼────────■─────────────┼─ ┌───┐ │P(π/2) └───┘ │P(π/4) │ q_2: ┤ H ├─■─────────────■──────────────────────X─ └───┘
and now looks like
┌──────┐ q_0: ┤0 ├ │ │ q_1: ┤1 QFT ├ │ │ q_2: ┤2 ├ └──────┘
To obtain the old circuit, you can call the
decompose()
method on the circuitThis change was primarily made for consistency as before this release some circuit classes in
qiskit.circuit.library
were previously wrapped in anInstruction
orGate
but not all.
Deprecation Notes
- The class
qiskit.exceptions.QiskitIndexError
is deprecated and will be removed in a future release. This exception was not actively being used by anything in Qiskit, if you were using it you can create a custom exception class to replace it. - The kwargs
epsilon
andfactr
for theqiskit.algorithms.optimizers.L_BFGS_B
constructor andfactr
kwarg of theP_BFGS
optimizer class are deprecated and will be removed in a future release. Instead, please use theeps
karg instead ofepsilon
. Thefactr
kwarg is replaced withftol
. The relationship between the two isftol = factr * numpy.finfo(float).eps
. This change was made to be consistent with the usage of thescipy.optimize.minimize
functions'L-BFGS-B'
method. See the:scipy.optimize.minimize(method='L-BFGS-B')
documentation for more information on how these new parameters are used. - The legacy providers interface, which consisted of the
qiskit.providers.BaseBackend
,qiskit.providers.BaseJob
, andqiskit.providers.BaseProvider
abstract classes, has been deprecated and will be removed in a future release. Instead you should use the versioned interface, which the current abstract class versions areqiskit.providers.BackendV1
,qiskit.providers.JobV1
, andqiskit.providers.ProviderV1
. The V1 objects are mostly backwards compatible to ease migration from the legacy interface to the versioned one. However, expect future versions of the abstract interfaces to diverge more. You can refer to theqiskit.providers
documentation for more high level details about the versioned interface. - The
condition
kwarg to theDAGDepNode
constructor along with the correspondingcondition
attribute of theDAGDepNode
have been deprecated and will be removed in a future release. Instead, you can access thecondition
of aDAGDepNode
if the node is of typeop
, by usingDAGDepNode.op.condition
. - The
condition
attribute of theDAGNode
class has been deprecated and will be removed in a future release. Instead, you can access thecondition
of aDAGNode
object if the node is of typeop
, by usingDAGNode.op.condition
. - The pulse builder (
qiskit.pulse.builder.build()
) syntaxqiskit.pulse.builder.inline()
is deprecated and will be removed in a future release. Instead of using this context, you can just remove alignment contexts within the inline context. - The pulse builder (
qiskit.pulse.builder.build()
) syntaxqiskit.pulse.builder.pad()
is deprecated and will be removed in a future release. This was done because theScheduleBlock
now being returned by the pulse builder doesn’t support the.insert
method (and there is no insert syntax in the builder). The use of timeslot placeholders to block the insertion of other instructions is no longer necessary.
Bug Fixes
-
The
OneQubitEulerDecomposer
andTwoQubitBasisDecomposer
classes for one and two qubit gate synthesis have been improved to tighten up tolerances, improved repeatability and simplification, and fix several global-phase-tracking bugs. -
Fixed an issue in the assignment of the
name
attribute toGate
generated by multiple calls to theinverse`()
method. Prior to this fix when theinverse`()
was called it would unconditionally append_dg
on each call to inverse. This has been corrected so on a second call ofinverse`()
the_dg
suffix is now removed. -
Fixes the triviality check conditions of
CZGate
,CRZGate
,CU1Gate
andMCU1Gate
in theHoareOptimizer
pass. Previously, in some cases the optimizer would remove these gates breaking the semantic equivalence of the transformation. -
Fixed an issue when converting a
ListOp
object ofPauliSumOp
objects usingPauliExpectation
orAerPauliExpectation
. Previously, it would raise a warning about it converting to a Pauli representation which is potentially expensive. This has been fixed by instead of internally converting theListOp
to aSummedOp
ofPauliOp
objects, it now creates aPauliSumOp
which is more efficient. Fixed #6159 -
Fixed an issue with the
NLocal
class in theqiskit.circuit.library
module where it wouldn’t properly raise an exception at object initialization if an invalid type was used for thereps
kwarg which would result in an unexpected runtime error later. ATypeError
will now be properly raised if thereps
kwarg is not anint
value. Fixed #6515 -
Fixed an issue where the
TwoLocal
class in theqiskit.circuit.library
module did not accept numpy integer types (e.g.numpy.int32
,numpy.int64
, etc) as a valid input for theentanglement
kwarg. Fixed #6455 -
When loading an OpenQASM2 file or string with the
from_qasm_file()
orfrom_qasm_str()
constructors for theQuantumCircuit
class, if the OpenQASM2 circuit contains an instruction with the namedelay
this will be mapped to aqiskit.circuit.Delay
instruction. For example:from qiskit import QuantumCircuit qasm = """OPENQASM 2.0; include "qelib1.inc"; opaque delay(time) q; qreg q[1]; delay(172) q[0]; u3(0.1,0.2,0.3) q[0]; """ circuit = QuantumCircuit.from_qasm_str(qasm) circuit.draw()
Fixed #6510
-
Fixed an issue with addition between
PauliSumOp
objects that hadParameterExpression
coefficients. Previously this would result in aQiskitError
exception being raised because the addition of theParameterExpression
was not handled correctly. This has been fixed so that addition can be performed betweenPauliSumOp
objects withParameterExpression
coefficients. -
Fixed an issue with the initialization of the
AmplificationProblem
class. Theis_good_state
kwarg was a required field but incorrectly being treated as optional (and documented as such). This has been fixed and also updated so unless the inputoracle
is aPhaseOracle
object (which provides it’s on evaluation method) the field is required and will raise aTypeError
when constructed withoutis_good_state
. -
Fixed an issue where adding a control to a
ControlledGate
with open controls would unset the inner open controls. Fixes #5857 -
Fixed an issue with the
convert()
method of thePauliExpectation
class where calling it on an operator that was non-Hermitian would return an incorrect result. Fixed #6307 -
Fixed an issue with the
qiskit.pulse.transforms.inline_subroutines()
function which would previously incorrectly not remove all the nested components when called on nested schedules. Fixed #6321 -
Fixed an issue when passing a partially bound callable created with the Python standard library’s
functools.partial()
function as theschedule
kwarg to theadd()
method of theInstructionScheduleMap
class, which would previously result in an error. Fixed #6278 -
Fixed an issue with the
PiecewiseChebyshev
when setting thebreakpoints
toNone
on an existing object was incorrectly being treated as a breakpoint. This has been corrected so that when it is set toNone
this will switch back to the default behavior of approximating over the full interval. Fixed #6198 -
Fixed an issue with the
num_connected_components()
method ofQuantumCircuit
which was returning the incorrect number of components when the circuit contains two or more gates conditioned on classical registers. Fixed #6477 -
Fixed an issue with the
qiskit.opflow.expectations
module where coefficients of a statefunction were not being multiplied correctly. This also fixed the calculations of Gradients and QFIs when using thePauliExpectation
orAerPauliExpectation
classes. For example, previously:from qiskit.opflow import StateFn, I, One exp = ~StateFn(I) @ (2 * One)
evaluated to
2
forAerPauliExpectation
and to4
for other expectation converters. Since~StateFn(I) @ (2 * One)
is a shorthand notation for~(2 * One) @ I @ (2 * One)
, the now correct coefficient of4
is returned for all expectation converters. Fixed #6497 -
Fixed the bug that caused
to_circuit()
to fail whenPauliOp
had a phase. At the same time, it was made more efficient to usePauliGate
. -
Fixed an issue where the QASM output generated by the
qasm()
method ofQuantumCircuit
for composite gates such asMCXGate
and its variants (MCXGrayCode
,MCXRecursive
, andMCXVChain
) would be incorrect. Now if aGate
in the circuit is not present inqelib1.inc
, its definition is added to the output QASM string. Fixed #4943 and #3945 -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
. When using thempl
orlatex
output modes, with thecregbundle
kwarg set toFalse
and thereverse_bits
kwarg set toTrue
, the bits in the classical registers displayed in the same order as whenreverse_bits
was set toFalse
. -
Fixed an issue when using the
qiskit.extensions.Initialize
instruction which was not correctly setting the global phase of the synthesized definition when constructed. Fixed #5320 -
Fixed an issue where the bit-order in
qiskit.circuit.library.PhaseOracle.evaluate_bitstring()
did not agree with the order of the measured bitstring. This fix also affects the execution of theGrover
algorithm class if the oracle is specified as aPhaseOracle
, which now will now correctly identify the correct bitstring. Fixed #6314 -
Fixes a bug in
Optimize1qGatesDecomposition()
previously causing certain short sequences of gates to erroneously not be rewritten. -
Fixed an issue in the
qiskit.opflow.gradients.Gradient.gradient_wrapper()
method with the gradient calculation. Previously, if the operator was not diagonal an incorrect result would be returned in some situations. This has been fixed by using an expectation converter to ensure the result is always correct. -
Fixed an issue with the
circuit_drawer()
function anddraw()
method ofQuantumCircuit
with all output modes where it would incorrectly render a custom instruction that includes classical bits in some circumstances. Fixed #3201, #3202, and #6178 -
Fixed an issue in
circuit_drawer()
and thedraw()
method of theQuantumCircuit
class when using thempl
output mode, controlled-Z Gates were incorrectly drawn as asymmetrical. Fixed #5981 -
Fixed an issue with the
OptimizeSwapBeforeMeasure
transpiler pass where in some situations aSwapGate
that that contained a classical condition would be removed. Fixed #6192 -
Fixed an issue with the phase of the
qiskit.opflow.gradients.QFI
class when theqfi_method
is set tolin_comb_full
which caused the incorrect observable to be evaluated. -
Fixed an issue with
VQE
algorithm class when run with theL_BFGS_B
orP_BFGS
optimizer classes and gradients are used, the gradient was incorrectly passed as a numpy array instead of the expected list of floats resulting in an error. This has been resolved so you can use gradients withVQE
and theL_BFGS_B
orP_BFGS
optimizers.
Other Notes
- The deprecation of the
parameters()
method for theInstruction
class has been reversed. This method was originally deprecated in the 0.17.0, but it is still necessary for several applications, including when running calibration experiments. This method will continue to be supported and will not be removed.
Aer 0.8.2
No change
Ignis 0.6.0
No change
Aqua 0.9.4
No change
IBM Q Provider 0.15.0
New Features
-
Add support for new method
qiskit.providers.ibmq.runtime.RuntimeJob.error_message()
which will return a string representing the reason if the job failed. -
The inputs parameter to
qiskit.providers.ibmq.runtime.IBMRuntimeService.run()
method can now be specified as aqiskit.providers.ibmq.runtime.ParameterNamespace
instance which supports auto-complete features. You can useqiskit.providers.ibmq.runtime.RuntimeProgram.parameters()
to retrieve anParameterNamespace
instance.For example:
from qiskit import IBMQ provider = IBMQ.load_account() # Set the "sample-program" program parameters. params = provider.runtime.program(program_id="sample-program").parameters() params.iterations = 2 # Configure backend options options = {'backend_name': 'ibmq_qasm_simulator'} # Execute the circuit using the "circuit-runner" program. job = provider.runtime.run(program_id="sample-program", options=options, inputs=params)
-
The user can now set the visibility (private/public) of a Qiskit Runtime program using
qiskit.providers.ibmq.runtime.IBMRuntimeService.set_program_visibility()
. -
An optional boolean parameter pending has been added to
qiskit.providers.ibmq.runtime.IBMRuntimeService.jobs()
and it allows filtering jobs by their status. If pending is not specified all jobs are returned. If pending is set to True, ‘QUEUED’ and ‘RUNNING’ jobs are returned. If pending is set to False, ‘DONE’, ‘ERROR’ and ‘CANCELLED’ jobs are returned. -
Add support for the
use_measure_esp
flag in theqiskit.providers.ibmq.IBMQBackend.run()
method. IfTrue
, the backend will use ESP readout for all measurements which are the terminal instruction on that qubit. If used and the backend does not support ESP readout, an error is raised.
Upgrade Notes
qiskit.providers.ibmq.runtime.RuntimeProgram.parameters()
is now a method that returns aqiskit.providers.ibmq.runtime.ParameterNamespace
instance, which you can use to fill in runtime program parameter values and pass toqiskit.providers.ibmq.runtime.IBMRuntimeService.run()
.- The
open_pulse
flag in backend configuration no longer indicates whether a backend supports pulse-level control. As a result,qiskit.providers.ibmq.IBMQBackend.configuration()
may return aPulseBackendConfiguration
instance even if itsopen_pulse
flag isFalse
. - Job share level is no longer supported due to low adoption and the corresponding interface will be removed in a future release. This means you should no longer pass share_level when creating a job or use
qiskit.providers.ibmq.job.IBMQJob.share_level()
method to get a job’s share level.
Deprecation Notes
- The
id
instruction has been deprecated on IBM hardware backends. Instead, please use thedelay
instruction which implements variable-length delays, specified in units ofdt
. When running a circuit containing anid
instruction, a warning will be raised on job submission and anyid
instructions in the job will be automatically replaced with their equivalentdelay
instruction.