Qiskit 0.34 release notes
0.34.2
Terra 0.19.2
Prelude
Qiskit Terra 0.19.2 is predominantly a bugfix release, but also now comes with wheels built for Python 3.10 on all major platforms.
New Features
- Added support for running with Python 3.10. This includes publishing precompiled binaries to PyPI for Python 3.10 on supported platforms.
Upgrade Notes
- Starting from Python 3.10, Qiskit Terra will have reduced support for 32-bit platforms. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: https://qiskit.org/documentation/getting_started.html#platform-support) This is because the upstream dependencies Numpy and Scipy have dropped support for them. Qiskit will still publish precompiled binaries for these platforms, but we’re unable to test the packages prior to publishing, and you will need a C/C++ compiler so that
pip
can build their dependencies from source. If you’re using one of these platforms, we recommended that you use Python 3.7, 3.8, or 3.9.
Bug Fixes
-
Fixed a bug where the
CVaRMeasurement
attempted to convert aPauliSumOp
to a dense matrix to check whether it were diagonal. For large operators (> 16 qubits) this computation was extremely expensive and raised an error if not explicitly enabled usingqiskit.utils.algorithm_globals.massive = True
. The check is now efficient even for large numbers of qubits. -
DAGCircuit.draw()
and the associated functiondag_drawer()
will now show a more useful error message when the provided filename is not valid. -
QuantumCircuit.add_register()
will no longer cause duplicateAncillaQubit
references in a circuit when given anAncillaRegister
whose bits are already present. -
Fixed conversion of
QuantumCircuit
s with classical conditions on single, registerlessClbit
s toInstruction
s when using thecircuit_to_instruction()
function or theQuantumCircuit.to_instruction()
method. For example, the following will now work:from qiskit.circuit import QuantumCircuit, Qubit, Clbit qc = QuantumCircuit([Qubit(), Clbit()]) qc.h(0).c_if(qc.clbits[0], 0) qc.to_instruction()
-
Registers will now correctly reject duplicate bits. Fixed #7446.
-
The
FakeOpenPulse2Q
mock backend now has T2 times and readout errors stored for its qubits. These are arbitrary values, approximately consistent with real backends at the time of its creation. -
Fix the qubit order of 2-qubit evolutions in the
PauliEvolutionGate
, if used with a product formula synthesis. For instance, before, the evolution ofIIZ + IZI + IZZ
from qiskit.circuit.library import PauliEvolutionGate from qiskit.opflow import I, Z operator = (I ^ I ^ Z) + (I ^ Z ^ I) + (I ^ Z ^ Z) print(PauliEvolutionGate(operator).definition.decompose())
produced
┌───────┐ q_0: ┤ Rz(2) ├──────── ├───────┤ q_1: ┤ Rz(2) ├─■────── └───────┘ │ZZ(2) q_2: ──────────■──────
whereas now it correctly yields
┌───────┐ q_0: ┤ Rz(2) ├─■────── ├───────┤ │ZZ(2) q_1: ┤ Rz(2) ├─■────── └───────┘ q_2: ─────────────────
-
Fixed a problem in the
latex
andmpl
circuit drawers when register names with multiple underscores in the name did not display correctly. -
Negative numbers in array outputs from the drawers will now appear as decimal numbers instead of fractions with huge numerators and denominators. Like positive numbers, they will still be fractions if the ratio is between small numbers.
-
Fixed an issue with the
Target.get_non_global_operation_names()
method when running on a target incorrectly raising an exception on targets with ideal global operations. Previously, if this method was called on a target that contained any ideal globally defined operations, where the instruction properties are set toNone
, this method would raise an exception instead of treating that instruction as global. -
Fixed an issue with the
transpile()
function where it could fail when being passed aTarget
object directly with thetarget
kwarg. -
Fixed an issue with the
transpile()
function where it could fail when thebackend
argument was aBackendV2
or aTarget
via thetarget
kwarg that contained ideal globally defined operations. -
Fixed an issue where plotting Bloch spheres could cause an
AttributeError
to be raised in Jupyter or when trying to crop figures down to size with Matplotlib 3.3 or 3.4 (but not 3.5). For example, the following code would previously crash with a message:AttributeError: 'Arrow3D' object has no attribute '_path2d'
but will now succeed with all current supported versions of Matplotlib:
from qiskit.visualization import plot_bloch_vector plot_bloch_vector([0, 1, 0]).savefig("tmp.png", bbox_inches='tight')
-
Fixed a bug in
PauliSumOp.permute()
where the object on which the method is called was permuted in-place, instead of returning a permuted copy. This bug only occured for permutations that left the number of qubits in the operator unchanged. -
Fixed the
PauliEvolutionGate.inverse()
method, which previously computed the inverse by inverting the evolution time. This was only the correct inverse if the operator was evolved exactly. In particular, this led to the inverse of Trotterization-based time evolutions being incorrect. -
The
QuantumInstance.execute()
method will no longer mutate its input if it is given a list of circuits. -
Fixed QPY serialisation of custom instructions which had an explicit no-op definition. Previously these would be written and subsequently read the same way as if they were opaque gates (with no given definition). They will now correctly round-trip an empty definition. For example, the following will now be correct:
import io from qiskit.circuit import Instruction, QuantumCircuit, qpy_serialization # This instruction is explicitly defined as a one-qubit gate with no # operations. empty = QuantumCircuit(1, name="empty").to_instruction() # This instruction will perform some operations that are only known # by the hardware backend. opaque = Instruction("opaque", 1, 0, []) circuit = QuantumCircuit(2) circuit.append(empty, [0], []) circuit.append(opaque, [1], []) qpy_file = io.BytesIO() qpy_serialization.dump(circuit, qpy_file) qpy_file.seek(0) new_circuit = qpy_serialization.load(qpy_file)[0] # Previously both instructions in `new_circuit` would now be opaque, but # there is now a correct distinction. circuit == new_circuit
-
Added a missing
BackendV2.provider
attribute to implementations of theBackendV2
abstract class. Previously,BackendV2
backends could be initialized with a provider but that was not accessible to users. -
Fixed support for the
QuantumInstance
class when running with aBackendV2
backend. Previously, attempting to use aQuantumInstance
with aBackendV2
would have resulted in an error. -
Fixed a bug in
VQE
where the parameters of the ansatz were still explicitly ASCII-sorted by their name if the ansatz was resized. This led to a mismatched order of the optimized values in theoptimal_point
attribute of the result object.In particular, this bug occurred if no ansatz was set by the user and the VQE chose a default with 11 or more free parameters.
-
Stopped the parser in
QuantumCircuit.from_qasm_str()
andfrom_qasm_file()
from accepting OpenQASM programs that identified themselves as being from a language version other than 2.0. This parser is only for OpenQASM 2.0; support for imported circuits from OpenQASM 3.0 will be added in an upcoming release. -
Fixed QPY serialization of
QuantumCircuit
objects that contained control flow instructions. Previously if you attempted to serialize a circuit containingIfElseOp
,WhileLoopOp
, orForLoopOp
the serialization would fail. Fixed #7583. -
Fixed QPY serialization of
QuantumCircuit
containing subsets of bits from aQuantumRegister
orClassicalRegister
. Previously if you tried to serialize a circuit like this it would incorrectly treat these bits as standaloneQubit
orClbit
without having a register set. For example, if you try to serialize a circuit like:import io from qiskit import QuantumCircuit, QuantumRegister from qiskit.circuit.qpy_serialization import load, dump qr = QuantumRegister(2) qc = QuantumCircuit([qr[0]]) qc.x(0) with open('file.qpy', 'wb') as fd: dump(qc, fd)
when that circuit is loaded now the registers will be correctly populated fully even though the circuit only contains a subset of the bits from the register.
-
QFT
will now warn if it is instantiated or built with settings that will cause it to lose precision, rather than raising anOverflowError
. This can happen if the number of qubits is very large (slightly over 1000) without the approximation degree being similarly large. The circuit will now build successfully, but some angles might be indistinguishable from zero, due to limitations in double-precision floating-point numbers.
Aer 0.10.3
Prelude
Qiskit Aer 0.10.3 is mainly a bugfix release, fixing several bugs that have been discovered since the 0.10.2 release. Howver, this release also introduces support for running with Python 3.10 including precompiled binary wheels on all major platforms. This release also includes precompiled binary wheels for arm64 on macOS.
New Features
-
Added support for running with Python 3.10. This includes publishing precompiled binaries to PyPI for Python 3.10 on supported platforms.
-
Added support for M1 macOS systems. Precompiled binaries for supported Python versions >=3.8 on arm64 macOS will now be published on PyPI for this and future releases.
Upgrade Notes
- Qiskit Aer no longer fully supports 32 bit platforms on Python >= 3.10. These are Linux i686 and 32-bit Windows. These platforms with Python 3.10 are now at Tier 3 instead of Tier 2 support (per the tiers defined in: https://qiskit.org/documentation/getting_started.html#platform-support) This is because the upstream dependencies Numpy and Scipy have dropped support for them. Qiskit will still publish precompiled binaries for these platforms, but we’re unable to test the packages prior to publishing, and you will need a C/C++ compiler so that
pip
can build their dependencies from source. If you’re using one of these platforms, we recommended that you use Python 3.7, 3.8, or 3.9.
Bug Fixes
-
Fixes a bug in
RelaxationNoisePass
where instruction durations were always assumed to be in dt time units, regardless of the actual unit of the isntruction. Now unit conversion is correctly handled for all instruction duration units.See #1453 for details.
-
Fixes an issue with
LocalNoisePass
for noise functions that return aQuantumCircuit
for the noise op. These were appended to the DAG as an opaque circuit instruction that must be unrolled to be simulated. This fix composes them so that the cirucit instructions are added to the new DAG and can be simulated without additional unrolling if all circuit instructions are supported by the simulator.See #1447 for details.
-
Multi-threaded transpilations to generate diagonal gates will now work correctly if the number of gates of a circuit exceeds
fusion_parallelization_threshold
. Previously, different threads would occasionally fuse the same element into multiple blocks, causing incorrect results. -
Fixes a bug with truncation of circuits in parameterized Qobjs. Previously parameters of parameterized QObj could be wrongly resolved if unused qubits of their circuits were truncated, because indices of the parameters were not updated after the instructions on unmeasured qubits were removed.
See #1427 for details.
Ignis 0.7.0
No change
IBM Q Provider 0.18.3
No change
0.34.1
Terra 0.19.1
No change
Aer 0.10.2
Bug Fixes
-
Fixed simulation of
for
loops where the loop parameter was not used in the body of the loop. For example, previously this code would fail, but will now succeed:import qiskit from qiskit.providers.aer import AerSimulator qc = qiskit.QuantumCircuit(2) with qc.for_loop(range(4)) as i: qc.h(0) qc.cx(0, 1) AerSimulator(method="statevector").run(qc)
-
Fixes a bug in
QuantumError.to_dict()
where N-qubit circuit instructions where the assembled instruction always applied to qubits[0, ..., N-1]
rather than the instruction qubits. This bug also affected device and fake backend noise models.See Issue 1415 for details.
Ignis 0.7.0
No change
IBM Q Provider 0.18.3
No change
0.34.0
Qiskit 0.34.0 includes a point release of Qiskit Aer: version 0.10.1, which patches performance regressions in version 0.10.0 that were discovered immediately post-release. See below for the release notes for both Qiskit Aer 0.10.0 and 0.10.1.
Terra 0.19.1
No change
Aer 0.10.1
Prelude
The Qiskit Aer 0.10.1 patch fixes performance regressions introduced in Qiskit Aer 0.10.0.
Bug Fixes
- Fix performance regression in noisy simulations due to large increase in serialization overhead for loading noise models from Python into C++ resulting from unintended nested Python multiprocessing calls. See issue 1407 for details.
Aer 0.10.0
Prelude
The Qiskit Aer 0.10 release includes several performance and noise model improvements. Some highlights are:
- Improved performance for parallel shot GPU and HPC simulations
- Support for simulation of circuits containing QASM 3.0 control-flow instructions
- Support for relaxation noise on scheduled circuits in backend noise models
- Support of user-created transpiler passes for defining custom gate errors and noise models, and inserting them into circuits.
New Features
-
Added support of QASM 3.0 control-flow instructions introduced in Qiskit-Terra 0.19.0. Supported instructions are
ForLoopOp
,WhileLoopOp
,ContinueLoopOp
,BreakLoopOp
,IfElseOp
. -
Added a batched-shot simulation optimization for GPU simulations. This optional feature will use available memory on 1 or more GPUs to run multiple simulation shots in parallel for greatly improved performance on multi-shot simulations with noise models and/or intermediate measurements.
This option is enabled by default when using
device="GPU"
and a simulationmethod
of either"statevector"
or"density_matrix"
with theAerSimulator
. It can be disabled by settingbatched_shots_gpu=False
in the simulator options.This optimization is most beneficial for small to medium numbers of qubits where there is sufficient GPU memory to run multiple simulations in parallel. The maximum number of active circuit qubits for enabling this optimization can be configured using the
batch_shots_gpu_max_qubits
simulator option. The default value of this option is 16. -
Added the new
max_shot_size
option to a custom executor for running multiple shots of a noisy circuit in parallel.For example configuring
max_shot_size
with a custom executor:backend = AerSimulator( max_shot_size=1, max_job_size=1, executor=custom_executor) job = backend.run(circuits)
will split the shots of a noisy circuit into multiple circuits. After all individual shots have finished executing, the job results are automatically combined into a single
Result
object that is returned byjob.result()
. -
Added the
mps_swap_direction
simulator option that allows the user to determine the direction of internal swaps, when they are inserted for a 2-qubit gate. Possible values are"mps_swap_right"
and"mps_swap_left"
. The direction of the swaps may affect performance, depending on the circuit. -
Implemented a new measurement sampling optimization for the
"matrix_product_state"
simulation method of theAerSimulator
. Currently this algorithm is used only when all qubits are measured and when the simulatormps_sample_measure_algorithm
simulator option is set to"mps_probabilities"
. -
Improved the performance of the measure instruction for the
"matrix_product_state"
simulation method of theAerSimulator
. -
Added a
SaveClifford
instruction for saving the state of the stabilizer simulation method as aClifford
object.Note that this instruction is essentially equivalent to the
SaveStabilizer
instruction, however that instruction will return the saved state as aStabilizerState
object instead of aClifford
object. -
Added two transpiler passes for inserting instruction-dependent quantum errors into circuits:
qiskit.providers.aer.noise.LocalNoisePass
qiskit.providers.aer.noise.RelaxationNoisePass
The
LocalNoisePass
pass can be used to implement custom parameterized noise models by defining a noise generating function of the formdef fn( inst: Instruction, qubits: Optional[List[int]] = None, ) -> InstructionLike
which returns a noise instruction (eg. a
QuantumError
or other instruction) that can depend on any properties or parameters of the instruction and qubit arguements.This function can be applied to all instructions in a circuit, or a specified subset (See the
LocalNoisePass
documentation for additional details.)The
RelaxationNoisePass
is a special case of theLocalNoisePass
using a predefined noise function that returns a tensor product ofthermal_relaxation_error()
on each qubit in an instruction, dependent on the instruction’s duration and the supplied relaxation time constant parameters of the pass. -
The basic device noise model implemented by
NoiseModel.from_backend()
andAerSimulator.from_backend()
has been upgraded to allow adding duration-dependent relaxation errors on circuit delay gates using theRelaxationNoisePass
.To enable this noise when running noisy simulations you must first schedule your circuit to insert scheduled delay instructions as follows:
backend = AerSimulator.from_backend(ibmq_backend) scheduled_circuit = qiskit.transpile( circuit, backend=backend, scheduling_method='asap') result = backend.run(scheduled_circuit).result()
If the circuit is transpiled without being scheduled (and also contains no delay instructions) the noisy simulation will not include the effect of delay relaxation errors. In this case the simulation will be equivalent to the previous qiskit-aer 0.9 simulation where relaxation noise is only added to gate instructions based on their duration as obtained from the backend properties.
-
The constructor of
QuantumError
now accepts several new types of input asnoise_ops
argument, for example:import numpy as np from qiskit import QuantumCircuit from qiskit.circuit.library import IGate, XGate, Reset from qiskit.quantum_info import Kraus from qiskit.providers.aer.noise import QuantumError # Quantum channels kraus = Kraus([ np.array([[1, 0], [0, np.sqrt(1 - 0.9)]], dtype=complex), np.array([[0, 0], [0, np.sqrt(0.9)]], dtype=complex) ]) print(QuantumError(kraus)) # Construction from a QuantumCircuit qc = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) error = QuantumError(qc) # Construction from a tuple of (Instruction, List[int]), where the list of # integers represents the qubits. error = QuantumError((Reset(), [0])) # Construction from an iterable of objects in the same form as above, but # where each also has an associated probability. error = QuantumError([ ((IGate(), [0]), 0.9), ((XGate(), [0]), 0.1), ]) # A short-hand for the iterable form above, where the qubits are implicit, # and each instruction is over all qubits. error = QuantumError([(IGate(), 0.9), (XGate(), 0.1)])
Note that the original JSON-based input format is deperecated.
-
Added a utility function
qiskit.providers.aer.utils.transform_noise_model()
for constructing a noise model by applying a supplied function to allQuantumError
s in the noise model. -
Added two utility functions
qiskit.providers.aer.utils.transpile_quantum_error()
andqiskit.providers.aer.utils.transpile_noise_model()
for transpiling the circuits contained inQuantumError
, and all errors in aNoiseModel
. -
Added the ability to add
QuantumError
objects directly to aQuantumCircuit
without converting to aKraus
instruction.Circuits containing quantum errors can now be run on the
AerSimulator
andQasmSimulator
simulators as an alternative to, or in addition to, building aNoiseModel
for defining noisy circuit instructions.Example:
from qiskit import QuantumCircuit from qiskit.providers.aer import AerSimulator from qiskit.providers.aer.noise import pauli_error error_h = pauli_error([('I', 0.95), ('X', 0.05)]) error_cx = pauli_error([('II', 0.9), ('XX', 0.1)]) qc = QuantumCircuit(3) qc.h(0) qc.append(error_h, [0]) qc.cx(0, 1) qc.append(error_cx, [0, 1]) qc.cx(0, 2) qc.append(error_cx, [0, 2]) qc.measure_all() backend = AerSimulator(method='stabilizer') result = backend.run(qc).result() result.get_counts(0)
Circuits containing quantum errors can also be evaluated using the
quantum_info
quantum channel andDensityMatrix
classes.
Upgrade Notes
-
The return type of several save instructions have been changed to be the corresponding Qiskit Terra classes rather than raw NumPy arrays or dictionaries. The types that have changed are
save_statevector()
now returns as aStatevector
save_density_matrix()
now returns as aDensityMatrix
save_stabilizer()
now returns asStabilizerState
save_unitary()
now returns asOperator
save_superop()
now returns asSuperOp
save_probabilities_dict()
now returns as aProbDistribution
-
Changed the default value of
standard_gates
toNone
for all functions inqiskit.providers.aer.noise.errors.standard_errors
as those functions are updated so that they use standard gates by default. -
When an unsupported argument is supplied to
approximate_quantum_error()
, it will now raise aNoiseError
instead of aRuntimeError
.
Deprecation Notes
-
Using NumPy
ndarray
methods and attributes on the return type ofsave_statevector()
,save_density_matrix()
,save_unitary()
, andsave_superop()
has been deprecated, and will stop working in a future release. These instructions now returnqiskit.quantum_info
classes for their return types. Partial backwards compatability with treating these objects as NumPy arrays is implemented by forwarding methods to the internal array during the deprecation period. -
Passing in a
BackendProperties
object for thebackend
argument ofNoiseModel.from_backend()
has been deprecated, as it is incompatible with duration dependent delay noises, and will be removed in a future release. Pass in a Qiskit TerraBackendV1
object instead. -
Deprecated the
number_of_qubits
option of theQuantumError
constructor in favor of automatic determination of the dimension. -
Deprecated the
standard_gates
option of theQuantumError
constructor in favor of externalizing such basis-change functionality. In many cases, you can transform any error into an error defined only with specific gates usingapproximate_quantum_error()
. -
Deprecated the
standard_gates
option of all functions inqiskit.providers.aer.noise.errors.standard_errors
in favor of returning errors in the form of a mixture of standard gates as much as possible by default. -
Deprecated all functions in
errorutils
because they are helper functions meant to be used only for implementing functions inqiskit.providers.aer.noise.errors.standard_errors
and they should have been provided as private functions. -
Deprecated the
standard_gates
option ofNoiseModel.from_backend()
in favor of externalizing such basis-change functionality. -
Deprecated
NoiseModel.from_dict()
to make the noise model independent of Qobj (JSON) format. -
Deprecated all public variables, functions and classes in
qiskit.providers.aer.noise.utils.noise_transformation
except forapproximate_quantum_error()
andapproximate_noise_model()
, because they are helper functions meant to be used only for implementing theapproximate_*
functions and they should have been provided as private functions. -
Deprecated
remap_noise_model()
since the C++ code now automatically truncates and remaps noise models if it truncates circuits.
Other Notes
- Changes in the implementation of the function
approximate_quantum_error()
may change the resulting approximate error compared to Qiskit Aer 0.9.
Ignis 0.7.0
No change
IBM Q Provider 0.18.3
Bug Fixes
- Fix delivered in #1100 for an issue with JSON encoding and decoding when using
ParameterExpression
s in conjunction with Qiskit Terra 0.19.1 and above. Previously, theParameter
instances reconstructed from the JSON output would have different unique identifiers, causing them to seem unequal to the input. They will now have the correct backing identities.