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_mitgationkwarg for theQuantumInstanceconstructor can now be set to theTensoredMeasFitterclass from qiskit-ignis in addition toCompleteMeasFitterthat was already supported. If you useTensoredMeasFitteryou will also be able to set the newmit_patternkwarg to specify the qubits on which to useTensoredMeasFitterYou can refer to the documentation formit_patternin theTensoredMeasFitterdocumentation for the expected format. -
The decomposition methods for single-qubit gates, specified via the
basiskwarg, inOneQubitEulerDecomposerhas been expanded to now also include the'ZSXX'basis, for making use of direct gate as well as gate. -
Added two new passes
AlignMeasuresandValidatePulseGatesto theqiskit.transpiler.passesmodule. 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
Measureinstructions (in terms of quantization in time), theAlignMeasurespass is used to adjust delays in a scheduled circuit to ensure that anyMeasureinstructions in the circuit are aligned given the constraints of the backend. TheValidatePulseGatespass is used to check if any custom pulse gates (gates that have a custom pulse definition in thecalibrationsattribute of aQuantumCircuitobject) are valid given an alignment constraint for the target backend.In the built-in
preset_passmangersused by thetranspile()function, these passes get automatically triggered if the alignment constraint, either via the dedicatedtiming_constraintskwarg ontranspile()or has antiming_constraintsattribute in theBackendConfigurationobject 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.BIPMappingthat 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
BIPMappingpass (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_mapbeyond 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_mapwhich 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 theScheduleandScheduleBlockclasses. 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_monitoroutput. Theline_disciplinekwarg defaults to'\r', which is what was in use before. -
The abstract
Pulseclass (which is the parent class for classes such asWaveform,Constant, andGaussiannow has a new kwarg on the constructor,limit_amplitude, which can be set toFalseto 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_infomodule. This class is used to efficiently represent a list ofPaulioperators. This new class inherets from the same parent class as the existingPauliTable(and therefore can be mostly used interchangeably), however it differs from thePauliTablebecause theqiskit.quantum_info.PauliListclass 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.optimizersmodule. This class is a simple wrapper class of thescipy.optimize.minimizefunction (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
HoareOptimizerpass has been improved so that it can now replace aControlledGatein 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 theDAGCircuitclass. 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.passesmodule. This pass is similar to the existingRZXCalibrationBuilderin that it creates calibrations for anRZXGate(theta), howeverRZXCalibrationBuilderNoEchodoes 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. TheRZXCalibrationBuilderNoEchopass 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 thePulseBackendConfigurationclass. This attribute represents the control channels on a backend as a mapping of qubits to a list ofControlChannelobjects. -
A new kwarg,
epsilon, has been added to the constructor for theIsometryclass and the correspondingQuantumCircuitmethodisometry(). This kwarg enables optionally setting the epsilon tolerance used by anIsometrygate. 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.passesfor 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
QuantumCircuitmethodqasm()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.librarymodule. 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 includeUCCSDclass in thechemistrymodule of Qiskit Nature or theQAOAAnsatzclass. -
A new fake backend class is available under
qiskit.test.mockfor theibmq_guadalupebackend. 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 theScheduleclass has been added. This method is used to return the child schedule components of theScheduleobject 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.optimizersmodule. 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 theGradientDescentclass documentation. -
A new optimizer class,
QNSPSA, has been added to theqiskit.algorithms.optimizersmodule. 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 theQNSPSAclass documentation. -
A new kwarg,
second_order, has been added to the constructor of theSPSAclass in theqiskit.algorithms.optimizersmodule. When set toTruethis 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 theSPSAclass documentation. -
When using the
latexorlatex_sourceoutput mode ofcircuit_drawer()or thedraw()ofQuantumCircuitthestylekwarg can now be used just as with themploutput formatting. However, unlike themploutput mode only thedisplaytextfield will be used when using thelatexorlatex_sourceoutput modes (because neither supports color). -
When using the
mplorlatexoutput methods for thecircuit_drawer()function or thedraw()ofQuantumCircuit, you can now use math mode formatting for text and set color formatting (mplonly) by setting thestylekwarg 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,ClassicalAdderandDraperQFTAdder, to theqiskit.circuit.librarymodule. 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,
RGQFTMultiplierandHRSCumulativeMultiplier, to theqiskit.circuit.librarymodule. 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
Delayclass now can accept aParameterExpressionorParametervalue for thedurationkwarg on its constructor and for itsdurationattribute.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_serializationmodule. 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
TwoQubitBasisDecomposerclass 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 forTwoQubitBasisDecomposerto 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
UnitarySynthesislocated inqiskit.transpiler.passeshas been updated to support performing pulse optimal decomposition. This is done primarily with the thepulse_optimizekeyword argument which was added to the constructor and used to control whether pulse optimal synthesis is performed. The behavior of this kwarg mirrors thepulse_optimizekwarg in theTwoQubitBasisDecomposerclass’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. IfNoneandpulse_optimizeisFalseorNone, 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 thenCXGatedurations 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 thebasisargumentOneQubitEulerDecomposerclass. -
Added a new method,
get_instructions(), was added to theQuantumCircuitclass. This method is used to return allInstructionobjects in the circuit which have anamethat matches the providednameargument along with its associatedqargsandcargslists ofQubitandClbitobjects. -
A new optional extra
allhas 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
ProbDistributionandQuasiDistributionfor 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
settingsproperty to theOptimizerabstract base class that all the optimizer classes in theqiskit.algorithms.optimizersmodule 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
settingsdictionary 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_configmodule. 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 = mplto thedefaultsection in thesettings.conffile.If no
file_pathargument is specified, the currently used path to the user config file (either the value of theQISKIT_SETTINGSenvironment 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_infomodule. 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 thesortkwarg of theqiskit.visualization.plot_histogram()function. Whensortis 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_PARALLELset 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_PARALLELis 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_PARALLELon 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_PARALLELenvironment variable toTRUE. -
The existing fake backend classes in
qiskit.test.mocknow strictly implement theBackendV1interface. This means that if you were manually constructingQasmQobjorPulseQobjobject for use with therun()method this will no longer work. Therun()method only acceptsQuantumCircuitorScheduleobjects 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 withQasmQobjorPulseQobjnew 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 theBackendV1interface and will not add new legacy backend classes for new fake backends. -
When creating a
Pauliobject with an invalid string label, aQiskitErroris now raised. This is a change from previous releases which would raise anAttributeErroron 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 aScheduleto 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-simulatorswhich could previously used to installqiskit-aerwith something likepip install qiskit-terra[full-featured-simulators]has been removed from the qiskit-terra package. If this was being used to installqiskit-aerwithqiskit-terrainstead 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
ParameterandParameterExpressionobjects. -
All library circuit classes, i.e. all
QuantumCircuitderived classes inqiskit.circuit.library, are now wrapped in aInstruction(orGate, if they are unitary). For example, importing and drawing theQFTcircuit: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.librarywere previously wrapped in anInstructionorGatebut not all.
Deprecation Notes
- The class
qiskit.exceptions.QiskitIndexErroris 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
epsilonandfactrfor theqiskit.algorithms.optimizers.L_BFGS_Bconstructor andfactrkwarg of theP_BFGSoptimizer class are deprecated and will be removed in a future release. Instead, please use theepskarg instead ofepsilon. Thefactrkwarg 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.minimizefunctions'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.BaseProviderabstract 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.providersdocumentation for more high level details about the versioned interface. - The
conditionkwarg to theDAGDepNodeconstructor along with the correspondingconditionattribute of theDAGDepNodehave been deprecated and will be removed in a future release. Instead, you can access theconditionof aDAGDepNodeif the node is of typeop, by usingDAGDepNode.op.condition. - The
conditionattribute of theDAGNodeclass has been deprecated and will be removed in a future release. Instead, you can access theconditionof aDAGNodeobject 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 theScheduleBlocknow being returned by the pulse builder doesn’t support the.insertmethod (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
OneQubitEulerDecomposerandTwoQubitBasisDecomposerclasses 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
nameattribute toGategenerated by multiple calls to theinverse`()method. Prior to this fix when theinverse`()was called it would unconditionally append_dgon each call to inverse. This has been corrected so on a second call ofinverse`()the_dgsuffix is now removed. -
Fixes the triviality check conditions of
CZGate,CRZGate,CU1GateandMCU1Gatein theHoareOptimizerpass. Previously, in some cases the optimizer would remove these gates breaking the semantic equivalence of the transformation. -
Fixed an issue when converting a
ListOpobject ofPauliSumOpobjects usingPauliExpectationorAerPauliExpectation. 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 theListOpto aSummedOpofPauliOpobjects, it now creates aPauliSumOpwhich is more efficient. Fixed #6159 -
Fixed an issue with the
NLocalclass in theqiskit.circuit.librarymodule where it wouldn’t properly raise an exception at object initialization if an invalid type was used for therepskwarg which would result in an unexpected runtime error later. ATypeErrorwill now be properly raised if therepskwarg is not anintvalue. Fixed #6515 -
Fixed an issue where the
TwoLocalclass in theqiskit.circuit.librarymodule did not accept numpy integer types (e.g.numpy.int32,numpy.int64, etc) as a valid input for theentanglementkwarg. Fixed #6455 -
When loading an OpenQASM2 file or string with the
from_qasm_file()orfrom_qasm_str()constructors for theQuantumCircuitclass, if the OpenQASM2 circuit contains an instruction with the namedelaythis will be mapped to aqiskit.circuit.Delayinstruction. 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
PauliSumOpobjects that hadParameterExpressioncoefficients. Previously this would result in aQiskitErrorexception being raised because the addition of theParameterExpressionwas not handled correctly. This has been fixed so that addition can be performed betweenPauliSumOpobjects withParameterExpressioncoefficients. -
Fixed an issue with the initialization of the
AmplificationProblemclass. Theis_good_statekwarg was a required field but incorrectly being treated as optional (and documented as such). This has been fixed and also updated so unless the inputoracleis aPhaseOracleobject (which provides it’s on evaluation method) the field is required and will raise aTypeErrorwhen constructed withoutis_good_state. -
Fixed an issue where adding a control to a
ControlledGatewith open controls would unset the inner open controls. Fixes #5857 -
Fixed an issue with the
convert()method of thePauliExpectationclass 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 theschedulekwarg to theadd()method of theInstructionScheduleMapclass, which would previously result in an error. Fixed #6278 -
Fixed an issue with the
PiecewiseChebyshevwhen setting thebreakpointstoNoneon an existing object was incorrectly being treated as a breakpoint. This has been corrected so that when it is set toNonethis will switch back to the default behavior of approximating over the full interval. Fixed #6198 -
Fixed an issue with the
num_connected_components()method ofQuantumCircuitwhich 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.expectationsmodule where coefficients of a statefunction were not being multiplied correctly. This also fixed the calculations of Gradients and QFIs when using thePauliExpectationorAerPauliExpectationclasses. For example, previously:from qiskit.opflow import StateFn, I, One exp = ~StateFn(I) @ (2 * One)evaluated to
2forAerPauliExpectationand to4for other expectation converters. Since~StateFn(I) @ (2 * One)is a shorthand notation for~(2 * One) @ I @ (2 * One), the now correct coefficient of4is returned for all expectation converters. Fixed #6497 -
Fixed the bug that caused
to_circuit()to fail whenPauliOphad 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 ofQuantumCircuitfor composite gates such asMCXGateand its variants (MCXGrayCode,MCXRecursive, andMCXVChain) would be incorrect. Now if aGatein 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 themplorlatexoutput modes, with thecregbundlekwarg set toFalseand thereverse_bitskwarg set toTrue, the bits in the classical registers displayed in the same order as whenreverse_bitswas set toFalse. -
Fixed an issue when using the
qiskit.extensions.Initializeinstruction 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 theGroveralgorithm 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 ofQuantumCircuitwith 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 theQuantumCircuitclass when using themploutput mode, controlled-Z Gates were incorrectly drawn as asymmetrical. Fixed #5981 -
Fixed an issue with the
OptimizeSwapBeforeMeasuretranspiler pass where in some situations aSwapGatethat that contained a classical condition would be removed. Fixed #6192 -
Fixed an issue with the phase of the
qiskit.opflow.gradients.QFIclass when theqfi_methodis set tolin_comb_fullwhich caused the incorrect observable to be evaluated. -
Fixed an issue with
VQEalgorithm class when run with theL_BFGS_BorP_BFGSoptimizer 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 withVQEand theL_BFGS_BorP_BFGSoptimizers.
Other Notes
- The deprecation of the
parameters()method for theInstructionclass 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.ParameterNamespaceinstance which supports auto-complete features. You can useqiskit.providers.ibmq.runtime.RuntimeProgram.parameters()to retrieve anParameterNamespaceinstance.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_espflag 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.ParameterNamespaceinstance, which you can use to fill in runtime program parameter values and pass toqiskit.providers.ibmq.runtime.IBMRuntimeService.run().- The
open_pulseflag in backend configuration no longer indicates whether a backend supports pulse-level control. As a result,qiskit.providers.ibmq.IBMQBackend.configuration()may return aPulseBackendConfigurationinstance even if itsopen_pulseflag 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
idinstruction has been deprecated on IBM hardware backends. Instead, please use thedelayinstruction which implements variable-length delays, specified in units ofdt. When running a circuit containing anidinstruction, a warning will be raised on job submission and anyidinstructions in the job will be automatically replaced with their equivalentdelayinstruction.