Qiskit 0.39 release notes
0.39.5
Terra 0.22.4
Prelude
Qiskit Terra 0.22.4 is a minor bugfix release, fixing some bugs identified in the 0.22 series.
Bug Fixes
-
Fixed a bug in
BackendSampler
that raised an error if itsrun()
method was called two times sequentially. -
Fixed two bugs in the
ComposedOp
where theComposedOp.to_matrix()
method did not provide the correct results for compositions withStateFn
and for compositions with a global coefficient. Fixed #9283. -
Fixed the problem in which primitives,
Sampler
andEstimator
, did not work when passed a circuit withnumpy.ndarray
as a parameter. -
Fixed a bug in
SamplingVQE
where theaggregation
argument did not have an effect. Now the aggregation function and, with it, the CVaR expectation value can correctly be specified. -
Fixed a performance bug where
SamplingVQE
evaluated the energies of eigenstates in a slow manner. -
Fixed the autoevaluation of the beta parameters in
VQD
, added support forSparsePauliOp
inputs, and fixed the energy evaluation function to leverage the asynchronous execution of primitives, by only retrieving the job results after both jobs have been submitted. -
Fixed an issue with the
Statevector.probabilities_dict()
andDensityMatrix.probabilities_dict()
methods where they would return incorrect results for non-qubit systems when theqargs
argument was specified. Fixed #9210 -
Fixed handling of some
classmethod
s bywrap_method()
in Python 3.11. Previously, in Python 3.11,wrap_method
would wrap the unbound function associated with theclassmethod
and then fail when invoked because the class object usually bound to theclassmethod
was not passed to the function. Starting in Python 3.11.1, this issue affectedQiskitTestCase
, preventing it from being imported by other test code. Fixed #9291.
Aer 0.11.2
No change
IBM Q Provider 0.19.2
No change
0.39.4
Terra 0.22.3
No change
Aer 0.11.2
New Features
- Added support for running Qiskit Aer with Python 3.11 support.
Known Issues
- Fix two bugs in AerStatevector. AerStatevector uses mc* instructions, which are not enabled in matrix_product_state method. This commit changes AerStatevector not to use MC* and use H, X, Y, Z, U and CX. AerStatevector also failed if an instruction is decomposed to empty QuantumCircuit. This commit allows such instruction.
Bug Fixes
-
Fixed support in the
AerSimulator.from_backend()
method for instantiating anAerSimulator
instance from an aBackendV2
object. Previously, attempting to useAerSimulator.from_backend()
with aBackendV2
object would have raised anAerError
saying this wasn’t supported. -
Fixes a bug where
NoiseModel.from_backend()
with aBackendV2
object may generate a noise model with excessiveQuantumError
s on non-Gate instructions while, for example, onlyReadoutError
s should be sufficient for measures. This commit updatesNoiseModel.from_backend()
with aBackendV2
object so that it returns the same noise model as that called with the correspondingBackendV1
object. That is, the resulting noise model does not contain anyQuantumError
s on measures and it may contain only thermal relaxation errors on other non-gate instructions such as resets. Note that it still containsReadoutError
s on measures. -
Fixed a bug in
NoiseModel.from_backend()
where using thetemperature
kwarg with a non-default value would incorrectly compute the excited state population for the specified temperature. Previously, there was an additional factor of 2 in the Boltzman distribution calculation leading to an incorrect smaller value for the excited state population. -
Fixed incorrect logic in the control-flow compiler that could allow unrelated instructions to appear “inside” control-flow bodies during execution, causing incorrect results. For example, previously:
from qiskit import QuantumCircuit from qiskit_aer import AerSimulator backend = AerSimulator(method="statevector") circuit = QuantumCircuit(3, 3) circuit.measure(0, 0) circuit.measure(1, 1) with circuit.if_test((0, True)): with circuit.if_test((1, False)): circuit.x(2) with circuit.if_test((0, False)): with circuit.if_test((1, True)): circuit.x(2) circuit.measure(range(3), range(3)) print(backend.run(circuit, method=method, shots=100).result())
would print
{'010': 100}
as the nested control-flow operations would accidentally jump over the first X gate on qubit 2, which should have been executed. -
Fixes a bug where
NoiseModel.from_backend()
prints verbose warnings when supplying a backend that reports un-physical device parameters such as T2 > 2 * T1 due to statistical errors in their estimation. This commit removes such warnings because they are not actionable for users in the sense that there are no means other than truncating them to the theoretical bounds as done withinnoise.device
module. See Issue 1631 for details of the fixed bug. -
This is fix for GPU statevector simulator. Chunk distribution tried to allocate all free memory on GPU, but this causes memory allocation error. So this fix allocates 80 percent of free memory. Also this fixes size of matrix buffer when noise sampling is applied.
-
This is a fix of AerState running with cache blocking. AerState wrongly configured transpiler of Aer for cache blocking, and then its algorithm to swap qubits worked wrongly. This fix corrects AerState to use this transpiler. More specifically, After the transpilation, a swapped qubit map is recoverd to the original map when using AerState. This fix is necessary for AerStatevector to use multiple-GPUs.
-
This is fix for AerStatevector. It was not possible to create an AerStatevector instance directly from terra’s Statevector. This fix allows a Statevector as AerStatevector’s input.
-
SamplerResult.quasi_dists
contain the data about the number of qubits.QuasiDistribution.binary_probabilities()
returns bitstrings with correct length. -
Previously seed is not initialized in AerStatevector and then sampled results are always same. With this commit, a seed is initialized for each sampling and sampled results can be vary.
IBM Q Provider 0.19.2
No change
0.39.3
Terra 0.22.3
Prelude
Qiskit Terra 0.22.3 is a minor bugfix release, fixing some further bugs in the 0.22 series.
Bug Fixes
-
AdaptVQE
now correctly indicates that it supports auxiliary operators. -
The circuit drawers (
QuantumCircuit.draw()
andcircuit_drawer()
) will no longer emit a warning about thecregbundle
parameter when using the default arguments, if the content of the circuit requires all bits to be drawn individually. This was most likely to appear when trying to draw circuits with new-style control-flow operations. -
Fixed a bug causing
QNSPSA
to fail whenmax_evals_grouped
was set to a value larger than 1. -
Fixed an issue with the
SabreSwap
pass which would cause the output of multiple runs of the pass without theseed
argument specified to reuse the same random number generator seed between runs instead of using different seeds. This previously caused identical results to be returned between runs even when noseed
was specified. -
Fixed an issue with the primitive classes,
BackendSampler
andBackendEstimator
, where instances were not able to be serialized withpickle
. In general these classes are not guaranteed to be serializable asBackendV2
andBackendV1
instances are not required to be serializable (and often are not), but the class definitions ofBackendSampler
andBackendEstimator
no longer prevent the use ofpickle
. -
The
pulse.Instruction.draw()
method will now succeed, as before. This method is deprecated with no replacement planned, but it should still work for the period of deprecation.
Aer 0.11.1
No change
IBM Q Provider 0.19.2
No change
0.39.2
Terra 0.22.2
Prelude
Qiskit Terra 0.22.2 is a minor bugfix release, and marks the first official support for Python 3.11.
Bug Fixes
-
Fixed an issue with the backend primitive classes
BackendSampler
andBackendEstimator
which prevented running with aBackendV1
instance that does not have amax_experiments
field set in itsBackendConfiguration
. -
Fixed a bug in the
VF2PostLayout
pass when transpiling for backends with a definedTarget
, where the interaction graph would be built incorrectly. This could result in excessive runtimes due to the graph being far more complex than necessary. -
The Pulse expression parser should no longer periodically hang when called from Jupyter notebooks. This is achieved by avoiding an internal
deepycopy
of a recursive object that seemed to be particularly difficult for the memoization to evaluate.
Aer 0.11.1
No change
IBM Q Provider 0.19.2
No change
0.39.1
Terra 0.22.1
Prelude
Qiskit Terra 0.22.1 is a bugfix release, addressing some minor issues identified since the 0.22.0 release.
Deprecation Notes
- The
pauli_list
kwarg ofpauli_basis()
has been deprecated aspauli_basis()
now always returns aPauliList
. This argument was removed prematurely from Qiskit Terra 0.22.0 which broke compatibility for users that were leveraging thepauli_list``argument. Now, the argument has been restored but will emit a ``DeprecationWarning
when used. If used it has no effect because since Qiskit Terra 0.22.0 aPauliList
is always returned.
Bug Fixes
-
Fixed the
BarrierBeforeFinalMeasurements
transpiler pass when there are conditions on looseClbit
s immediately before the final measurement layer. Previously, this would fail claiming that the bit was not present in an internal temporary circuit. Fixed #8923 -
The equality checkers for
QuantumCircuit
andDAGCircuit
(with objects of the same type) will now correctly handle conditions on single bits. Previously, these would produce false negatives for equality, as the bits would use “exact” equality checks instead of the “semantic” checks the rest of the properties of circuit instructions get. -
Fixed handling of classical bits in
StochasticSwap
with control flow. Previously, control-flow operations would be expanded to contain all the classical bits in the outer circuit and not contracted again, leading to a mismatch between the numbers of clbits the instruction reported needing and the actual number supplied to it. Fixed #8903 -
Fixed handling of globally defined instructions for the
Target
class. Previously, two methods,operations_for_qargs()
andoperation_names_for_qargs()
would ignore/incorrectly handle any globally defined ideal operations present in the target. For example:from qiskit.transpiler import Target from qiskit.circuit.library import CXGate target = Target(num_qubits=5) target.add_instruction(CXGate()) names = target.operation_names_for_qargs((1, 2)) ops = target.operations_for_qargs((1, 2))
will now return
{"cx"}
fornames
and[CXGate()]
forops
instead of raising aKeyError
or an empty return. -
Fixed an issue in the
Target.add_instruction()
method where it would previously have accepted an argument with an invalid number of qubits as part of theproperties
argument. For example:from qiskit.transpiler import Target from qiskit.circuit.library import CXGate target = Target() target.add_instruction(CXGate(), {(0, 1, 2): None})
This will now correctly raise a
TranspilerError
instead of causing runtime issues when interacting with the target. Fixed #8914 -
Fixed an issue with the
plot_state_hinton()
visualization function which would result in a misplaced axis that was offset from the actual plot. Fixed #8446 <https://github.com/Qiskit/qiskit-terra/issues/8446> -
Fixed the output of the
plot_state_hinton()
function so that the state labels are ordered ordered correctly, and the image matches up with the natural matrix ordering. Fixed #8324 -
Fixed an issue with the primitive classes,
BackendSampler
andBackendEstimator
when running on backends that have a limited number of circuits in each job. Not all backends support an unlimited batch size (most hardware backends do not) and previously the backend primitive classes would have potentially incorrectly sent more circuits than the backend supported. This has been corrected so thatBackendSampler
andBackendEstimator
will chunk the circuits into multiple jobs if the backend has a limited number of circuits per job. -
Fixed an issue with the
BackendEstimator
class where previously setting a run option namedmonitor
to a value that evaluated asTrue
would have incorrectly triggered a job monitor that only worked on backends from theqiskit-ibmq-provider
package. This has been removed so that you can use amonitor
run option if needed without causing any issues. -
Fixed an issue with the
Target.build_coupling_map()
method where it would incorrectly returnNone
for aTarget
object with a mix of ideal globally available instructions and instructions that have qubit constraints. Now in such cases theTarget.build_coupling_map()
will return a coupling map for the constrained instruction (unless it’s a 2 qubit operation which will returnNone
because globally there is no connectivity constraint). Fixed #8971 -
Fixed an issue with the
Target.qargs
attribute where it would incorrectly returnNone
for aTarget
object that contained any globally available ideal instruction. -
Fixed the premature removal of the
pauli_list
keyword argument of thepauli_basis()
function which broke existing code using thepauli_list=True
future compatibility path on upgrade to Qiskit Terra 0.22.0. This keyword argument has been added back to the function and is now deprecated and will be removed in a future release. -
Fixed an issue in QPY serialization (
dump()
) when a customControlledGate
subclass that overloaded the_define()
method to provide a custom definition for the operation. Previously, this case of operation was not serialized correctly because it wasn’t accounting for using the potentially_define()
method to provide a definition. Fixes #8794 -
QPY deserialisation will no longer add extra
Clbit
instances to the circuit if there are both looseClbit
s in the circuit and moreQubit
s thanClbit
s. -
QPY deserialisation will no longer add registers named q and c if the input circuit contained only loose bits.
-
Fixed the
SparsePauliOp.dot()
method when run on two operators with real coefficients. To fix this, the dtype thatSparsePauliOp
can take is restricted tonp.complex128
andobject
. Fixed #8992 -
Fixed an issue in the
circuit_drawer()
function andQuantumCircuit.draw()
method where the only built-in style for thempl
output that was usable wasdefault
. If another built-in style, such asiqx
, were used then a warning about the style not being found would be emitted and the drawer would fall back to use thedefault
style. Fixed #8991 -
Fixed an issue with the
transpile()
where it would previously fail with aTypeError
if a customTarget
object was passed in via thetarget
argument and a list of multiple circuits were specified for thecircuits
argument. -
Fixed an issue with
transpile()
when targeting aTarget
(either directly via thetarget
argument or via aBackendV2
instance from thebackend
argument) that contained an idealMeasure
instruction (one that does not have any properties defined). Previously this would raise an exception trying to parse the target. Fixed #8969 -
Fixed an issue with the
VF2Layout
pass where it would error when running with aTarget
that had instructions that were missing error rates. This has been corrected so in such cases the lack of an error rate will be treated as an ideal implementation and if no error rates are present it will just select the first matching layout. Fixed #8970 -
Fixed an issue with the
VF2PostLayout
pass where it would error when running with aTarget
that had instructions that were missing. In such cases the lack of an error rate will be treated as an ideal implementation of the operation. -
Fixed an issue with the
VQD
class if more thank=2
eigenvalues were computed. Previously this would fail due to an internal type mismatch, but now runs as expected. Fixed #8982 -
Fixed a performance bug where the new primitive-based variational algorithms
minimum_eigensolvers.VQE
,eigensolvers.VQD
andSamplingVQE
did not batch energy evaluations per default, which resulted in a significant slowdown if a hardware backend was used. -
Zero-operand gates and instructions will now work with
circuit_to_gate()
,QuantumCircuit.to_gate()
,Gate.control()
, and the construction of anOperator
from aQuantumCircuit
containing zero-operand instructions. This edge case is occasionally useful in creating global-phase gates as part of larger compound instructions, though for many uses,QuantumCircuit.global_phase
may be more appropriate. -
Fixes issue where
Statevector.evolve()
andDensityMatrix.evolve()
would raise an exeception for nested subsystem evolution for non-qubit subsystems. Fixes issue #8897 -
Fixes bug in
Statevector.evolve()
where subsystem evolution will return the incorrect value in certain cases where there are 2 or more than non-evolved subsystems with different subsystem dimensions. Fixes issue #8899
Aer 0.11.1
Bug Fixes
-
Fixed a potential build error when trying to use CMake 3.18 or newer and building qiskit-aer with GPU support enabled. Since CMake 3.18 or later when building with CUDA the
CMAKE_CUDA_ARCHITECTURES
was required to be set with the architecture value for the target GPU. This has been corrected so that settingAER_CUDA_ARCH
will be used if this was not set. -
Fixes a bug in the handling of instructions with clbits in
LocalNoisePass
. Previously, it was accidentally erasing clbits of instructions (e.g. measures) to which the noise is applied in the case ofmethod="append"
. -
Fixed the performance overhead of the Sampler class when running with identical circuits on multiple executions. This was accomplished by skipping/caching the transpilation of these identical circuits on subsequent executions.
-
Fixed compatibility of the
Sampler
andEstimator
primitive classes with qiskit-terra 0.22.0 release. In qiskit-terra 0.22.0 breaking API changes were made to the abstract interface which broke compatibility with these classes, this has been addressed so thatSampler
andEstimator
can now be used with qiskit-terra >= 0.22.0.
IBM Q Provider 0.19.2
No change
0.39.0
This release also officially deprecates the Qiskit Aer project as part of the Qiskit metapackage. This means that in a future release pip install qiskit
will no longer include qiskit-aer
. If you’re currently installing or listing qiskit
as a dependency to get Aer you should upgrade this to explicitly list qiskit-aer
as well.
The qiskit-aer
project is still active and maintained moving forward but for the Qiskit metapackage (i.e. what gets installed via pip install qiskit
) the project is moving towards a model where the Qiskit package only contains the common core functionality for building and compiling quantum circuits, programs, and applications and packages that build on it or link Qiskit to hardware or simulators are separate packages.
Terra 0.22.0
Prelude
The Qiskit Terra 0.22.0 release is a major feature release that includes a myriad of new feature and bugfixes. The highlights for this release are:
- Adding initial support to the transpiler for transpiling
QuantumCircuit
objects that contain control flow instructions such asForLoopOp
andWhileLoopOp
.- Greatly improved scaling and performance for the
transpile()
function with large numbers of qubits, especially whenoptimization_level=3
is used.- External plugin interface for
transpile()
that enables external packages to implement stages for the default pass managers. More details on this can be found atqiskit.transpiler.preset_passmanagers.plugin
. Additionally,BackendV2
backends can now optionally set custom default plugins to use for the scheduling and translation stages.- Updated algorithm implementations in
qiskit.algorithms
that leverage theprimitives
classes that implement theBaseSampler
andBaseEstimator
.
New Features
-
Add support for representing an operation that has a variable width to the
Target
class. Previously, aTarget
object needed to have an instance ofOperation
defined for each operation supported in the target. This was used for both validation of arguments and parameters of the operation. However, for operations that have a variable width this wasn’t possible because each instance of anOperation
class can only have a fixed number of qubits. For cases where a backend supports variable width operations the instruction can be added with the class of the operation instead of an instance. In such cases the operation will be treated as globally supported on all qubits. For example, if building a target like:from qiskit.circuit import Parameter, Measure, IfElseOp, ForLoopOp, WhileLoopOp from qiskit.circuit.library import IGate, RZGate, SXGate, XGate, CXGate from qiskit.transpiler import Target, InstructionProperties theta = Parameter("theta") ibm_target = Target() i_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(IGate(), i_props) rz_props = { (0,): InstructionProperties(duration=0, error=0), (1,): InstructionProperties(duration=0, error=0), (2,): InstructionProperties(duration=0, error=0), (3,): InstructionProperties(duration=0, error=0), (4,): InstructionProperties(duration=0, error=0), } ibm_target.add_instruction(RZGate(theta), rz_props) sx_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(SXGate(), sx_props) x_props = { (0,): InstructionProperties(duration=35.5e-9, error=0.000413), (1,): InstructionProperties(duration=35.5e-9, error=0.000502), (2,): InstructionProperties(duration=35.5e-9, error=0.0004003), (3,): InstructionProperties(duration=35.5e-9, error=0.000614), (4,): InstructionProperties(duration=35.5e-9, error=0.006149), } ibm_target.add_instruction(XGate(), x_props) cx_props = { (3, 4): InstructionProperties(duration=270.22e-9, error=0.00713), (4, 3): InstructionProperties(duration=305.77e-9, error=0.00713), (3, 1): InstructionProperties(duration=462.22e-9, error=0.00929), (1, 3): InstructionProperties(duration=497.77e-9, error=0.00929), (1, 2): InstructionProperties(duration=227.55e-9, error=0.00659), (2, 1): InstructionProperties(duration=263.11e-9, error=0.00659), (0, 1): InstructionProperties(duration=519.11e-9, error=0.01201), (1, 0): InstructionProperties(duration=554.66e-9, error=0.01201), } ibm_target.add_instruction(CXGate(), cx_props) measure_props = { (0,): InstructionProperties(duration=5.813e-6, error=0.0751), (1,): InstructionProperties(duration=5.813e-6, error=0.0225), (2,): InstructionProperties(duration=5.813e-6, error=0.0146), (3,): InstructionProperties(duration=5.813e-6, error=0.0215), (4,): InstructionProperties(duration=5.813e-6, error=0.0333), } ibm_target.add_instruction(Measure(), measure_props) ibm_target.add_instruction(IfElseOp, name="if_else") ibm_target.add_instruction(ForLoopOp, name="for_loop") ibm_target.add_instruction(WhileLoopOp, name="while_loop")
The
IfElseOp
,ForLoopOp
, andWhileLoopOp
operations are globally supported for any number of qubits. This is then reflected by other calls in theTarget
API such asinstruction_supported()
:ibm_target.instruction_supported(operation_class=WhileLoopOp, qargs=(0, 2, 3, 4)) ibm_target.instruction_supported('if_else', qargs=(0, 1))
both return
True
. -
Added new primitive implementations,
BackendSampler
andBackendEstimator
, toqiskit.primitives
. Thes new primitive class implementation wrap aBackendV1
orBackendV2
instance as aBaseSampler
orBaseEstimator
respectively. The intended use case for these primitive implementations is to bridge the gap between providers that do not have native primitive implementations and use that provider’s backend with APIs that work with primitives. For example, theSamplingVQE
class takes aBaseSampler
instance to function. If you’d like to run that class with a backend from a provider without a native primitive implementation you can construct aBackendSampler
to do this:from qiskit.algorithms.minimum_eigensolvers import SamplingVQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import BackendSampler from qiskit.providers.fake_provider import FakeHanoi from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp backend = FakeHanoi() sampler = BackendSampler(backend=backend) operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12])) ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() sampling_vqe = SamplingVQE(sampler, ansatz, optimizer) result = sampling_vqe.compute_minimum_eigenvalue(operator) eigenvalue = result.eigenvalue
If you’re using a provider that has native primitive implementations (such as
qiskit-ibm-runtime
orqiskit-aer
) it is always a better choice to use that native primitive implementation instead ofBackendEstimator
orBackendSampler
as the native implementations will be much more efficient and/or do additional pre and post processing.BackendEstimator
andBackendSampler
are designed to be generic that can work with any backend that returnsCounts
in theirResults
which precludes additional optimization. -
Added a new algorithm class,
AdaptVQE
toqiskit.algorithms
This algorithm uses aqiskit.algorithms.minimum_eigensolvers.VQE
in combination with a pool of operators from which to build out anqiskit.circuit.library.EvolvedOperatorAnsatz
adaptively. For example:from qiskit.algorithms.minimum_eigensolvers import AdaptVQE, VQE from qiskit.algorithms.optimizers import SLSQP from qiskit.primitives import Estimator from qiskit.circuit.library import EvolvedOperatorAnsatz # get your Hamiltonian hamiltonian = ... # construct your ansatz ansatz = EvolvedOperatorAnsatz(...) vqe = VQE(Estimator(), ansatz, SLSQP()) adapt_vqe = AdaptVQE(vqe) result = adapt_vqe.compute_minimum_eigenvalue(hamiltonian)
-
The
BackendV2
class now has support for two new optional hook points enabling backends to inject custom compilation steps as part oftranspile()
andgenerate_preset_pass_manager()
. If aBackendV2
implementation includes the methodsget_scheduling_stage_plugin()
orget_translation_stage_plugin()
the transpiler will use the returned string as the default value for thescheduling_method
andtranslation_method
arguments. This enables backends to run additional custom transpiler passes when targetting that backend by leveraging the transpiler stageplugin
interface. For more details on how to use this see: Custom Transpiler Passes. -
Added a new keyword argument,
ignore_backend_supplied_default_methods
, to thetranspile()
function which can be used to disable a backend’s custom selection of a default method if the target backend hasget_scheduling_stage_plugin()
orget_translation_stage_plugin()
defined. -
Added a
label
parameter to theBarrier
class’s constructor and thebarrier()
method which allows a user to assign a label to an instance of theBarrier
directive. For visualizations generated withcircuit_drawer()
orQuantumCircuit.draw()
this label will be printed at the top of thebarrier
.from qiskit import QuantumCircuit circuit = QuantumCircuit(2) circuit.h(0) circuit.h(1) circuit.barrier(label="After H") circuit.draw('mpl')
-
Add new gates
CCZGate
,CSGate
, andCSdgGate
to the standard gates in the Circuit Library (qiskit.circuit.library
). -
Added
qiskit.algorithms.eigensolvers
package to include interfaces for primitive-enabled algorithms. This new module will eventually replace the previousqiskit.algorithms.eigen_solvers
. This new module contains an alternative implementation of theVQD
which instead of taking a backend orQuantumInstance
instead takes an instance ofBaseEstimator
, includingEstimator
,BackendEstimator
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
.For example, to use the new implementation with an instance of
Estimator
class:from qiskit.algorithms.eigensolvers import VQD from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Sampler, Estimator from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp h2_op = PauliSumOp(SparsePauliOp( ["II", "IZ", "ZI", "ZZ", "XX"], coeffs=[ -1.052373245772859, 0.39793742484318045, -0.39793742484318045, -0.01128010425623538, 0.18093119978423156, ], )) estimator = Estimator() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() fidelity = ComputeUncompute(Sampler()) vqd = VQD(estimator, fidelity, ansatz, optimizer, k=2) result = vqd.compute_eigenvalues(h2_op) eigenvalues = result.eigenvalues
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field. -
Added new algorithms to calculate state fidelities/overlaps for pairs of quantum circuits (that can be parametrized). Apart from the base class (
BaseStateFidelity
) which defines the interface, there is an implementation of the compute-uncompute method that leverages instances of theBaseSampler
primitive:qiskit.algorithms.state_fidelities.ComputeUncompute
.For example:
import numpy as np from qiskit.primitives import Sampler from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.circuit.library import RealAmplitudes sampler = Sampler(...) fidelity = ComputeUncompute(sampler) circuit = RealAmplitudes(2) values = np.random.random(circuit.num_parameters) shift = np.ones_like(values) * 0.01 job = fidelity.run([circuit], [circuit], [values], [values+shift]) fidelities = job.result().fidelities
-
Added a new module
qiskit.algorithms.gradients
that contains classes which are used to compute gradients using the primitive interfaces defined inqiskit.primitives
. There are 4 types of gradient classes: Finite Difference, Parameter Shift, Linear Combination of Unitary, and SPSA with implementations that either use an instance of theBaseEstimator
interface:or an instance of the
BaseSampler
interface:The estimator-based gradients compute the gradient of expectation values, while the sampler-based gradients return gradients of the measurement outcomes (also referred to as “probability gradients”).
For example:
estimator = Estimator(...) gradient = ParamShiftEstimatorGradient(estimator) job = gradient.run(circuits, observables, parameters) gradients = job.result().gradients
-
The
Grover
class has a new keyword argument,sampler
which is used to run the algorithm using an instance of theBaseSampler
interface to calculate the results. This new argument supersedes the thequantum_instance
argument and accordingly,quantum_instance
is pending deprecation and will be deprecated and subsequently removed in future releases.Example:
from qiskit import QuantumCircuit from qiskit.primitives import Sampler from qiskit.algorithms import Grover, AmplificationProblem sampler = Sampler() oracle = QuantumCircuit(2) oracle.cz(0, 1) problem = AmplificationProblem(oracle, is_good_state=["11"]) grover = Grover(sampler=sampler) result = grover.amplify(problem)
-
A new option,
"formatter.control.fill_waveform"
has been added to the pulse drawer (pulse_v2.draw()
andSchedule.draw()
) style sheets. This option can be used to remove the face color of pulses in the output visualization which allows for drawing pulses only with lines.For example:
from qiskit.visualization.pulse_v2 import IQXStandard my_style = IQXStandard( **{"formatter.control.fill_waveform": False, "formatter.line_width.fill_waveform": 2} ) my_sched.draw(style=my_style)
-
Added a new transpiler pass,
ResetAfterMeasureSimplification
, which is used to replace aReset
operation after aMeasure
with a conditionalXGate
. This pass can be used on backends where aReset
operation is performed by doing a measurement and then a conditional X gate so that this will remove the duplicate implicitMeasure
from theReset
operation. For example:from qiskit import QuantumCircuit from qiskit.transpiler.passes import ResetAfterMeasureSimplification qc = QuantumCircuit(1) qc.measure_all() qc.reset(0) qc.draw('mpl')
result = ResetAfterMeasureSimplification()(qc) result.draw('mpl')
-
Added a new supported value,
"reverse_linear"
for theentanglement
keyword argument to the constructor for theNLocal
circuit class. ForTwoLocal
circuits (which are subclassess ofNLocal
), ifentanglement_blocks="cx"
then usingentanglement="reverse_linear"
provides an equivalent n-qubit circuit asentanglement="full"
but with onlyCXGate
gates, instead of . -
ScheduleBlock
has been updated so that it can manage unassigned subroutine, in other words, to allow lazy calling of other programs. For example, this enables the following workflow:from qiskit import pulse with pulse.build() as prog: pulse.reference("x", "q0") with pulse.build() as xq0: pulse.play(Gaussian(160, 0.1, 40), pulse.DriveChannel(0)) prog.assign_references({("x", "q0"): xq0})
Now a user can create
prog
without knowing actual implementation of the reference("x", "q0")
, and assign it at a later time for execution. This improves modularity of pulse programs, and thus one can easily write a template pulse program relying on other calibrations.To realize this feature, the new pulse instruction (compiler directive)
Reference
has been added. This instruction is injected into the current builder scope when thereference()
command is used. All references defined in the current pulse program can be listed with thereferences
property.In addition, every reference is managed with a scope to ease parameter management.
scoped_parameters()
andsearch_parameters()
have been added toScheduleBlock
. See API documentation for more details. -
Added a new method
SparsePauliOp.argsort()
, which returns the composition of permutations in the order of sorting by coefficient and sorting by Pauli. By using theweight
keyword argument for the method the output can additionally be sorted by the number of non-identity terms in the Pauli, where the set of all Paulis of a given weight are still ordered lexicographically. -
Added a new method
SparsePauliOp.sort()
, which will first sort the coefficients using numpy’sargsort()
and then sort by Pauli, where the Pauli sort takes precedence. If the Pauli sort is the same, it will then be sorted by coefficient. By using theweight
keyword argument the output can additionally be sorted by the number of non-identity terms in the Pauli, where the set of all Paulis of a given weight are still ordered lexicographically. -
Added a new keyword argument,
wire_order
, to thecircuit_drawer()
function andQuantumCircuit.draw()
method which allows arbitrarily reordering both the quantum and classical bits in the output visualization. For example:from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister qr = QuantumRegister(4, "q") cr = ClassicalRegister(4, "c") cr2 = ClassicalRegister(2, "ca") circuit = QuantumCircuit(qr, cr, cr2) circuit.h(0) circuit.h(3) circuit.x(1) circuit.x(3).c_if(cr, 10) circuit.draw('mpl', cregbundle=False, wire_order=[2, 1, 3, 0, 6, 8, 9, 5, 4, 7])
-
Added support for the
CSGate
,CSdgGate
andCCZGate
classes to the constructor for the operator classCNOTDihedral
. The input circuits when creating aCNOTDihedral
operator will now support circuits using these gates. For example:from qiskit import QuantumCircuit from qiskit.quantum_info import CNOTDihedral qc = QuantumCircuit(2) qc.t(0) qc.cs(0, 1) qc.tdg(0) operator = CNOTDihedral(qc)
-
The amplitude estimation algorithm classes:
Now have a new keyword argument,
sampler
on their constructor that takes an instance of an object that implements theBaseSampler
interface includingBackendSampler
,Sampler
, or any provider implementations such as those as those present in qiskit-ibm-runtime and qiskit-aer. This provides an alternative to using thequantum_instance
argument to set the targetBackend
orQuantumInstance
to run the algorithm on. Using aQuantumInstance
is pending deprecation and will be deprecated in a future release. -
Added a new class,
BackendV2Converter
, which is used to wrap aBackendV1
instance in aBackendV2
interface. It enables you to have aBackendV2
instance from anyBackendV1
. This enables standardizing access patterns on the newerBackendV2
interface even if you still supportBackendV1
. -
Added a new function
convert_to_target()
which is used to take aBackendConfiguration
, and optionally aBackendProperties
andPulseDefaults
and create aTarget
object equivalent to the contents of those objects. -
qiskit.quantum_info.BaseOperator
subclasses (such asScalarOp
,SparsePauliOp
andPauliList
) can now be used with the built-in Pythonsum()
function. -
A new transpiler pass,
ConvertConditionsToIfOps
was added, which can be used to convert old-styleInstruction.c_if()
-conditioned instructions intoIfElseOp
objects. This is to help ease the transition from the old type to the new type for backends. For most users, there is no need to add this to your pass managers, and it is not included in any preset pass managers. -
Refactored gate commutativity analysis into a class
CommutationChecker
. This class allows you to check (based on matrix multiplication) whether two gates commute or do not commute, and to cache the results (so that a similar check in the future will no longer require matrix multiplication).For example we can now do:
from qiskit.circuit import QuantumRegister, CommutationChecker comm_checker = CommutationChecker() qr = QuantumRegister(4) res = comm_checker.commute(CXGate(), [qr[1], qr[0]], [], CXGate(), [qr[1], qr[2]], [])
As the two CX gates commute (the first CX gate is over qubits
qr[1]
andqr[0]
, and the second CX gate is over qubitsqr[1]
andqr[2]
), we will have thatres
isTrue
.This commutativity checking is over-conservative for conditional and parameterized gates, and may return
False
even when such gates commute. -
Added a new transpiler pass
CommutativeInverseCancellation
that cancels pairs of inverse gates exploiting commutation relations between gates. This pass is a generalization of the transpiler passInverseCancellation
as it detects a larger set of inverse gates, and as it takes commutativity into account. The pass also avoids some problems associated with the transpiler passCommutativeCancellation
.For example:
from qiskit.circuit import QuantumCircuit from qiskit.transpiler import PassManager from qiskit.transpiler.passes import CommutativeInverseCancellation circuit = QuantumCircuit(2) circuit.z(0) circuit.x(1) circuit.cx(0, 1) circuit.z(0) circuit.x(1) passmanager = PassManager(CommutativeInverseCancellation()) new_circuit = passmanager.run(circuit)
cancels the pair of self-inverse Z-gates, and the pair of self-inverse X-gates (as the relevant gates commute with the CX-gate), producing a circuit consisting of a single CX-gate.
The inverse checking is over-conservative for conditional and parameterized gates, and may not cancel some of such gates.
-
QuantumCircuit.compose()
will now accept an operand with classical bits if the base circuit has none itself. The pattern of composing a circuit with measurements onto a quantum-only circuit is now valid. For example:from qiskit import QuantumCircuit base = QuantumCircuit(3) terminus = QuantumCircuit(3, 3) terminus.measure_all() # This will now succeed, though it was previously a CircuitError. base.compose(terminus)
-
The
DAGCircuit
methodsdepth()
andsize()
have a newrecurse
keyword argument for use with circuits that contain control-flow operations (such asIfElseOp
,WhileLoopOp
, andForLoopOp
). By default this isFalse
and will raise an error if control-flow operations are present, to avoid poorly defined results. If set toTrue
, a proxy value that attempts to fairly weigh each control-flow block relative to its condition is returned, even though the depth or size of a concrete run is generally unknowable. See each method’s documentation for how each control-flow operation affects the output. -
DAGCircuit.count_ops()
gained arecurse
keyword argument for recursing into control-flow blocks. By default this isTrue
, and all operations in all blocks will be returned, as well as the control-flow operations themselves. -
Added an argument
create_preds_and_succs
to the functionscircuit_to_dagdependency()
anddag_to_dagdependency()
that convert fromQuantumCircuit
andDAGCircuit
, respectively, toDAGDependency
. When the value ofcreate_preds_and_succs
is False, the transitive predecessors and successors for nodes inDAGDependency
are not constructed, making the conversions faster and significantly less memory-intensive. The direct predecessors and successors for nodes inDAGDependency
are constructed as usual.For example:
from qiskit.converters import circuit_to_dagdependency from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit circuit_in = QuantumCircuit(2) circuit_in.h(qr[0]) circuit_in.h(qr[1]) dag_dependency = circuit_to_dagdependency(circuit_in, create_preds_and_succs=False)
-
Added new attributes
Clifford.symplectic_matrix
,Clifford.tableau
,Clifford.z
,Clifford.x
,Clifford.phase
,Clifford.stab
,Clifford.stab_z
,Clifford.stab_x
,Clifford.stab_phase
,Clifford.destab
,Clifford.destab_z
,Clifford.destab_x
,Clifford.destab_phase
to theClifford
class. These can be used instead ofClifford.table
, that will be deprecated in the future.StabilizerTable
andPauliTable
are pending deprecation and will be deprecated in the future release and subsequently removed after that. -
The
Commuting2qGateRouter
constructor now has a new keyword argument,edge_coloring
. This argument is used to provide an edge coloring of the coupling map to determine the order in which the commuting gates are applied. -
Added a new algorithms interface for creating time evolution algorithms using the primitives
BaseSampler
andBaseEstimator
. This new interface consists of:This new interface is an alternative to the previously existing time evolution algorithms interface available defined with
EvolutionProblem
,EvolutionResult
,RealEvolver
, andImaginaryEvolver
which worked with aQuantumInstance
object instead of primitives. This new interface supersedes the previous interface which will eventually be deprecated and subsequently removed in future releases. -
Added new backend classes to
qiskit.providers.fake_provider
:These new classes implement the
BackendV2
interface and are created using stored snapshots of the backend information from the IBM Quantum systemsibm_auckland
,ibm_oslo
,ibm_geneva
, andibm_perth
systems respectively. -
The
Z2Symmetries
class has two new methods,convert_clifford()
andtaper_clifford()
. These two methods are the two operations necessary for taperng an operator based on the Z2 symmetries in the object and were previously performed internally via thetaper()
method. However, these methods are now public methods of the class which can be called individually if needed. -
The runtime performance for conjugation of a long
PauliList
object by aClifford
using thePauliList.evolve()
has significantly improved. It will now run significantly faster than before. -
Added a new abstract class
ClassicalIOChannel
to theqiskit.pulse.channels
module. This class is used to represent classical I/O channels and differentiate these channels from other subclasses ofChannel
. This new class is the base class for theMemorySlot
,RegisterSlot
, andSnapshotChannel
classes. Accordingly, thepad()
canonicalization pulse transform inqiskit.pulse.transforms
will not introduce delays to any instances ofClassicalIOChannel
-
The
SabreSwap
transpiler pass has a new keyword argument on its constructor,trials
. Thetrials
argument is used to specify the number of random seed trials to attempt. The output from the SABRE algorithm can differ greatly based on the seed used for the random number.SabreSwap
will now run the algorithm withtrials
number of random seeds and pick the best (with the fewest swaps inserted). Iftrials
is not specified the pass will default to use the number of physical CPUs on the local system. -
The
SabreLayout
transpiler pass has a new keyword argument on its constructor,swap_trials
. Theswap_trials
argument is used to specify how many random seed trials to run on theSabreSwap
pass internally. It corresponds to thetrials
arugment on theSabreSwap
pass. When set, each iteration ofSabreSwap
will be run internallyswap_trials
times. Ifswap_trials
is not specified the will default to use the number of physical CPUs on the local system. -
Added a new function,
estimate_observables()
which uses an implementation of theBaseEstimator
interface (e.g.Estimator
,BackendEstimator
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
) to calculate the expectation values, their means and standard deviations from a list or dictionary of observables. This serves a similar purpose to the pre-existing functioneval_observables()
which performed the calculation using aQuantumInstance
object and has been superseded (and will be deprecated and subsequently removed in future releases) by this new function. -
Added a new
Operation
base class which provides a lightweight abstract interface for objects that can be put onQuantumCircuit
. This allows to store “higher-level” objects directly on a circuit (for instance,Clifford
objects), to directly combine such objects (for instance, to compose several consecutiveClifford
objects over the same qubits), and to synthesize such objects at run time (for instance, to synthesizeClifford
in a way that optimizes depth and/or exploits device connectivity). Previously, only subclasses ofqiskit.circuit.Instruction
could be put onQuantumCircuit
, but this interface has become unwieldy and includes too many methods and attributes for general-purpose objects.The new
Operation
interface includesname
,num_qubits
andnum_clbits
(in the future this may be slightly adjusted), but importantly does not includedefinition
(and thus does not tie synthesis to the object), does not includecondition
(this should be part of separate classical control flow), and does not includeduration
andunit
(as these are properties of the output of the transpiler).As of now,
Operation
includesGate
,Reset
,Barrier
,Measure
, and “higher-level” objects such asClifford
. This list of “higher-level” objects will grow in the future. -
A
Clifford
is now added to a quantum circuit as anOperation
, without first synthesizing a subcircuit implementing this Clifford. The actual synthesis is postponed to a laterHighLevelSynthesis
transpilation pass.For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford qc = QuantumCircuit(3) cliff = random_clifford(2) qc.append(cliff, [0, 1])
no longer converts
cliff
toqiskit.circuit.Instruction
, which includes synthesizing the clifford into a circuit, when it is appended toqc
. -
Added a new transpiler pass
OptimizeCliffords
that collects blocks of consecutiveClifford
objects in a circuit, and replaces each block with a singleClifford
.For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford from qiskit.transpiler.passes import OptimizeCliffords from qiskit.transpiler import PassManager qc = QuantumCircuit(3) cliff1 = random_clifford(2) cliff2 = random_clifford(2) qc.append(cliff1, [2, 1]) qc.append(cliff2, [2, 1]) qc_optimized = PassManager(OptimizeCliffords()).run(qc)
first stores the two Cliffords
cliff1
andcliff2
onqc
as “higher-level” objects, and then the transpiler passOptimizeCliffords
optimizes the circuit by composing these two Cliffords into a single Clifford. Note that the resulting Clifford is still stored onqc
as a higher-level object. This pass is not yet included in any of preset pass managers. -
Added a new transpiler pass
HighLevelSynthesis
that synthesizes higher-level objects (for instance,Clifford
objects).For example, the following code:
from qiskit import QuantumCircuit from qiskit.quantum_info import random_clifford from qiskit.transpiler import PassManager from qiskit.transpiler.passes import HighLevelSynthesis qc = QuantumCircuit(3) qc.h(0) cliff = random_clifford(2) qc.append(cliff, [0, 1]) qc_synthesized = PassManager(HighLevelSynthesis()).run(qc)
will synthesize the higher-level Clifford stored in
qc
using the defaultdecompose_clifford()
function.This new transpiler pass
HighLevelSynthesis
is integrated into the preset pass managers, running right afterUnitarySynthesis
pass. Thus,transpile()
will synthesize all higher-level Cliffords present in the circuit.It is important to note that the work done to store
Clifford
objects as “higher-level” objects and to transpile these objects usingHighLevelSynthesis
pass should be completely transparent, and no code changes are required. -
SparsePauliOp
s can now be constructed with coefficient arrays that are general Python objects. This is intended for use withParameterExpression
objects; other objects may work, but do not have first-class support. SomeSparsePauliOp
methods (such as conversion to other class representations) may not work when usingobject
arrays, if the desired target cannot represent these general arrays.For example, a
ParameterExpression
SparsePauliOp
could be constructed by:import numpy as np from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp print(SparsePauliOp(["II", "XZ"], np.array([Parameter("a"), Parameter("b")])))
which gives
SparsePauliOp(['II', 'XZ'], coeffs=[ParameterExpression(1.0*a), ParameterExpression(1.0*b)])
-
Added a new function
plot_distribution()
for plotting distributions over quasi-probabilities. This is suitable forCounts
,QuasiDistribution
andProbDistribution
. Raw dict can be passed as well. For example:from qiskit.visualization import plot_distribution quasi_dist = {'0': .98, '1': -.01} plot_distribution(quasi_dist)
-
Introduced a new high level synthesis plugin interface which is used to enable using alternative synthesis techniques included in external packages seamlessly with the
HighLevelSynthesis
transpiler pass. These alternative synthesis techniques can be specified for any “higher-level” objects of typeOperation
, as for example forClifford
andLinearFunction
objects. This plugin interface is similar to the one for unitary synthesis. In the latter case, the details on writing a new plugin appear in theqiskit.transpiler.passes.synthesis.plugin
module documentation. -
Introduced a new class
HLSConfig
which can be used to specify alternative synthesis algorithms for “higher-level” objects of typeOperation
. For each higher-level object of interest, an objectHLSConfig
specifies a list of synthesis methods and their arguments. This object can be passed toHighLevelSynthesis
transpiler pass or specified as a parameterhls_config
intranspile()
.As an example, let us assume that
op_a
andop_b
are names of two higher-level objects, thatop_a
-objects have two synthesis methodsdefault
which does require any additional parameters andother
with two optional integer parametersoption_1
andoption_2
, thatop_b
-objects have a single synthesis methoddefault
, andqc
is a quantum circuit containingop_a
andop_b
objects. The following code snippet:hls_config = HLSConfig(op_b=[("other", {"option_1": 7, "option_2": 4})]) pm = PassManager([HighLevelSynthesis(hls_config=hls_config)]) transpiled_qc = pm.run(qc)
shows how to run the alternative synthesis method
other
forop_b
-objects, while using thedefault
methods for all other high-level objects, includingop_a
-objects. -
Added new methods for executing primitives:
BaseSampler.run()
andBaseEstimator.run()
. These methods execute asynchronously and returnJobV1
objects which provide a handle to the exections. These new run methods can be passedQuantumCircuit
objects (and observables forBaseEstimator
) that are not registered in the constructor. For example:estimator = Estimator() result = estimator.run(circuits, observables, parameter_values).result()
This provides an alternative to the previous execution model (which is now deprecated) for the
BaseSampler
andBaseEstimator
primitives which would take all the inputs via the constructor and calling the primitive object with the combination of those input parameters to use in the execution. -
Added
shots
option for reference implementations of primitives. Random numbers can be fixed by givingseed_primitive
. For example:from qiskit.primitives import Sampler from qiskit import QuantumCircuit bell = QuantumCircuit(2) bell.h(0) bell.cx(0, 1) bell.measure_all() with Sampler(circuits=[bell]) as sampler: result = sampler(circuits=[0], shots=1024, seed_primitive=15) print([q.binary_probabilities() for q in result.quasi_dists])
-
The constructors for the
BaseSampler
andBaseEstimator
primitive classes have a new optional keyword argument,options
which is used to set the default values for the options exposed via theoptions
attribute. -
Added the
PVQD
class to the time evolution framework inqiskit.algorithms
. This class implements the projected Variational Quantum Dynamics (p-VQD) algorithm Barison et al..In each timestep this algorithm computes the next state with a Trotter formula and projects it onto a variational form. The projection is determined by maximizing the fidelity of the Trotter-evolved state and the ansatz, using a classical optimization routine.
import numpy as np from qiskit.algorithms.state_fidelities import ComputeUncompute from qiskit.algorithms.evolvers import EvolutionProblem from qiskit.algorithms.time_evolvers.pvqd import PVQD from qiskit.primitives import Estimator, Sampler from qiskit import BasicAer from qiskit.circuit.library import EfficientSU2 from qiskit.quantum_info import Pauli, SparsePauliOp from qiskit.algorithms.optimizers import L_BFGS_B sampler = Sampler() fidelity = ComputeUncompute(sampler) estimator = Estimator() hamiltonian = 0.1 * SparsePauliOp([Pauli("ZZ"), Pauli("IX"), Pauli("XI")]) observable = Pauli("ZZ") ansatz = EfficientSU2(2, reps=1) initial_parameters = np.zeros(ansatz.num_parameters) time = 1 optimizer = L_BFGS_B() # setup the algorithm pvqd = PVQD( fidelity, ansatz, initial_parameters, estimator, num_timesteps=100, optimizer=optimizer, ) # specify the evolution problem problem = EvolutionProblem( hamiltonian, time, aux_operators=[hamiltonian, observable] ) # and evolve! result = pvqd.evolve(problem)
-
The
QNSPSA.get_fidelity()
static method now supports an optionalsampler
argument which is used to provide an implementation of theBaseSampler
interface (such asSampler
,BackendSampler
, or any provider implementations such as those present inqiskit-ibm-runtime
andqiskit-aer
) to compute the fidelity of aQuantumCircuit
. For example:from qiskit.primitives import Sampler from qiskit.algorithms.optimizers import QNSPSA fidelity = QNSPSA.get_fidelity(my_circuit, Sampler())
-
Added a new keyword argument
sampler
to the constructors of the phase estimation classes:This argument is used to provide an implementation of the
BaseSampler
interface such asSampler
,BackendSampler
, or any provider implementations such as those as those present inqiskit-ibm-runtime
andqiskit-aer
.For example:
from qiskit.primitives import Sampler from qiskit.algorithms.phase_estimators import HamiltonianPhaseEstimation from qiskit.synthesis import MatrixExponential from qiskit.quantum_info import SparsePauliOp from qiskit.opflow import PauliSumOp sampler = Sampler() num_evaluation_qubits = 6 phase_est = HamiltonianPhaseEstimation( num_evaluation_qubits=num_evaluation_qubits, sampler=sampler ) hamiltonian = PauliSumOp(SparsePauliOp.from_list([("X", 0.5), ("Y", 0.6), ("I", 0.7)])) result = phase_est.estimate( hamiltonian=hamiltonian, state_preparation=None, evolution=MatrixExponential(), bound=1.05, )
-
The
SabreSwap
transpiler pass has significantly improved runtime performance due to a rewrite of the algorithm in Rust. -
Symbolic pulse subclasses
Gaussian
,GaussianSquare
,Drag
andConstant
have been upgraded to instantiateSymbolicPulse
rather than the subclass itself. All parametric pulse objects in pulse programs must be symbolic pulse instances, because subclassing is no longer neccesary. Note thatSymbolicPulse
can uniquely identify a particular envelope with the symbolic expression object defined inSymbolicPulse.envelope
. -
Added a new function,
sampled_expectation_value()
, that allows for computing expectation values for diagonal operators from distributions such asCounts
andQuasiDistribution
. Valid operators for use with this function are:str
,Pauli
,PauliOp
,PauliSumOp
, andSparsePauliOp
. -
A
SamplingVQE
class is introduced, which is optimized for diagonal hamiltonians and leverages asampler
primitive. AQAOA
class is also added that subclassesSamplingVQE
.To use the new
SamplingVQE
with a reference primitive, one can do, for example:from qiskit.algorithms.minimum_eigensolvers import SamplingVQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Sampler from qiskit.opflow import PauliSumOp from qiskit.quantum_info import SparsePauliOp operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12])) sampler = Sampler() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() sampling_vqe = SamplingVQE(sampler, ansatz, optimizer) result = sampling_vqe.compute_minimum_eigenvalue(operator) eigenvalue = result.eigenvalue
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field. -
Added a new
atol
keyword argument to theSparsePauliOp.equiv()
method to adjust to tolerance of the equivalence check, -
Introduced a new plugin interface for transpiler stages which is used to enable alternative
PassManager
objects from an external package in a particular stage as part oftranspile()
or theStagedPassManager
output fromgenerate_preset_pass_manager()
,level_0_pass_manager()
,level_1_pass_manager()
,level_2_pass_manager()
, andlevel_3_pass_manager()
. Users can select a plugin to use for a transpiler stage with theinit_method
,layout_method
,routing_method
,translation_method
,optimization_method
, andscheduling_method
keyword arguments ontranspile()
andgenerate_preset_pass_manager()
. A full list of plugin names currently installed can be found with thelist_stage_plugins()
function. For creating plugins refer to theqiskit.transpiler.preset_passmanagers.plugin
module documentation which includes a guide for writing stage plugins. -
The
transpile()
has two new keyword arguments,init_method
andoptimization_method
which are used to specify alternative plugins to use for theinit
stage andoptimization
stages respectively. -
The
PassManagerConfig
class has 2 new attributes,init_method
andoptimization_method
along with matching keyword arguments on the constructor methods. These represent the user specifiedinit
andoptimization
plugins to use for compilation. -
The
SteppableOptimizer
class is added. It allows one to perfore classical optimizations step-by-step using thestep()
method. These optimizers implement the “ask and tell” interface which (optionally) allows to manually compute the required function or gradient evaluations and plug them back into the optimizer. For more information about this interface see: ask and tell interface. A very simple use case when the user might want to do the optimization step by step is for readout:import random import numpy as np from qiskit.algorithms.optimizers import GradientDescent def objective(x): return (np.linalg.norm(x) - 1) ** 2 def grad(x): return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x) initial_point = np.random.normal(0, 1, size=(100,)) optimizer = GradientDescent(maxiter=20) optimizer.start(x0=initial_point, fun=objective, jac=grad) for _ in range(maxiter): state = optimizer.state # Here you can manually read out anything from the optimizer state. optimizer.step() result = optimizer.create_result()
A more complex case would be error handling. Imagine that the function you are evaluating has a random chance of failing. In this case you can catch the error and run the function again until it yields the desired result before continuing the optimization process. In this case one would use the ask and tell interface.
import random import numpy as np from qiskit.algorithms.optimizers import GradientDescent def objective(x): if random.choice([True, False]): return None else: return (np.linalg.norm(x) - 1) ** 2 def grad(x): if random.choice([True, False]): return None else: return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x) initial_point = np.random.normal(0, 1, size=(100,)) optimizer = GradientDescent(maxiter=20) optimizer.start(x0=initial_point, fun=objective, jac=grad) while optimizer.continue_condition(): ask_data = optimizer.ask() evaluated_gradient = None while evaluated_gradient is None: evaluated_gradient = grad(ask_data.x_center) optimizer.state.njev += 1 optmizer.state.nit += 1 cf = TellData(eval_jac=evaluated_gradient) optimizer.tell(ask_data=ask_data, tell_data=tell_data) result = optimizer.create_result()
Transitioned
GradientDescent
to be a subclass ofSteppableOptimizer
. -
The
subset_fitter
method is added to theTensoredMeasFitter
class. The implementation is restricted to mitigation patterns in which each qubit is mitigated individually, e.g.[[0], [1], [2]]
. This is, however, the most widely used case. It allows theTensoredMeasFitter
to be used in cases where the numberical order of the physical qubits does not match the index of the classical bit. -
Control-flow operations are now supported through the transpiler at optimization levels 0 and 1 (e.g. calling
transpile()
orgenerate_preset_pass_manager()
with keyword argumentoptimization_level=1
). One can now construct a circuit such asfrom qiskit import QuantumCircuit qc = QuantumCircuit(2, 1) qc.h(0) qc.measure(0, 0) with qc.if_test((0, True)) as else_: qc.x(1) with else_: qc.y(1)
and successfully transpile this, such as by:
from qiskit import transpile from qiskit_aer import AerSimulator backend = AerSimulator(method="statevector") transpiled = transpile(qc, backend)
The available values for the keyword argument
layout_method
are “trivial” and “dense”. Forrouting_method
, “stochastic” and “none” are available. Translation (translation_method
) can be done using “translator” or “unroller”. Optimization levels 2 and 3 are not yet supported with control flow, nor is circuit scheduling (i.e. providing a value toscheduling_method
), though we intend to expand support for these, and the other layout, routing and translation methods in subsequent releases of Qiskit Terra.In order for transpilation with control-flow operations to succeed with a backend, the backend must have the requisite control-flow operations in its stated basis. Qiskit Aer, for example, does this. If you simply want to try out such transpilations, consider overriding the
basis_gates
argument totranspile()
. -
The following transpiler passes have all been taught to understand control-flow constructs in the form of
ControlFlowOp
instructions in a circuit:Layout-related
ApplyLayout
DenseLayout
EnlargeWithAncilla
FullAncillaAllocation
SetLayout
TrivialLayout
VF2Layout
VF2PostLayout
Routing-related
Translation-related
BasisTranslator
ContainsInstruction
GatesInBasis
UnitarySynthesis
Unroll3qOrMore
UnrollCustomDefinitions
Unroller
Optimization-related
BarrierBeforeFinalMeasurements
Depth
FixedPoint
Size
Optimize1qGatesDecomposition
CXCancellation
RemoveResetInZeroState
These passes are most commonly used via the preset pass managers (those used internally by
transpile()
andgenerate_preset_pass_manager()
), but are also available for other uses. These passes will now recurse into control-flow operations where appropriate, updating or analysing the internal blocks. -
Added a new
TrotterQRTE
class that implements theRealTimeEvolver
interface that uses anqiskit.primitives.BaseEstimator
to perform the calculation. This new class supersedes the previously availableqiskit.algorithms.TrotterQRTE
class (which will be deprecated and subsequenty removed in future releases) that used aBackend
orQuantumInstance
to perform the calculation. -
DAGCircuit.substitute_node_with_dag()
now takespropagate_condition
as a keyword argument. This defaults toTrue
, which was the previous behavior, and copies any condition on the node to be replaced onto every operation node in the replacement. If set toFalse
, the condition will not be copied, which allows replacement of a conditional node with a sub-DAG that already faithfully implements the condition. -
DAGCircuit.substitute_node_with_dag()
can now take a mapping for itswires
parameter as well as a sequence. The mapping should map bits in the replacement DAG to the bits in the DAG it is being inserted into. This permits an easier style of construction for callers when the input node has both classical bits and a condition, and the replacement DAG may use these out-of-order. -
Added the
qiskit.algorithms.minimum_eigensolvers
package to include interfaces for primitive-enabled algorithms.VQE
has been refactored in this implementation to leverage primitives.To use the new implementation with a reference primitive, one can do, for example:
from qiskit.algorithms.minimum_eigensolvers import VQE from qiskit.algorithms.optimizers import SLSQP from qiskit.circuit.library import TwoLocal from qiskit.primitives import Estimator from qiskit.quantum_info import SparsePauliOp h2_op = SparsePauliOp( ["II", "IZ", "ZI", "ZZ", "XX"], coeffs=[ -1.052373245772859, 0.39793742484318045, -0.39793742484318045, -0.01128010425623538, 0.18093119978423156, ], ) estimator = Estimator() ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz") optimizer = SLSQP() vqe = VQE(estimator, ansatz, optimizer) result = vqe.compute_minimum_eigenvalue(h2_op) eigenvalue = result.eigenvalue
Note that the evaluated auxillary operators are now obtained via the
aux_operators_evaluated
field on the results. This will consist of a list or dict of tuples containing the expectation values for these operators, as we well as the metadata from primitive run.aux_operator_eigenvalues
is no longer a valid field.
Upgrade Notes
-
For
Target
objects that only contain globally defined 2 qubit operations without any connectivity constaints the return from theTarget.build_coupling_map()
method will now returnNone
instead of aCouplingMap
object that containsnum_qubits
nodes and no edges. This change was made to better reflect the actual connectivity constraints of theTarget
because in this case there are no connectivity constraints on the backend being modeled by theTarget
, not a lack of connecitvity. If you desire the previous behavior for any reason you can reproduce it by checking for aNone
return and manually building a coupling map, for example:from qiskit.transpiler import Target, CouplingMap from qiskit.circuit.library import CXGate target = Target(num_qubits=3) target.add_instruction(CXGate()) cmap = target.build_coupling_map() if cmap is None: cmap = CouplingMap() for i in range(target.num_qubits): cmap.add_physical_qubit(i)
-
The default value for the
entanglement
keyword argument on the constructor for theRealAmplitudes
andEfficientSU2
classes has changed from"full"
to"reverse_linear"
. This change was made because the output circuit is equivalent but uses only instead ofCXGate
gates. If you desire the previous default you can explicity setentanglement="full"
when calling either constructor. -
Added a validation check to
BaseSampler.run()
. It raises an error if there is no classical bit. -
Behavior of the
call()
pulse builder function has been upgraded. When aScheduleBlock
instance is called by this method, it internally creates aReference
in the current context, and immediately assigns the called program to the reference. Thus, theCall
instruction is no longer generated. Along with this change, it is prohibited to call different blocks with the samename
argument. Such operation will result in an error. -
For most architectures starting in the following release of Qiskit Terra, 0.23, the
tweedledum
package will become an optional dependency, instead of a requirement. This is currently used by some classical phase-oracle functions. If your application or library needs this functionality, you may want to prepare by addingtweedledum
to your package’s dependencies immediately.tweedledum
is no longer a requirement on macOS arm64 (M1) with immediate effect in Qiskit Terra 0.22. This is because the provided wheels for this platform are broken, and building from the sdist is not reliable for most people. If you manually install a working version oftweedledum
, all the dependent functionality will continue to work. -
The
._layout
attribute of theQuantumCircuit
object has been changed from storing aLayout
object to storing a data class with 2 attributes,initial_layout
which contains aLayout
object for the initial layout set during compilation andinput_qubit_mapping
which contains a dictionary mapping qubits to position indices in the original circuit. This change was necessary to provide all the information for a post-transpiled circuit to be able to fully reverse the permutation caused by initial layout in all situations. While this attribute is private and shouldn’t be used externally, it is the only way to track the initial layout throughtranspile()
so the change is being documented in case you’re relying on it. If you have a use case for the_layout
attribute that is not being addressed by the Qiskit API please open an issue so we can address this feature gap. -
The constructors for the
SetPhase
,ShiftPhase
,SetFrequency
, andShiftFrequency
classes will now raise aPulseError
if the value passed in via thechannel
argument is not an instance ofPulseChannel
. This change was made to validate the input to the constructors are valid as the instructions are only valid for pulse channels and not other types of channels. -
The
plot_histogram()
function has been modified to return an actual histogram of discrete binned values. The previous behavior for the function was despite the name to actually generate a visualization of the distribution of the input. Due to this disparity between the name of the function and the behavior the function behavior was changed so it’s actually generating a proper histogram of discrete data now. If you wish to preserve the previous behavior of plotting a probability distribution of the counts data you can leverage theplot_distribution()
to generate an equivalent graph. For example, the previous behavior ofplot_histogram({'00': 512, '11': 500})
can be re-created with:from qiskit.visualization import plot_distribution import matplotlib.pyplot as plt ax = plt.subplot() plot_distribution({'00': 512, '11': 500}, ax=ax) ax.set_ylabel('Probabilities')
-
The
qiskit.pulse.builder
contextsinline
andpad
have been removed. These were first deprecated in Terra 0.18.0 (July 2021). There is no replacement forinline
; one can simply write the pulses in the containing scope. Thepad
context manager has had no effect since it was deprecated. -
The output from the
SabreSwap
transpiler pass (including whenoptimization_level=3
orrouting_method
orlayout_method
are set to'sabre'
when callingtranspile()
) with a fixed seed value may change from previous releases. This is caused by a new random number generator being used as part of the rewrite of theSabreSwap
pass in Rust which significantly improved the performance. If you rely on having consistent output you can run the pass in an earlier version of Qiskit and leverageqiskit.qpy
to save the circuit and then load it using the current version. -
The
Layout.add()
behavior when not specifying aphysical_bit
has changed from previous releases. In previous releases, a new physical bit would be added based on the length of theLayout
object. For example if you had aLayout
with the physical bits 1 and 3 successive calls toadd()
would add physical bits 2, 4, 5, 6, etc. While if the physical bits were 2 and 3 then successive calls would add 4, 5, 6, 7, etc. This has changed so that insteadLayout.add()
will first add any missing physical bits between 0 and the max physical bit contained in theLayout
. So for the 1 and 3 example it now adds 0, 2, 4, 5 and for the 2 and 3 example it adds 0, 1, 4, 5 to theLayout
. This change was made for both increased predictability of the outcome, and also to fix a class of bugs caused by the unexpected behavior. As physical bits on a backend always are contiguous sequences from 0 to adding new bits when there are still unused physical bits could potentially cause the layout to use more bits than available on the backend. If you desire the previous behavior, you can specify the desired physical bit manually when callingLayout.add()
. -
The deprecated method
SparsePauliOp.table
attribute has been removed. It was originally deprecated in Qiskit Terra 0.19. Instead thepaulis()
method should be used. -
Support for returning a
PauliTable
from thepauli_basis()
function has been removed. Similarly, thepauli_list
argument on thepauli_basis()
function which was used to switch to aPauliList
(now the only return type) has been removed. This functionality was deprecated in the Qiskit Terra 0.19 release. -
The fake backend objects
FakeJohannesburg
,FakeJohannesburgV2
,FakeAlmaden
,FakeAlmadenV2
,FakeSingapore
, andFakeSingaporeV2
no longer contain the pulse defaults payloads. This means for theBackendV1
based classes theBackendV1.defaults()
method and pulse simulation viaBackendV1.run()
is no longer available. ForBackendV2
based classes thecalibration
property for instructions in theTarget
is no longer populated. This change was done because these systems had exceedingly large pulse defaults payloads (in total ~50MB) due to using sampled waveforms instead of parameteric pulse definitions. These three payload files took > 50% of the disk space required to install qiskit-terra. When weighed against the potential value of being able to compile with pulse awareness or pulse simulate these retired devices the file size is not worth the cost. If you require to leverage these properties you can leverage an older version of Qiskit and leverageqpy
to transfer circuits from older versions of qiskit into the current release. -
isinstance
check with pulse classesGaussian
,GaussianSquare
,Drag
andConstant
will be invalidated because these pulse subclasses are no longer instantiated. They will still work in Terra 0.22, but you should begin transitioning immediately. Instead of using type information,SymbolicPulse.pulse_type
should be used. This is assumed to be a unique string identifer for pulse envelopes, and we can use string equality to investigate the pulse types. For example,from qiskit.pulse.library import Gaussian pulse = Gaussian(160, 0.1, 40) if isinstance(pulse, Gaussian): print("This is Gaussian pulse.")
This code should be upgraded to
from qiskit.pulse.library import Gaussian pulse = Gaussian(160, 0.1, 40) if pulse.pulse_type == "Gaussian": print("This is Gaussian pulse.")
With the same reason, the class attributes such as
pulse.__class__.__name__
should not be accessed to get pulse type information. -
The exception
qiskit.exceptions.QiskitIndexError
has been removed and no longer exists as per the deprecation notice from qiskit-terra 0.18.0 (released on Jul 12, 2021). -
The deprecated arguments
epsilon
andfactr
for the constructor of theL_BFGS_B
optimizer class have been removed. These arguments were originally deprecated as part of the 0.18.0 release (released on July 12, 2021). Instead theftol
argument should be used, you can refer to the scipy docs on the optimizer for more detail on the relationship between these arguments. -
The preset pass managers for levels 1 and 2, which will be used when
optimization_level=1
oroptimization_level=2
withtranspile()
orgenerate_preset_pass_manager()
and output fromlevel_1_pass_manager()
andlevel_2_pass_manager()
, will now useSabreLayout
andSabreSwap
by default instead of the previous defaultsDenseLayout
andStochasticSwap
. This change was made to improve the output quality of the transpiler, theSabreLayout
andSabreSwap
combination typically results in fewerSwapGate
objects being inserted into the output circuit. If you would like to use the previous default passes you can setlayout_method='dense'
androuting_method='stochastic'
ontranspile()
orgenerate_preset_pass_manager()
to leverageDenseLayout
andStochasticSwap
respectively. -
The implicit use of
approximation_degree!=1.0
by default in in thetranspile()
function whenoptimization_level=3
is set has been disabled. The transpiler should, by default, preserve unitarity of the input up to known transformations such as one-sided permutations and similarity transformations. This was broken by the previous use ofapproximation_degree=None
leading to incorrect results in cases such as Trotterized evolution with many time steps where unitaries were being overly approximated leading to incorrect results. It was decided that transformations that break unitary equivalence should be explicitly activated by the user. If you desire the previous default behavior where synthesizedUnitaryGate
instructions are approximated up to the error rates of the target backend’s native instructions you can explicitly setapproximation_degree=None
when callingtranspile()
withoptimization_level=3
, for example:transpile(circuit, backend, approximation_degree=None, optimization_level=3)
-
Change the default of maximum number of allowed function evaluations (
maxfun
) inL_BFGS_B
from 1000 to 15000 to match the SciPy default. This number also matches the default number of iterations (maxiter
). -
Updated
ProbDistribution
andQuasiDistribution
to store the information of the number of bits if bitstrings without prefix “0b” are given.ProbDistribution.binary_probabilities()
andQuasiDistribution.binary_probabilities()
use the stored number of bits as the default value of the number of bits. -
RZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
have been upgraded to skip stretching CX gates implemented by non-echoed cross resonance (ECR) sequence to avoid termination of the pass with unexpected errors. These passes take new argumentverbose
that controls whether the passes warn when this occurs. Ifverbose=True
is set, pass raises user warning when it enconters non-ECR sequence. -
The visualization module
qiskit.visualization
has seen some internal reorganisation. This should not have affected the public interface, but if you were accessing any internals of the circuit drawers, they may now be in different places. The only parts of the visualization module that are considered public are the components that are documented in this online documentation.
Deprecation Notes
-
Importing the names
Int1
,Int2
,classical_function
andBooleanExpression
directly fromqiskit.circuit
is deprecated. This is part of the move to maketweedledum
an optional dependency rather than a full requirement. Instead, you should import these names fromqiskit.circuit.classicalfunction
. -
Modules
qiskit.algorithms.factorizers
andqiskit.algorithms.linear_solvers
are deprecated and will be removed in a future release. They are replaced by tutorials in the Qiskit Textbook: Shor HHL -
The
random_stabilizer_table()
has been deprecated and will be removed in a future release. Instead therandom_pauli_list()
function should be used. -
The pulse-module function
qiskit.pulse.utils.deprecated_functionality
is deprecated and will be removed in a future release. This was a primarily internal-only function. The same functionality is supplied byqiskit.utils.deprecate_function
, which should be used instead. -
The method of executing primitives has been changed. The
BaseSampler.__call__()
andBaseEstimator.__call__()
methods were deprecated. For example:estimator = Estimator(...) result = estimator(circuits, observables, parameters) sampler = Sampler(...) result = sampler(circuits, observables, parameters)
should be rewritten as
estimator = Estimator() result = estimator.run(circuits, observables, parameter_values).result() sampler = Sampler() result = sampler.run(circuits, parameter_values).result()
Using primitives as context managers is deprecated. Not all primitives have a context manager available. When available (e.g. in
qiskit-ibm-runtime
), the session’s context manager provides equivalent functionality.circuits
,observables
, andparameters
in the constructor was deprecated.circuits
andobservables
can be passed fromrun
methods.run
methods do not supportparameters
. Users need to resort parameter values by themselves. -
The unused argument
qubit_channel_mapping
in theRZXCalibrationBuilder
andRZXCalibrationBuilderNoEcho
transpiler passes have been deprecated and will be removed in a future release. This argument is no longer used and has no effect on the operation of the passes.
Bug Fixes
-
Fixed an issue where
Pauli.evolve()
andPauliList.evolve()
would raise a dtype error when evolving by certain Clifford gates which modified the Pauli’s phase. Fixed #8438 -
Fixed a bug in
QuantumCircuit.initialize()
andQuantumCircuit.prepare_state()
that caused them to not accept a singleQubit
as argument to initialize. -
The method
QuantumCircuit.while_loop()
will now resolve classical bit references in its condition in the same way thatQuantumCircuit.if_test()
andInstructionSet.c_if()
do. -
The
DAGCircuit
methodsdepth()
,size()
andDAGCircuit.count_ops()
would previously silently return results that had little-to-no meaning if control-flow was present in the circuit. Thedepth()
andsize()
methods will now correctly throw an error in these cases, but have a newrecurse
keyword argument to allow the calculation of a proxy value, whilecount_ops()
will by default recurse into the blocks and count the operations within them. -
Fixed an issue in the
DenseLayout
transpiler pass where any looseQubit
objects (i.e. not part of aQuantumRegister
) that were part of aQuantumCircuit
would not be included in the outputLayout
that was generated by the pass. -
The
Operator.from_circuit()
constructor method has been updated so that it can handle the layout output fromtranspile()
and correctly reverse the qubit permutation caused by layout in all cases. Previously, if your transpiled circuit used looseQubit
objects, multipleQuantumRegister
objects, or a singleQuantumRegister
with a name other than"q"
the constructor would have failed to create anOperator
from the circuit. Fixed #8800. -
Fixed a bug where decomposing an instruction with one qubit and one classical bit containing a single quantum gate failed. Now the following decomposes as expected:
block = QuantumCircuit(1, 1) block.h(0) circuit = QuantumCircuit(1, 1) circuit.append(block, [0], [0]) decomposed = circuit.decompose()
-
Fixed initialization of empty symplectic matrix in
from_symplectic()
inPauliList
class For example:from qiskit.quantum_info.operators import PauliList x = np.array([], dtype=bool).reshape((1,0)) z = np.array([], dtype=bool).reshape((1,0)) pauli_list = PauliList.from_symplectic(x, z)
-
Fix a problem in the
GateDirection
transpiler pass for theCZGate
. The CZ gate is symmetric, so flipping the qubit arguments is allowed to match the directed coupling map. -
Fixed issues with the
DerivativeBase.gradient_wrapper()
method when reusing a circuit sampler between the calls and binding nested parameters. -
Fixed an issue in the
mpl
andlatex
circuit drawers, when setting theidle_wires
option to False when there was abarrier
in the circuit would cause the drawers to fail, has been fixed. Fixed #8313 -
Fixed an issue in
circuit_drawer()
andQuantumCircuit.draw()
with thelatex
method where anOSError
would be raised on systems whose temporary directories (e.g/tmp
) are on a different filesystem than the working directory. Fixes #8542 -
Nesting a
FlowController
inside another in aPassManager
could previously cause some transpiler passes to become “forgotten” during transpilation, if the passes returned a newDAGCircuit
rather than mutating their input. NestedFlowController
s will now affect the transpilation correctly. -
Comparing
QuantumCircuit
andDAGCircuit
s for equality was previously non-deterministic if the circuits contained more than one register of the same type (e.g. two or moreQuantumRegister
s), sometimes returningFalse
even if the registers were identical. It will now correctly compare circuits with multiple registers. -
The OpenQASM 2 exporter (
QuantumCircuit.qasm()
) will now correctly define the qubit parameters forUnitaryGate
operations that do not affect all the qubits they are defined over. Fixed #8224. -
There were two bugs in the
text
circuit drawer that were fixed. These appeared whenvertical_compression
was set tomedium
, which is the default. The first would sometimes cause text to overwrite other text or gates, and the second would sometimes cause the connections between a gate and its controls to break. See #8588. -
Fixed an issue with the
UnitarySynthesis
pass where a circuit with 1 qubit gates and aTarget
input would sometimes fail instead of processing the circuit as expected. -
The
GateDirection
transpiler pass will now respect the available values for gate parameters when handling parametrised gates with aTarget
. -
Fixed an issue in the
SNOBFIT
optimizer class when an internal error would be raised during the execution of theminimize()
method if no input bounds where specified. This is now checked at call time to quickly raise aValueError
if required bounds are missing from theminimize()
call. Fixes #8580 -
Fixed an issue in the output callable from the
get_energy_evaluation()
method of theVQD
class will now correctly call the specifiedcallback
when run. Previously the callback would incorrectly not be used in this case. Fixed #8575 -
Fixed an issue when
circuit_drawer()
was used withreverse_bits=True
on a circuit without classical bits that would cause a potentially confusing warning aboutcregbundle
to be emitted. Fixed #8690 -
The OpenQASM 3 exporter (
qiskit.qasm3
) will now correctly handle OpenQASM built-ins (such asreset
andmeasure
) that have a classical condition applied byc_if()
. Previously the condition would have been ignored. -
Fixed an issue with the
SPSA
class where internally it was trying to batch jobs into even sized batches which would raise an exception if creating even batches was not possible. This has been fixed so it will always batch jobs successfully even if they’re not evenly sized. -
Fixed the behavior of
Layout.add()
which was potentially causing the output oftranspile()
to be invalid and contain more Qubits than what was available on the target backend. Fixed: #8667 -
Fixed an issue with the
state_to_latex()
function: passing a latex string to the optionalprefix
argument of the function would raise an error. Fixed #8460 -
The function
state_to_latex()
produced not valid LaTeX in presence of close-to-zero values, resulting in errors whenstate_drawer()
is called. Fixed #8169. -
GradientDescent
will now correctly count the number of iterations, function evaluations and gradient evaluations. Also the documentation now correctly states that the gradient is approximated by a forward finite difference method. -
Fix deprecation warnings in
NaturalGradient
, which now uses theStandardScaler
to scale the data before fitting the model if thenormalize
parameter is set toTrue
.
Aer 0.11.0
No change
IBM Q Provider 0.19.2
No change