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
BackendSamplerthat raised an error if itsrun()method was called two times sequentially. -
Fixed two bugs in the
ComposedOpwhere theComposedOp.to_matrix()method did not provide the correct results for compositions withStateFnand for compositions with a global coefficient. Fixed #9283. -
Fixed the problem in which primitives,
SamplerandEstimator, did not work when passed a circuit withnumpy.ndarrayas a parameter. -
Fixed a bug in
SamplingVQEwhere theaggregationargument 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
SamplingVQEevaluated the energies of eigenstates in a slow manner. -
Fixed the autoevaluation of the beta parameters in
VQD, added support forSparsePauliOpinputs, 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 theqargsargument was specified. Fixed #9210 -
Fixed handling of some
classmethods bywrap_method()in Python 3.11. Previously, in Python 3.11,wrap_methodwould wrap the unbound function associated with theclassmethodand then fail when invoked because the class object usually bound to theclassmethodwas 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 anAerSimulatorinstance from an aBackendV2object. Previously, attempting to useAerSimulator.from_backend()with aBackendV2object would have raised anAerErrorsaying this wasn’t supported. -
Fixes a bug where
NoiseModel.from_backend()with aBackendV2object may generate a noise model with excessiveQuantumErrors on non-Gate instructions while, for example, onlyReadoutErrors should be sufficient for measures. This commit updatesNoiseModel.from_backend()with aBackendV2object so that it returns the same noise model as that called with the correspondingBackendV1object. That is, the resulting noise model does not contain anyQuantumErrors on measures and it may contain only thermal relaxation errors on other non-gate instructions such as resets. Note that it still containsReadoutErrors on measures. -
Fixed a bug in
NoiseModel.from_backend()where using thetemperaturekwarg 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.devicemodule. 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_distscontain 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
-
AdaptVQEnow correctly indicates that it supports auxiliary operators. -
The circuit drawers (
QuantumCircuit.draw()andcircuit_drawer()) will no longer emit a warning about thecregbundleparameter 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
QNSPSAto fail whenmax_evals_groupedwas set to a value larger than 1. -
Fixed an issue with the
SabreSwappass which would cause the output of multiple runs of the pass without theseedargument 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 noseedwas specified. -
Fixed an issue with the primitive classes,
BackendSamplerandBackendEstimator, where instances were not able to be serialized withpickle. In general these classes are not guaranteed to be serializable asBackendV2andBackendV1instances are not required to be serializable (and often are not), but the class definitions ofBackendSamplerandBackendEstimatorno 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
BackendSamplerandBackendEstimatorwhich prevented running with aBackendV1instance that does not have amax_experimentsfield set in itsBackendConfiguration. -
Fixed a bug in the
VF2PostLayoutpass 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
deepycopyof 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_listkwarg 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 ``DeprecationWarningwhen used. If used it has no effect because since Qiskit Terra 0.22.0 aPauliListis always returned.
Bug Fixes
-
Fixed the
BarrierBeforeFinalMeasurementstranspiler pass when there are conditions on looseClbits 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
QuantumCircuitandDAGCircuit(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
StochasticSwapwith 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
Targetclass. 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"}fornamesand[CXGate()]foropsinstead of raising aKeyErroror 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 thepropertiesargument. 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
TranspilerErrorinstead 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/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,
BackendSamplerandBackendEstimatorwhen 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 thatBackendSamplerandBackendEstimatorwill chunk the circuits into multiple jobs if the backend has a limited number of circuits per job. -
Fixed an issue with the
BackendEstimatorclass where previously setting a run option namedmonitorto a value that evaluated asTruewould have incorrectly triggered a job monitor that only worked on backends from theqiskit-ibmq-providerpackage. This has been removed so that you can use amonitorrun option if needed without causing any issues. -
Fixed an issue with the
Target.build_coupling_map()method where it would incorrectly returnNonefor aTargetobject 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 returnNonebecause globally there is no connectivity constraint). Fixed #8971 -
Fixed an issue with the
Target.qargsattribute where it would incorrectly returnNonefor aTargetobject that contained any globally available ideal instruction. -
Fixed the premature removal of the
pauli_listkeyword argument of thepauli_basis()function which broke existing code using thepauli_list=Truefuture 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 customControlledGatesubclass 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
Clbitinstances to the circuit if there are both looseClbits in the circuit and moreQubits thanClbits. -
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 thatSparsePauliOpcan take is restricted tonp.complex128andobject. Fixed #8992 -
Fixed an issue in the
circuit_drawer()function andQuantumCircuit.draw()method where the only built-in style for themploutput 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 thedefaultstyle. Fixed #8991 -
Fixed an issue with the
transpile()where it would previously fail with aTypeErrorif a customTargetobject was passed in via thetargetargument and a list of multiple circuits were specified for thecircuitsargument. -
Fixed an issue with
transpile()when targeting aTarget(either directly via thetargetargument or via aBackendV2instance from thebackendargument) that contained an idealMeasureinstruction (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
VF2Layoutpass where it would error when running with aTargetthat 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
VF2PostLayoutpass where it would error when running with aTargetthat 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
VQDclass if more thank=2eigenvalues 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.VQDandSamplingVQEdid 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 anOperatorfrom aQuantumCircuitcontaining 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_phasemay 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_ARCHITECTURESwas required to be set with the architecture value for the target GPU. This has been corrected so that settingAER_CUDA_ARCHwill 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
SamplerandEstimatorprimitive 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 thatSamplerandEstimatorcan 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
QuantumCircuitobjects that contain control flow instructions such asForLoopOpandWhileLoopOp.- Greatly improved scaling and performance for the
transpile()function with large numbers of qubits, especially whenoptimization_level=3is 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,BackendV2backends can now optionally set custom default plugins to use for the scheduling and translation stages.- Updated algorithm implementations in
qiskit.algorithmsthat leverage theprimitivesclasses that implement theBaseSamplerandBaseEstimator.
New Features
-
Add support for representing an operation that has a variable width to the
Targetclass. Previously, aTargetobject needed to have an instance ofOperationdefined 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 anOperationclass 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, andWhileLoopOpoperations are globally supported for any number of qubits. This is then reflected by other calls in theTargetAPI 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,
BackendSamplerandBackendEstimator, toqiskit.primitives. Thes new primitive class implementation wrap aBackendV1orBackendV2instance as aBaseSamplerorBaseEstimatorrespectively. 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, theSamplingVQEclass takes aBaseSamplerinstance to function. If you’d like to run that class with a backend from a provider without a native primitive implementation you can construct aBackendSamplerto 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.eigenvalueIf you’re using a provider that has native primitive implementations (such as
qiskit-ibm-runtimeorqiskit-aer) it is always a better choice to use that native primitive implementation instead ofBackendEstimatororBackendSampleras the native implementations will be much more efficient and/or do additional pre and post processing.BackendEstimatorandBackendSamplerare designed to be generic that can work with any backend that returnsCountsin theirResultswhich precludes additional optimization. -
Added a new algorithm class,
AdaptVQEtoqiskit.algorithmsThis algorithm uses aqiskit.algorithms.minimum_eigensolvers.VQEin combination with a pool of operators from which to build out anqiskit.circuit.library.EvolvedOperatorAnsatzadaptively. 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
BackendV2class now has support for two new optional hook points enabling backends to inject custom compilation steps as part oftranspile()andgenerate_preset_pass_manager(). If aBackendV2implementation includes the methodsget_scheduling_stage_plugin()orget_translation_stage_plugin()the transpiler will use the returned string as the default value for thescheduling_methodandtranslation_methodarguments. This enables backends to run additional custom transpiler passes when targetting that backend by leveraging the transpiler stageplugininterface. 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
labelparameter to theBarrierclass’s constructor and thebarrier()method which allows a user to assign a label to an instance of theBarrierdirective. 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, andCSdgGateto the standard gates in the Circuit Library (qiskit.circuit.library). -
Added
qiskit.algorithms.eigensolverspackage 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 theVQDwhich instead of taking a backend orQuantumInstanceinstead takes an instance ofBaseEstimator, includingEstimator,BackendEstimator, or any provider implementations such as those as those present inqiskit-ibm-runtimeandqiskit-aer.For example, to use the new implementation with an instance of
Estimatorclass: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.eigenvaluesNote that the evaluated auxillary operators are now obtained via the
aux_operators_evaluatedfield 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_eigenvaluesis 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 theBaseSamplerprimitive: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.gradientsthat 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 theBaseEstimatorinterface:or an instance of the
BaseSamplerinterface: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
Groverclass has a new keyword argument,samplerwhich is used to run the algorithm using an instance of theBaseSamplerinterface to calculate the results. This new argument supersedes the thequantum_instanceargument and accordingly,quantum_instanceis 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 aResetoperation after aMeasurewith a conditionalXGate. This pass can be used on backends where aResetoperation is performed by doing a measurement and then a conditional X gate so that this will remove the duplicate implicitMeasurefrom theResetoperation. 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 theentanglementkeyword argument to the constructor for theNLocalcircuit class. ForTwoLocalcircuits (which are subclassess ofNLocal), ifentanglement_blocks="cx"then usingentanglement="reverse_linear"provides an equivalent n-qubit circuit asentanglement="full"but with onlyCXGategates, instead of . -
ScheduleBlockhas 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
progwithout 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)
Referencehas 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 thereferencesproperty.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 theweightkeyword 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 theweightkeyword 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,CSdgGateandCCZGateclasses to the constructor for the operator classCNOTDihedral. The input circuits when creating aCNOTDihedraloperator 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,
sampleron their constructor that takes an instance of an object that implements theBaseSamplerinterface 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_instanceargument to set the targetBackendorQuantumInstanceto run the algorithm on. Using aQuantumInstanceis pending deprecation and will be deprecated in a future release. -
Added a new class,
BackendV2Converter, which is used to wrap aBackendV1instance in aBackendV2interface. It enables you to have aBackendV2instance from anyBackendV1. This enables standardizing access patterns on the newerBackendV2interface even if you still supportBackendV1. -
Added a new function
convert_to_target()which is used to take aBackendConfiguration, and optionally aBackendPropertiesandPulseDefaultsand create aTargetobject equivalent to the contents of those objects. -
qiskit.quantum_info.BaseOperatorsubclasses (such asScalarOp,SparsePauliOpandPauliList) can now be used with the built-in Pythonsum()function. -
A new transpiler pass,
ConvertConditionsToIfOpswas added, which can be used to convert old-styleInstruction.c_if()-conditioned instructions intoIfElseOpobjects. 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 thatresisTrue.This commutativity checking is over-conservative for conditional and parameterized gates, and may return
Falseeven when such gates commute. -
Added a new transpiler pass
CommutativeInverseCancellationthat cancels pairs of inverse gates exploiting commutation relations between gates. This pass is a generalization of the transpiler passInverseCancellationas 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
DAGCircuitmethodsdepth()andsize()have a newrecursekeyword argument for use with circuits that contain control-flow operations (such asIfElseOp,WhileLoopOp, andForLoopOp). By default this isFalseand 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 arecursekeyword 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_succsto the functionscircuit_to_dagdependency()anddag_to_dagdependency()that convert fromQuantumCircuitandDAGCircuit, respectively, toDAGDependency. When the value ofcreate_preds_and_succsis False, the transitive predecessors and successors for nodes inDAGDependencyare not constructed, making the conversions faster and significantly less memory-intensive. The direct predecessors and successors for nodes inDAGDependencyare 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_phaseto theCliffordclass. These can be used instead ofClifford.table, that will be deprecated in the future.StabilizerTableandPauliTableare pending deprecation and will be deprecated in the future release and subsequently removed after that. -
The
Commuting2qGateRouterconstructor 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
BaseSamplerandBaseEstimator. 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, andImaginaryEvolverwhich worked with aQuantumInstanceobject 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
BackendV2interface and are created using stored snapshots of the backend information from the IBM Quantum systemsibm_auckland,ibm_oslo,ibm_geneva, andibm_perthsystems respectively. -
The
Z2Symmetriesclass 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
PauliListobject by aCliffordusing thePauliList.evolve()has significantly improved. It will now run significantly faster than before. -
Added a new abstract class
ClassicalIOChannelto theqiskit.pulse.channelsmodule. 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, andSnapshotChannelclasses. Accordingly, thepad()canonicalization pulse transform inqiskit.pulse.transformswill not introduce delays to any instances ofClassicalIOChannel -
The
SabreSwaptranspiler pass has a new keyword argument on its constructor,trials. Thetrialsargument 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.SabreSwapwill now run the algorithm withtrialsnumber of random seeds and pick the best (with the fewest swaps inserted). Iftrialsis not specified the pass will default to use the number of physical CPUs on the local system. -
The
SabreLayouttranspiler pass has a new keyword argument on its constructor,swap_trials. Theswap_trialsargument is used to specify how many random seed trials to run on theSabreSwappass internally. It corresponds to thetrialsarugment on theSabreSwappass. When set, each iteration ofSabreSwapwill be run internallyswap_trialstimes. Ifswap_trialsis 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 theBaseEstimatorinterface (e.g.Estimator,BackendEstimator, or any provider implementations such as those as those present inqiskit-ibm-runtimeandqiskit-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 aQuantumInstanceobject and has been superseded (and will be deprecated and subsequently removed in future releases) by this new function. -
Added a new
Operationbase 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,Cliffordobjects), to directly combine such objects (for instance, to compose several consecutiveCliffordobjects over the same qubits), and to synthesize such objects at run time (for instance, to synthesizeCliffordin a way that optimizes depth and/or exploits device connectivity). Previously, only subclasses ofqiskit.circuit.Instructioncould be put onQuantumCircuit, but this interface has become unwieldy and includes too many methods and attributes for general-purpose objects.The new
Operationinterface includesname,num_qubitsandnum_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 includedurationandunit(as these are properties of the output of the transpiler).As of now,
OperationincludesGate,Reset,Barrier,Measure, and “higher-level” objects such asClifford. This list of “higher-level” objects will grow in the future. -
A
Cliffordis now added to a quantum circuit as anOperation, without first synthesizing a subcircuit implementing this Clifford. The actual synthesis is postponed to a laterHighLevelSynthesistranspilation 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
clifftoqiskit.circuit.Instruction, which includes synthesizing the clifford into a circuit, when it is appended toqc. -
Added a new transpiler pass
OptimizeCliffordsthat collects blocks of consecutiveCliffordobjects 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
cliff1andcliff2onqcas “higher-level” objects, and then the transpiler passOptimizeCliffordsoptimizes the circuit by composing these two Cliffords into a single Clifford. Note that the resulting Clifford is still stored onqcas a higher-level object. This pass is not yet included in any of preset pass managers. -
Added a new transpiler pass
HighLevelSynthesisthat synthesizes higher-level objects (for instance,Cliffordobjects).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
qcusing the defaultdecompose_clifford()function.This new transpiler pass
HighLevelSynthesisis integrated into the preset pass managers, running right afterUnitarySynthesispass. Thus,transpile()will synthesize all higher-level Cliffords present in the circuit.It is important to note that the work done to store
Cliffordobjects as “higher-level” objects and to transpile these objects usingHighLevelSynthesispass should be completely transparent, and no code changes are required. -
SparsePauliOps can now be constructed with coefficient arrays that are general Python objects. This is intended for use withParameterExpressionobjects; other objects may work, but do not have first-class support. SomeSparsePauliOpmethods (such as conversion to other class representations) may not work when usingobjectarrays, if the desired target cannot represent these general arrays.For example, a
ParameterExpressionSparsePauliOpcould 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,QuasiDistributionandProbDistribution. 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
HighLevelSynthesistranspiler pass. These alternative synthesis techniques can be specified for any “higher-level” objects of typeOperation, as for example forCliffordandLinearFunctionobjects. 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.pluginmodule documentation. -
Introduced a new class
HLSConfigwhich can be used to specify alternative synthesis algorithms for “higher-level” objects of typeOperation. For each higher-level object of interest, an objectHLSConfigspecifies a list of synthesis methods and their arguments. This object can be passed toHighLevelSynthesistranspiler pass or specified as a parameterhls_configintranspile().As an example, let us assume that
op_aandop_bare names of two higher-level objects, thatop_a-objects have two synthesis methodsdefaultwhich does require any additional parameters andotherwith two optional integer parametersoption_1andoption_2, thatop_b-objects have a single synthesis methoddefault, andqcis a quantum circuit containingop_aandop_bobjects. 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
otherforop_b-objects, while using thedefaultmethods for all other high-level objects, includingop_a-objects. -
Added new methods for executing primitives:
BaseSampler.run()andBaseEstimator.run(). These methods execute asynchronously and returnJobV1objects which provide a handle to the exections. These new run methods can be passedQuantumCircuitobjects (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
BaseSamplerandBaseEstimatorprimitives 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
shotsoption 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
BaseSamplerandBaseEstimatorprimitive classes have a new optional keyword argument,optionswhich is used to set the default values for the options exposed via theoptionsattribute. -
Added the
PVQDclass 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 optionalsamplerargument which is used to provide an implementation of theBaseSamplerinterface (such asSampler,BackendSampler, or any provider implementations such as those present inqiskit-ibm-runtimeandqiskit-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
samplerto the constructors of the phase estimation classes:This argument is used to provide an implementation of the
BaseSamplerinterface such asSampler,BackendSampler, or any provider implementations such as those as those present inqiskit-ibm-runtimeandqiskit-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
SabreSwaptranspiler pass has significantly improved runtime performance due to a rewrite of the algorithm in Rust. -
Symbolic pulse subclasses
Gaussian,GaussianSquare,DragandConstanthave been upgraded to instantiateSymbolicPulserather than the subclass itself. All parametric pulse objects in pulse programs must be symbolic pulse instances, because subclassing is no longer neccesary. Note thatSymbolicPulsecan 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 asCountsandQuasiDistribution. Valid operators for use with this function are:str,Pauli,PauliOp,PauliSumOp, andSparsePauliOp. -
A
SamplingVQEclass is introduced, which is optimized for diagonal hamiltonians and leverages asamplerprimitive. AQAOAclass is also added that subclassesSamplingVQE.To use the new
SamplingVQEwith 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.eigenvalueNote that the evaluated auxillary operators are now obtained via the
aux_operators_evaluatedfield 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_eigenvaluesis no longer a valid field. -
Added a new
atolkeyword 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
PassManagerobjects from an external package in a particular stage as part oftranspile()or theStagedPassManageroutput 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_methodkeyword 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.pluginmodule documentation which includes a guide for writing stage plugins. -
The
transpile()has two new keyword arguments,init_methodandoptimization_methodwhich are used to specify alternative plugins to use for theinitstage andoptimizationstages respectively. -
The
PassManagerConfigclass has 2 new attributes,init_methodandoptimization_methodalong with matching keyword arguments on the constructor methods. These represent the user specifiedinitandoptimizationplugins to use for compilation. -
The
SteppableOptimizerclass 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
GradientDescentto be a subclass ofSteppableOptimizer. -
The
subset_fittermethod is added to theTensoredMeasFitterclass. 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 theTensoredMeasFitterto 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_methodare “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_gatesargument totranspile(). -
The following transpiler passes have all been taught to understand control-flow constructs in the form of
ControlFlowOpinstructions in a circuit:Layout-related
ApplyLayoutDenseLayoutEnlargeWithAncillaFullAncillaAllocationSetLayoutTrivialLayoutVF2LayoutVF2PostLayout
Routing-related
Translation-related
BasisTranslatorContainsInstructionGatesInBasisUnitarySynthesisUnroll3qOrMoreUnrollCustomDefinitionsUnroller
Optimization-related
BarrierBeforeFinalMeasurementsDepthFixedPointSizeOptimize1qGatesDecompositionCXCancellationRemoveResetInZeroState
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
TrotterQRTEclass that implements theRealTimeEvolverinterface that uses anqiskit.primitives.BaseEstimatorto perform the calculation. This new class supersedes the previously availableqiskit.algorithms.TrotterQRTEclass (which will be deprecated and subsequenty removed in future releases) that used aBackendorQuantumInstanceto perform the calculation. -
DAGCircuit.substitute_node_with_dag()now takespropagate_conditionas 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 itswiresparameter 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_eigensolverspackage to include interfaces for primitive-enabled algorithms.VQEhas 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.eigenvalueNote that the evaluated auxillary operators are now obtained via the
aux_operators_evaluatedfield 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_eigenvaluesis no longer a valid field.
Upgrade Notes
-
For
Targetobjects that only contain globally defined 2 qubit operations without any connectivity constaints the return from theTarget.build_coupling_map()method will now returnNoneinstead of aCouplingMapobject that containsnum_qubitsnodes and no edges. This change was made to better reflect the actual connectivity constraints of theTargetbecause 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 aNonereturn 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
entanglementkeyword argument on the constructor for theRealAmplitudesandEfficientSU2classes has changed from"full"to"reverse_linear". This change was made because the output circuit is equivalent but uses only instead ofCXGategates. 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 aScheduleBlockinstance is called by this method, it internally creates aReferencein the current context, and immediately assigns the called program to the reference. Thus, theCallinstruction is no longer generated. Along with this change, it is prohibited to call different blocks with the samenameargument. Such operation will result in an error. -
For most architectures starting in the following release of Qiskit Terra, 0.23, the
tweedledumpackage 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 addingtweedledumto your package’s dependencies immediately.tweedledumis 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
._layoutattribute of theQuantumCircuitobject has been changed from storing aLayoutobject to storing a data class with 2 attributes,initial_layoutwhich contains aLayoutobject for the initial layout set during compilation andinput_qubit_mappingwhich 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_layoutattribute 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, andShiftFrequencyclasses will now raise aPulseErrorif the value passed in via thechannelargument 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.buildercontextsinlineandpadhave 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. Thepadcontext manager has had no effect since it was deprecated. -
The output from the
SabreSwaptranspiler pass (including whenoptimization_level=3orrouting_methodorlayout_methodare 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 theSabreSwappass 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.qpyto save the circuit and then load it using the current version. -
The
Layout.add()behavior when not specifying aphysical_bithas changed from previous releases. In previous releases, a new physical bit would be added based on the length of theLayoutobject. For example if you had aLayoutwith 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.tableattribute has been removed. It was originally deprecated in Qiskit Terra 0.19. Instead thepaulis()method should be used. -
Support for returning a
PauliTablefrom thepauli_basis()function has been removed. Similarly, thepauli_listargument 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, andFakeSingaporeV2no longer contain the pulse defaults payloads. This means for theBackendV1based classes theBackendV1.defaults()method and pulse simulation viaBackendV1.run()is no longer available. ForBackendV2based classes thecalibrationproperty for instructions in theTargetis 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 leverageqpyto transfer circuits from older versions of qiskit into the current release. -
isinstancecheck with pulse classesGaussian,GaussianSquare,DragandConstantwill 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_typeshould 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.QiskitIndexErrorhas 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
epsilonandfactrfor the constructor of theL_BFGS_Boptimizer class have been removed. These arguments were originally deprecated as part of the 0.18.0 release (released on July 12, 2021). Instead theftolargument 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=1oroptimization_level=2withtranspile()orgenerate_preset_pass_manager()and output fromlevel_1_pass_manager()andlevel_2_pass_manager(), will now useSabreLayoutandSabreSwapby default instead of the previous defaultsDenseLayoutandStochasticSwap. This change was made to improve the output quality of the transpiler, theSabreLayoutandSabreSwapcombination typically results in fewerSwapGateobjects 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 leverageDenseLayoutandStochasticSwaprespectively. -
The implicit use of
approximation_degree!=1.0by default in in thetranspile()function whenoptimization_level=3is 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=Noneleading 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 synthesizedUnitaryGateinstructions are approximated up to the error rates of the target backend’s native instructions you can explicitly setapproximation_degree=Nonewhen 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_Bfrom 1000 to 15000 to match the SciPy default. This number also matches the default number of iterations (maxiter). -
Updated
ProbDistributionandQuasiDistributionto 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. -
RZXCalibrationBuilderandRZXCalibrationBuilderNoEchohave 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 argumentverbosethat controls whether the passes warn when this occurs. Ifverbose=Trueis set, pass raises user warning when it enconters non-ECR sequence. -
The visualization module
qiskit.visualizationhas 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_functionandBooleanExpressiondirectly fromqiskit.circuitis deprecated. This is part of the move to maketweedleduman optional dependency rather than a full requirement. Instead, you should import these names fromqiskit.circuit.classicalfunction. -
Modules
qiskit.algorithms.factorizersandqiskit.algorithms.linear_solversare 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_functionalityis 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, andparametersin the constructor was deprecated.circuitsandobservablescan be passed fromrunmethods.runmethods do not supportparameters. Users need to resort parameter values by themselves. -
The unused argument
qubit_channel_mappingin theRZXCalibrationBuilderandRZXCalibrationBuilderNoEchotranspiler 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 singleQubitas 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
DAGCircuitmethodsdepth(),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 newrecursekeyword 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
DenseLayouttranspiler pass where any looseQubitobjects (i.e. not part of aQuantumRegister) that were part of aQuantumCircuitwould not be included in the outputLayoutthat 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 looseQubitobjects, multipleQuantumRegisterobjects, or a singleQuantumRegisterwith a name other than"q"the constructor would have failed to create anOperatorfrom 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()inPauliListclass 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
GateDirectiontranspiler 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
mplandlatexcircuit drawers, when setting theidle_wiresoption to False when there was abarrierin the circuit would cause the drawers to fail, has been fixed. Fixed #8313 -
Fixed an issue in
circuit_drawer()andQuantumCircuit.draw()with thelatexmethod where anOSErrorwould be raised on systems whose temporary directories (e.g/tmp) are on a different filesystem than the working directory. Fixes #8542 -
Nesting a
FlowControllerinside another in aPassManagercould previously cause some transpiler passes to become “forgotten” during transpilation, if the passes returned a newDAGCircuitrather than mutating their input. NestedFlowControllers will now affect the transpilation correctly. -
Comparing
QuantumCircuitandDAGCircuits for equality was previously non-deterministic if the circuits contained more than one register of the same type (e.g. two or moreQuantumRegisters), sometimes returningFalseeven 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 forUnitaryGateoperations that do not affect all the qubits they are defined over. Fixed #8224. -
There were two bugs in the
textcircuit drawer that were fixed. These appeared whenvertical_compressionwas 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
UnitarySynthesispass where a circuit with 1 qubit gates and aTargetinput would sometimes fail instead of processing the circuit as expected. -
The
GateDirectiontranspiler pass will now respect the available values for gate parameters when handling parametrised gates with aTarget. -
Fixed an issue in the
SNOBFIToptimizer 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 aValueErrorif required bounds are missing from theminimize()call. Fixes #8580 -
Fixed an issue in the output callable from the
get_energy_evaluation()method of theVQDclass will now correctly call the specifiedcallbackwhen run. Previously the callback would incorrectly not be used in this case. Fixed #8575 -
Fixed an issue when
circuit_drawer()was used withreverse_bits=Trueon a circuit without classical bits that would cause a potentially confusing warning aboutcregbundleto be emitted. Fixed #8690 -
The OpenQASM 3 exporter (
qiskit.qasm3) will now correctly handle OpenQASM built-ins (such asresetandmeasure) that have a classical condition applied byc_if(). Previously the condition would have been ignored. -
Fixed an issue with the
SPSAclass 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 optionalprefixargument 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. -
GradientDescentwill 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 theStandardScalerto scale the data before fitting the model if thenormalizeparameter is set toTrue.
Aer 0.11.0
No change
IBM Q Provider 0.19.2
No change