Release 0.36.0
New features since last release
Estimate errors in a quantum circuit 🧮
- This version of PennyLane lays the foundation for estimating the total error in a quantum circuit from the combination of individual gate errors. (#5154) (#5464) (#5465) (#5278) (#5384)
Two new user-facing classes enable calculating and propagating gate errors in PennyLane:
-
qml.resource.SpectralNormError
: the spectral norm error is defined as the distance, in spectral norm, between the true unitary we intend to apply and the approximate unitary that is actually applied. -
qml.resource.ErrorOperation
: a base class that inherits fromqml.operation.Operation
and represents quantum operations which carry some form of algorithmic error.SpectralNormError
can be used for back-of-the-envelope type calculations like obtaining the spectral norm error between two unitaries viaget_error
:import pennylane as qml from pennylane.resource import ErrorOperation, SpectralNormError intended_op = qml.RY(0.40, 0) actual_op = qml.RY(0.41, 0) # angle of rotation is slightly off
>>> SpectralNormError.get_error(intended_op, actual_op) 0.004999994791668309
SpectralNormError
is also a key tool to specify errors in larger quantum circuits: -
For operations representing a major building block of an algorithm, we can create a custom operation that inherits from
ErrorOperation
. This child class must override theerror
method and should return aSpectralNormError
instance:class MyErrorOperation(ErrorOperation): def __init__(self, error_val, wires): self.error_val = error_val super().__init__(wires=wires) def error(self): return SpectralNormError(self.error_val)
In this toy example,
MyErrorOperation
introduces an arbitrarySpectralNormError
when called in a QNode. It does not require a decomposition or matrix representation when used withnull.qubit
(suggested for use with resource and error estimation since circuit executions are not required to calculate resources or errors).dev = qml.device("null.qubit") @qml.qnode(dev) def circuit(): MyErrorOperation(0.1, wires=0) MyErrorOperation(0.2, wires=1) return qml.state()
The total spectral norm error of the circuit can be calculated using
qml.specs
:>>> qml.specs(circuit)()['errors'] {'SpectralNormError': SpectralNormError(0.30000000000000004)}
-
PennyLane already includes a number of built-in building blocks for algorithms like
QuantumPhaseEstimation
andTrotterProduct
.TrotterProduct
now propagates errors based on the number of steps performed in the Trotter product.QuantumPhaseEstimation
now propagates errors based on the error of its input unitary.dev = qml.device('null.qubit') hamiltonian = qml.dot([1.0, 0.5, -0.25], [qml.X(0), qml.Y(0), qml.Z(0)]) @qml.qnode(dev) def circuit(): qml.TrotterProduct(hamiltonian, time=0.1, order=2) qml.QuantumPhaseEstimation(MyErrorOperation(0.01, wires=0), estimation_wires=[1, 2, 3]) return qml.state()
Again, the total spectral norm error of the circuit can be calculated using
qml.specs
:>>> qml.specs(circuit)()["errors"] {'SpectralNormError': SpectralNormError(0.07616666666666666)}
Check out our error propagation demo to see how to use these new features in a real-world example!
Access an extended arsenal of quantum algorithms 🏹
-
The Fast Approximate BLock-Encodings (FABLE) algorithm for embedding a matrix into a quantum circuit as outlined in arXiv:2205.00081 is now accessible via the
qml.FABLE
template. (#5107)The usage of
qml.FABLE
is similar toqml.BlockEncode
but provides a more efficient circuit construction at the cost of a user-defined approximation level,tol
. The number of wires thatqml.FABLE
operates on is2*n + 1
, wheren
defines the dimension of the $2^n \times 2^n$ matrix that we want to block-encode.import numpy as np A = np.array([[0.1, 0.2], [0.3, 0.4]]) dev = qml.device('default.qubit', wires=3) @qml.qnode(dev) def circuit(): qml.FABLE(A, tol = 0.001, wires=range(3)) return qml.state()
>>> mat = qml.matrix(circuit)() >>> 2 * mat[0:2, 0:2] array([[0.1+0.j, 0.2+0.j], [0.3+0.j, 0.4+0.j]])
-
A high-level interface for amplitude amplification and its variants is now available via the new
qml.AmplitudeAmplification
template. (#5160)Based on arXiv:quant-ph/0005055, given a state $\vert \Psi \rangle = \alpha \vert \phi \rangle + \beta \vert \phi^{\perp} \rangle$,
qml.AmplitudeAmplification
amplifies the amplitude of $\vert \phi \rangle$.Here's an example with a target state $\vert \phi \rangle = \vert 2 \rangle = \vert 010 \rangle$, an input state $\vert \Psi \rangle = H^{\otimes 3} \vert 000 \rangle$, as well as an oracle that flips the sign of $\vert \phi \rangle$ and does nothing to $\vert \phi^{\perp} \rangle$, which can be achieved in this case through
qml.FlipSign
.@qml.prod def generator(wires): for wire in wires: qml.Hadamard(wires=wire) U = generator(wires=range(3)) O = qml.FlipSign(2, wires=range(3))
Here,
U
is a quantum operation that is created by decorating a quantum function with@qml.prod
. This could alternatively be done by creating a user-defined custom operation with a decomposition. Amplitude amplification can then be set up within a circuit:dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(): generator(wires=range(3)) # prepares |Psi> = U|0> qml.AmplitudeAmplification(U, O, iters=10) return qml.probs(wires=range(3))
>>> print(np.round(circuit(), 3)) [0.01 0.01 0.931 0.01 0.01 0.01 0.01 0.01 ]
As expected, we amplify the $\vert 2 \rangle$ state.
-
Reflecting about a given quantum state is now available via
qml.Reflection
. This operation is very useful in the amplitude amplification algorithm and offers a generalization ofqml.FlipSign
, which operates on basis states. (#5159)qml.Reflection
works by providing an operation, $U$, that prepares the desired state, $\vert \psi \rangle$, that we want to reflect about. In other words, $U$ is such that $U \vert 0 \rangle = \vert \psi \rangle$. In PennyLane, $U$ must be anOperator
. For example, if we want to reflect about $\vert \psi \rangle = \vert + \rangle$, then $U = H$:U = qml.Hadamard(wires=0) dev = qml.device('default.qubit') @qml.qnode(dev) def circuit(): qml.Reflection(U) return qml.state()
>>> circuit() tensor([0.-6.123234e-17j, 1.+6.123234e-17j], requires_grad=True)
-
Performing qubitization is now easily accessible with the new
qml.Qubitization
operator. (#5500)qml.Qubitization
encodes a Hamiltonian into a suitable unitary operator. When applied in conjunction with quantum phase estimation (QPE), it allows for computing the eigenvalue of an eigenvector of the given Hamiltonian.H = qml.dot([0.1, 0.3, -0.3], [qml.Z(0), qml.Z(1), qml.Z(0) @ qml.Z(2)]) @qml.qnode(qml.device("default.qubit")) def circuit(): # initialize the eigenvector qml.PauliX(2) # apply QPE measurements = qml.iterative_qpe( qml.Qubitization(H, control = [3,4]), ancilla = 5, iters = 3 ) return qml.probs(op = measurements)
Make use of more methods to map from molecules 🗺️
-
A new function called
qml.bravyi_kitaev
has been added to perform the Bravyi-Kitaev mapping of fermionic Hamiltonians to qubit Hamiltonians. (#5390)This function presents an alternative mapping to
qml.jordan_wigner
orqml.parity_transform
which can help us measure expectation values more efficiently on hardware. Simply provide a fermionic Hamiltonian (created fromfrom_string
,FermiA
,FermiC
,FermiSentence
, orFermiWord
) and the number of qubits / spin orbitals in the system,n
:>>> fermi_ham = qml.fermi.from_string('0+ 1+ 1- 0-') >>> qubit_ham = qml.bravyi_kitaev(fermi_ham, n=6, tol=0.0) >>> print(qubit_ham) 0.25 * I(0) + -0.25 * Z(0) + -0.25 * (Z(0) @ Z(1)) + 0.25 * Z(1)
-
The
qml.qchem.hf_state
function has been upgraded to be compatible withqml.parity_transform
and the new Bravyi-Kitaev mapping (qml.bravyi_kitaev
). (#5472) (#5472)>>> state_bk = qml.qchem.hf_state(2, 6, basis="bravyi_kitaev") >>> print(state_bk) [1 0 0 0 0 0] >>> state_parity = qml.qchem.hf_state(2, 6, basis="parity") >>> print(state_parity) [1 0 0 0 0 0]
Calculate dynamical Lie algebras 👾
The dynamical Lie algebra (DLA) of a set of operators captures the range of unitary evolutions that the operators can generate. In v0.36 of PennyLane, we have added support for calculating important DLA concepts including:
-
A new
qml.lie_closure
function to compute the Lie closure of a list of operators, providing one way to obtain the DLA. (#5161) (#5169) (#5627)For a list of operators
ops = [op1, op2, op3, ..]
, one computes all nested commutators betweenops
until no new operators are generated from commutation. All these operators together form the DLA, see e.g. section IIB of arXiv:2308.01432.Take for example the following operators:
from pennylane import X, Y, Z ops = [X(0) @ X(1), Z(0), Z(1)]
A first round of commutators between all elements yields the new operators
Y(0) @ X(1)
andX(0) @ Y(1)
(omitting scalar prefactors).>>> qml.commutator(X(0) @ X(1), Z(0)) -2j * (Y(0) @ X(1)) >>> qml.commutator(X(0) @ X(1), Z(1)) -2j * (X(0) @ Y(1))
A next round of commutators between all elements further yields the new operator
Y(0) @ Y(1)
.>>> qml.commutator(X(0) @ Y(1), Z(0)) -2j * (Y(0) @ Y(1))
After that, no new operators emerge from taking nested commutators and we have the resulting DLA. This can now be done in short via
qml.lie_closure
as follows.>>> ops = [X(0) @ X(1), Z(0), Z(1)] >>> dla = qml.lie_closure(ops) >>> dla [X(0) @ X(1), Z(0), Z(1), -1.0 * (Y(0) @ X(1)), -1.0 * (X(0) @ Y(1)), -1.0 * (Y(0) @ Y(1))]
-
Computing the structure constants (the adjoint representation) of a dynamical Lie algebra. (5406)
For example, we can compute the adjoint representation of the transverse field Ising model DLA.
>>> dla = [X(0) @ X(1), Z(0), Z(1), Y(0) @ X(1), X(0) @ Y(1), Y(0) @ Y(1)] >>> structure_const = qml.structure_constants(dla) >>> structure_const.shape (6, 6, 6)
Visit the documentation of qml.structure_constants to understand how structure constants are a useful way to represent a DLA.
-
Computing the center of a dynamical Lie algebra. (#5477)
Given a DLA
g
, we can now compute its centre. Thecenter
is the collection of operators that commute with all other operators in the DLA.>>> g = [X(0), X(1) @ X(0), Y(1), Z(1) @ X(0)] >>> qml.center(g) [X(0)]
To help explain these concepts, check out the dynamical Lie algebras demo.
Improvements 🛠
Simulate mixed-state qutrit systems
-
Mixed qutrit states can now be simulated with the
default.qutrit.mixed
device. (#5495) (#5451) (#5186) (#5082) (#5213)Thanks to contributors from the University of British Columbia, a mixed-state qutrit device is now available for simulation, providing a noise-capable equivalent to
default.qutrit
.dev = qml.device("default.qutrit.mixed") def circuit(): qml.TRY(0.1, wires=0) @qml.qnode(dev) def shots_circuit(): circuit() return qml.sample(), qml.expval(qml.GellMann(wires=0, index=1)) @qml.qnode(dev) def density_matrix_circuit(): circuit() return qml.state()
>>> shots_circuit(shots=5) (array([0, 0, 0, 0, 0]), 0.19999999999999996) >>> density_matrix_circuit() tensor([[0.99750208+0.j, 0.04991671+0.j, 0. +0.j], [0.04991671+0.j, 0.00249792+0.j, 0. +0.j], [0. +0.j, 0. +0.j, 0. +0.j]], requires_grad=True)
However, there's one crucial ingredient that we still need to add: support for qutrit noise operations. Keep your eyes peeled for this to arrive in the coming releases!
Work easily and efficiently with operators
-
This release completes the main phase of PennyLane's switchover to an updated approach for handling arithmetic operations between operators. The new approach is now enabled by default and is intended to realize a few objectives: 1. To make it as easy to work with PennyLane operators as it would be with pen and paper. 2. To improve the efficiency of operator arithmetic.
In many cases, this update should not break code. If issues do arise, check out the updated operator troubleshooting page and don't hesitate to reach out to us on the PennyLane discussion forum. As a last resort the old behaviour can be enabled by calling
qml.operation.disable_new_opmath()
, but this is not recommended because support will not continue in future PennyLane versions (v0.36 and higher). (#5269) -
A new class called
qml.ops.LinearCombination
has been introduced. In essence, this class is an updated equivalent of the now-deprecatedqml.ops.Hamiltonian
but for usage with the new operator arithmetic. (#5216) -
qml.ops.Sum
now supports storing grouping information. Grouping type and method can be specified during construction using thegrouping_type
andmethod
keyword arguments ofqml.dot
,qml.sum
, orqml.ops.Sum
. The grouping indices are stored inSum.grouping_indices
. (#5179)a = qml.X(0) b = qml.prod(qml.X(0), qml.X(1)) c = qml.Z(0) obs = [a, b, c] coeffs = [1.0, 2.0, 3.0] op = qml.dot(coeffs, obs, grouping_type="qwc")
>>> op.grouping_indices ((2,), (0, 1))
Additionally,
grouping_type
andmethod
can be set or changed after construction usingSum.compute_grouping()
:a = qml.X(0) b = qml.prod(qml.X(0), qml.X(1)) c = qml.Z(0) obs = [a, b, c] coeffs = [1.0, 2.0, 3.0] op = qml.dot(coeffs, obs)
>>> op.grouping_indices is None True >>> op.compute_grouping(grouping_type="qwc") >>> op.grouping_indices ((2,), (0, 1))
Note that the grouping indices refer to the lists returned by
Sum.terms()
, notSum.operands
. -
A new function called
qml.operation.convert_to_legacy_H
that convertsSum
,SProd
, andProd
toHamiltonian
instances has been added. This function is intended for developers and will be removed in a future release without a deprecation cycle. (#5309) -
The
qml.is_commuting
function now acceptsSum
,SProd
, andProd
instances. (#5351) -
Operators can now be left-multiplied by NumPy arrays (i.e.,
arr * op
). (#5361) -
op.generator()
, whereop
is anOperator
instance, now returns operators consistent with the global setting forqml.operator.active_new_opmath()
wherever possible.Sum
,SProd
andProd
instances will be returned even after disabling the new operator arithmetic in cases where they offer additional functionality not available using legacy operators. (#5253) (#5410) (#5411) (#5421) -
Prod
instances temporarily have a newobs
property, which helps smoothen the transition of the new operator arithmetic system. In particular, this is aimed at preventing breaking code that usesTensor.obs
. The property has been immediately deprecated. Moving forward, we recommend usingop.operands
. (#5539) -
qml.ApproxTimeEvolution
is now compatible with any operator that has a definedpauli_rep
. (#5362) -
Hamiltonian.pauli_rep
is now defined if the Hamiltonian is a linear combination of Pauli operators. (#5377) -
Prod
instances created with qutrit operators now have a definedeigvals()
method. (#5400) -
qml.transforms.hamiltonian_expand
andqml.transforms.sum_expand
can now handle multi-term observables with a constant offset (i.e., terms likeqml.I()
). (#5414) (#5543) -
qml.qchem.taper_operation
is now compatible with the new operator arithmetic. (#5326) -
The warning for an observable that might not be hermitian in QNode executions has been removed. This enables jit-compilation. (#5506)
-
qml.transforms.split_non_commuting
will now work with single-term operator arithmetic. (#5314) -
LinearCombination
andSum
now accept_grouping_indices
on initialization. This addition is relevant to developers only. (#5524) -
Calculating the dense, differentiable matrix for
PauliSentence
and operators with Pauli sentences is now faster. (#5578)
Community contributions 🥳
-
ExpectationMP
,VarianceMP
,CountsMP
, andSampleMP
now have aprocess_counts
method (similar toprocess_samples
). This allows for calculating measurements given acounts
dictionary. (#5256) (#5395) -
Type-hinting has been added in the
Operator
class for better interpretability. (#5490) -
An alternate strategy for sampling with multiple different
shots
values has been implemented via theshots.bins()
method, which samples all shots at once and then processes each separately. (#5476)
Mid-circuit measurements and dynamic circuits
-
A new module called
qml.capture
that will contain PennyLane's own capturing mechanism for hybrid quantum-classical programs has been added. (#5509) -
The
dynamic_one_shot
transform has been introduced, enabling dynamic circuit execution on circuits with finiteshots
and devices that natively support mid-circuit measurements. (#5266) -
The
QubitDevice
class and children classes support thedynamic_one_shot
transform provided that they support mid-circuit measurement operations natively. (#5317) -
default.qubit
can now be provided a random seed for sampling mid-circuit measurements with finite shots. This (1) ensures that random behaviour is more consistent withdynamic_one_shot
anddefer_measurements
and (2) makes our continuous-integration (CI) have less failures due to stochasticity. (#5337)
Performance and broadcasting
-
Gradient transforms may now be applied to batched/broadcasted QNodes as long as the broadcasting is in non-trainable parameters. (#5452)
-
The performance of computing the matrix of
qml.QFT
has been improved. (#5351) -
qml.transforms.broadcast_expand
now supports shot vectors when returningqml.sample()
. (#5473) -
LightningVJPs
is now compatible with Lightning devices using the new device API. (#5469)
Device capabilities
-
Obtaining classical shadows using the
default.clifford
device is now compatible with stimv1.13.0
. (#5409) -
default.mixed
has improved support for sampling-based measurements with non-NumPy interfaces. (#5514) (#5530) -
default.mixed
now supports arbitrary state-based measurements withqml.Snapshot
. (#5552) -
null.qubit
has been upgraded to the new device API and has support for all measurements and various modes of differentiation. (#5211)
Other improvements
-
Entanglement entropy can now be calculated with
qml.math.vn_entanglement_entropy
, which computes the von Neumann entanglement entropy from a density matrix. A corresponding QNode transform,qml.qinfo.vn_entanglement_entropy
, has also been added. (#5306) -
qml.draw
andqml.draw_mpl
will now attempt to sort the wires if no wire order is provided by the user or the device. (#5576) -
A clear error message is added in
KerasLayer
when using the newest version of TensorFlow with Keras 3 (which is not currently compatible withKerasLayer
), linking to instructions to enable Keras 2. (#5488) -
qml.ops.Conditional
now stores thedata
,num_params
, andndim_param
attributes of the operator it wraps. (#5473) -
The
molecular_hamiltonian
function callsPySCF
directly whenmethod='pyscf'
is selected. (#5118) -
cache_execute
has been replaced with an alternate implementation based on@transform
. (#5318) -
QNodes now defer
diff_method
validation to the device under the new device API. (#5176) -
The device test suite has been extended to cover gradient methods, templates and arithmetic observables. (#5273) (#5518)
-
A typo and string formatting mistake have been fixed in the error message for
ClassicalShadow._convert_to_pauli_words
when the input is not a validpauli_rep
. (#5572) -
Circuits running on
lightning.qubit
and that returnqml.state()
now preserve thedtype
when specified. (#5547)
Breaking changes 💔
-
qml.matrix()
called on the following will now raise an error ifwire_order
is not specified: * tapes with more than one wire * quantum functions *Operator
classes wherenum_wires
does not equal to 1 * QNodes if the device does not have wires specified. *PauliWord
s andPauliSentence
s with more than one wire. (#5328) (#5359) -
single_tape_transform
,batch_transform
,qfunc_transform
,op_transform
,gradient_transform
andhessian_transform
have been removed. Instead, switch to using the newqml.transform
function. Please refer tothe transform docs <https://docs.pennylane.ai/en/stable/code/qml_transforms.html#custom-transforms>
_ to see how this can be done. (#5339) -
Attempting to multiply
PauliWord
andPauliSentence
with*
will raise an error. Instead, use@
to conform with the PennyLane convention. (#5341) -
DefaultQubit
now uses a pre-emptive key-splitting strategy to avoid reusing JAX PRNG keys throughout a singleexecute
call. (#5515) -
qml.pauli.pauli_mult
andqml.pauli.pauli_mult_with_phase
have been removed. Instead, useqml.simplify(qml.prod(pauli_1, pauli_2))
to get the reduced operator. (#5324)
>>> op = qml.simplify(qml.prod(qml.PauliX(0), qml.PauliZ(0)))
>>> op -1j*(PauliY(wires=[0]))
>>> [phase], [base] = op.terms()
>>> phase, base
(-1j, PauliY(wires=[0]))
-
The
dynamic_one_shot
transform now uses sampling (SampleMP
) to get back the values of the mid-circuit measurements. (#5486) -
Operator
dunder methods now combine like-operator arithmetic classes vialazy=False
. This reduces the chances of getting aRecursionError
and makes nested operators easier to work with. (#5478) -
The private functions
_pauli_mult
,_binary_matrix
and_get_pauli_map
from thepauli
module have been removed. The same functionality can be achieved using newer features in thepauli
module. (#5323) -
MeasurementProcess.name
andMeasurementProcess.data
have been removed. UseMeasurementProcess.obs.name
andMeasurementProcess.obs.data
instead. (#5321) -
Operator.validate_subspace(subspace)
has been removed. Instead, useqml.ops.qutrit.validate_subspace(subspace)
. (#5311) -
The contents of
qml.interfaces
has been moved insideqml.workflow
. The old import path no longer exists. (#5329) -
Since
default.mixed
does not support snapshots with measurements, attempting to do so will result in aDeviceError
instead of getting the density matrix. (#5416) -
LinearCombination._obs_data
has been removed. You can still useLinearCombination.compare
to check mathematical equivalence between aLinearCombination
and another operator. (#5504)
Deprecations 👋
-
Accessing
qml.ops.Hamiltonian
is deprecated because it points to the old version of the class that may not be compatible with the new approach to operator arithmetic. Instead, usingqml.Hamiltonian
is recommended because it dispatches to theLinearCombination
class when the new approach to operator arithmetic is enabled. This will allow you to continue to useqml.Hamiltonian
with existing code without needing to make any changes. (#5393) -
qml.load
has been deprecated. Instead, please use the functions outlined in the Importing workflows quickstart guide. (#5312) -
Specifying
control_values
with a bit string inqml.MultiControlledX
has been deprecated. Instead, use a list of booleans or 1s and 0s. (#5352) -
qml.from_qasm_file
has been deprecated. Instead, please open the file and then load its content usingqml.from_qasm
. (#5331)
>>> with open("test.qasm", "r") as f:
... circuit = qml.from_qasm(f.read())
Documentation 📝
-
A new page explaining the shapes and nesting of return types has been added. (#5418)
-
Redundant documentation for the
evolve
function has been removed. (#5347) -
The final example in the
compile
docstring has been updated to use transforms correctly. (#5348) -
A link to the demos for using
qml.SpecialUnitary
andqml.QNGOptimizer
has been added to their respective docstrings. (#5376) -
A code example in the
qml.measure
docstring has been added that showcases returning mid-circuit measurement statistics from QNodes. (#5441) -
The computational basis convention used for
qml.measure
— 0 and 1 rather than ±1 — has been clarified in its docstring. (#5474) -
A new Release news section has been added to the table of contents, containing release notes, deprecations, and other pages focusing on recent changes. (#5548)
-
A summary of all changes has been added in the "Updated Operators" page in the new "Release news" section in the docs. (#5483) (#5636)
Bug fixes 🐛
-
Patches the QNode so that parameter-shift will be considered best with lightning if
qml.metric_tensor
is in the transform program. (#5624) -
Stopped printing the ID of
qcut.MeasureNode
andqcut.PrepareNode
in tape drawing. (#5613) -
Improves the error message for setting shots on the new device interface, or trying to access a property that no longer exists. (#5616)
-
Fixed a bug where
qml.draw
andqml.draw_mpl
incorrectly raised errors for circuits collecting statistics on mid-circuit measurements while usingqml.defer_measurements
. (#5610) -
Using shot vectors with
param_shift(... broadcast=True)
caused a bug. This combination is no longer supported and will be added again in the next release. Fixed a bug with custom gradient recipes that only consist of unshifted terms. (#5612) (#5623) -
qml.counts
now returns the same keys withdynamic_one_shot
anddefer_measurements
. (#5587) -
null.qubit
now automatically supports any operation without a decomposition. (#5582) -
Fixed a bug where the shape and type of derivatives obtained by applying a gradient transform to a QNode differed based on whether the QNode uses classical coprocessing. (#4945)
-
ApproxTimeEvolution
,CommutingEvolution
,QDrift
, andTrotterProduct
now de-queue their input observable. (#5524) -
(In)equality of
qml.HilbertSchmidt
instances is now reported correctly byqml.equal
. (#5538) -
qml.ParticleConservingU1
andqml.ParticleConservingU2
no longer raise an error when the initial state is not specified but default to the all-zeros state. (#5535) -
qml.counts
no longer returns negative samples when measuring 8 or more wires. (#5544) (#5556) -
The
dynamic_one_shot
transform now works with broadcasting. (#5473) -
Diagonalizing gates are now applied when measuring
qml.probs
on non-computational basis states on a Lightning device. (#5529) -
two_qubit_decomposition
no longer diverges at a special case of a unitary matrix. (#5448) -
The
qml.QNSPSAOptimizer
now correctly handles optimization for legacy devices that do not follow the new device API. (#5497) -
Operators applied to all wires are now drawn correctly in a circuit with mid-circuit measurements. (#5501)
-
Fixed a bug where certain unary mid-circuit measurement expressions would raise an uncaught error. (#5480)
-
Probabilities now sum to 1 when using the
torch
interface withdefault_dtype
set totorch.float32
. (#5462) -
Tensorflow can now handle devices with
float32
results butfloat64
input parameters. (#5446) -
Fixed a bug where the
argnum
keyword argument ofqml.gradients.stoch_pulse_grad
references the wrong parameters in a tape, creating an inconsistency with other differentiation methods and preventing some use cases. (#5458) -
Bounded value failures due to numerical noise with calls to
np.random.binomial
is now avoided. (#5447) -
Using
@
with legacy Hamiltonian instances now properly de-queues the previously existing operations. (#5455) -
The
QNSPSAOptimizer
now properly handles differentiable parameters, resulting in being able to use it for more than one optimization step. (#5439) -
The QNode interface now resets if an error occurs during execution. (#5449)
-
Failing tests due to changes with Lightning's adjoint diff pipeline have been fixed. (#5450)
-
Failures occurring when making autoray-dispatched calls to Torch with paired CPU data have been fixed. (#5438)
-
jax.jit
now works withqml.sample
with a multi-wire observable. (#5422) -
qml.qinfo.quantum_fisher
now works with non-default.qubit
devices. (#5423) -
We no longer perform unwanted
dtype
promotion in thepauli_rep
ofSProd
instances when using Tensorflow. (#5246) -
Fixed
TestQubitIntegration.test_counts
intests/interfaces/test_jax_qnode.py
to always produce counts for all outcomes. (#5336) -
Fixed
PauliSentence.to_mat(wire_order)
to support identities with wires. (#5407) -
CompositeOp.map_wires
now correctly maps theoverlapping_ops
property. (#5430) -
DefaultQubit.supports_derivatives
has been updated to correctly handle circuits containing mid-circuit measurements and adjoint differentiation. (#5434) -
SampleMP
,ExpectationMP
,CountsMP
, andVarianceMP
constructed witheigvals
can now properly process samples. (#5463) -
Fixed a bug in
hamiltonian_expand
that produces incorrect output dimensions when shot vectors are combined with parameter broadcasting. (#5494) -
default.qubit
now allows measuringIdentity
on no wires and observables containingIdentity
on no wires. (#5570) -
Fixed a bug where
TorchLayer
does not work with shot vectors. (#5492) -
Fixed a bug where the output shape of a QNode returning a list containing a single measurement is incorrect when combined with shot vectors. (#5492)
-
Fixed a bug in
qml.math.kron
that makes Torch incompatible with NumPy. (#5540) -
Fixed a bug in
_group_measurements
that fails to group measurements with commuting observables when they are operands ofProd
. (#5525) -
qml.equal
can now be used with sums and products that contain operators on no wires likeI
andGlobalPhase
. (#5562) -
CompositeOp.has_diagonalizing_gates
now does a more complete check of the base operators to ensure consistency betweenop.has_diagonalzing_gates
andop.diagonalizing_gates()
(#5603) -
Updated the
method
kwarg ofqml.TrotterProduct().error()
to be more clear that we are computing upper-bounds. (#5637)
Contributors ✍️
This release contains contributions from (in alphabetical order):
Tarun Kumar Allamsetty, Guillermo Alonso, Mikhail Andrenkov, Utkarsh Azad, Gabriel Bottrill, Thomas Bromley, Astral Cai, Diksha Dhawan, Isaac De Vlugt, Amintor Dusko, Pietropaolo Frisoni, Lillian M. A. Frederiksen, Diego Guala, Austin Huang, Soran Jahangiri, Korbinian Kottmann, Christina Lee, Vincent Michaud-Rioux, Mudit Pandey, Kenya Sakka, Jay Soni, Matthew Silverman, David Wierichs.