New features since last release
Creating spin Hamiltonians on lattices 💞
-
Functionality for creating custom Hamiltonians on arbitrary lattices has been added. (#6226) (#6237)
Hamiltonians beyond the available boiler-plate ones in the
qml.spin
module can be created with the addition of three new functions:-
qml.spin.Lattice
: a new object for instantiating customized lattices via primitive translation vectors and unit cell parameters, -
qml.spin.generate_lattice
: a utility function for creating standardLattice
objects, including'chain'
,'square'
,'rectangle'
,'triangle'
,'honeycomb'
,'kagome'
,'lieb'
,'cubic'
,'bcc'
,'fcc'
, and'diamond'
, -
qml.spin.spin_hamiltonian
: generates a spinHamiltonian
object given aLattice
object with custom edges/nodes.
An example is shown below for a
$3 \times 3$ triangular lattice with open boundary conditions.lattice = qml.spin.Lattice( n_cells=[3, 3], vectors=[[1, 0], [np.cos(np.pi/3), np.sin(np.pi/3)]], positions=[[0, 0]], boundary_condition=False )
We can validate this
lattice
againstqml.spin.generate_lattice('triangle', ...)
by checking thelattice_points
(the$(x, y)$ coordinates of all sites in the lattice):>>> lp = lattice.lattice_points >>> triangular_lattice = qml.spin.generate_lattice('triangle', n_cells=[3, 3]) >>> np.allclose(lp, triangular_lattice.lattice_points) True
The
edges
of theLattice
object are nearest-neighbour by default, where we can add edges by using itsadd_edge
method.Optionally, a
Lattice
object can have interactions and fields endowed to it by specifying values for itscustom_edges
andcustom_nodes
keyword arguments. The Hamiltonian can then be extracted with theqml.spin.spin_hamiltonian
function. An example is shown below for the transverse-field Ising model Hamiltonian on a$3 \times 3$ triangular lattice. Note that thecustom_edges
andcustom_nodes
keyword arguments only need to be defined for one unit cell repetition.edges = [ (0, 1), (0, 3), (1, 3) ] lattice = qml.spin.Lattice( n_cells=[3, 3], vectors=[[1, 0], [np.cos(np.pi/3), np.sin(np.pi/3)]], positions=[[0, 0]], boundary_condition=False, custom_edges=[[edge, ("ZZ", -1.0)] for edge in edges], custom_nodes=[[i, ("X", -0.5)] for i in range(3*3)], )
>>> tfim_ham = qml.spin.transverse_ising('triangle', [3, 3], coupling=1.0, h=0.5) >>> tfim_ham == qml.spin.spin_hamiltonian(lattice=lattice) True
-
-
More industry-standard spin Hamiltonians have been added in the
qml.spin
module. (#6174) (#6201)Three new industry-standard spin Hamiltonians are now available with PennyLane v0.39:
-
qml.spin.emery
: the Emery model -
qml.spin.haldane
: the Haldane model -
qml.spin.kitaev
: the Kitaev model
These additions accompany
qml.spin.heisenberg
,qml.spin.transverse_ising
, andqml.spin.fermi_hubbard
, which were introduced in v0.38. -
Calculating Polynomials 🔢
-
Polynomial functions can now be easily encoded into quantum circuits with
qml.OutPoly
. (#6320)A new template called
qml.OutPoly
is available, which provides the ability to encode a polynomial function in a quantum circuit. Given a polynomial function$f(x_1, x_2, \cdots, x_N)$ ,qml.OutPoly
requires:-
f
: a standard Python function that represents$f(x_1, x_2, \cdots, x_N)$ , -
input_registers
($\vert x_1 \rangle$ ,$\vert x_2 \rangle$ , ...,$\vert x_N \rangle$ ) : a list/tuple containingWires
objects that correspond to the embedded numeric values of$x_1, x_2, \cdots, x_N$ , -
output_wires
: theWires
for which the numeric value of$f(x_1, x_2, \cdots, x_N)$ is stored.
Here is an example of using
qml.OutPoly
to calculate$f(x_1, x_2) = 3x_1^2 - x_1x_2$ for$f(1, 2) = 1$ .wires = qml.registers({"x1": 1, "x2": 2, "output": 2}) def f(x1, x2): return 3 * x1 ** 2 - x1 * x2 @qml.qnode(qml.device("default.qubit", shots = 1)) def circuit(): # load values of x1 and x2 qml.BasisEmbedding(1, wires=wires["x1"]) qml.BasisEmbedding(2, wires=wires["x2"]) # apply the polynomial qml.OutPoly( f, input_registers = [wires["x1"], wires["x2"]], output_wires = wires["output"]) return qml.sample(wires=wires["output"])
>>> circuit() array([0, 1])
The result,
[0, 1]
, is the binary representation of$1$ . By default, the result is calculated modulo$2^\text{len(output wires)}$ but can be overridden with themod
keyword argument. -
Readout Noise 📠
-
Readout errors can now be included in
qml.NoiseModel
andqml.add_noise
with the newqml.noise.meas_eq
function. (#6321)Measurement/readout errors can be specified in a similar fashion to regular gate noise in PennyLane: a newly added Boolean function called
qml.noise.meas_eq
that accepts a measurement function (e.g.,qml.expval
,qml.sample
, or any other function that can be returned from a QNode) that, when present in the QNode, inserts a noisy operation viaqml.noise.partial_wires
or a custom noise function. Readout noise in PennyLane also follows the insertion convention, where the specified noise is inserted before the measurement.Here is an example of adding
qml.PhaseFlip
noise to anyqml.expval
measurement:c0 = qml.noise.meas_eq(qml.expval) n0 = qml.noise.partial_wires(qml.PhaseFlip, 0.2)
To include this in a
qml.NoiseModel
, use itsmeas_map
keyword argument:# gate-based noise c1 = qml.noise.wires_in([0, 2]) n1 = qml.noise.partial_wires(qml.RY, -0.42) noise_model = qml.NoiseModel({c1: n1}, meas_map={c0: n0})
>>> noise_model NoiseModel({ WiresIn([0, 2]): RY(phi=-0.42) }, meas_map = { MeasEq(expval): PhaseFlip(p=0.2) })
qml.noise.meas_eq
can also be combined with other Boolean functions inqml.noise
via bitwise operators for more versatility.To add this
noise_model
to a circuit, use theqml.add_noise
transform as per usual. For example,@qml.qnode(qml.device("default.mixed", wires=3)) def circuit(): qml.RX(0.1967, wires=0) for i in range(3): qml.Hadamard(i) return qml.expval(qml.X(0) @ qml.X(1))
>>> noisy_circuit = qml.add_noise(circuit, noise_model) >>> print(qml.draw(noisy_circuit)()) 0: ──RX(0.20)──RY(-0.42)────────H──RY(-0.42)──PhaseFlip(0.20)─┤ ╭<X@X> 1: ──H─────────PhaseFlip(0.20)────────────────────────────────┤ ╰<X@X> 2: ──H─────────RY(-0.42)──────────────────────────────────────┤ >>> print(circuit(), noisy_circuit()) 0.9807168489852615 0.35305806563469433
User-friendly decompositions 📠
-
A new transform called
qml.transforms.decompose
has been added to better facilitate the custom decomposition of operators in PennyLane circuits. (#6334)Previous to the addition of
qml.transforms.decompose
, decomposing operators in PennyLane had to be done by specifying astopping_condition
inqml.device.preprocess.decompose
. Withqml.transforms.decompose
, the user-interface for specifying decompositions is much simpler and more versatile.Decomposing gates in a circuit can be done a few ways:
-
Specifying a
gate_set
comprising PennyLaneOperator
s to decompose into:from functools import partial dev = qml.device('default.qubit') allowed_gates = {qml.Toffoli, qml.RX, qml.RZ} @partial(qml.transforms.decompose, gate_set=allowed_gates) @qml.qnode(dev) def circuit(): qml.Hadamard(wires=[0]) qml.Toffoli(wires=[0, 1, 2]) return qml.expval(qml.Z(0))
>>> print(qml.draw(circuit)()) 0: ──RZ(1.57)──RX(1.57)──RZ(1.57)─╭●─┤ <Z> 1: ───────────────────────────────├●─┤ 2: ───────────────────────────────╰X─┤
-
Specifying a
gate_set
that is defined by a rule (Boolean function). For example, one can specify an arbitrary gate set to decompose into, so long as the resulting gates only act on one or two qubits:@partial(qml.transforms.decompose, gate_set = lambda op: len(op.wires) <= 2) @qml.qnode(dev) def circuit(): qml.Toffoli(wires=[0, 1, 2]) return qml.expval(qml.Z(0))
>>> print(qml.draw(circuit)()) 0: ───────────╭●───────────╭●────╭●──T──╭●─┤ <Z> 1: ────╭●─────│─────╭●─────│───T─╰X──T†─╰X─┤ 2: ──H─╰X──T†─╰X──T─╰X──T†─╰X──T──H────────┤
-
Specifying a value for
max_expansion
. By default, decomposition occurs recursively until the desired gate set is reached, but this can be overridden to control the number of passes.phase = 1.0 target_wires = [0] unitary = qml.RX(phase, wires=0).matrix() n_estimation_wires = 1 estimation_wires = range(1, n_estimation_wires + 1) def qfunc(): qml.QuantumPhaseEstimation( unitary, target_wires=target_wires, estimation_wires=estimation_wires, ) decompose_once = qml.transforms.decompose(qfunc, max_expansion=1) decompose_twice = qml.transforms.decompose(qfunc, max_expansion=2)
>>> print(qml.draw(decompose_once)()) 0: ────╭U(M0)¹───────┤ 1: ──H─╰●───────QFT†─┤ M0 = [[0.87758256+0.j 0. -0.47942554j] [0. -0.47942554j 0.87758256+0.j ]] >>> print(qml.draw(decompose_twice)()) 0: ──RZ(1.57)──RY(0.50)─╭X──RY(-0.50)──RZ(-6.28)─╭X──RZ(4.71)─┤ 1: ──H──────────────────╰●───────────────────────╰●──H†───────┤
-
Improvements 🛠
qjit/jit compatibility and improvements
Quantum just-in-time (qjit) compilation is the compilation of hybrid quantum-classical programs during execution of a program, rather than before execution. PennyLane provides just-in-time compilation with its @qml.qjit
decorator, powered by the Catalyst compiler.
-
Several templates are now compatible with qjit:
-
The sample-based measurements now support samples that are JAX tracers, allowing compatiblity with qjit workflows. (#6211)
-
The
qml.FABLE
template now returns the correct value when jit is enabled. (#6263) -
qml.metric_tensor
is now jit compatible. (#6468) -
qml.QutritBasisStatePreparation
is now jit compatible. (#6308) -
All PennyLane templates are now unit tested to ensure jit compatibility. (#6309)
Various improvements to fermionic operators
-
qml.fermi.FermiWord
andqml.fermi.FermiSentence
are now compatible with JAX arrays. (#6324)Fermionic operators interacting, in some way, with a JAX array will no longer raise an error. For example:
>>> import jax.numpy as jnp >>> w = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'}) >>> jnp.array([3]) * w FermiSentence({FermiWord({(0, 0): '+', (1, 1): '-'}): Array([3], dtype=int32)})
-
The
qml.fermi.FermiWord
class now has ashift_operator
method to apply anti-commutator relations. (#6196)>>> w = qml.fermi.FermiWord({(0, 0): '+', (1, 1): '-'}) >>> w FermiWord({(0, 0): '+', (1, 1): '-'}) >>> w.shift_operator(0, 1) FermiSentence({FermiWord({(0, 1): '-', (1, 0): '+'}): -1})
-
The
qml.fermi.FermiWord
andqml.fermi.FermiSentence
classes now anadjoint
method. (#6166)>>> w = qml.fermi.FermiWord({(0, 0): '+', (1, 1): '-'}) >>> w.adjoint() FermiWord({(0, 1): '+', (1, 0): '-'})
-
The
to_mat
methods forqml.fermi.FermiWord
andqml.fermi.FermiSentence
now optionally return a sparse matrix with theformat
keyword argument. (#6173)>>> w = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'}) >>> w.to_mat(format="dense") array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j], [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]]) >>> w.to_mat(format="csr") <4x4 sparse matrix of type '<class 'numpy.complex128'>' with 1 stored elements in Compressed Sparse Row format>
-
When printed,
qml.fermi.FermiWord
andqml.fermi.FermiSentence
now return a unique representation of the object. (#6167)>>> w = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'}) >>> print(w) a⁺(0) a(1)
-
qml.qchem.excitations
now optionally returns fermionic operators with a newfermionic
keyword argument (defaults toFalse
). (#6171)>>> singles, doubles = excitations(electrons, orbitals, fermionic=True) >>> print(singles) [FermiWord({(0, 0): '+', (1, 2): '-'}), FermiWord({(0, 1): '+', (1, 3): '-'})]
A new optimizer
- A new optimizer called
qml.MomentumQNGOptimizer
has been added. It inherits from the basicqml.QNGOptimizer
optimizer and requires one additional hyperparameter: the momentum coefficient,$0 \leq \rho < 1$ , the default value being$\rho=0.9$ . For$\rho=0$ ,qml.MomentumQNGOptimizer
reduces down toqml.QNGOptimizer
. (#6240)
Other Improvements
-
default.tensor
can now handle mid-circuit measurements via the deferred measurement principle. (#6408) -
process_density_matrix
was implemented in 5StateMeasurement
subclasses:ExpVal
,Var
,Purity
,MutualInformation
, andVnEntropy
. This facilitates future support for mixed-state devices and expanded density matrix operations. Also, a fix was made in theProbabilityMP
class to useqml.math.sqrt
instead ofnp.sqrt
. (#6330) -
The decomposition for
qml.Qubitization
has been improved to useqml.PrepSelPrep
. (#6182) -
A
ReferenceQubit
device (shortname:"reference.qubit"
) has been introduced for testing purposes and referencing for future plugin development. (#6181) -
qml.transforms.mitigate_with_zne
now gives a clearer error message when being applied on circuits, not devices, that include channel noise. (#6346) -
A new function called
get_best_diff_method
has been added toqml.workflow
. (#6399) -
A new method called
construct_tape
has been added toqml.workflow
for users to construct single tapes from aQNode
. (#6419) -
An infrastructural improvement was made to PennyLane datasets that allows us to upload datasets more easily. (#6126)
-
qml.Hadamard
now has a more friendly alias:qml.H
. (#6450) -
A Boolean keyword argument called
show_wire_labels
has been added todraw
anddraw_mpl
, which hides wire labels when set toFalse
(the default isTrue
). (#6410) -
A new function called
sample_probs
has been added to theqml.devices.qubit
andqml.devices.qutrit_mixed
modules. This function takes probability distributions as input and returns sampled outcomes, simplifying the sampling process by separating it from other operations in the measurement chain and improving modularity. (#6354) -
qml.labs
has been added to the PennyLane documentation. (#6397) (#6369) -
A
has_sparse_matrix
property has been added toOperator
to indicate whether a sparse matrix is defined. (#6278) (#6310) -
qml.matrix
now works with empty objects (e.g., empty tapes, QNodes and quantum functions that do not call operations, and single operators with empty decompositions). (#6347)dev = qml.device("default.qubit", wires=1) @qml.qnode(dev) def node(): return qml.expval(qml.Z(0))
>>> qml.matrix(node)() array([[1., 0.], [0., 1.]])
-
PennyLane is now compatible with NumPy 2.0. (#6061) (#6258) (#6342)
-
PennyLane is now compatible with Jax 0.4.28. (#6255)
-
The
diagonalize_measurements
transform now uses a more efficient method of diagonalization when possible, based on thepauli_rep
of the relevant observables. (#6113) -
The
QuantumScript.copy
method now takesoperations
,measurements
,shots
andtrainable_params
as keyword arguments. If any of these are passed when copying a tape, the specified attributes will replace the copied attributes on the new tape. (#6285) (#6363) -
The
Hermitian
operator now has acompute_sparse_matrix
implementation. (#6225) -
When an observable is repeated on a tape,
tape.diagonalizing_gates
no longer returns the diagonalizing gates for each instance of the observable. Instead, the diagonalizing gates of each observable on the tape are included just once. (#6288) -
The number of diagonalizing gates returned in
qml.specs
now follows thelevel
keyword argument regarding whether the diagonalizing gates are modified by device, instead of always counting unprocessed diagonalizing gates. (#6290) -
A more sensible error message is raised from a
RecursionError
encountered when accessing properties and methods of a nestedCompositeOp
orSProd
. (#6375)By default,
qml.sum
andqml.prod
setlazy=True
, which keeps its operands nested. Given the recursive nature of such structures, if there are too many levels of nesting, aRecursionError
would occur when accessing many of the properties and methods. -
The performance of the decomposition of
qml.QFT
has been improved. (#6434)
Capturing and representing hybrid programs
-
qml.wires.Wires
now accepts JAX arrays as input. In many workflows with JAX, PennyLane may attempt to assign a JAX array to aWires
object, which will cause an error since JAX arrays are not hashable. Now, JAX arrays are validWires
types. Furthermore, aFutureWarning
is no longer raised inJAX 0.4.30+
when providing JAX tracers as input toqml.wires.Wires
. (#6312) -
A new function called
qml.capture.make_plxpr
has been added to take a function and create aCallable
that, when called, will return a PLxPR representation of the input function. (#6326)` -
Differentiation of hybrid programs via
qml.grad
andqml.jacobian
can now be captured with PLxPR. When evaluating a capturedqml.grad
(qml.jacobian
) instruction, it will dispatch tojax.grad
(jax.jacobian
), which differs from the Autograd implementation without capture. Pytree inputs and outputs are supported. (#6120) (#6127) (#6134) -
Unit testing for capturing nested control flow has been improved. (#6111)
-
Some custom primitives for the capture project can now be imported via
from pennylane.capture.primitives import *
. (#6129) -
All higher order primitives now use
jax.core.Jaxpr
as metadata instead of sometimes usingjax.core.ClosedJaxpr
orjax.core.Jaxpr
. (#6319)
Breaking changes 💔
-
Red-herring validation in
QNode.construct
has been removed, which fixed a bug withqml.GlobalPhase
. (#6373)Removing the
AllWires
validation inQNode.construct
was addressed as a solution to the following example not being able to run:@qml.qnode(qml.device('default.qubit', wires=2)) def circuit(x): qml.GlobalPhase(x, wires=0) return qml.state()
>>> circuit(0.5) array([0.87758256-0.47942554j, 0. +0.j , 1. +0.j , 0. +0.j ])
-
The
simplify
argument inqml.Hamiltonian
andqml.ops.LinearCombination
has been removed. Instead,qml.simplify()
can be called on the constructed operator. (#6279) -
The functions
qml.qinfo.classical_fisher
andqml.qinfo.quantum_fisher
have been removed and migrated to theqml.gradients
module.qml.gradients.classical_fisher
andqml.gradients.quantum_fisher
should be used instead. (#5911) -
Python 3.9 is no longer supported. Please update to 3.10 or newer. (#6223)
-
default.qubit.legacy
,default.qubit.tf
,default.qubit.torch
,default.qubit.jax
, anddefault.qubit.autograd
have been removed. Please usedefault.qubit
for all interfaces. (#6207) (#6208) (#6209) (#6210) (#6266) -
expand_fn
,max_expansion
,override_shots
, anddevice_batch_transform
have been removed from the signature ofqml.execute
. (#6203) -
max_expansion
andexpansion_strategy
have been removed from the QNode. (#6203) -
expansion_strategy
has been removed fromqml.draw
,qml.draw_mpl
, andqml.specs
.max_expansion
has been removed fromqml.specs
, as it had no impact on the output. (#6203) -
qml.transforms.hamiltonian_expand
andqml.transforms.sum_expand
have been removed. Please useqml.transforms.split_non_commuting
instead. (#6204) -
The
decomp_depth
keyword argument toqml.device
has been removed. (#6234) -
Operator.expand
has been removed. Please useqml.tape.QuantumScript(op.decomposition())
instead. (#6227) -
The native folding method
qml.transforms.fold_global
for theqml.transforms.mitigate_with_zne
transform no longer expands the circuit automatically. Instead, the user should applyqml.transforms.decompose
to decompose a circuit into a target gate set before applyingfold_global
ormitigate_with_zne
. (#6382) -
The
LightningVJPs
class has been removed, as all lightning devices now follow the new device interface. (#6420)
Deprecations 👋
-
The
expand_depth
andmax_expansion
arguments forqml.transforms.compile
andqml.transforms.decompositions.clifford_t_decomposition
respectively have been deprecated. (#6404) -
Legacy operator arithmetic has been deprecated. This includes
qml.ops.Hamiltonian
,qml.operation.Tensor
,qml.operation.enable_new_opmath
,qml.operation.disable_new_opmath
, andqml.operation.convert_to_legacy_H
. Note that when new operator arithmetic is enabled,qml.Hamiltonian
will continue to dispatch toqml.ops.LinearCombination
; this behaviour is not deprecated. For more information, check out the updated operator troubleshooting page. (#6287) (#6365) -
qml.pauli.PauliSentence.hamiltonian
andqml.pauli.PauliWord.hamiltonian
have been deprecated. Instead, please useqml.pauli.PauliSentence.operation
andqml.pauli.PauliWord.operation
, respectively. (#6287) -
qml.pauli.simplify()
has been deprecated. Instead, please useqml.simplify(op)
orop.simplify()
. (#6287) -
The
qml.BasisStatePreparation
template has been deprecated. Instead, useqml.BasisState
. (#6021) -
The
'ancilla'
argument forqml.iterative_qpe
has been deprecated. Instead, use the'aux_wire'
argument. (#6277) -
qml.shadows.shadow_expval
has been deprecated. Instead, use theqml.shadow_expval
measurement process. (#6277) -
qml.broadcast
has been deprecated. Please use Pythonfor
loops instead. (#6277) -
The
qml.QubitStateVector
template has been deprecated. Instead, useqml.StatePrep
. (#6172) -
The
qml.qinfo
module has been deprecated. Please see the respective functions in theqml.math
andqml.measurements
modules instead. (#5911) -
Device
,QubitDevice
, andQutritDevice
will no longer be accessible via top-level import in v0.40. They will still be accessible asqml.devices.LegacyDevice
,qml.devices.QubitDevice
, andqml.devices.QutritDevice
respectively. (#6238) -
QNode.gradient_fn
has been deprecated. Please useQNode.diff_method
andQNode.get_gradient_fn
instead. (#6244)
Documentation 📝
-
Updated
qml.spin
documentation. (#6387) -
Updated links to PennyLane.ai in the documentation to use the latest URL format, which excludes the
.html
prefix. (#6412) -
Update
qml.Qubitization
documentation based on new decomposition. (#6276) -
Fixed examples in the documentation of a few optimizers. (#6303) (#6315)
-
Corrected examples in the documentation of
qml.jacobian
. (#6283) (#6315) -
Fixed spelling in a number of places across the documentation. (#6280)
-
Add
work_wires
parameter toqml.MultiControlledX
docstring signature. (#6271) -
Removed ambiguity in error raised by the
PauliRot
class. (#6298) -
Renamed an incorrectly named test in
test_pow_ops.py
. (#6388) -
Removed outdated Docker description from installation page. (#6487)
Bug fixes 🐛
-
The wire order for
Snapshot
's now matches the wire order of the device, rather than the simulation. (#6461) -
Fixed a bug where
QNSPSAOptimizer
,QNGOptimizer
andMomentumQNGOptimizer
calculate invalid parameter updates if the metric tensor becomes singular. (#6471) -
The
default.qubit
device now supports parameter broadcasting withqml.classical_shadow
andqml.shadow_expval
. (#6301) -
Fixed unnecessary call of
eigvals
inqml.ops.op_math.decompositions.two_qubit_unitary.py
that was causing an error in VJP. Raises warnings to users if this essentially nondifferentiable module is used. (#6437) -
Patches the
math
module to function with autoray 0.7.0. (#6429) -
Fixed incorrect differentiation of
PrepSelPrep
when usingdiff_method="parameter-shift"
. (#6423) -
The
validate_device_wires
transform now raises an error if abstract wires are provided. (#6405) -
Fixed
qml.math.expand_matrix
for qutrit and arbitrary qudit operators. (#6398) -
MeasurementValue
now raises an error when it is used as a boolean. (#6386) -
default.qutrit
now returns integer samples. (#6385) -
adjoint_metric_tensor
now works with circuits containing state preparation operations. (#6358) -
quantum_fisher
now respects the classical Jacobian of QNodes. (#6350) -
qml.map_wires
can now be applied to a batch of tapes. (#6295) -
Fixed float-to-complex casting in various places across PennyLane. (#6260) (#6268)
-
Fixed a bug where zero-valued JVPs were calculated wrongly in the presence of shot vectors. (#6219)
-
Fixed
qml.PrepSelPrep
template to work withtorch
. (#6191) -
Fixed a bug where
qml.equal
now correctly comparesqml.PrepSelPrep
operators. (#6182) -
The
qml.QSVT
template now orders theprojector
wires first and theUA
wires second, which is the expected order of the decomposition. (#6212) -
The
qml.Qubitization
template now orders thecontrol
wires first and thehamiltonian
wires second, which is the expected according to other templates. (#6229) -
Fixed a bug where a circuit using the
autograd
interface sometimes returns nested values that are not of theautograd
interface. (#6225) -
Fixed a bug where a simple circuit with no parameters or only builtin/NumPy arrays as parameters returns autograd tensors. (#6225)
-
qml.pauli.PauliVSpace
now uses a more stable SVD-based linear independence check to avoid running intoLinAlgError: Singular matrix
. This stabilizes the usage ofqml.lie_closure
. It also introduces normalization of the basis vector's internal representation_M
to avoid exploding coefficients. (#6232) -
Fixed a bug where
csc_dot_product
is used during measurement forSum
/Hamiltonian
that contains observables that does not define a sparse matrix. (#6278) (#6310) -
Fixed a bug where
None
was added to the wires inqml.PhaseAdder
,qml.Adder
andqml.OutAdder
. (#6360) -
Fixed a test after updating to the nightly version of Catalyst. (#6362)
-
Fixed a bug where
CommutingEvolution
with a trainableHamiltonian
cannot be differentiated using parameter shift. (#6372) -
Fixed a bug where
mitigate_with_zne
loses theshots
information of the original tape. (#6444) -
Fixed a bug where
default.tensor
raises an error when applyingIdentity
/GlobalPhase
on no wires, andPauliRot
/MultiRZ
on a single wire. (#6448) -
Fixes a bug where applying
qml.ctrl
andqml.adjoint
on an operator type instead of an operator instance results in extra operators in the queue. (#6284)
Contributors ✍️
This release contains contributions from (in alphabetical order):
Guillermo Alonso, Utkarsh Azad, Oleksandr Borysenko, Astral Cai, Yushao Chen, Isaac De Vlugt, Diksha Dhawan, Lillian M. A. Frederiksen, Pietropaolo Frisoni, Emiliano Godinez, Anthony Hayes, Austin Huang, Soran Jahangiri, Jacob Kitchen, Korbinian Kottmann, Christina Lee, William Maxwell, Erick Ochoa Lopez, Lee J. O'Riordan, Mudit Pandey, Andrija Paurevic, Alex Preciado, Ashish Kanwar Singh, David Wierichs