Pennylane

Latest version: v0.39.0

Safety actively analyzes 682404 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 11

0.39.0

<h3>New features since last release</h3>

<h4>Creating spin Hamiltonians on lattices ๐Ÿ’ž</h4>

* Functionality for creating custom Hamiltonians on arbitrary lattices has been added. [(6226)](https://github.com/PennyLaneAI/pennylane/pull/6226) [(#6237)](https://github.com/PennyLaneAI/pennylane/pull/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 standard `Lattice` objects, including `'chain'`, `'square'`, `'rectangle'`, `'triangle'`, `'honeycomb'`, `'kagome'`, `'lieb'`, `'cubic'`, `'bcc'`, `'fcc'`, and `'diamond'`,
* `qml.spin.spin_hamiltonian`: generates a spin `Hamiltonian` object given a `Lattice` object with custom edges/nodes.

An example is shown below for a $3 \times 3$ triangular lattice with open boundary conditions.

python
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` against `qml.spin.generate_lattice('triangle', ...)` by checking the `lattice_points` (the $(x, y)$ coordinates of all sites in the lattice):

pycon
>>> 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 the `Lattice` object are nearest-neighbour by default, where we can add edges by using its `add_edge` method.

Optionally, a `Lattice` object can have interactions and fields endowed to it by specifying values for its `custom_edges` and `custom_nodes` keyword arguments. The Hamiltonian can then be extracted with the `qml.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 the `custom_edges` and `custom_nodes` keyword arguments only need to be defined for one unit cell repetition.

python
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)],
)


pycon
>>> 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)](https://github.com/PennyLaneAI/pennylane/pull/6174) [(#6201)](https://github.com/PennyLaneAI/pennylane/pull/6201)

Three new industry-standard spin Hamiltonians are now available with PennyLane v0.39:

* `qml.spin.emery` : the [Emery model](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.58.2794)
* `qml.spin.haldane` : the [Haldane model](https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.61.2015)
* `qml.spin.kitaev` : the [Kitaev model](https://arxiv.org/abs/cond-mat/0506438)

These additions accompany `qml.spin.heisenberg`, `qml.spin.transverse_ising`, and `qml.spin.fermi_hubbard`, which were introduced in v0.38.

<h4>Calculating Polynomials ๐Ÿ”ข</h4>

* Polynomial functions can now be easily encoded into quantum circuits with `qml.OutPoly`. [(6320)](https://github.com/PennyLaneAI/pennylane/pull/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 containing ``Wires`` objects that correspond to the embedded numeric values of $x_1, x_2, \cdots, x_N$,
* `output_wires` : the `Wires` 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$.

python
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"])


pycon
>>> 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 the `mod` keyword argument.

<h4>Readout Noise ๐Ÿ“ </h4>

* Readout errors can now be included in `qml.NoiseModel` and `qml.add_noise` with the new `qml.noise.meas_eq` function. [(6321)](https://github.com/PennyLaneAI/pennylane/pull/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 via `qml.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 any `qml.expval` measurement:

python
c0 = qml.noise.meas_eq(qml.expval)
n0 = qml.noise.partial_wires(qml.PhaseFlip, 0.2)


To include this in a `qml.NoiseModel`, use its `meas_map` keyword argument:

python
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})


pycon
>>> 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 in `qml.noise` via bitwise operators for more versatility.

To add this `noise_model` to a circuit, use the `qml.add_noise` transform as per usual. For example,

python
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))


pycon
>>> 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)โ”€โ”ค โ•ญ<XX>
1: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€PhaseFlip(0.20)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ•ฐ<XX>
2: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€RY(-0.42)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
>>> print(circuit(), noisy_circuit())
0.9807168489852615 0.35305806563469433


<h4>User-friendly decompositions ๐Ÿ“ </h4>

* A new transform called `qml.transforms.decompose` has been added to better facilitate the custom decomposition of operators in PennyLane circuits. [(6334)](https://github.com/PennyLaneAI/pennylane/pull/6334)

Previous to the addition of `qml.transforms.decompose`, decomposing operators in PennyLane had to be done by specifying a `stopping_condition` in `qml.device.preprocess.decompose`. With `qml.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 PennyLane `Operator`s to decompose into:

python
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))


pycon
>>> 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:

python
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))


pycon
>>> 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.

python
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)


pycon
>>> 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โ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค


<h3>Improvements ๐Ÿ› </h3>

<h4>qjit/jit compatibility and improvements</h4>

[Quantum just-in-time (qjit) compilation](https://pennylane.ai/qml/glossary/what-is-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](https://docs.pennylane.ai/projects/catalyst/en/stable/index.html) compiler.

* Several templates are now compatible with qjit:
* `qml.AmplitudeAmplification` [(6306)](https://github.com/PennyLaneAI/pennylane/pull/6306)
* All quantum arithmetic templates [(6307)](https://github.com/PennyLaneAI/pennylane/pull/6307)
* `qml.Qubitization` [(6305)](https://github.com/PennyLaneAI/pennylane/pull/6305)

* The sample-based measurements now support samples that are JAX tracers, allowing compatiblity with qjit workflows. [(6211)](https://github.com/PennyLaneAI/pennylane/pull/6211)

* The `qml.FABLE` template now returns the correct value when jit is enabled. [(6263)](https://github.com/PennyLaneAI/pennylane/pull/6263)

* `qml.metric_tensor` is now jit compatible. [(6468)](https://github.com/PennyLaneAI/pennylane/pull/6468)

* `qml.QutritBasisStatePreparation` is now jit compatible. [(6308)](https://github.com/PennyLaneAI/pennylane/pull/6308)

* All PennyLane templates are now unit tested to ensure jit compatibility. [(6309)](https://github.com/PennyLaneAI/pennylane/pull/6309)

<h4>Various improvements to fermionic operators</h4>

* `qml.fermi.FermiWord` and `qml.fermi.FermiSentence` are now compatible with JAX arrays. [(6324)](https://github.com/PennyLaneAI/pennylane/pull/6324)

Fermionic operators interacting, in some way, with a JAX array will no longer raise an error. For example:

pycon
>>> 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 a `shift_operator` method to apply anti-commutator relations. [(6196)](https://github.com/PennyLaneAI/pennylane/pull/6196)

pycon
>>> 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` and `qml.fermi.FermiSentence` classes now an `adjoint` method. [(6166)](https://github.com/PennyLaneAI/pennylane/pull/6166)

pycon
>>> w = qml.fermi.FermiWord({(0, 0): '+', (1, 1): '-'})
>>> w.adjoint()
FermiWord({(0, 1): '+', (1, 0): '-'})


* The `to_mat` methods for `qml.fermi.FermiWord` and `qml.fermi.FermiSentence` now optionally return a sparse matrix with the `format` keyword argument. [(6173)](https://github.com/PennyLaneAI/pennylane/pull/6173)

pycon
>>> 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` and `qml.fermi.FermiSentence` now return a unique representation of the object. [(6167)](https://github.com/PennyLaneAI/pennylane/pull/6167)

pycon
>>> w = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> print(w)
aโบ(0) a(1)


* `qml.qchem.excitations` now optionally returns fermionic operators with a new `fermionic` keyword argument (defaults to `False`). [(6171)](https://github.com/PennyLaneAI/pennylane/pull/6171)

pycon
>>> singles, doubles = excitations(electrons, orbitals, fermionic=True)
>>> print(singles)
[FermiWord({(0, 0): '+', (1, 2): '-'}), FermiWord({(0, 1): '+', (1, 3): '-'})]


<h4>A new optimizer</h4>

* A new optimizer called `qml.MomentumQNGOptimizer` has been added. It inherits from the basic `qml.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 to `qml.QNGOptimizer`. [(6240)](https://github.com/PennyLaneAI/pennylane/pull/6240)

<h4>Other Improvements</h4>

* `default.tensor` can now handle mid-circuit measurements via the deferred measurement principle. [(6408)](https://github.com/PennyLaneAI/pennylane/pull/6408)

* `process_density_matrix` was implemented in 5 `StateMeasurement` subclasses: `ExpVal`, `Var`, `Purity`, `MutualInformation`, and `VnEntropy`. This facilitates future support for mixed-state devices and expanded density matrix operations. Also, a fix was made in the `ProbabilityMP` class to use `qml.math.sqrt` instead of `np.sqrt`. [(6330)](https://github.com/PennyLaneAI/pennylane/pull/6330)

* The decomposition for `qml.Qubitization` has been improved to use `qml.PrepSelPrep`. [(6182)](https://github.com/PennyLaneAI/pennylane/pull/6182)

* A `ReferenceQubit` device (shortname: `"reference.qubit"`) has been introduced for testing purposes and referencing for future plugin development. [(6181)](https://github.com/PennyLaneAI/pennylane/pull/6181)

* `qml.transforms.mitigate_with_zne` now gives a clearer error message when being applied on circuits, not devices, that include channel noise. [(6346)](https://github.com/PennyLaneAI/pennylane/pull/6346)

* A new function called `get_best_diff_method` has been added to `qml.workflow`. [(6399)](https://github.com/PennyLaneAI/pennylane/pull/6399)

* A new method called `construct_tape` has been added to `qml.workflow` for users to construct single tapes from a `QNode`. [(6419)](https://github.com/PennyLaneAI/pennylane/pull/6419)

* An infrastructural improvement was made to PennyLane datasets that allows us to upload datasets more easily. [(6126)](https://github.com/PennyLaneAI/pennylane/pull/6126)

* `qml.Hadamard` now has a more friendly alias: `qml.H`. [(6450)](https://github.com/PennyLaneAI/pennylane/pull/6450)

* A Boolean keyword argument called `show_wire_labels` has been added to `draw` and `draw_mpl`, which hides wire labels when set to `False` (the default is `True`). [(6410)](https://github.com/PennyLaneAI/pennylane/pull/6410)

* A new function called `sample_probs` has been added to the `qml.devices.qubit` and `qml.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)](https://github.com/PennyLaneAI/pennylane/pull/6354)

* `qml.labs` has been added to the PennyLane documentation. [(6397)](https://github.com/PennyLaneAI/pennylane/pull/6397) [(#6369)](https://github.com/PennyLaneAI/pennylane/pull/6369)

* A `has_sparse_matrix` property has been added to `Operator` to indicate whether a sparse matrix is defined. [(6278)](https://github.com/PennyLaneAI/pennylane/pull/6278) [(#6310)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/6347)

python
dev = qml.device("default.qubit", wires=1)

qml.qnode(dev)
def node():
return qml.expval(qml.Z(0))


pycon
>>> qml.matrix(node)()
array([[1., 0.],
[0., 1.]])


* PennyLane is now compatible with NumPy 2.0. [(6061)](https://github.com/PennyLaneAI/pennylane/pull/6061) [(#6258)](https://github.com/PennyLaneAI/pennylane/pull/6258) [(#6342)](https://github.com/PennyLaneAI/pennylane/pull/6342)

* PennyLane is now compatible with Jax 0.4.28. [(6255)](https://github.com/PennyLaneAI/pennylane/pull/6255)

* The `diagonalize_measurements` transform now uses a more efficient method of diagonalization when possible, based on the `pauli_rep` of the relevant observables. [(6113)](https://github.com/PennyLaneAI/pennylane/pull/6113/)

* The `QuantumScript.copy` method now takes `operations`, `measurements`, `shots` and `trainable_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)](https://github.com/PennyLaneAI/pennylane/pull/6285) [(#6363)](https://github.com/PennyLaneAI/pennylane/pull/6363)

* The `Hermitian` operator now has a `compute_sparse_matrix` implementation. [(6225)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/6288)

* The number of diagonalizing gates returned in `qml.specs` now follows the `level` keyword argument regarding whether the diagonalizing gates are modified by device, instead of always counting unprocessed diagonalizing gates. [(6290)](https://github.com/PennyLaneAI/pennylane/pull/6290)

* A more sensible error message is raised from a `RecursionError` encountered when accessing properties and methods of a nested `CompositeOp` or `SProd`. [(6375)](https://github.com/PennyLaneAI/pennylane/pull/6375)

By default, `qml.sum` and `qml.prod` set `lazy=True`, which keeps its operands nested. Given the recursive nature of such structures, if there are too many levels of nesting, a `RecursionError` would occur when accessing many of the properties and methods.

* The performance of the decomposition of `qml.QFT` has been improved. [(6434)](https://github.com/PennyLaneAI/pennylane/pull/6434)

<h4>Capturing and representing hybrid programs</h4>

* `qml.wires.Wires` now accepts JAX arrays as input. In many workflows with JAX, PennyLane may attempt to assign a JAX array to a `Wires` object, which will cause an error since JAX arrays are not hashable. Now, JAX arrays are valid `Wires` types. Furthermore, a `FutureWarning` is no longer raised in `JAX 0.4.30+` when providing JAX tracers as input to `qml.wires.Wires`. [(6312)](https://github.com/PennyLaneAI/pennylane/pull/6312)

* A new function called `qml.capture.make_plxpr` has been added to take a function and create a `Callable` that, when called, will return a PLxPR representation of the input function. [(6326)](https://github.com/PennyLaneAI/pennylane/pull/6326)`

* Differentiation of hybrid programs via `qml.grad` and `qml.jacobian` can now be captured with PLxPR. When evaluating a captured `qml.grad` (`qml.jacobian`) instruction, it will dispatch to `jax.grad` (`jax.jacobian`), which differs from the Autograd implementation without capture. Pytree inputs and outputs are supported. [(6120)](https://github.com/PennyLaneAI/pennylane/pull/6120) [(#6127)](https://github.com/PennyLaneAI/pennylane/pull/6127) [(#6134)](https://github.com/PennyLaneAI/pennylane/pull/6134)

* Unit testing for capturing nested control flow has been improved. [(6111)](https://github.com/PennyLaneAI/pennylane/pull/6111)

* Some custom primitives for the capture project can now be imported via `from pennylane.capture.primitives import *`. [(6129)](https://github.com/PennyLaneAI/pennylane/pull/6129)

* All higher order primitives now use `jax.core.Jaxpr` as metadata instead of sometimes using `jax.core.ClosedJaxpr` or `jax.core.Jaxpr`. [(6319)](https://github.com/PennyLaneAI/pennylane/pull/6319)

<h3>Breaking changes ๐Ÿ’”</h3>

* Red-herring validation in `QNode.construct` has been removed, which fixed a bug with `qml.GlobalPhase`. [(6373)](https://github.com/PennyLaneAI/pennylane/pull/6373)

Removing the `AllWires` validation in `QNode.construct` was addressed as a solution to the following example not being able to run:

python
qml.qnode(qml.device('default.qubit', wires=2))
def circuit(x):
qml.GlobalPhase(x, wires=0)
return qml.state()


pycon
>>> circuit(0.5)
array([0.87758256-0.47942554j, 0. +0.j ,
1. +0.j , 0. +0.j ])


* The `simplify` argument in `qml.Hamiltonian` and `qml.ops.LinearCombination` has been removed. Instead, `qml.simplify()` can be called on the constructed operator. [(6279)](https://github.com/PennyLaneAI/pennylane/pull/6279)

* The functions `qml.qinfo.classical_fisher` and `qml.qinfo.quantum_fisher` have been removed and migrated to the `qml.gradients` module. `qml.gradients.classical_fisher` and `qml.gradients.quantum_fisher` should be used instead. [(5911)](https://github.com/PennyLaneAI/pennylane/pull/5911)

* Python 3.9 is no longer supported. Please update to 3.10 or newer. [(6223)](https://github.com/PennyLaneAI/pennylane/pull/6223)

* `default.qubit.legacy`, `default.qubit.tf`, `default.qubit.torch`, `default.qubit.jax`, and `default.qubit.autograd` have been removed. Please use `default.qubit` for all interfaces. [(6207)](https://github.com/PennyLaneAI/pennylane/pull/6207) [(#6208)](https://github.com/PennyLaneAI/pennylane/pull/6208) [(#6209)](https://github.com/PennyLaneAI/pennylane/pull/6209) [(#6210)](https://github.com/PennyLaneAI/pennylane/pull/6210) [(#6266)](https://github.com/PennyLaneAI/pennylane/pull/6266)

* `expand_fn`, `max_expansion`, `override_shots`, and `device_batch_transform` have been removed from the signature of `qml.execute`. [(6203)](https://github.com/PennyLaneAI/pennylane/pull/6203)

* `max_expansion` and `expansion_strategy` have been removed from the QNode. [(6203)](https://github.com/PennyLaneAI/pennylane/pull/6203)

* `expansion_strategy` has been removed from `qml.draw`, `qml.draw_mpl`, and `qml.specs`. `max_expansion` has been removed from `qml.specs`, as it had no impact on the output. [(6203)](https://github.com/PennyLaneAI/pennylane/pull/6203)

* `qml.transforms.hamiltonian_expand` and `qml.transforms.sum_expand` have been removed. Please use `qml.transforms.split_non_commuting` instead. [(6204)](https://github.com/PennyLaneAI/pennylane/pull/6204)

* The `decomp_depth` keyword argument to `qml.device` has been removed. [(6234)](https://github.com/PennyLaneAI/pennylane/pull/6234)

* `Operator.expand` has been removed. Please use `qml.tape.QuantumScript(op.decomposition())` instead. [(6227)](https://github.com/PennyLaneAI/pennylane/pull/6227)

* The native folding method `qml.transforms.fold_global` for the `qml.transforms.mitigate_with_zne` transform no longer expands the circuit automatically. Instead, the user should apply `qml.transforms.decompose` to decompose a circuit into a target gate set before applying `fold_global` or `mitigate_with_zne`. [(6382)](https://github.com/PennyLaneAI/pennylane/pull/6382)

* The `LightningVJPs` class has been removed, as all lightning devices now follow the new device interface. [(6420)](https://github.com/PennyLaneAI/pennylane/pull/6420)

<h3>Deprecations ๐Ÿ‘‹</h3>

* The `expand_depth` and `max_expansion` arguments for `qml.transforms.compile` and `qml.transforms.decompositions.clifford_t_decomposition` respectively have been deprecated. [(6404)](https://github.com/PennyLaneAI/pennylane/pull/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`, and `qml.operation.convert_to_legacy_H`. Note that when new operator arithmetic is enabled, `qml.Hamiltonian` will continue to dispatch to `qml.ops.LinearCombination`; this behaviour is not deprecated. For more information, check out the [updated operator troubleshooting page](https://docs.pennylane.ai/en/stable/news/new_opmath.html). [(#6287)](https://github.com/PennyLaneAI/pennylane/pull/6287) [(#6365)](https://github.com/PennyLaneAI/pennylane/pull/6365)

* `qml.pauli.PauliSentence.hamiltonian` and `qml.pauli.PauliWord.hamiltonian` have been deprecated. Instead, please use `qml.pauli.PauliSentence.operation` and `qml.pauli.PauliWord.operation`, respectively. [(6287)](https://github.com/PennyLaneAI/pennylane/pull/6287)

* `qml.pauli.simplify()` has been deprecated. Instead, please use `qml.simplify(op)` or `op.simplify()`. [(6287)](https://github.com/PennyLaneAI/pennylane/pull/6287)

* The `qml.BasisStatePreparation` template has been deprecated. Instead, use `qml.BasisState`. [(6021)](https://github.com/PennyLaneAI/pennylane/pull/6021)

* The `'ancilla'` argument for `qml.iterative_qpe` has been deprecated. Instead, use the `'aux_wire'` argument. [(6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* `qml.shadows.shadow_expval` has been deprecated. Instead, use the `qml.shadow_expval` measurement process. [(6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* `qml.broadcast` has been deprecated. Please use Python `for` loops instead. [(6277)](https://github.com/PennyLaneAI/pennylane/pull/6277)

* The `qml.QubitStateVector` template has been deprecated. Instead, use `qml.StatePrep`. [(6172)](https://github.com/PennyLaneAI/pennylane/pull/6172)

* The `qml.qinfo` module has been deprecated. Please see the respective functions in the `qml.math` and `qml.measurements` modules instead. [(5911)](https://github.com/PennyLaneAI/pennylane/pull/5911)

* `Device`, `QubitDevice`, and `QutritDevice` will no longer be accessible via top-level import in v0.40. They will still be accessible as `qml.devices.LegacyDevice`, `qml.devices.QubitDevice`, and `qml.devices.QutritDevice` respectively. [(6238)](https://github.com/PennyLaneAI/pennylane/pull/6238/)

* `QNode.gradient_fn` has been deprecated. Please use `QNode.diff_method` and `QNode.get_gradient_fn` instead. [(6244)](https://github.com/PennyLaneAI/pennylane/pull/6244)

<h3>Documentation ๐Ÿ“</h3>

* Updated `qml.spin` documentation. [(6387)](https://github.com/PennyLaneAI/pennylane/pull/6387)

* Updated links to PennyLane.ai in the documentation to use the latest URL format, which excludes the `.html` prefix. [(6412)](https://github.com/PennyLaneAI/pennylane/pull/6412)

* Update `qml.Qubitization` documentation based on new decomposition. [(6276)](https://github.com/PennyLaneAI/pennylane/pull/6276)

* Fixed examples in the documentation of a few optimizers. [(6303)](https://github.com/PennyLaneAI/pennylane/pull/6303) [(#6315)](https://github.com/PennyLaneAI/pennylane/pull/6315)

* Corrected examples in the documentation of `qml.jacobian`. [(6283)](https://github.com/PennyLaneAI/pennylane/pull/6283) [(#6315)](https://github.com/PennyLaneAI/pennylane/pull/6315)

* Fixed spelling in a number of places across the documentation. [(6280)](https://github.com/PennyLaneAI/pennylane/pull/6280)

* Add `work_wires` parameter to `qml.MultiControlledX` docstring signature. [(6271)](https://github.com/PennyLaneAI/pennylane/pull/6271)

* Removed ambiguity in error raised by the `PauliRot` class. [(6298)](https://github.com/PennyLaneAI/pennylane/pull/6298)

* Renamed an incorrectly named test in `test_pow_ops.py`. [(6388)](https://github.com/PennyLaneAI/pennylane/pull/6388)

* Removed outdated Docker description from installation page. [(6487)](https://github.com/PennyLaneAI/pennylane/pull/6487)

<h3>Bug fixes ๐Ÿ›</h3>

* The wire order for `Snapshot`'s now matches the wire order of the device, rather than the simulation. [(6461)](https://github.com/PennyLaneAI/pennylane/pull/6461)

* Fixed a bug where `QNSPSAOptimizer`, `QNGOptimizer` and `MomentumQNGOptimizer` calculate invalid parameter updates if the metric tensor becomes singular. [(6471)](https://github.com/PennyLaneAI/pennylane/pull/6471)

* The `default.qubit` device now supports parameter broadcasting with `qml.classical_shadow` and `qml.shadow_expval`. [(6301)](https://github.com/PennyLaneAI/pennylane/pull/6301)

* Fixed unnecessary call of `eigvals` in `qml.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)](https://github.com/PennyLaneAI/pennylane/pull/6437)

* Patches the `math` module to function with autoray 0.7.0. [(6429)](https://github.com/PennyLaneAI/pennylane/pull/6429)

* Fixed incorrect differentiation of `PrepSelPrep` when using `diff_method="parameter-shift"`. [(6423)](https://github.com/PennyLaneAI/pennylane/pull/6423)

* The `validate_device_wires` transform now raises an error if abstract wires are provided. [(6405)](https://github.com/PennyLaneAI/pennylane/pull/6405)

* Fixed `qml.math.expand_matrix` for qutrit and arbitrary qudit operators. [(6398)](https://github.com/PennyLaneAI/pennylane/pull/6398/)

* `MeasurementValue` now raises an error when it is used as a boolean. [(6386)](https://github.com/PennyLaneAI/pennylane/pull/6386)

* `default.qutrit` now returns integer samples. [(6385)](https://github.com/PennyLaneAI/pennylane/pull/6385)

* `adjoint_metric_tensor` now works with circuits containing state preparation operations. [(6358)](https://github.com/PennyLaneAI/pennylane/pull/6358)

* `quantum_fisher` now respects the classical Jacobian of QNodes. [(6350)](https://github.com/PennyLaneAI/pennylane/pull/6350)

* `qml.map_wires` can now be applied to a batch of tapes. [(6295)](https://github.com/PennyLaneAI/pennylane/pull/6295)

* Fixed float-to-complex casting in various places across PennyLane. [(6260)](https://github.com/PennyLaneAI/pennylane/pull/6260) [(#6268)](https://github.com/PennyLaneAI/pennylane/pull/6268)

* Fixed a bug where zero-valued JVPs were calculated wrongly in the presence of shot vectors. [(6219)](https://github.com/PennyLaneAI/pennylane/pull/6219)

* Fixed `qml.PrepSelPrep` template to work with `torch`. [(6191)](https://github.com/PennyLaneAI/pennylane/pull/6191)

* Fixed a bug where `qml.equal` now correctly compares `qml.PrepSelPrep` operators. [(6182)](https://github.com/PennyLaneAI/pennylane/pull/6182)

* The `qml.QSVT` template now orders the `projector` wires first and the `UA` wires second, which is the expected order of the decomposition. [(6212)](https://github.com/PennyLaneAI/pennylane/pull/6212)

* The `qml.Qubitization` template now orders the `control` wires first and the `hamiltonian` wires second, which is the expected according to other templates. [(6229)](https://github.com/PennyLaneAI/pennylane/pull/6229)

* Fixed a bug where a circuit using the `autograd` interface sometimes returns nested values that are not of the `autograd` interface. [(6225)](https://github.com/PennyLaneAI/pennylane/pull/6225)

* Fixed a bug where a simple circuit with no parameters or only builtin/NumPy arrays as parameters returns autograd tensors. [(6225)](https://github.com/PennyLaneAI/pennylane/pull/6225)

* `qml.pauli.PauliVSpace` now uses a more stable SVD-based linear independence check to avoid running into `LinAlgError: Singular matrix`. This stabilizes the usage of `qml.lie_closure`. It also introduces normalization of the basis vector's internal representation `_M` to avoid exploding coefficients. [(6232)](https://github.com/PennyLaneAI/pennylane/pull/6232)

* Fixed a bug where `csc_dot_product` is used during measurement for `Sum`/`Hamiltonian` that contains observables that does not define a sparse matrix. [(6278)](https://github.com/PennyLaneAI/pennylane/pull/6278) [(#6310)](https://github.com/PennyLaneAI/pennylane/pull/6310)

* Fixed a bug where `None` was added to the wires in `qml.PhaseAdder`, `qml.Adder` and `qml.OutAdder`. [(6360)](https://github.com/PennyLaneAI/pennylane/pull/6360)

* Fixed a test after updating to the nightly version of Catalyst. [(6362)](https://github.com/PennyLaneAI/pennylane/pull/6362)

* Fixed a bug where `CommutingEvolution` with a trainable `Hamiltonian` cannot be differentiated using parameter shift. [(6372)](https://github.com/PennyLaneAI/pennylane/pull/6372)

* Fixed a bug where `mitigate_with_zne` loses the `shots` information of the original tape. [(6444)](https://github.com/PennyLaneAI/pennylane/pull/6444)

* Fixed a bug where `default.tensor` raises an error when applying `Identity`/`GlobalPhase` on no wires, and `PauliRot`/`MultiRZ` on a single wire. [(6448)](https://github.com/PennyLaneAI/pennylane/pull/6448)

* Fixes a bug where applying `qml.ctrl` and `qml.adjoint` on an operator type instead of an operator instance results in extra operators in the queue. [(6284)](https://github.com/PennyLaneAI/pennylane/pull/6284)

<h3>Contributors โœ๏ธ</h3>

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

0.38.0

<h3>New features since last release</h3>

<h4>Registers of wires ๐Ÿงธ</h4>

* A new function called `qml.registers` has been added that lets you seamlessly create registers of wires. [(5957)](https://github.com/PennyLaneAI/pennylane/pull/5957) [(#6102)](https://github.com/PennyLaneAI/pennylane/pull/6102)

Using registers, it is easier to build large algorithms and circuits by applying gates and operations to predefined collections of wires. With `qml.registers`, you can create registers of wires by providing a dictionary whose keys are register names and whose values are the number of wires in each register.

python
>>> wire_reg = qml.registers({"alice": 4, "bob": 3})
>>> wire_reg
{'alice': Wires([0, 1, 2, 3]), 'bob': Wires([4, 5, 6])}


The resulting data structure of `qml.registers` is a dictionary with the same register names as keys, but the values are `qml.wires.Wires` instances.

Nesting registers within other registers can be done by providing a nested dictionary, where the ordering of wire labels is based on the order of appearance and nestedness.

python
>>> wire_reg = qml.registers({"alice": {"alice1": 1, "alice2": 2}, "bob": {"bob1": 2, "bob2": 1}})
>>> wire_reg
{'alice1': Wires([0]), 'alice2': Wires([1, 2]), 'alice': Wires([0, 1, 2]), 'bob1': Wires([3, 4]), 'bob2': Wires([5]), 'bob': Wires([3, 4, 5])}


Since the values of the dictionary are `Wires` instances, their use within quantum circuits is very similar to that of a `list` of integers.

python
dev = qml.device("default.qubit")

qml.qnode(dev)
def circuit():
for w in wire_reg["alice"]:
qml.Hadamard(w)

for w in wire_reg["bob1"]:
qml.RX(0.1967, wires=w)

qml.CNOT(wires=[wire_reg["alice1"][0], wire_reg["bob2"][0]])

return [qml.expval(qml.Y(w)) for w in wire_reg["bob1"]]

print(qml.draw(circuit)())


pycon
0: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”ค
1: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”ค
2: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”ค
3: โ”€โ”€RX(0.20)โ”€โ”‚โ”€โ”€โ”ค <Y>
4: โ”€โ”€RX(0.20)โ”€โ”‚โ”€โ”€โ”ค <Y>
5: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”ค


In tandem with `qml.registers`, we've also made the following improvements to `qml.wires.Wires`:

* `Wires` instances now have a more copy-paste friendly representation when printed. [(5958)](https://github.com/PennyLaneAI/pennylane/pull/5958)

python
>>> from pennylane.wires import Wires
>>> w = Wires([1, 2, 3])
>>> w
Wires([1, 2, 3])


* Python set-based combinations are now supported by `Wires`. [(5983)](https://github.com/PennyLaneAI/pennylane/pull/5983)

This new feature unlocks the ability to combine `Wires` instances in the following ways:

* intersection with `&` or `intersection()`:

python
>>> wires1 = Wires([1, 2, 3])
>>> wires2 = Wires([2, 3, 4])
>>> wires1.intersection(wires2) or wires1 & wires2
Wires([2, 3])


* symmetric difference with `^` or `symmetric_difference()`:

python
>>> wires1.symmetric_difference(wires2) or wires1 ^ wires2
Wires([1, 4])


* union with `|` or `union()`:

python
>>> wires1.union(wires2) or wires1 | wires2
Wires([1, 2, 3, 4])


* difference with `-` or `difference()`:

python
>>> wires1.difference(wires2) or wires1 - wires2
Wires([1])


<h4>Quantum arithmetic operations ๐Ÿงฎ</h4>

* Several new operator templates have been added to PennyLane that let you perform quantum arithmetic operations. [(6109)](https://github.com/PennyLaneAI/pennylane/pull/6109) [(#6112)](https://github.com/PennyLaneAI/pennylane/pull/6112) [(#6121)](https://github.com/PennyLaneAI/pennylane/pull/6121)

* `qml.Adder` performs in-place modular addition: $\text{Adder}(k, m)\vert x \rangle = \vert x + k \; \text{mod} \; m\rangle$.

* `qml.PhaseAdder` is similar to `qml.Adder`, but it performs in-place modular addition in the Fourier basis.

* `qml.Multiplier` performs in-place multiplication: $\text{Multiplier}(k, m)\vert x \rangle = \vert x \times k \; \text{mod} \; m \rangle$.

* `qml.OutAdder` performs out-place modular addition: $\text{OutAdder}(m)\vert x \rangle \vert y \rangle \vert b \rangle = \vert x \rangle \vert y \rangle \vert b + x + y \; \text{mod} \; m \rangle$.

* `qml.OutMultiplier` performs out-place modular multiplication: $\text{OutMultiplier}(m)\vert x \rangle \vert y \rangle \vert b \rangle = \vert x \rangle \vert y \rangle \vert b + x \times y \; \text{mod} \; m \rangle$.

* `qml.ModExp` performs modular exponentiation: $\text{ModExp}(base, m) \vert x \rangle \vert k \rangle = \vert x \rangle \vert k \times base^x \; \text{mod} \; m \rangle$.

Here is a comprehensive example that performs the following calculation: `(2 + 1) * 3 mod 7 = 2` (or `010` in binary).

python
dev = qml.device("default.qubit", shots=1)

wire_reg = qml.registers({
"x_wires": 2, |x>: stores the result of 2 + 1 = 3
"y_wires": 2, |y>: multiples x by 3
"output_wires": 3, stores the result of (2 + 1) * 3 m 7 = 2
"work_wires": 2 for qml.OutMultiplier
})

qml.qnode(dev)
def circuit():
In-place addition
qml.BasisEmbedding(2, wires=wire_reg["x_wires"])
qml.Adder(1, x_wires=wire_reg["x_wires"]) add 1 to wires [0, 1]

Out-place multiplication
qml.BasisEmbedding(3, wires=wire_reg["y_wires"])
qml.OutMultiplier(
wire_reg["x_wires"],
wire_reg["y_wires"],
wire_reg["output_wires"],
work_wires=wire_reg["work_wires"],
mod=7
)

return qml.sample(wires=wire_reg["output_wires"])



>>> circuit()
array([0, 1, 0])


<h4>Converting noise models from Qiskit โ™ป๏ธ</h4>

* Convert Qiskit noise models into a PennyLane `NoiseModel` with `qml.from_qiskit_noise`. [(5996)](https://github.com/PennyLaneAI/pennylane/pull/5996)

In the last few releases, we've added substantial improvements and new features to the [Pennylane-Qiskit plugin](https://docs.pennylane.ai/projects/qiskit/en/latest/installation.html). With this release, a new `qml.from_qiskit_noise` function allows you to convert a Qiskit noise model into a PennyLane `NoiseModel`. Here is a simple example with two quantum errors that add two different depolarizing errors based on the presence of different gates in the circuit:

python
import pennylane as qml
import qiskit_aer.noise as noise

error_1 = noise.depolarizing_error(0.001, 1) 1-qubit noise
error_2 = noise.depolarizing_error(0.01, 2) 2-qubit noise

noise_model = noise.NoiseModel()

noise_model.add_all_qubit_quantum_error(error_1, ['rz', 'ry'])
noise_model.add_all_qubit_quantum_error(error_2, ['cx'])


pycon
>>> qml.from_qiskit_noise(noise_model)
NoiseModel({
OpIn(['RZ', 'RY']): QubitChannel(num_kraus=4, num_wires=1)
OpIn(['CNOT']): QubitChannel(num_kraus=16, num_wires=2)
})


Under the hood, PennyLane converts each quantum error in the Qiskit noise model into an equivalent `qml.QubitChannel` operator with the same canonical [Kraus representation](https://en.wikipedia.org/wiki/Quantum_operation#Kraus_operators). Currently, noise models in PennyLane do not support readout errors. As such, those will be skipped during conversion if they are present in the Qiskit noise model.

Make sure to `pip install pennylane-qiskit` to access this new feature!

<h4>Substantial upgrades to mid-circuit measurements using tree-traversal ๐ŸŒณ</h4>

* The `"tree-traversal"` algorithm for mid-circuit measurements (MCMs) on `default.qubit` has been internally redesigned for better performance. [(5868)](https://github.com/PennyLaneAI/pennylane/pull/5868)

In the last release (v0.37), we introduced the tree-traversal MCM method, which was implemented in a recursive way for simplicity. However, this had the unintended consequence of very deep [stack calls](https://en.wikipedia.org/wiki/Call_stack) for circuits with many MCMs, resulting in [stack overflows](https://en.wikipedia.org/wiki/Stack_overflow) in some cases. With this release, we've refactored the implementation of the tree-traversal method into an iterative approach, which solves those inefficiencies when many MCMs are present in a circuit.

* The `tree-traversal` algorithm is now compatible with analytic-mode execution (`shots=None`). [(5868)](https://github.com/PennyLaneAI/pennylane/pull/5868)

python
dev = qml.device("default.qubit")

n_qubits = 5

qml.qnode(dev, mcm_method="tree-traversal")
def circuit():
for w in range(n_qubits):
qml.Hadamard(w)

for w in range(n_qubits - 1):
qml.CNOT(wires=[w, w+1])

for w in range(n_qubits):
m = qml.measure(w)
qml.cond(m == 1, qml.RX)(0.1967 * (w + 1), w)

return [qml.expval(qml.Z(w)) for w in range(n_qubits)]


pycon
>>> circuit()
[tensor(0.00964158, requires_grad=True),
tensor(0.03819446, requires_grad=True),
tensor(0.08455748, requires_grad=True),
tensor(0.14694258, requires_grad=True),
tensor(0.2229438, requires_grad=True)]


<h3>Improvements ๐Ÿ› </h3>

<h4>Creating spin Hamiltonians</h4>

* Three new functions are now available for creating commonly-used spin Hamiltonians in PennyLane: [(6106)](https://github.com/PennyLaneAI/pennylane/pull/6106) [(#6128)](https://github.com/PennyLaneAI/pennylane/pull/6128)

* `qml.spin.transverse_ising` creates the [transverse-field Ising model](https://en.wikipedia.org/wiki/Transverse-field_Ising_model) Hamiltonian.
* `qml.spin.heisenberg` creates the [Heisenberg model](https://en.wikipedia.org/wiki/Quantum_Heisenberg_model) Hamiltonian.
* `qml.spin.fermi_hubbard` creates the [Fermi-Hubbard model](https://en.wikipedia.org/wiki/Hubbard_model) Hamiltonian.

Each Hamiltonian can be instantiated by specifying a `lattice`, the number of [unit cells](https://en.wikipedia.org/wiki/Unit_cell), `n_cells`, and the Hamiltonian parameters as keyword arguments. Here is an example with the transverse-field Ising model:

pycon
>>> tfim_ham = qml.spin.transverse_ising(lattice="square", n_cells=[2, 2], coupling=0.5, h=0.2)
>>> tfim_ham
(
-0.5 * (Z(0) Z(1))
+ -0.5 * (Z(0) Z(2))
+ -0.5 * (Z(1) Z(3))
+ -0.5 * (Z(2) Z(3))
+ -0.2 * X(0)
+ -0.2 * X(1)
+ -0.2 * X(2)
+ -0.2 * X(3)
)


The resulting object is a `qml.Hamiltonian` instance, making it easy to use in circuits like the following.

python
dev = qml.device("default.qubit", shots=1)

qml.qnode(dev)
def circuit():
return qml.expval(tfim_ham)



>>> circuit()
-2.0


More features will be added to the `qml.spin` module in the coming releases, so stay tuned!

<h4>A Prep-Select-Prep template</h4>

* A new template called `qml.PrepSelPrep` has been added that implements a block-encoding of a linear combination of unitaries. [(5756)](https://github.com/PennyLaneAI/pennylane/pull/5756) [(#5987)](https://github.com/PennyLaneAI/pennylane/pull/5987)

This operator acts as a nice wrapper for having to perform `qml.StatePrep`, `qml.Select`, and `qml.adjoint(qml.StatePrep)` in succession, which is quite common in many quantum algorithms (e.g., [LCU and block encoding](https://pennylane.ai/qml/demos/tutorial_lcu_blockencoding/)). Here is an example showing the equivalence between using `qml.PrepSelPrep` and `qml.StatePrep`, `qml.Select`, and `qml.adjoint(qml.StatePrep)`.

python
coeffs = [0.3, 0.1]
alphas = (np.sqrt(coeffs) / np.linalg.norm(np.sqrt(coeffs)))
unitaries = [qml.X(2), qml.Z(2)]

lcu = qml.dot(coeffs, unitaries)
control = [0, 1]

def prep_sel_prep(alphas, unitaries):
qml.StatePrep(alphas, wires=control, pad_with=0)
qml.Select(unitaries, control=control)
qml.adjoint(qml.StatePrep)(alphas, wires=control, pad_with=0)

qml.qnode(qml.device("default.qubit"))
def circuit(lcu, control, alphas, unitaries):
qml.PrepSelPrep(lcu, control)
qml.adjoint(prep_sel_prep)(alphas, unitaries)
return qml.state()


pycon
>>> import numpy as np
>>> np.round(circuit(lcu, control, alphas, unitaries), decimals=2)
tensor([1.+0.j -0.+0.j -0.+0.j -0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j], requires_grad=True)


<h4>QChem improvements</h4>

* Molecules and Hamiltonians can now be constructed for all the elements present in the periodic table. [(5821)](https://github.com/PennyLaneAI/pennylane/pull/5821)

This new feature is made possible by integrating with the [basis-set-exchange package](https://pypi.org/project/basis-set-exchange/). If loading basis sets from `basis-set-exchange` is needed for your molecule, make sure that you `pip install basis-set-exchange` and set `load_data=True`.

python
symbols = ['Ti', 'Ti']
geometry = np.array([[0.0, 0.0, -1.1967],
[0.0, 0.0, 1.1967]], requires_grad=True)
mol = qml.qchem.Molecule(symbols, geometry, load_data=True)


pycon
>>> mol.n_electrons
44


* `qml.UCCSD` now accepts an additional optional argument, `n_repeats`, which defines the number of times the UCCSD template is repeated. This can improve the accuracy of the template by reducing the Trotter error, but would result in deeper circuits. [(5801)](https://github.com/PennyLaneAI/pennylane/pull/5801)

* The `qml.qchem.qubit_observable` function has been modified to return an ascending wire order for molecular Hamiltonians. [(5950)](https://github.com/PennyLaneAI/pennylane/pull/5950)

* A new method called `to_mat` has been added to the `qml.FermiWord` and `qml.FermiSentence` classes, which allows for computing the matrix representation of these Fermi operators. [(5920)](https://github.com/PennyLaneAI/pennylane/pull/5920)

<h4>Improvements to operators</h4>

* `qml.GlobalPhase` now supports parameter broadcasting. [(5923)](https://github.com/PennyLaneAI/pennylane/pull/5923)

* `qml.Hermitian` now has a `compute_decomposition` method. [(6062)](https://github.com/PennyLaneAI/pennylane/pull/6062)

* The implementation of `qml.PhaseShift`, `qml.S`, and `qml.T` has been improved, resulting in faster circuit execution times. [(5876)](https://github.com/PennyLaneAI/pennylane/pull/5876)

* The `qml.CNOT` operator no longer decomposes into itself. Instead, it raises a `qml.DecompositionUndefinedError`. [(6039)](https://github.com/PennyLaneAI/pennylane/pull/6039)

<h4>Mid-circuit measurements</h4>

* The `qml.dynamic_one_shot` transform now supports circuits using the `"tensorflow"` interface. [(5973)](https://github.com/PennyLaneAI/pennylane/pull/5973)

* If the conditional does not include a mid-circuit measurement, then `qml.cond` will automatically evaluate conditionals using standard Python control flow. [(6016)](https://github.com/PennyLaneAI/pennylane/pull/6016)

This allows `qml.cond` to be used to represent a wider range of conditionals:

python
dev = qml.device("default.qubit", wires=1)

qml.qnode(dev)
def circuit(x):
c = qml.cond(x > 2.7, qml.RX, qml.RZ)
c(x, wires=0)
return qml.probs(wires=0)


pycon
>>> print(qml.draw(circuit)(3.8))
0: โ”€โ”€RX(3.80)โ”€โ”ค Probs
>>> print(qml.draw(circuit)(0.54))
0: โ”€โ”€RZ(0.54)โ”€โ”ค Probs


<h4>Transforms</h4>

* `qml.transforms.single_qubit_fusion` and `qml.transforms.merge_rotations` now respect global phases. [(6031)](https://github.com/PennyLaneAI/pennylane/pull/6031)

* A new transform called `qml.transforms.diagonalize_measurements` has been added. This transform converts measurements to the computational basis by applying the relevant diagonalizing gates. It can be set to diagonalize only a subset of the base observables `{qml.X, qml.Y, qml.Z, qml.Hadamard}`. [(5829)](https://github.com/PennyLaneAI/pennylane/pull/5829)

* A new transform called `split_to_single_terms` has been added. This transform splits expectation values of sums into multiple single-term measurements on a single tape, providing better support for simulators that can handle non-commuting observables but don't natively support multi-term observables. [(5884)](https://github.com/PennyLaneAI/pennylane/pull/5884)

* New functionality has been added to natively support exponential extrapolation when using `qml.transforms.mitigate_with_zne`. This allows users to have more control over the error mitigation protocol without needing to add further dependencies. [(5972)](https://github.com/PennyLaneAI/pennylane/pull/5972)

<h4>Capturing and representing hybrid programs</h4>

* `qml.for_loop` now supports `range`-like syntax with default `step=1`. [(6068)](https://github.com/PennyLaneAI/pennylane/pull/6068)

* Applying `adjoint` and `ctrl` to a quantum function can now be captured into plxpr. Furthermore, the `qml.cond` function can be captured into plxpr. [(5966)](https://github.com/PennyLaneAI/pennylane/pull/5966) [(#5967)](https://github.com/PennyLaneAI/pennylane/pull/5967) [(#5999)](https://github.com/PennyLaneAI/pennylane/pull/5999) [(#6058)](https://github.com/PennyLaneAI/pennylane/pull/6058)

* During experimental program capture, functions that accept and/or return `pytree` structures can now be handled in the `qml.QNode` call, `qml.cond`, `qml.for_loop` and `qml.while_loop`. [(6081)](https://github.com/PennyLaneAI/pennylane/pull/6081)

* During experimental program capture, QNodes can now use closure variables. [(6052)](https://github.com/PennyLaneAI/pennylane/pull/6052)

* Mid-circuit measurements can now be captured with `qml.capture` enabled. [(6015)](https://github.com/PennyLaneAI/pennylane/pull/6015)

* `qml.for_loop` can now be captured into plxpr. [(6041)](https://github.com/PennyLaneAI/pennylane/pull/6041) [(#6064)](https://github.com/PennyLaneAI/pennylane/pull/6064)

* `qml.for_loop` and `qml.while_loop` now fall back to standard Python control flow if `qjit` is not present, allowing the same code to work with and without `qjit` without any rewrites. [(6014)](https://github.com/PennyLaneAI/pennylane/pull/6014)

python
dev = qml.device("lightning.qubit", wires=3)

qml.qnode(dev)
def circuit(x, n):

qml.for_loop(0, n, 1)
def init_state(i):
qml.Hadamard(wires=i)

init_state()

qml.for_loop(0, n, 1)
def apply_operations(i, x):
qml.RX(x, wires=i)

qml.for_loop(i + 1, n, 1)
def inner(j):
qml.CRY(x**2, [i, j])

inner()
return jnp.sin(x)

apply_operations(x)
return qml.probs()


pycon
>>> print(qml.draw(circuit)(0.5, 3))
0: โ”€โ”€Hโ”€โ”€RX(0.50)โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Probs
1: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐRY(0.25)โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€RX(0.48)โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค Probs
2: โ”€โ”€Hโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐRY(0.25)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐRY(0.23)โ”€โ”€RX(0.46)โ”€โ”ค Probs
>>> circuit(0.5, 3)
array([0.125 , 0.125 , 0.09949758, 0.15050242, 0.07594666,
0.11917543, 0.08942104, 0.21545687])
>>> qml.qjit(circuit)(0.5, 3)
Array([0.125 , 0.125 , 0.09949758, 0.15050242, 0.07594666,
0.11917543, 0.08942104, 0.21545687], dtype=float64)


<h4>Community contributions ๐Ÿฅณ</h4>

* Fixed a bug in `qml.ThermalRelaxationError` where there was a typo from `tq` to `tg`. [(5988)](https://github.com/PennyLaneAI/pennylane/issues/5988)

* Readout error has been added using parameters `readout_relaxation_probs` and `readout_misclassification_probs` on the `default.qutrit.mixed` device. These parameters add a `qml.QutritAmplitudeDamping` and a `qml.TritFlip` channel, respectively, after measurement diagonalization. The amplitude damping error represents the potential for relaxation to occur during longer measurements. The trit flip error represents misclassification during readout. [(5842)](https://github.com/PennyLaneAI/pennylane/pull/5842)

* `qml.ops.qubit.BasisStateProjector` now has a `compute_sparse_matrix` method that computes the sparse CSR matrix representation of the projector onto the given basis state. [(5790)](https://github.com/PennyLaneAI/pennylane/pull/5790)

<h4>Other improvements</h4>

* `qml.pauli.group_observables` now uses `rustworkx` colouring algorithms to solve the [Minimum Clique Cover problem](https://en.wikipedia.org/wiki/Clique_cover), resulting in orders of magnitude performance improvements. [(#6043)](https://github.com/PennyLaneAI/pennylane/pull/6043)

This adds two new options for the `method` argument: `dsatur` (degree of saturation) and `gis` (independent set). In addition, the creation of the adjacency matrix now takes advantage of the symplectic representation of the Pauli observables.

Additionally, a new function called `qml.pauli.compute_partition_indices` has been added to calculate the indices from the partitioned observables more efficiently. These changes improve the wall time of `qml.LinearCombination.compute_grouping` and the `grouping_type='qwc'` by orders of magnitude.

* `qml.counts` measurements with `all_outcomes=True` can now be used with JAX jitting. Additionally, measurements broadcasted across all available wires (e.g., `qml.probs()`) can now be used with JAX jit and devices that allow dynamic numbers of wires (only `'default.qubit'` currently). [(6108)](https://github.com/PennyLaneAI/pennylane/pull/6108/)

* `qml.ops.op_math.ctrl_decomp_zyz` can now decompose special unitaries with multiple control wires. [(6042)](https://github.com/PennyLaneAI/pennylane/pull/6042)

* A new method called `process_density_matrix` has been added to the `ProbabilityMP` and `DensityMatrixMP` measurement processes, allowing for more efficient handling of quantum density matrices, particularly with batch processing support. This method simplifies the calculation of probabilities from quantum states represented as density matrices. [(5830)](https://github.com/PennyLaneAI/pennylane/pull/5830)

* `SProd.terms` now flattens out the terms if the base is a multi-term observable. [(5885)](https://github.com/PennyLaneAI/pennylane/pull/5885)

* `qml.QNGOptimizer` now supports cost functions with multiple arguments, updating each argument independently. [(5926)](https://github.com/PennyLaneAI/pennylane/pull/5926)

* `semantic_version` has been removed from the list of required packages in PennyLane. [(5836)](https://github.com/PennyLaneAI/pennylane/pull/5836)

* `qml.devices.LegacyDeviceFacade` has been added to map the legacy devices to the new device interface, making it easier for developers to develop legacy devices. [(5927)](https://github.com/PennyLaneAI/pennylane/pull/5927)

* `StateMP.process_state` now defines rules in `cast_to_complex` for complex casting, avoiding a superfluous statevector copy in PennyLane-Lightning simulations. [(5995)](https://github.com/PennyLaneAI/pennylane/pull/5995)

* `QuantumScript.hash` is now cached, leading to performance improvements. [(5919)](https://github.com/PennyLaneAI/pennylane/pull/5919)

* Observable validation for `default.qubit` is now based on execution mode (analytic vs. finite shots) and measurement type (sample measurement vs. state measurement). This improves our error handling when, for example, non-hermitian operators are given to `qml.expval`. [(5890)](https://github.com/PennyLaneAI/pennylane/pull/5890)

* A new `is_leaf` parameter has been added to the function `flatten` in the `qml.pytrees` module. This is to allow for node flattening to be stopped for any node where the `is_leaf` optional argument evaluates to being `True`. [(6107)](https://github.com/PennyLaneAI/pennylane/issues/6107)

* A progress bar has been added to `qml.data.load()` when downloading a dataset. [(5560)](https://github.com/PennyLaneAI/pennylane/pull/5560)

* Upgraded and simplified `StatePrep` and `AmplitudeEmbedding` templates. [(6034)](https://github.com/PennyLaneAI/pennylane/pull/6034) [(#6170)](https://github.com/PennyLaneAI/pennylane/pull/6170)

* Upgraded and simplified `BasisState` and `BasisEmbedding` templates. [(6021)](https://github.com/PennyLaneAI/pennylane/pull/6021)

<h3>Breaking changes ๐Ÿ’”</h3>

* `MeasurementProcess.shape(shots: Shots, device:Device)` is now `MeasurementProcess.shape(shots: Optional[int], num_device_wires:int = 0)`. This has been done to allow for jitting when a measurement is broadcasted across all available wires, but the device does not specify wires. [(6108)](https://github.com/PennyLaneAI/pennylane/pull/6108/)

* If the shape of a probability measurement is affected by a `Device.cutoff` property, it will no longer work with jitting. [(6108)](https://github.com/PennyLaneAI/pennylane/pull/6108/)

* `qml.GlobalPhase` is considered non-differentiable with tape transforms. As a consequence, `qml.gradients.finite_diff` and `qml.gradients.spsa_grad` no longer support differentiating `qml.GlobalPhase` with state-based outputs. [(5620)](https://github.com/PennyLaneAI/pennylane/pull/5620)

* The `CircuitGraph.graph` `rustworkx` graph now stores indices into the circuit as the node labels, instead of the operator/ measurement itself. This allows the same operator to occur multiple times in the circuit. [(5907)](https://github.com/PennyLaneAI/pennylane/pull/5907)

* The `queue_idx` attribute has been removed from the `Operator`, `CompositeOp`, and `SymbolicOp` classes. [(6005)](https://github.com/PennyLaneAI/pennylane/pull/6005)

* `qml.from_qasm` no longer removes measurements from the QASM code. Use `measurements=[]` to remove measurements from the original circuit. [(5982)](https://github.com/PennyLaneAI/pennylane/pull/5982)

* `qml.transforms.map_batch_transform` has been removed, since transforms can be applied directly to a batch of tapes. See `qml.transform` for more information. [(5981)](https://github.com/PennyLaneAI/pennylane/pull/5981)

* `QuantumScript.interface` has been removed. [(5980)](https://github.com/PennyLaneAI/pennylane/pull/5980)

<h3>Deprecations ๐Ÿ‘‹</h3>

* The `decomp_depth` argument in `qml.device` has been deprecated. [(6026)](https://github.com/PennyLaneAI/pennylane/pull/6026)

* The `max_expansion` argument in `qml.QNode` has been deprecated. [(6026)](https://github.com/PennyLaneAI/pennylane/pull/6026)

* The `expansion_strategy` attribute `qml.QNode` has been deprecated. [(5989)](https://github.com/PennyLaneAI/pennylane/pull/5989)

* The `expansion_strategy` argument has been deprecated in all of `qml.draw`, `qml.draw_mpl`, and `qml.specs`. The `level` argument should be used instead. [(5989)](https://github.com/PennyLaneAI/pennylane/pull/5989)

* `Operator.expand` has been deprecated. Users should simply use `qml.tape.QuantumScript(op.decomposition())` for equivalent behaviour. [(5994)](https://github.com/PennyLaneAI/pennylane/pull/5994)

* `qml.transforms.sum_expand` and `qml.transforms.hamiltonian_expand` have been deprecated. Users should instead use `qml.transforms.split_non_commuting` for equivalent behaviour. [(6003)](https://github.com/PennyLaneAI/pennylane/pull/6003)

* The `expand_fn` argument in `qml.execute` has been deprecated. Instead, please create a `qml.transforms.core.TransformProgram` with the desired preprocessing and pass it to the `transform_program` argument of `qml.execute`. [(5984)](https://github.com/PennyLaneAI/pennylane/pull/5984)

* The `max_expansion` argument in `qml.execute` has been deprecated. Instead, please use `qml.devices.preprocess.decompose` with the desired expansion level, add it to a `qml.transforms.core.TransformProgram` and pass it to the `transform_program` argument of `qml.execute`. [(5984)](https://github.com/PennyLaneAI/pennylane/pull/5984)

* The `override_shots` argument in `qml.execute` has been deprecated. Instead, please add the shots to the `QuantumTape`s to be executed. [(5984)](https://github.com/PennyLaneAI/pennylane/pull/5984)

* The `device_batch_transform` argument in `qml.execute` has been deprecated. Instead, please create a `qml.transforms.core.TransformProgram` with the desired preprocessing and pass it to the `transform_program` argument of `qml.execute`. [(5984)](https://github.com/PennyLaneAI/pennylane/pull/5984)

* `qml.qinfo.classical_fisher` and `qml.qinfo.quantum_fisher` have been deprecated. Instead, use `qml.gradients.classical_fisher` and `qml.gradients.quantum_fisher`. [(5985)](https://github.com/PennyLaneAI/pennylane/pull/5985)

* The legacy devices `default.qubit.{autograd,torch,tf,jax,legacy}` have been deprecated. Instead, use `default.qubit`, as it now supports backpropagation through the several backends. [(5997)](https://github.com/PennyLaneAI/pennylane/pull/5997)

* The logic for internally switching a device for a different backpropagation compatible device is now deprecated, as it was in place for the deprecated `default.qubit.legacy`. [(6032)](https://github.com/PennyLaneAI/pennylane/pull/6032)

<h3>Documentation ๐Ÿ“</h3>

* The docstring for `qml.qinfo.quantum_fisher`, regarding the internally used functions and potentially required auxiliary wires, has been improved. [(6074)](https://github.com/PennyLaneAI/pennylane/pull/6074)

* The docstring for `QuantumScript.expand` and `qml.tape.tape.expand_tape` has been improved. [(5974)](https://github.com/PennyLaneAI/pennylane/pull/5974)

<h3>Bug fixes ๐Ÿ›</h3>

* The sparse matrix can now be computed for a product operator when one operand is a `GlobalPhase` on no wires. [(6197)](https://github.com/PennyLaneAI/pennylane/pull/6197)

* For `default.qubit`, JAX is now used for sampling whenever the state is a JAX array. This fixes normalization issues that can occur when the state uses 32-bit precision. [(6190)](https://github.com/PennyLaneAI/pennylane/pull/6190)

* Fix Pytree serialization of operators with empty shot vectors [(6155)](https://github.com/PennyLaneAI/pennylane/pull/6155)

* Fixes an error in the `dynamic_one_shot` transform when used with sampling a single shot. [(6149)](https://github.com/PennyLaneAI/pennylane/pull/6149)

* `qml.transforms.pattern_matching_optimization` now preserves the tape measurements. [(6153)](https://github.com/PennyLaneAI/pennylane/pull/6153)

* `qml.transforms.broadcast_expand` no longer squeezes out batch sizes of size 1, as a batch size of 1 is still a batch size. [(6147)](https://github.com/PennyLaneAI/pennylane/pull/6147)

* Catalyst replaced `argnum` with `argnums` in gradient related functions, therefore we updated the Catalyst calls to those functions in PennyLane. [(6117)](https://github.com/PennyLaneAI/pennylane/pull/6117)

* `fuse_rot_angles` now returns NaN instead of incorrect derivatives at singular points. [(6031)](https://github.com/PennyLaneAI/pennylane/pull/6031)

* `qml.GlobalPhase` and `qml.Identity` can now be captured with plxpr when acting on no wires. [(6060)](https://github.com/PennyLaneAI/pennylane/pull/6060)

* Fixed `jax.grad` and `jax.jit` to work for `qml.AmplitudeEmbedding`, `qml.StatePrep` and `qml.MottonenStatePreparation`. [(5620)](https://github.com/PennyLaneAI/pennylane/pull/5620)

* Fixed a bug in `qml.center` that omitted elements from the center if they were linear combinations of input elements. [(6049)](https://github.com/PennyLaneAI/pennylane/pull/6049)

* Fix a bug where the global phase returned by `one_qubit_decomposition` gained a broadcasting dimension. [(5923)](https://github.com/PennyLaneAI/pennylane/pull/5923)

* Fixed a bug in `qml.SPSAOptimizer` that ignored keyword arguments in the objective function. [(6027)](https://github.com/PennyLaneAI/pennylane/pull/6027)

* Fixed `dynamic_one_shot` for use with devices using the old device API, since `override_shots` was deprecated. [(6024)](https://github.com/PennyLaneAI/pennylane/pull/6024)

* `CircuitGraph` can now handle circuits with the same operation instance occuring multiple times. [(5907)](https://github.com/PennyLaneAI/pennylane/pull/5907)

* `qml.QSVT` has been updated to store wire order correctly. [(5959)](https://github.com/PennyLaneAI/pennylane/pull/5959)

* `qml.devices.qubit.measure_with_samples` now returns the correct result if the provided measurements contain a sum of operators acting on the same wire. [(5978)](https://github.com/PennyLaneAI/pennylane/pull/5978)

* `qml.AmplitudeEmbedding` has better support for features using low precision integer data types. [(5969)](https://github.com/PennyLaneAI/pennylane/pull/5969)

* `qml.BasisState` and `qml.BasisEmbedding` now works with jax.jit, `lightning.qubit`, and give the correct decomposition. [(6021)](https://github.com/PennyLaneAI/pennylane/pull/6021)

* Jacobian shape has been fixed for measurements with dimension in `qml.gradients.vjp.compute_vjp_single`. [(5986)](https://github.com/PennyLaneAI/pennylane/pull/5986)

* `qml.lie_closure` now works with sums of Paulis. [(6023)](https://github.com/PennyLaneAI/pennylane/pull/6023)

* Workflows that parameterize the coefficients of `qml.exp` are now jit-compatible. [(6082)](https://github.com/PennyLaneAI/pennylane/pull/6082)

* Fixed a bug where `CompositeOp.overlapping_ops` changes the original ordering of operators, causing an incorrect matrix to be generated for `Prod` with `Sum` as operands. [(6091)](https://github.com/PennyLaneAI/pennylane/pull/6091)

* `qml.qsvt` now works with "Wx" convention and any number of angles. [(6105)](https://github.com/PennyLaneAI/pennylane/pull/6105)

* Basis set data from the Basis Set Exchange library can now be loaded for elements with `SPD`-type orbitals. [(6159)](https://github.com/PennyLaneAI/pennylane/pull/6159)

<h3>Contributors โœ๏ธ</h3>

This release contains contributions from (in alphabetical order):

Tarun Kumar Allamsetty, Guillermo Alonso, Ali Asadi, Utkarsh Azad, Tonmoy T. Bhattacharya, Gabriel Bottrill, Jack Brown, Ahmed Darwish, Astral Cai, Yushao Chen, Ahmed Darwish, Diksha Dhawan Maja Franz, Lillian M. A. Frederiksen, Pietropaolo Frisoni, Emiliano Godinez, Austin Huang, Renke Huang, Josh Izaac, Soran Jahangiri, Korbinian Kottmann, Christina Lee, Jorge Martinez de Lejarza, William Maxwell, Vincent Michaud-Rioux, Anurav Modak, Mudit Pandey, Andrija Paurevic, Erik Schultheis, nate stemen, David Wierichs,

0.37.0

<h3>New features since last release</h3>

<h4>Execute wide circuits with Default Tensor ๐Ÿ”—</h4>

* A new `default.tensor` device is now available for performing [tensor network](https://en.wikipedia.org/wiki/Tensor_network) and [matrix product state](https://en.wikipedia.org/wiki/Matrix_product_state) simulations of quantum circuits using the [quimb backend](https://quimb.readthedocs.io/en/latest/). [(#5699)](https://github.com/PennyLaneAI/pennylane/pull/5699) [(#5744)](https://github.com/PennyLaneAI/pennylane/pull/5744) [(#5786)](https://github.com/PennyLaneAI/pennylane/pull/5786) [(#5795)](https://github.com/PennyLaneAI/pennylane/pull/5795)

Either method can be selected when instantiating the `default.tensor` device by setting the `method` keyword argument to `"tn"` (tensor network) or `"mps"` (matrix product state).

There are [several templates in PennyLane](https://docs.pennylane.ai/en/stable/introduction/templates.html#tensor-networks) that are tensor-network focused, which are excellent candidates for the `"tn"` method for `default.tensor`. The following example shows how a circuit comprising gates in a tree tensor network architecture can be efficiently simulated using `method="tn"`.

python
import pennylane as qml

n_wires = 16
dev = qml.device("default.tensor", method="tn")

def block(weights, wires):
qml.CNOT(wires=[wires[0], wires[1]])
qml.RY(weights[0], wires=wires[0])
qml.RY(weights[1], wires=wires[1])

n_block_wires = 2
n_params_block = 2
n_blocks = qml.TTN.get_n_blocks(range(n_wires), n_block_wires)
template_weights = [[0.1, -0.3]] * n_blocks

qml.qnode(dev)
def circuit(template_weights):
for i in range(n_wires):
qml.Hadamard(i)
qml.TTN(range(n_wires), n_block_wires, block, n_params_block, template_weights)
return qml.expval(qml.Z(n_wires - 1))


pycon
>>> circuit(template_weights)
0.3839174759751649


For matrix product state simulations (`method="mps"`), we can make the execution be approximate by setting `max_bond_dim` (see the [device's documentation](https://docs.pennylane.ai/en/stable/code/api/pennylane.devices.default_tensor.DefaultTensor.html) for more details). The maximum bond dimension has implications for the speed of the simulation and lets us control the degree of the approximation, as shown in the following example. First, set up the circuit:

python
import numpy as np

n_layers = 10
n_wires = 10
initial_shape, weights_shape = qml.SimplifiedTwoDesign.shape(n_layers, n_wires)
np.random.seed(1967)
initial_layer_weights = np.random.random(initial_shape)
weights = np.random.random(weights_shape)

def f():
qml.SimplifiedTwoDesign(initial_layer_weights, weights, range(n_wires))
return qml.expval(qml.Z(0))


The `default.tensor` device is instantiated with a `max_bond_dim` value:

python
dev_dq = qml.device("default.qubit")
value_dq = qml.QNode(f, dev_dq)()

dev_mps = qml.device("default.tensor", max_bond_dim=5)
value_mps = qml.QNode(f, dev_mps)()


With this bond dimension, the expectation values calculated for `default.qubit` and `default.tensor` are different:

pycon
>>> np.abs(value_dq - value_mps)
tensor(0.0253213, requires_grad=True)


Learn more about `default.tensor` and how to configure it by [visiting the how-to guide](https://pennylane.ai/qml/demos/tutorial_How_to_simulate_quantum_circuits_with_tensor_networks/).

<h4>Add noise models to your quantum circuits ๐Ÿ“บ</h4>

* Support for building noise models and applying them to a quantum circuit has been added via the `NoiseModel` class and an `add_noise` transform. [(5674)](https://github.com/PennyLaneAI/pennylane/pull/5674) [(#5684)](https://github.com/PennyLaneAI/pennylane/pull/5684) [(#5718)](https://github.com/PennyLaneAI/pennylane/pull/5718)

Under the hood, PennyLane's approach to noise models is insertion-based, meaning that noise is included by *inserting* additional operators (gates or channels) that describe the noise into the quantum circuit. Creating a `NoiseModel` boils down to defining Boolean conditions under which specific noisy operations are inserted. There are several ways to specify conditions for adding noisy operations:

* `qml.noise.op_eq(op)`: if the operator `op` is encountered in the circuit, add noise.
* `qml.noise.op_in(ops)`: if any operators in `ops` are encountered in the circuit, add noise.
* `qml.noise.wires_eq(wires)`: if an operator is applied to `wires`, add noise.
* `qml.noise.wires_in(wires)`: if an operator is applied to any wire in `wires`, add noise.
* custom noise conditions: custom conditions can be defined as functions decorated with `qml.BooleanFn` that return a Boolean value. For example, the following function will insert noise if a `qml.RY` operator is encountered with an angle of rotation that is less than `0.5`:

python
qml.BooleanFn
def c0(op):
return isinstance(op, qml.RY) and op.parameters[0] < 0.5


Conditions can also be combined together with `&`, `and`, `|`, etc. Once the conditions under which noise is to be inserted have been stated, we can specify exactly what noise is inserted with the following:

* `qml.noise.partial_wires(op)`: insert `op` on the wires that are specified by the condition that triggers adding this noise
* custom noise operations: custom noise can be specified by defining a standard quantum function like below.
python
def n0(op, **kwargs):
qml.RY(op.parameters[0] * 0.05, wires=op.wires)


With that, we can create a `qml.NoiseModel` object whose argument must be a dictionary mapping conditions to noise:

python
c1 = qml.noise.op_eq(qml.X) & qml.noise.wires_in([0, 1])
n1 = qml.noise.partial_wires(qml.AmplitudeDamping, 0.4)

noise_model = qml.NoiseModel({c0: n0, c1: n1})


pycon
>>> noise_model
NoiseModel({ BooleanFn(c0): n0 OpEq(PauliX) | WiresIn([0, 1]): AmplitudeDamping(gamma=0.4) })


The noise model created can then be added to a QNode with `qml.add_noise`:

python
dev = qml.device("lightning.qubit", wires=3)

qml.qnode(dev)
def circuit():
qml.Y(0)
qml.CNOT([0, 1])
qml.RY(0.3, wires=2) triggers c0
qml.X(1) triggers c1
return qml.state()


pycon
>>> print(qml.draw(circuit)())
0: โ”€โ”€Yโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”ค State
1: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”€Xโ”€โ”ค State
2: โ”€โ”€RY(0.30)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค State
>>> circuit = qml.add_noise(circuit, noise_model)
>>> print(qml.draw(circuit)())
0: โ”€โ”€Yโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค State
1: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€Xโ”€โ”€AmplitudeDamping(0.40)โ”€โ”ค State
2: โ”€โ”€RY(0.30)โ”€โ”€RY(0.01)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค State


If more than one transform is applied to a QNode, control over when/where the `add_noise` transform is applied in relation to the other transforms can be specified with the `level` keyword argument. By default, `add_noise` is applied after all the transforms that have been manually applied to the QNode until that point. To learn more about this new functionality, check out our [noise module documentation](https://docs.pennylane.ai/en/stable/code/qml_noise.html) and keep your eyes peeled for an in-depth demo!

<h4>Catch bugs with the PennyLane debugger ๐Ÿšซ๐Ÿž</h4>

* The new PennyLane quantum debugger allows pausing simulation via the `qml.breakpoint()` command and provides tools for analyzing quantum circuits during execution. [(5680)](https://github.com/PennyLaneAI/pennylane/pull/5680) [(#5749)](https://github.com/PennyLaneAI/pennylane/pull/5749) [(#5789)](https://github.com/PennyLaneAI/pennylane/pull/5789)

This includes monitoring the circuit via measurements using `qml.debug_state()`, `qml.debug_probs()`, `qml.debug_expval()`, and `qml.debug_tape()`, stepping through the operations in a quantum circuit, and interactively adding operations during execution.

Including `qml.breakpoint()` in a circuit will cause the simulation to pause during execution and bring up the interactive console. For example, consider the following code in a Python file called `script.py`:

python
qml.qnode(qml.device('default.qubit', wires=(0,1,2)))
def circuit(x):
qml.Hadamard(wires=0)
qml.CNOT(wires=(0,2))
qml.breakpoint()

qml.RX(x, wires=1)
qml.RY(x, wires=2)
qml.breakpoint()

return qml.sample()

circuit(1.2345)


Upon executing `script.py`, the simulation pauses at the first breakpoint:

pycon
> /Users/your/path/to/script.py(8)circuit()
-> qml.RX(x, wires=1)
[pldb]


While debugging, we can access circuit information. For example, `qml.debug_tape()` returns the tape of the circuit, giving access to its operations and drawing:

pycon
[pldb] tape = qml.debug_tape()
[pldb] print(tape.draw(wire_order=[0,1,2]))
0: โ”€โ”€Hโ”€โ•ญโ—โ”€โ”ค
2: โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”ค
[pldb] tape.operations
[Hadamard(wires=[0]), CNOT(wires=[0, 2])]


While `qml.debug_state()` is equivalent to `qml.state()` and gives the current state:

pycon
[pldb] print(qml.debug_state())
[0.70710678+0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j 0.70710678+0.j 0. +0.j 0. +0.j]


Other debugger functions like `qml.debug_probs()` and `qml.debug_expval()` also function like their simulation counterparts (`qml.probs` and `qml.expval`, respectively) and are described in more detail in the [debugger documentation](https://docs.pennylane.ai/en/stable/code/qml_debugging.html) Additionally, standard debugging commands are available to navigate through code, including `list`, `longlist`, `next`, `continue`, and `quit`, as described in [the debugging documentation](https://docs.pennylane.ai/en/stable/code/qml_debugging.html#controlling-code-execution-in-the-debugging-context). Finally, to modify a circuit mid-run, simply call the desired PennyLane operations:

pycon
[pldb] qml.CNOT(wires=(0,2))
CNOT(wires=[0, 2])
[pldb] print(qml.debug_tape().draw(wire_order=[0,1,2]))
0: โ”€โ”€Hโ”€โ•ญโ—โ”€โ•ญโ—โ”€โ”ค
2: โ”€โ”€โ”€โ”€โ•ฐXโ”€โ•ฐXโ”€โ”ค


Stay tuned for an in-depth demonstration on using this feature with real-world examples! <h4>Convert between OpenFermion and PennyLane ๐Ÿค</h4>

* Two new functions called `qml.from_openfermion` and `qml.to_openfermion` are now available to convert between OpenFermion and PennyLane objects. This includes both fermionic and qubit operators. [(5773)](https://github.com/PennyLaneAI/pennylane/pull/5773) [(#5808)](https://github.com/PennyLaneAI/pennylane/pull/5808) [(#5881)](https://github.com/PennyLaneAI/pennylane/pull/5881)

For fermionic operators:

pycon
>>> import openfermion
>>> of_fermionic = openfermion.FermionOperator('0^ 2')
>>> type(of_fermionic)
<class 'openfermion.ops.operators.fermion_operator.FermionOperator'>
>>> pl_fermionic = qml.from_openfermion(of_fermionic)
>>> type(pl_fermionic)
<class 'pennylane.fermi.fermionic.FermiWord'>
>>> print(pl_fermionic)
aโบ(0) a(2)


And for qubit operators:

pycon
>>> of_qubit = 0.5 * openfermion.QubitOperator('X0 X5')
>>> pl_qubit = qml.from_openfermion(of_qubit)
>>> print(pl_qubit)
0.5 * (X(0) X(5))


<h4>Better control over when drawing and specs take place ๐ŸŽš๏ธ</h4>

* It is now possible to control the stage at which `qml.draw`, `qml.draw_mpl`, and `qml.specs` occur within a QNode's [transform](https://docs.pennylane.ai/en/stable/code/qml_transforms.html) program. [(#5855)](https://github.com/PennyLaneAI/pennylane/pull/5855) [(#5781)](https://github.com/PennyLaneAI/pennylane/pull/5781/)

Consider the following circuit which has multiple transforms applied:

python
qml.transforms.split_non_commuting
qml.transforms.cancel_inverses
qml.transforms.merge_rotations
qml.qnode(qml.device("default.qubit"))
def f():
qml.Hadamard(0)
qml.Y(0)
qml.RX(0.4, 0)
qml.RX(-0.4, 0)
qml.Y(0)
return qml.expval(qml.X(0) + 2 * qml.Y(0))


We can specify a `level` value when using `qml.draw()`:

pycon
>>> print(qml.draw(f, level=0)()) input program
0: โ”€โ”€Hโ”€โ”€Yโ”€โ”€RX(0.40)โ”€โ”€RX(-0.40)โ”€โ”€Yโ”€โ”ค <X+(2.00*Y)>
>>> print(qml.draw(f, level=1)()) rotations merged
0: โ”€โ”€Hโ”€โ”€Yโ”€โ”€Yโ”€โ”ค <X+(2.00*Y)>
>>> print(qml.draw(f, level=2)()) inverses cancelled
0: โ”€โ”€Hโ”€โ”ค <X+(2.00*Y)>
>>> print(qml.draw(f, level=3)()) Hamiltonian expanded
0: โ”€โ”€Hโ”€โ”ค <X>

0: โ”€โ”€Hโ”€โ”ค <Y>


The [qml.workflow.get_transform_program function](https://docs.pennylane.ai/en/latest/code/api/pennylane.workflow.get_transform_program.html) can be used to see the full transform program.

pycon
>>> qml.workflow.get_transform_program(f)
TransformProgram(merge_rotations, cancel_inverses, split_non_commuting, validate_device_wires, mid_circuit_measurements, decompose, validate_measurements, validate_observables, no_sampling)


Note that additional transforms can be added automatically from device preprocessing or gradient calculations. Rather than providing an integer value to `level`, it is possible to target the `"user"`, `"gradient"` or `"device"` stages:

python
n_wires = 3
x = np.random.random((2, n_wires))

qml.qnode(qml.device("default.qubit"))
def f():
qml.BasicEntanglerLayers(x, range(n_wires))
return qml.expval(qml.X(0))


pycon
>>> print(qml.draw(f, level="device")())
0: โ”€โ”€RX(0.28)โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ•ญXโ”€โ”€RX(0.70)โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ•ญXโ”€โ”ค <X>
1: โ”€โ”€RX(0.52)โ”€โ•ฐXโ”€โ•ญโ—โ”€โ”‚โ”€โ”€โ”€RX(0.65)โ”€โ•ฐXโ”€โ•ญโ—โ”€โ”‚โ”€โ”€โ”ค
2: โ”€โ”€RX(0.00)โ”€โ”€โ”€โ”€โ•ฐXโ”€โ•ฐโ—โ”€โ”€RX(0.03)โ”€โ”€โ”€โ”€โ•ฐXโ”€โ•ฐโ—โ”€โ”ค


<h3>Improvements ๐Ÿ› </h3>

<h4>Community contributions, including UnitaryHACK ๐Ÿ’›</h4>

* `default.clifford` now supports arbitrary state-based measurements with `qml.Snapshot`. [(5794)](https://github.com/PennyLaneAI/pennylane/pull/5794)

* `qml.equal` now properly handles `Pow`, `Adjoint`, `Exp`, and `SProd` operators as arguments across different interfaces and tolerances with the addition of four new keyword arguments: `check_interface`, `check_trainability`, `atol` and `rtol`. [(5668)](https://github.com/PennyLaneAI/pennylane/pull/5668)

* The implementation for `qml.assert_equal` has been updated for `Operator`, `Controlled`, `Adjoint`, `Pow`, `Exp`, `SProd`, `ControlledSequence`, `Prod`, `Sum`, `Tensor` and `Hamiltonian` instances. [(5780)](https://github.com/PennyLaneAI/pennylane/pull/5780) [(#5877)](https://github.com/PennyLaneAI/pennylane/pull/5877)

* `qml.from_qasm` now supports the ability to convert mid-circuit measurements from `OpenQASM 2` code, and it can now also take an optional argument to specify a list of measurements to be performed at the end of the circuit, just like `qml.from_qiskit`. [(5818)](https://github.com/PennyLaneAI/pennylane/pull/5818)

* Four new operators have been added for simulating noise on the `default.qutrit.mixed` device: [(5502)](https://github.com/PennyLaneAI/pennylane/pull/5502) [(#5793)](https://github.com/PennyLaneAI/pennylane/issues/5793) [(#5503)](https://github.com/PennyLaneAI/pennylane/pull/5503) [(#5757)](https://github.com/PennyLaneAI/pennylane/pull/5757) [(#5799)](https://github.com/PennyLaneAI/pennylane/pull/5799) [(#5784)](https://github.com/PennyLaneAI/pennylane/pull/5784)

* `qml.QutritDepolarizingChannel`: a channel that adds depolarizing noise.
* `qml.QutritChannel`: enables the specification of noise using a collection of (3x3) Kraus matrices.
* `qml.QutritAmplitudeDamping`: a channel that adds noise processes modelled by amplitude damping.
* `qml.TritFlip`: a channel that adds trit flip errors, such as misclassification.

<h4>Faster and more flexible mid-circuit measurements</h4>

* The `default.qubit` device supports a depth-first tree-traversal algorithm to accelerate native mid-circuit measurement execution. Accessible through the QNode argument `mcm_method="tree-traversal"`, this new implementation supports classical control, collecting statistics, and post-selection, along with all measurements enabled with `qml.dynamic_one_shot`. More information about this new mid-circuit measurement method can be found on our [measurement documentation page](https://docs.pennylane.ai/en/stable/introduction/dynamic_quantum_circuits.html#tree-traversal-algorithm). [(5180)](https://github.com/PennyLaneAI/pennylane/pull/5180)

* `qml.QNode` and the `qml.qnode` decorator now accept two new keyword arguments: `postselect_mode` and `mcm_method`. These keyword arguments can be used to configure how the device should behave when running circuits with mid-circuit measurements. [(5679)](https://github.com/PennyLaneAI/pennylane/pull/5679) [(#5833)](https://github.com/PennyLaneAI/pennylane/pull/5833) [(#5850)](https://github.com/PennyLaneAI/pennylane/pull/5850)

* `postselect_mode="hw-like"` indicates to devices to discard invalid shots when postselecting mid-circuit measurements. Use `postselect_mode="fill-shots"` to unconditionally sample the postselected value, thus making all samples valid. This is equivalent to sampling until the number of valid samples matches the total number of shots.
* `mcm_method` will indicate which strategy to use for running circuits with mid-circuit measurements. Use `mcm_method="deferred"` to use the deferred measurements principle, or `mcm_method="one-shot"` to execute once for each shot. If `qml.qjit` is being used (the Catalyst compiler), `mcm_method="single-branch-statistics"` is also available. Using this method, a single branch of the execution tree will be randomly explored.

* The `dynamic_one_shot` transform received a few improvements:
* `dynamic_one_shot` is now compatible with `qml.qjit` (the Catalyst compiler). [(5766)](https://github.com/PennyLaneAI/pennylane/pull/5766) [(#5888)](https://github.com/PennyLaneAI/pennylane/pull/5888)
* `dynamic_one_shot` now uses a single auxiliary tape with a shot vector and `default.qubit` implements the loop over shots with `jax.vmap`. [(5617)](https://github.com/PennyLaneAI/pennylane/pull/5617)
* `dynamic_one_shot` is now compatible with `jax.jit`. [(5557)](https://github.com/PennyLaneAI/pennylane/pull/5557)

* When using `defer_measurements` with postselection, operations that will never be active due to the postselected state are skipped in the transformed quantum circuit. In addition, postselected controls are skipped, as they are evaluated when the transform is applied. This optimization feature can be turned off by setting `reduce_postselected=False`. [(5558)](https://github.com/PennyLaneAI/pennylane/pull/5558)

Consider a simple circuit with three mid-circuit measurements, two of which are postselecting, and a single gate conditioned on those measurements:

python
qml.qnode(qml.device("default.qubit"))
def node(x):
qml.RX(x, 0)
qml.RX(x, 1)
qml.RX(x, 2)
mcm0 = qml.measure(0, postselect=0, reset=False)
mcm1 = qml.measure(1, postselect=None, reset=True)
mcm2 = qml.measure(2, postselect=1, reset=False)
qml.cond(mcm0 + mcm1 + mcm2 == 1, qml.RX)(0.5, 3)
return qml.expval(qml.Z(0) qml.Z(3))


Without the new optimization, we obtain three gates, each controlled on the three measured qubits. They correspond to the combinations of controls that satisfy the condition `mcm0 + mcm1 + mcm2 == 1`:

pycon
>>> print(qml.draw(qml.defer_measurements(node, reduce_postselected=False))(0.6))
0: โ”€โ”€RX(0.60)โ”€โ”€|0โŸฉโŸจ0|โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ•ญ<ZZ>
1: โ”€โ”€RX(0.60)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ•ญโ—โ”€โ•ญXโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚
2: โ”€โ”€RX(0.60)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€|1โŸฉโŸจ1|โ”€โ•ญโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚
3: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œRX(0.50)โ”€โ”œRX(0.50)โ”€โ”œRX(0.50)โ”€โ”ค โ•ฐ<ZZ>
4: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
5: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค


If we do not explicitly deactivate the optimization, we obtain a much simpler circuit:

pycon
>>> print(qml.draw(qml.defer_measurements(node))(0.6))
0: โ”€โ”€RX(0.60)โ”€โ”€|0โŸฉโŸจ0|โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ•ญ<ZZ>
1: โ”€โ”€RX(0.60)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ•ญโ—โ”€โ•ญXโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚
2: โ”€โ”€RX(0.60)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€|1โŸฉโŸจ1|โ”€โ”€โ”€โ”ค โ”‚
3: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ•ญRX(0.50)โ”€โ”ค โ•ฐ<ZZ>
4: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
5: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐXโ”€โ•ฐโ—โ”€โ•ฐโ—‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค


There is only one controlled gate with only one control wire.

* Mid-circuit measurement tests have been streamlined and refactored, removing most end-to-end tests from the native MCM test file, but keeping one that validates multiple mid-circuit measurements with any allowed return and interface end-to-end tests. [(5787)](https://github.com/PennyLaneAI/pennylane/pull/5787)

<h4>Access to QROM</h4>

* [The QROM algorithm](https://arxiv.org/abs/1812.00954) is now available in PennyLane with `qml.QROM`. This template allows you to enter classical data in the form of bitstrings. [(#5688)](https://github.com/PennyLaneAI/pennylane/pull/5688)

python
bitstrings = ["010", "111", "110", "000"]

dev = qml.device("default.qubit", shots = 1)

qml.qnode(dev)
def circuit():
qml.BasisEmbedding(2, wires = [0,1])

qml.QROM(bitstrings = bitstrings, control_wires = [0,1], target_wires = [2,3,4], work_wires = [5,6,7])

return qml.sample(wires = [2,3,4])

pycon
>>> print(circuit())
[1 1 0]


<h4>Capturing and representing hybrid programs</h4>

* A number of templates have been updated to be valid PyTrees and PennyLane operations. [(5698)](https://github.com/PennyLaneAI/pennylane/pull/5698)

* PennyLane operators, measurements, and QNodes can now automatically be captured as instructions in JAXPR. [(5564)](https://github.com/PennyLaneAI/pennylane/pull/5564) [(#5511)](https://github.com/PennyLaneAI/pennylane/pull/5511) [(#5708)](https://github.com/PennyLaneAI/pennylane/pull/5708) [(#5523)](https://github.com/PennyLaneAI/pennylane/pull/5523) [(#5686)](https://github.com/PennyLaneAI/pennylane/pull/5686) [(#5889)](https://github.com/PennyLaneAI/pennylane/pull/5889)

* The `qml.PyTrees` module now has `flatten` and `unflatten` methods for serializing PyTrees. [(5701)](https://github.com/PennyLaneAI/pennylane/pull/5701)

* `qml.sample` can now be used on Boolean values representing mid-circuit measurement results in traced quantum functions. This feature is used with Catalyst to enable the pattern `m = measure(0); qml.sample(m)`. [(5673)](https://github.com/PennyLaneAI/pennylane/pull/5673)

<h4>Quantum chemistry</h4>

* The `qml.qchem.Molecule` object received a few improvements:
* `qml.qchem.Molecule` is now the central object used by all qchem functions. [(5571)](https://github.com/PennyLaneAI/pennylane/pull/5571)
* `qml.qchem.Molecule` now supports Angstrom as a unit. [(5694)](https://github.com/PennyLaneAI/pennylane/pull/5694)
* `qml.qchem.Molecule` now supports open-shell systems. [(5655)](https://github.com/PennyLaneAI/pennylane/pull/5655)

* The `qml.qchem.molecular_hamiltonian` function now supports parity and Bravyi-Kitaev mappings. [(5657)](https://github.com/PennyLaneAI/pennylane/pull/5657/)

* `qml.qchem.molecular_dipole` function has been added for calculating the dipole operator using the `"dhf"` and `"openfermion"` backends. [(5764)](https://github.com/PennyLaneAI/pennylane/pull/5764)

* The qchem module now has dedicated functions for calling the `pyscf` and `openfermion` backends and the `molecular_hamiltonian` and `molecular_dipole` functions have been moved to `hamiltonian` and `dipole` modules. [(5553)](https://github.com/PennyLaneAI/pennylane/pull/5553) [(#5863)](https://github.com/PennyLaneAI/pennylane/pull/5863)

* More fermionic-to-qubit tests have been added to cover cases when the mapped operator is different for various mapping schemes. [(5873)](https://github.com/PennyLaneAI/pennylane/pull/5873)

<h4>Easier development</h4>

* Logging now allows for an easier opt-in across the stack and support has been extended to Catalyst. [(5528)](https://github.com/PennyLaneAI/pennylane/pull/5528)

* Three new Pytest markers have been added for easier management of our test suite: `unit`, `integration` and `system`. [(5517)](https://github.com/PennyLaneAI/pennylane/pull/5517)

<h4>Other improvements</h4>

* `qml.MultiControlledX` can now be decomposed even when no `work_wires` are provided. The implementation returns $\mathcal{O}(\mbox{len(control wires)}^2)$ operations and is applicable for any multi-controlled unitary gate. This decomposition is provided in [arXiv:quant-ph/9503016](https://arxiv.org/abs/quant-ph/9503016). [(#5735)](https://github.com/PennyLaneAI/pennylane/pull/5735)

* A new function called `expectation_value` has been added to `qml.math` to calculate the expectation value of a matrix for pure states. [(4484)](https://github.com/PennyLaneAI/pennylane/pull/4484)

pycon
>>> state_vector = [1/np.sqrt(2), 0, 1/np.sqrt(2), 0]
>>> operator_matrix = qml.matrix(qml.PauliZ(0), wire_order=[0,1])
>>> qml.math.expectation_value(operator_matrix, state_vector)
tensor(-2.23711432e-17+0.j, requires_grad=True)


* `param_shift` with the `broadcast=True` option now supports shot vectors and multiple measurements. [(5667)](https://github.com/PennyLaneAI/pennylane/pull/5667)

* `qml.TrotterProduct` is now compatible with resource tracking by inheriting from `ResourcesOperation`. [(5680)](https://github.com/PennyLaneAI/pennylane/pull/5680)

* `packaging` is now a required package in PennyLane. [(5769)](https://github.com/PennyLaneAI/pennylane/pull/5769)

* `qml.ctrl` now works with tuple-valued `control_values` when applied to any already controlled operation. [(5725)](https://github.com/PennyLaneAI/pennylane/pull/5725)

* The sorting order of parameter-shift terms is now guaranteed to resolve ties in the absolute value with the sign of the shifts. [(5582)](https://github.com/PennyLaneAI/pennylane/pull/5582)

* `qml.transforms.split_non_commuting` can now handle circuits containing measurements of multi-term observables. [(5729)](https://github.com/PennyLaneAI/pennylane/pull/5729) [(#5838)](https://github.com/PennyLaneAI/pennylane/pull/5838) [(#5828)](https://github.com/PennyLaneAI/pennylane/pull/5828) [(#5869)](https://github.com/PennyLaneAI/pennylane/pull/5869) [(#5939)](https://github.com/PennyLaneAI/pennylane/pull/5939) [(#5945)](https://github.com/PennyLaneAI/pennylane/pull/5945)

* `qml.devices.LegacyDevice` is now an alias for `qml.Device`, so it is easier to distinguish it from `qml.devices.Device`, which follows the new device API. [(5581)](https://github.com/PennyLaneAI/pennylane/pull/5581)

* The `dtype` for `eigvals` of `X`, `Y`, `Z` and `Hadamard` is changed from `int` to `float`, making them consistent with the other observables. The `dtype` of the returned values when sampling these observables (e.g. `qml.sample(X(0))`) is also changed to `float`. [(5607)](https://github.com/PennyLaneAI/pennylane/pull/5607)

* The framework for the development of an `assert_equal` function for testing operator comparison has been set up. [(5634)](https://github.com/PennyLaneAI/pennylane/pull/5634) [(#5858)](https://github.com/PennyLaneAI/pennylane/pull/5858)

* The `decompose` transform has an `error` keyword argument to specify the type of error that should be raised, allowing error types to be more consistent with the context the `decompose` function is used in. [(5669)](https://github.com/PennyLaneAI/pennylane/pull/5669)

* Empty initialization of `PauliVSpace` is permitted. [(5675)](https://github.com/PennyLaneAI/pennylane/pull/5675)

* `qml.tape.QuantumScript` properties are only calculated when needed, instead of on initialization. This decreases the classical overhead by over 20%. Also, `par_info`, `obs_sharing_wires`, and `obs_sharing_wires_id` are now public attributes. [(5696)](https://github.com/PennyLaneAI/pennylane/pull/5696)

* The `qml.data` module now supports PyTree data types as dataset attributes [(5732)](https://github.com/PennyLaneAI/pennylane/pull/5732)

* `qml.ops.Conditional` now inherits from `qml.ops.SymbolicOp`, thus it inherits several useful common functionalities. Other properties such as adjoint and diagonalizing gates have been added using the `base` properties. [(5772)](https://github.com/PennyLaneAI/pennylane/pull/5772)

* New dispatches for `qml.ops.Conditional` and `qml.MeasurementValue` have been added to `qml.equal`. [(5772)](https://github.com/PennyLaneAI/pennylane/pull/5772)

* The `qml.snapshots` transform now supports arbitrary devices by running a separate tape for each snapshot for unsupported devices. [(5805)](https://github.com/PennyLaneAI/pennylane/pull/5805)

* The `qml.Snapshot` operator now accepts sample-based measurements for finite-shot devices. [(5805)](https://github.com/PennyLaneAI/pennylane/pull/5805)

* Device preprocess transforms now happen inside the ML boundary. [(5791)](https://github.com/PennyLaneAI/pennylane/pull/5791)

* Transforms applied to callables now use `functools.wraps` to preserve the docstring and call signature of the original function. [(5857)](https://github.com/PennyLaneAI/pennylane/pull/5857)

* `qml.qsvt()` now supports JAX arrays with angle conversions. [(5853)](https://github.com/PennyLaneAI/pennylane/pull/5853)

* The sorting order of parameter-shift terms is now guaranteed to resolve ties in the absolute value with the sign of the shifts. [(5583)](https://github.com/PennyLaneAI/pennylane/pull/5583)

<h3>Breaking changes ๐Ÿ’”</h3>

* Passing `shots` as a keyword argument to a `QNode` initialization now raises an error instead of ignoring the input. [(5748)](https://github.com/PennyLaneAI/pennylane/pull/5748)

* A custom decomposition can no longer be provided to `qml.QDrift`. Instead, apply the operations in your custom operation directly with `qml.apply`. [(5698)](https://github.com/PennyLaneAI/pennylane/pull/5698)

* Sampling observables composed of `X`, `Y`, `Z` and `Hadamard` now returns values of type `float` instead of `int`. [(5607)](https://github.com/PennyLaneAI/pennylane/pull/5607)

* `qml.is_commuting` no longer accepts the `wire_map` argument, which does not bring any functionality. [(5660)](https://github.com/PennyLaneAI/pennylane/pull/5660)

* `qml.from_qasm_file` has been removed. The user can open files and load their content using `qml.from_qasm`. [(5659)](https://github.com/PennyLaneAI/pennylane/pull/5659)

* `qml.load` has been removed in favour of more specific functions, such as `qml.from_qiskit`, etc. [(5654)](https://github.com/PennyLaneAI/pennylane/pull/5654)

* `qml.transforms.convert_to_numpy_parameters` is now a proper transform and its output signature has changed, returning a list of `QuantumScript`s and a post-processing function instead of simply the transformed circuit. [(5693)](https://github.com/PennyLaneAI/pennylane/pull/5693)

* `Controlled.wires` does not include `self.work_wires` anymore. That can be accessed separately through `Controlled.work_wires`. Consequently, `Controlled.active_wires` has been removed in favour of the more common `Controlled.wires`. [(5728)](https://github.com/PennyLaneAI/pennylane/pull/5728)

<h3>Deprecations ๐Ÿ‘‹</h3>

* The `simplify` argument in `qml.Hamiltonian` and `qml.ops.LinearCombination` has been deprecated. Instead, `qml.simplify()` can be called on the constructed operator. [(5677)](https://github.com/PennyLaneAI/pennylane/pull/5677)

* `qml.transforms.map_batch_transform` has been deprecated, since a transform can be applied directly to a batch of tapes. [(5676)](https://github.com/PennyLaneAI/pennylane/pull/5676)

* The default behaviour of `qml.from_qasm()` to remove measurements in the QASM code has been deprecated. Use `measurements=[]` to keep this behaviour or `measurements=None` to keep the measurements from the QASM code. [(5882)](https://github.com/PennyLaneAI/pennylane/pull/5882) [(#5904)](https://github.com/PennyLaneAI/pennylane/pull/5904)

<h3>Documentation ๐Ÿ“</h3>

* The `qml.qchem` docs have been updated to showcase the new improvements. [(5758)](https://github.com/PennyLaneAI/pennylane/pull/5758/) [(#5638)](https://github.com/PennyLaneAI/pennylane/pull/5638/)

* Several links to other functions in measurement process docstrings have been fixed. [(5913)](https://github.com/PennyLaneAI/pennylane/pull/5913)

* Information about mid-circuit measurements has been moved from the measurements quickstart page to its own [mid-circuit measurements quickstart page](https://docs.pennylane.ai/en/stable/introduction/mid_circuit_measurements.html) [(#5870)](https://github.com/PennyLaneAI/pennylane/pull/5870)

* The documentation for the `default.tensor` device has been added. [(5719)](https://github.com/PennyLaneAI/pennylane/pull/5719)

* A small typo was fixed in the docstring for `qml.sample`. [(5685)](https://github.com/PennyLaneAI/pennylane/pull/5685)

* Typesetting for some of the documentation was fixed, (use of left/right delimiters, fractions, and fixing incorrectly set up commands) [(5804)](https://github.com/PennyLaneAI/pennylane/pull/5804)

* The `qml.Tracker` examples have been updated. [(5803)](https://github.com/PennyLaneAI/pennylane/pull/5803)

* The input types for `coupling_map` in `qml.transpile` have been updated to reflect all the allowed input types by `nx.to_networkx_graph`. [(5864)](https://github.com/PennyLaneAI/pennylane/pull/5864)

* The text in the `qml.data` module and datasets quickstart has been slightly modified to lead to the quickstart first and highlight `list_datasets`. [(5484)](https://github.com/PennyLaneAI/pennylane/pull/5484)

<h3>Bug fixes ๐Ÿ›</h3>

* `qml.compiler.active` first checks whether Catalyst is imported at all to avoid changing `jax_enable_x64` on module initialization. [(5960)](https://github.com/PennyLaneAI/pennylane/pull/5960)

* The `__invert__` dunder method of the `MeasurementValue` class uses an array-valued function. [(5955)](https://github.com/PennyLaneAI/pennylane/pull/5955)

* Skip `Projector`-measurement tests on devices that do not support it. [(5951)](https://github.com/PennyLaneAI/pennylane/pull/5951)

* The `default.tensor` device now preserves the order of wires if the initial MPS is created from a dense state vector. [(5892)](https://github.com/PennyLaneAI/pennylane/pull/5892)

* Fixed a bug where `hadamard_grad` returned a wrong shape for `qml.probs()` without wires. [(5860)](https://github.com/PennyLaneAI/pennylane/pull/5860)

* An error is now raised on processing an `AnnotatedQueue` into a `QuantumScript` if the queue contains something other than an `Operator`, `MeasurementProcess`, or `QuantumScript`. [(5866)](https://github.com/PennyLaneAI/pennylane/pull/5866)

* Fixed a bug in the wire handling on special controlled ops. [(5856)](https://github.com/PennyLaneAI/pennylane/pull/5856)

* Fixed a bug where `Sum`'s with repeated identical operations ended up with the same hash as `Sum`'s with different numbers of repeats. [(5851)](https://github.com/PennyLaneAI/pennylane/pull/5851)

* `qml.qaoa.cost_layer` and `qml.qaoa.mixer_layer` can now be used with `Sum` operators. [(5846)](https://github.com/PennyLaneAI/pennylane/pull/5846)

* Fixed a bug where `qml.MottonenStatePreparation` produces wrong derivatives at special parameter values. [(5774)](https://github.com/PennyLaneAI/pennylane/pull/5774)

* Fixed a bug where fractional powers and adjoints of operators were commuted, which is not well-defined/correct in general. Adjoints of fractional powers can no longer be evaluated. [(5835)](https://github.com/PennyLaneAI/pennylane/pull/5835)

* `qml.qnn.TorchLayer` now works with tuple returns. [(5816)](https://github.com/PennyLaneAI/pennylane/pull/5816)

* An error is now raised if a transform is applied to a catalyst qjit object. [(5826)](https://github.com/PennyLaneAI/pennylane/pull/5826)

* `qml.qnn.KerasLayer` and `qml.qnn.TorchLayer` no longer mutate the input `qml.QNode`'s interface. [(5800)](https://github.com/PennyLaneAI/pennylane/pull/5800)

* Docker builds on PR merging has been disabled. [(5777)](https://github.com/PennyLaneAI/pennylane/pull/5777)

* The validation of the adjoint method in `DefaultQubit` correctly handles device wires now. [(5761)](https://github.com/PennyLaneAI/pennylane/pull/5761)

* `QuantumPhaseEstimation.map_wires` on longer modifies the original operation instance. [(5698)](https://github.com/PennyLaneAI/pennylane/pull/5698)

* The decomposition of `qml.AmplitudeAmplification` now correctly queues all operations. [(5698)](https://github.com/PennyLaneAI/pennylane/pull/5698)

* Replaced `semantic_version` with `packaging.version.Version`, since the former cannot handle the metadata `.post` in the version string. [(5754)](https://github.com/PennyLaneAI/pennylane/pull/5754)

* The `dynamic_one_shot` transform now has expanded support for the `jax` and `torch` interfaces. [(5672)](https://github.com/PennyLaneAI/pennylane/pull/5672)

* The decomposition of `StronglyEntanglingLayers` is now compatible with broadcasting. [(5716)](https://github.com/PennyLaneAI/pennylane/pull/5716)

* `qml.cond` can now be applied to `ControlledOp` operations when deferring measurements. [(5725)](https://github.com/PennyLaneAI/pennylane/pull/5725)

* The legacy `Tensor` class can now handle a `Projector` with abstract tracer input. [(5720)](https://github.com/PennyLaneAI/pennylane/pull/5720)

* Fixed a bug that raised an error regarding expected versus actual `dtype` when using `JAX-JIT` on a circuit that returned samples of observables containing the `qml.Identity` operator. [(5607)](https://github.com/PennyLaneAI/pennylane/pull/5607)

* The signature of `CaptureMeta` objects (like `Operator`) now match the signature of the `__init__` call. [(5727)](https://github.com/PennyLaneAI/pennylane/pull/5727)

* Vanilla NumPy arrays are now used in `test_projector_expectation` to avoid differentiating `qml.Projector` with respect to the state attribute. [(5683)](https://github.com/PennyLaneAI/pennylane/pull/5683)

* `qml.Projector` is now compatible with `jax.jit`. [(5595)](https://github.com/PennyLaneAI/pennylane/pull/5595)

* Finite-shot circuits with a `qml.probs` measurement, both with a `wires` or `op` argument, can now be compiled with `jax.jit`. [(5619)](https://github.com/PennyLaneAI/pennylane/pull/5619)

* `param_shift`, `finite_diff`, `compile`, `insert`, `merge_rotations`, and `transpile` now all work with circuits with non-commuting measurements. [(5424)](https://github.com/PennyLaneAI/pennylane/pull/5424) [(#5681)](https://github.com/PennyLaneAI/pennylane/pull/5681)

* A correction has been added to `qml.bravyi_kitaev` to call the correct function for a `qml.FermiSentence` input. [(5671)](https://github.com/PennyLaneAI/pennylane/pull/5671)

* Fixed a bug where `sum_expand` produces incorrect result dimensions when combined with shot vectors, multiple measurements, and parameter broadcasting. [(5702)](https://github.com/PennyLaneAI/pennylane/pull/5702)

* Fixed a bug in `qml.math.dot` that raises an error when only one of the operands is a scalar. [(5702)](https://github.com/PennyLaneAI/pennylane/pull/5702)

* `qml.matrix` is now compatible with QNodes compiled by `qml.qjit`. [(5753)](https://github.com/PennyLaneAI/pennylane/pull/5753)

* `qml.snapshots` raises an error when a measurement other than `qml.state` is requested from `default.qubit.legacy` instead of silently returning the statevector. [(5805)](https://github.com/PennyLaneAI/pennylane/pull/5805)

* Fixed a bug where `default.qutrit` was falsely determined to be natively compatible with `qml.snapshots`. [(5805)](https://github.com/PennyLaneAI/pennylane/pull/5805)

* Fixed a bug where the measurement of a `qml.Snapshot` instance was not passed on during the `qml.adjoint` and `qml.ctrl` operations. [(5805)](https://github.com/PennyLaneAI/pennylane/pull/5805)

* `qml.CNOT` and `qml.Toffoli` now have an `arithmetic_depth` of `1`, as they are controlled operations. [(5797)](https://github.com/PennyLaneAI/pennylane/pull/5797)

* Fixed a bug where the gradient of `ControlledSequence`, `Reflection`, `AmplitudeAmplification`, and `Qubitization` was incorrect on `default.qubit.legacy` with `parameter_shift`. [(5806)](https://github.com/PennyLaneAI/pennylane/pull/5806)

* Fixed a bug where `split_non_commuting` raises an error when the circuit contains measurements of observables that are not Pauli words. [(5827)](https://github.com/PennyLaneAI/pennylane/pull/5827)

* The `simplify` method for `qml.Exp` now returns an operator with the correct number of Trotter steps, i.e. equal to the one from the pre-simplified operator. [(5831)](https://github.com/PennyLaneAI/pennylane/pull/5831)

* Fixed a bug where `CompositeOp.overlapping_ops` would put overlapping operators in different groups, leading to incorrect results returned by `LinearCombination.eigvals()`. [(5847)](https://github.com/PennyLaneAI/pennylane/pull/5847)

* The correct decomposition for a `qml.PauliRot` with an identity as `pauli_word` has been implemented, i.e. returns a `qml.GlobalPhase` with half the angle. [(5875)](https://github.com/PennyLaneAI/pennylane/pull/5875)

* `qml.pauli_decompose` now works in a jit-ted context, such as `jax.jit` and `qml.qjit`. [(5878)](https://github.com/PennyLaneAI/pennylane/pull/5878)

<h3>Contributors โœ๏ธ</h3>

This release contains contributions from (in alphabetical order):

Tarun Kumar Allamsetty, Guillermo Alonso-Linaje, Utkarsh Azad, Lillian M. A. Frederiksen, Ludmila Botelho, Gabriel Bottrill, Thomas Bromley, Jack Brown, Astral Cai, Ahmed Darwish, Isaac De Vlugt, Diksha Dhawan, Pietropaolo Frisoni, Emiliano Godinez, Diego Guala, Daria Van Hende, Austin Huang, David Ittah, Soran Jahangiri, Rohan Jain, Mashhood Khan, Korbinian Kottmann, Christina Lee, Vincent Michaud-Rioux, Lee James O'Riordan, Mudit Pandey, Kenya Sakka, Jay Soni, Kazuki Tsuoka, Haochen Paul Wang, David Wierichs.

0.36.0

<h3>New features since last release</h3>

<h4>Estimate errors in a quantum circuit ๐Ÿงฎ</h4>

* This version of PennyLane lays the foundation for estimating the total error in a quantum circuit from the combination of individual gate errors. [(5154)](https://github.com/PennyLaneAI/pennylane/pull/5154) [(#5464)](https://github.com/PennyLaneAI/pennylane/pull/5464) [(#5465)](https://github.com/PennyLaneAI/pennylane/pull/5465) [(#5278)](https://github.com/PennyLaneAI/pennylane/pull/5278) [(#5384)](https://github.com/PennyLaneAI/pennylane/pull/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](https://en.wikipedia.org/wiki/Matrix_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 from `qml.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 via `get_error`:

python
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

pycon
>>> 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 the `error` method and should return a `SpectralNormError` instance:

python
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 arbitrary `SpectralNormError` when called in a QNode. It does not require a decomposition or matrix representation when used with `null.qubit` (suggested for use with resource and error estimation since circuit executions are not required to calculate resources or errors).

python
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`:

pycon
>>> qml.specs(circuit)()['errors']
{'SpectralNormError': SpectralNormError(0.30000000000000004)}


* PennyLane already includes a number of built-in building blocks for algorithms like `QuantumPhaseEstimation` and `TrotterProduct`. `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.

python
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`:

pycon
>>> qml.specs(circuit)()["errors"]
{'SpectralNormError': SpectralNormError(0.07616666666666666)}


Check out our [error propagation demo](https://pennylane.ai/qml/demos/tutorial_error_prop/) to see how to use these new features in a real-world example!

<h4>Access an extended arsenal of quantum algorithms ๐Ÿน</h4>

* The Fast Approximate BLock-Encodings (FABLE) algorithm for embedding a matrix into a quantum circuit as outlined in [arXiv:2205.00081](https://arxiv.org/abs/2205.00081) is now accessible via the `qml.FABLE` template. [(#5107)](https://github.com/PennyLaneAI/pennylane/pull/5107)

The usage of `qml.FABLE` is similar to `qml.BlockEncode` but provides a more efficient circuit construction at the cost of a user-defined approximation level, `tol`. The number of wires that `qml.FABLE` operates on is `2*n + 1`, where `n` defines the dimension of the $2^n \times 2^n$ matrix that we want to block-encode.

python
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()


pycon
>>> 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)](https://github.com/PennyLaneAI/pennylane/pull/5160)

Based on [arXiv:quant-ph/0005055](https://arxiv.org/abs/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`.

python
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](https://docs.pennylane.ai/en/stable/development/adding_operators.html) with a decomposition. Amplitude amplification can then be set up within a circuit:

python
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))


pycon
>>> 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 of `qml.FlipSign`, which operates on basis states. [(5159)](https://github.com/PennyLaneAI/pennylane/pull/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 an `Operator`. For example, if we want to reflect about $\vert \psi \rangle = \vert + \rangle$, then $U = H$:

python
U = qml.Hadamard(wires=0)
dev = qml.device('default.qubit')

qml.qnode(dev)
def circuit():
qml.Reflection(U)
return qml.state()


pycon
>>> 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)](https://github.com/PennyLaneAI/pennylane/pull/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.

python
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)


<h4>Make use of more methods to map from molecules ๐Ÿ—บ๏ธ</h4>

* A new function called `qml.bravyi_kitaev` has been added to perform the Bravyi-Kitaev mapping of fermionic Hamiltonians to qubit Hamiltonians. [(5390)](https://github.com/PennyLaneAI/pennylane/pull/5390)

This function presents an alternative mapping to `qml.jordan_wigner` or `qml.parity_transform` which can help us measure expectation values more efficiently on hardware. Simply provide a fermionic Hamiltonian (created from `from_string`, `FermiA`, `FermiC`, `FermiSentence`, or `FermiWord`) and the number of qubits / spin orbitals in the system, `n`:

pycon
>>> 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 with `qml.parity_transform` and the new Bravyi-Kitaev mapping (`qml.bravyi_kitaev`). [(5472)](https://github.com/PennyLaneAI/pennylane/pull/5472) [(#5472)](https://github.com/PennyLaneAI/pennylane/pull/5472)

pycon
>>> 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]


<h4>Calculate dynamical Lie algebras ๐Ÿ‘พ</h4>

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)](https://github.com/PennyLaneAI/pennylane/pull/5161) [(#5169)](https://github.com/PennyLaneAI/pennylane/pull/5169) [(#5627)](https://github.com/PennyLaneAI/pennylane/pull/5627)

For a list of operators `ops = [op1, op2, op3, ..]`, one computes all nested commutators between `ops` until no new operators are generated from commutation. All these operators together form the DLA, see e.g. section IIB of [arXiv:2308.01432](https://arxiv.org/abs/2308.01432).

Take for example the following operators:

python
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)` and `X(0) Y(1)` (omitting scalar prefactors).

python
>>> 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)`.

python
>>> 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.

python
>>> 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)](https://github.com/PennyLaneAI/pennylane/pull/5406)

For example, we can compute the adjoint representation of the transverse field Ising model DLA.

pycon
>>> 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](https://docs.pennylane.ai/en/stable/code/api/pennylane.structure_constants.html) to understand how structure constants are a useful way to represent a DLA.

* Computing the center of a dynamical Lie algebra. [(5477)](https://github.com/PennyLaneAI/pennylane/pull/5477)

Given a DLA `g`, we can now compute its centre. The `center` is the collection of operators that commute with _all_ other operators in the DLA.

pycon
>>> 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](https://pennylane.ai/qml/demos/tutorial_liealgebra).

<h3>Improvements ๐Ÿ› </h3>

<h4>Simulate mixed-state qutrit systems</h4>

* Mixed qutrit states can now be simulated with the `default.qutrit.mixed` device. [(5495)](https://github.com/PennyLaneAI/pennylane/pull/5495) [(#5451)](https://github.com/PennyLaneAI/pennylane/pull/5451) [(#5186)](https://github.com/PennyLaneAI/pennylane/pull/5186) [(#5082)](https://github.com/PennyLaneAI/pennylane/pull/5082) [(#5213)](https://github.com/PennyLaneAI/pennylane/pull/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`.

python
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()


pycon
>>> 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!

<h4>Work easily and efficiently with operators</h4>

* 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](https://docs.pennylane.ai/en/stable/news/new_opmath.html) and don't hesitate to reach out to us on the [PennyLane discussion forum](https://discuss.pennylane.ai/). 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)](https://github.com/PennyLaneAI/pennylane/pull/5269)

* A new class called `qml.ops.LinearCombination` has been introduced. In essence, this class is an updated equivalent of the now-deprecated `qml.ops.Hamiltonian` but for usage with the new operator arithmetic. [(5216)](https://github.com/PennyLaneAI/pennylane/pull/5216)

* `qml.ops.Sum` now supports storing grouping information. Grouping type and method can be specified during construction using the `grouping_type` and `method` keyword arguments of `qml.dot`, `qml.sum`, or `qml.ops.Sum`. The grouping indices are stored in `Sum.grouping_indices`. [(5179)](https://github.com/PennyLaneAI/pennylane/pull/5179)

python
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")


pycon
>>> op.grouping_indices
((2,), (0, 1))


Additionally, `grouping_type` and `method` can be set or changed after construction using `Sum.compute_grouping()`:

python
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)


pycon
>>> 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()`, not `Sum.operands`.

* A new function called `qml.operation.convert_to_legacy_H` that converts `Sum`, `SProd`, and `Prod` to `Hamiltonian` instances has been added. This function is intended for developers and will be removed in a future release without a deprecation cycle. [(5309)](https://github.com/PennyLaneAI/pennylane/pull/5309)

* The `qml.is_commuting` function now accepts `Sum`, `SProd`, and `Prod` instances. [(5351)](https://github.com/PennyLaneAI/pennylane/pull/5351)

* Operators can now be left-multiplied by NumPy arrays (i.e., `arr * op`). [(5361)](https://github.com/PennyLaneAI/pennylane/pull/5361)

* `op.generator()`, where `op` is an `Operator` instance, now returns operators consistent with the global setting for `qml.operator.active_new_opmath()` wherever possible. `Sum`, `SProd` and `Prod` instances will be returned even after disabling the new operator arithmetic in cases where they offer additional functionality not available using legacy operators. [(5253)](https://github.com/PennyLaneAI/pennylane/pull/5253) [(#5410)](https://github.com/PennyLaneAI/pennylane/pull/5410) [(#5411)](https://github.com/PennyLaneAI/pennylane/pull/5411) [(#5421)](https://github.com/PennyLaneAI/pennylane/pull/5421)

* `Prod` instances temporarily have a new `obs` property, which helps smoothen the transition of the new operator arithmetic system. In particular, this is aimed at preventing breaking code that uses `Tensor.obs`. The property has been immediately deprecated. Moving forward, we recommend using `op.operands`. [(5539)](https://github.com/PennyLaneAI/pennylane/pull/5539)

* `qml.ApproxTimeEvolution` is now compatible with any operator that has a defined `pauli_rep`. [(5362)](https://github.com/PennyLaneAI/pennylane/pull/5362)

* `Hamiltonian.pauli_rep` is now defined if the Hamiltonian is a linear combination of Pauli operators. [(5377)](https://github.com/PennyLaneAI/pennylane/pull/5377)

* `Prod` instances created with qutrit operators now have a defined `eigvals()` method. [(5400)](https://github.com/PennyLaneAI/pennylane/pull/5400)

* `qml.transforms.hamiltonian_expand` and `qml.transforms.sum_expand` can now handle multi-term observables with a constant offset (i.e., terms like `qml.I()`). [(5414)](https://github.com/PennyLaneAI/pennylane/pull/5414) [(#5543)](https://github.com/PennyLaneAI/pennylane/pull/5543)

* `qml.qchem.taper_operation` is now compatible with the new operator arithmetic. [(5326)](https://github.com/PennyLaneAI/pennylane/pull/5326)

* The warning for an observable that might not be hermitian in QNode executions has been removed. This enables jit-compilation. [(5506)](https://github.com/PennyLaneAI/pennylane/pull/5506)

* `qml.transforms.split_non_commuting` will now work with single-term operator arithmetic. [(5314)](https://github.com/PennyLaneAI/pennylane/pull/5314)

* `LinearCombination` and `Sum` now accept `_grouping_indices` on initialization. This addition is relevant to developers only. [(5524)](https://github.com/PennyLaneAI/pennylane/pull/5524)

* Calculating the dense, differentiable matrix for `PauliSentence` and operators with Pauli sentences is now faster. [(5578)](https://github.com/PennyLaneAI/pennylane/pull/5578)

<h4>Community contributions ๐Ÿฅณ</h4>

* `ExpectationMP`, `VarianceMP`, `CountsMP`, and `SampleMP` now have a `process_counts` method (similar to `process_samples`). This allows for calculating measurements given a `counts` dictionary. [(5256)](https://github.com/PennyLaneAI/pennylane/pull/5256) [(#5395)](https://github.com/PennyLaneAI/pennylane/pull/5395)

* Type-hinting has been added in the `Operator` class for better interpretability. [(5490)](https://github.com/PennyLaneAI/pennylane/pull/5490)

* An alternate strategy for sampling with multiple different `shots` values has been implemented via the `shots.bins()` method, which samples all shots at once and then processes each separately. [(5476)](https://github.com/PennyLaneAI/pennylane/pull/5476)

<h4>Mid-circuit measurements and dynamic circuits</h4>

* A new module called `qml.capture` that will contain PennyLane's own capturing mechanism for hybrid quantum-classical programs has been added. [(5509)](https://github.com/PennyLaneAI/pennylane/pull/5509)

* The `dynamic_one_shot` transform has been introduced, enabling dynamic circuit execution on circuits with finite `shots` and devices that natively support mid-circuit measurements. [(5266)](https://github.com/PennyLaneAI/pennylane/pull/5266)

* The `QubitDevice` class and children classes support the `dynamic_one_shot` transform provided that they support mid-circuit measurement operations natively. [(5317)](https://github.com/PennyLaneAI/pennylane/pull/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 with `dynamic_one_shot` and `defer_measurements` and (2) makes our continuous-integration (CI) have less failures due to stochasticity. [(5337)](https://github.com/PennyLaneAI/pennylane/pull/5337)

<h4>Performance and broadcasting</h4>

* Gradient transforms may now be applied to batched/broadcasted QNodes as long as the broadcasting is in non-trainable parameters. [(5452)](https://github.com/PennyLaneAI/pennylane/pull/5452)

* The performance of computing the matrix of `qml.QFT` has been improved. [(5351)](https://github.com/PennyLaneAI/pennylane/pull/5351)

* `qml.transforms.broadcast_expand` now supports shot vectors when returning `qml.sample()`. [(5473)](https://github.com/PennyLaneAI/pennylane/pull/5473)

* `LightningVJPs` is now compatible with Lightning devices using the new device API. [(5469)](https://github.com/PennyLaneAI/pennylane/pull/5469)

<h4>Device capabilities</h4>

* Obtaining classical shadows using the `default.clifford` device is now compatible with [stim](https://github.com/quantumlib/Stim) `v1.13.0`. [(#5409)](https://github.com/PennyLaneAI/pennylane/pull/5409)

* `default.mixed` has improved support for sampling-based measurements with non-NumPy interfaces. [(5514)](https://github.com/PennyLaneAI/pennylane/pull/5514) [(#5530)](https://github.com/PennyLaneAI/pennylane/pull/5530)

* `default.mixed` now supports arbitrary state-based measurements with `qml.Snapshot`. [(5552)](https://github.com/PennyLaneAI/pennylane/pull/5552)

* `null.qubit` has been upgraded to the new device API and has support for all measurements and various modes of differentiation. [(5211)](https://github.com/PennyLaneAI/pennylane/pull/5211)

<h4>Other improvements</h4>

* 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)](https://github.com/PennyLaneAI/pennylane/pull/5306)

* `qml.draw` and `qml.draw_mpl` will now attempt to sort the wires if no wire order is provided by the user or the device. [(5576)](https://github.com/PennyLaneAI/pennylane/pull/5576)

* A clear error message is added in `KerasLayer` when using the newest version of TensorFlow with Keras 3 (which is not currently compatible with `KerasLayer`), linking to instructions to enable Keras 2. [(5488)](https://github.com/PennyLaneAI/pennylane/pull/5488)

* `qml.ops.Conditional` now stores the `data`, `num_params`, and `ndim_param` attributes of the operator it wraps. [(5473)](https://github.com/PennyLaneAI/pennylane/pull/5473)

* The `molecular_hamiltonian` function calls `PySCF` directly when `method='pyscf'` is selected. [(5118)](https://github.com/PennyLaneAI/pennylane/pull/5118)

* `cache_execute` has been replaced with an alternate implementation based on `transform`. [(5318)](https://github.com/PennyLaneAI/pennylane/pull/5318)

* QNodes now defer `diff_method` validation to the device under the new device API. [(5176)](https://github.com/PennyLaneAI/pennylane/pull/5176)

* The device test suite has been extended to cover gradient methods, templates and arithmetic observables. [(5273)](https://github.com/PennyLaneAI/pennylane/pull/5273) [(#5518)](https://github.com/PennyLaneAI/pennylane/pull/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 valid `pauli_rep`. [(5572)](https://github.com/PennyLaneAI/pennylane/pull/5572)

* Circuits running on `lightning.qubit` and that return `qml.state()` now preserve the `dtype` when specified. [(5547)](https://github.com/PennyLaneAI/pennylane/pull/5547)

<h3>Breaking changes ๐Ÿ’”</h3>

* `qml.matrix()` called on the following will now raise an error if `wire_order` is not specified: * tapes with more than one wire * quantum functions * `Operator` classes where `num_wires` does not equal to 1 * QNodes if the device does not have wires specified. * `PauliWord`s and `PauliSentence`s with more than one wire. [(5328)](https://github.com/PennyLaneAI/pennylane/pull/5328) [(#5359)](https://github.com/PennyLaneAI/pennylane/pull/5359)

* `single_tape_transform`, `batch_transform`, `qfunc_transform`, `op_transform`, `gradient_transform` and `hessian_transform` have been removed. Instead, switch to using the new `qml.transform` function. Please refer to `the transform docs <https://docs.pennylane.ai/en/stable/code/qml_transforms.html#custom-transforms>`_ to see how this can be done. [(5339)](https://github.com/PennyLaneAI/pennylane/pull/5339)

* Attempting to multiply `PauliWord` and `PauliSentence` with `*` will raise an error. Instead, use `` to conform with the PennyLane convention. [(5341)](https://github.com/PennyLaneAI/pennylane/pull/5341)

* `DefaultQubit` now uses a pre-emptive key-splitting strategy to avoid reusing JAX PRNG keys throughout a single `execute` call. [(5515)](https://github.com/PennyLaneAI/pennylane/pull/5515)

* `qml.pauli.pauli_mult` and `qml.pauli.pauli_mult_with_phase` have been removed. Instead, use `qml.simplify(qml.prod(pauli_1, pauli_2))` to get the reduced operator. [(5324)](https://github.com/PennyLaneAI/pennylane/pull/5324)

pycon
>>> 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)](https://github.com/PennyLaneAI/pennylane/pull/5486)

* `Operator` dunder methods now combine like-operator arithmetic classes via `lazy=False`. This reduces the chances of getting a `RecursionError` and makes nested operators easier to work with. [(5478)](https://github.com/PennyLaneAI/pennylane/pull/5478)

* The private functions `_pauli_mult`, `_binary_matrix` and `_get_pauli_map` from the `pauli` module have been removed. The same functionality can be achieved using newer features in the `pauli` module. [(5323)](https://github.com/PennyLaneAI/pennylane/pull/5323)

* `MeasurementProcess.name` and `MeasurementProcess.data` have been removed. Use `MeasurementProcess.obs.name` and `MeasurementProcess.obs.data` instead. [(5321)](https://github.com/PennyLaneAI/pennylane/pull/5321)

* `Operator.validate_subspace(subspace)` has been removed. Instead, use `qml.ops.qutrit.validate_subspace(subspace)`. [(5311)](https://github.com/PennyLaneAI/pennylane/pull/5311)

* The contents of `qml.interfaces` has been moved inside `qml.workflow`. The old import path no longer exists. [(5329)](https://github.com/PennyLaneAI/pennylane/pull/5329)

* Since `default.mixed` does not support snapshots with measurements, attempting to do so will result in a `DeviceError` instead of getting the density matrix. [(5416)](https://github.com/PennyLaneAI/pennylane/pull/5416)

* `LinearCombination._obs_data` has been removed. You can still use `LinearCombination.compare` to check mathematical equivalence between a `LinearCombination` and another operator. [(5504)](https://github.com/PennyLaneAI/pennylane/pull/5504)

<h3>Deprecations ๐Ÿ‘‹</h3>

* 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, using `qml.Hamiltonian` is recommended because it dispatches to the `LinearCombination` class when the new approach to operator arithmetic is enabled. This will allow you to continue to use `qml.Hamiltonian` with existing code without needing to make any changes. [(5393)](https://github.com/PennyLaneAI/pennylane/pull/5393)

* `qml.load` has been deprecated. Instead, please use the functions outlined in the [Importing workflows quickstart guide](https://docs.pennylane.ai/en/latest/introduction/importing_workflows.html). [(#5312)](https://github.com/PennyLaneAI/pennylane/pull/5312)

* Specifying `control_values` with a bit string in `qml.MultiControlledX` has been deprecated. Instead, use a list of booleans or 1s and 0s. [(5352)](https://github.com/PennyLaneAI/pennylane/pull/5352)

* `qml.from_qasm_file` has been deprecated. Instead, please open the file and then load its content using `qml.from_qasm`. [(5331)](https://github.com/PennyLaneAI/pennylane/pull/5331)

pycon
>>> with open("test.qasm", "r") as f:
... circuit = qml.from_qasm(f.read())


<h3>Documentation ๐Ÿ“</h3>

* [A new page](https://docs.pennylane.ai/en/latest/code/qml_workflow.html#return-type-specification) explaining the shapes and nesting of return types has been added. [(5418)](https://github.com/PennyLaneAI/pennylane/pull/5418)

* Redundant documentation for the `evolve` function has been removed. [(5347)](https://github.com/PennyLaneAI/pennylane/pull/5347)

* The final example in the `compile` docstring has been updated to use transforms correctly. [(5348)](https://github.com/PennyLaneAI/pennylane/pull/5348)

* A link to the demos for using `qml.SpecialUnitary` and `qml.QNGOptimizer` has been added to their respective docstrings. [(5376)](https://github.com/PennyLaneAI/pennylane/pull/5376)

* A code example in the `qml.measure` docstring has been added that showcases returning mid-circuit measurement statistics from QNodes. [(5441)](https://github.com/PennyLaneAI/pennylane/pull/5441)

* The computational basis convention used for `qml.measure` โ€” 0 and 1 rather than ยฑ1 โ€” has been clarified in its docstring. [(5474)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/5548)

* A summary of all changes has been added in the "Updated Operators" page in the new "Release news" section in the docs. [(5483)](https://github.com/PennyLaneAI/pennylane/pull/5483) [(#5636)](https://github.com/PennyLaneAI/pennylane/pull/5636)

<h3>Bug fixes ๐Ÿ›</h3>

* Patches the QNode so that parameter-shift will be considered best with lightning if `qml.metric_tensor` is in the transform program. [(5624)](https://github.com/PennyLaneAI/pennylane/pull/5624)

* Stopped printing the ID of `qcut.MeasureNode` and `qcut.PrepareNode` in tape drawing. [(5613)](https://github.com/PennyLaneAI/pennylane/pull/5613)

* Improves the error message for setting shots on the new device interface, or trying to access a property that no longer exists. [(5616)](https://github.com/PennyLaneAI/pennylane/pull/5616)

* Fixed a bug where `qml.draw` and `qml.draw_mpl` incorrectly raised errors for circuits collecting statistics on mid-circuit measurements while using `qml.defer_measurements`. [(5610)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/5612) [(#5623)](https://github.com/PennyLaneAI/pennylane/pull/5623)

* `qml.counts` now returns the same keys with `dynamic_one_shot` and `defer_measurements`. [(5587)](https://github.com/PennyLaneAI/pennylane/pull/5587)

* `null.qubit` now automatically supports any operation without a decomposition. [(5582)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/4945)

* `ApproxTimeEvolution`, `CommutingEvolution`, `QDrift`, and `TrotterProduct` now de-queue their input observable. [(5524)](https://github.com/PennyLaneAI/pennylane/pull/5524)

* (In)equality of `qml.HilbertSchmidt` instances is now reported correctly by `qml.equal`. [(5538)](https://github.com/PennyLaneAI/pennylane/pull/5538)

* `qml.ParticleConservingU1` and `qml.ParticleConservingU2` no longer raise an error when the initial state is not specified but default to the all-zeros state. [(5535)](https://github.com/PennyLaneAI/pennylane/pull/5535)

* `qml.counts` no longer returns negative samples when measuring 8 or more wires. [(5544)](https://github.com/PennyLaneAI/pennylane/pull/5544) [(#5556)](https://github.com/PennyLaneAI/pennylane/pull/5556)

* The `dynamic_one_shot` transform now works with broadcasting. [(5473)](https://github.com/PennyLaneAI/pennylane/pull/5473)

* Diagonalizing gates are now applied when measuring `qml.probs` on non-computational basis states on a Lightning device. [(5529)](https://github.com/PennyLaneAI/pennylane/pull/5529)

* `two_qubit_decomposition` no longer diverges at a special case of a unitary matrix. [(5448)](https://github.com/PennyLaneAI/pennylane/pull/5448)

* The `qml.QNSPSAOptimizer` now correctly handles optimization for legacy devices that do not follow the new device API. [(5497)](https://github.com/PennyLaneAI/pennylane/pull/5497)

* Operators applied to all wires are now drawn correctly in a circuit with mid-circuit measurements. [(5501)](https://github.com/PennyLaneAI/pennylane/pull/5501)

* Fixed a bug where certain unary mid-circuit measurement expressions would raise an uncaught error. [(5480)](https://github.com/PennyLaneAI/pennylane/pull/5480)

* Probabilities now sum to 1 when using the `torch` interface with `default_dtype` set to `torch.float32`. [(5462)](https://github.com/PennyLaneAI/pennylane/pull/5462)

* Tensorflow can now handle devices with `float32` results but `float64` input parameters. [(5446)](https://github.com/PennyLaneAI/pennylane/pull/5446)

* Fixed a bug where the `argnum` keyword argument of `qml.gradients.stoch_pulse_grad` references the wrong parameters in a tape, creating an inconsistency with other differentiation methods and preventing some use cases. [(5458)](https://github.com/PennyLaneAI/pennylane/pull/5458)

* Bounded value failures due to numerical noise with calls to `np.random.binomial` is now avoided. [(5447)](https://github.com/PennyLaneAI/pennylane/pull/5447)

* Using `` with legacy Hamiltonian instances now properly de-queues the previously existing operations. [(5455)](https://github.com/PennyLaneAI/pennylane/pull/5455)

* The `QNSPSAOptimizer` now properly handles differentiable parameters, resulting in being able to use it for more than one optimization step. [(5439)](https://github.com/PennyLaneAI/pennylane/pull/5439)

* The QNode interface now resets if an error occurs during execution. [(5449)](https://github.com/PennyLaneAI/pennylane/pull/5449)

* Failing tests due to changes with Lightning's adjoint diff pipeline have been fixed. [(5450)](https://github.com/PennyLaneAI/pennylane/pull/5450)

* Failures occurring when making autoray-dispatched calls to Torch with paired CPU data have been fixed. [(5438)](https://github.com/PennyLaneAI/pennylane/pull/5438)

* `jax.jit` now works with `qml.sample` with a multi-wire observable. [(5422)](https://github.com/PennyLaneAI/pennylane/pull/5422)

* `qml.qinfo.quantum_fisher` now works with non-`default.qubit` devices. [(5423)](https://github.com/PennyLaneAI/pennylane/pull/5423)

* We no longer perform unwanted `dtype` promotion in the `pauli_rep` of `SProd` instances when using Tensorflow. [(5246)](https://github.com/PennyLaneAI/pennylane/pull/5246)

* Fixed `TestQubitIntegration.test_counts` in `tests/interfaces/test_jax_qnode.py` to always produce counts for all outcomes. [(5336)](https://github.com/PennyLaneAI/pennylane/pull/5336)

* Fixed `PauliSentence.to_mat(wire_order)` to support identities with wires. [(5407)](https://github.com/PennyLaneAI/pennylane/pull/5407)

* `CompositeOp.map_wires` now correctly maps the `overlapping_ops` property. [(5430)](https://github.com/PennyLaneAI/pennylane/pull/5430)

* `DefaultQubit.supports_derivatives` has been updated to correctly handle circuits containing mid-circuit measurements and adjoint differentiation. [(5434)](https://github.com/PennyLaneAI/pennylane/pull/5434)

* `SampleMP`, `ExpectationMP`, `CountsMP`, and `VarianceMP` constructed with `eigvals` can now properly process samples. [(5463)](https://github.com/PennyLaneAI/pennylane/pull/5463)

* Fixed a bug in `hamiltonian_expand` that produces incorrect output dimensions when shot vectors are combined with parameter broadcasting. [(5494)](https://github.com/PennyLaneAI/pennylane/pull/5494)

* `default.qubit` now allows measuring `Identity` on no wires and observables containing `Identity` on no wires. [(5570)](https://github.com/PennyLaneAI/pennylane/pull/5570/)

* Fixed a bug where `TorchLayer` does not work with shot vectors. [(5492)](https://github.com/PennyLaneAI/pennylane/pull/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)](https://github.com/PennyLaneAI/pennylane/pull/5492)

* Fixed a bug in `qml.math.kron` that makes Torch incompatible with NumPy. [(5540)](https://github.com/PennyLaneAI/pennylane/pull/5540)

* Fixed a bug in `_group_measurements` that fails to group measurements with commuting observables when they are operands of `Prod`. [(5525)](https://github.com/PennyLaneAI/pennylane/pull/5525)

* `qml.equal` can now be used with sums and products that contain operators on no wires like `I` and `GlobalPhase`. [(5562)](https://github.com/PennyLaneAI/pennylane/pull/5562)

* `CompositeOp.has_diagonalizing_gates` now does a more complete check of the base operators to ensure consistency between `op.has_diagonalzing_gates` and `op.diagonalizing_gates()` [(5603)](https://github.com/PennyLaneAI/pennylane/pull/5603)

* Updated the `method` kwarg of `qml.TrotterProduct().error()` to be more clear that we are computing upper-bounds. [(5637)](https://github.com/PennyLaneAI/pennylane/pull/5637)

<h3>Contributors โœ๏ธ</h3>

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.

0.35.1

<h3>Bug fixes ๐Ÿ›</h3>

* Lightning simulators need special handling of diagonalizing gates when performing sampling measurements. [(5343)](https://github.com/PennyLaneAI/pennylane/pull/5343)

* Updated the lower bound on the required Catalyst version to `v0.5.0`. [(5320)](https://github.com/PennyLaneAI/pennylane/pull/5320)

<h3>Contributors โœ๏ธ</h3>

This release contains contributions from (in alphabetical order):

Vincent Michaud-Rioux, Erick Ochoa Lopez.

0.35.0

<h3>New features since last release</h3>

<h4>Qiskit 1.0 integration ๐Ÿ”Œ</h4>

* This version of PennyLane makes it easier to import circuits from Qiskit. [(5218)](https://github.com/PennyLaneAI/pennylane/pull/5218) [(#5168)](https://github.com/PennyLaneAI/pennylane/pull/5168)

The `qml.from_qiskit` function converts a Qiskit [QuantumCircuit](https://docs.quantum.ibm.com/api/qiskit/qiskit.circuit.QuantumCircuit) into a PennyLane [quantum function](https://docs.pennylane.ai/en/stable/introduction/circuits.html#quantum-functions). Although `qml.from_qiskit` already exists in PennyLane, we have made a number of improvements to make importing from Qiskit easier. And yes โ€” `qml.from_qiskit` functionality is compatible with both Qiskit [1.0](https://docs.quantum.ibm.com/api/qiskit/release-notes/1.0) and earlier versions! Here's a comprehensive list of the improvements:

* You can now append PennyLane measurements onto the quantum function returned by `qml.from_qiskit`. Consider this simple Qiskit circuit:

python
import pennylane as qml
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.rx(0.785, 0)
qc.ry(1.57, 1)


We can convert it into a PennyLane QNode in just a few lines, with PennyLane `measurements` easily included:

pycon
>>> dev = qml.device("default.qubit")
>>> measurements = qml.expval(qml.Z(0) qml.Z(1))
>>> qfunc = qml.from_qiskit(qc, measurements=measurements)
>>> qnode = qml.QNode(qfunc, dev)
>>> qnode()
tensor(0.00056331, requires_grad=True)


* Quantum circuits that already contain Qiskit-side measurements can be faithfully converted with `qml.from_qiskit`. Consider this example Qiskit circuit:

python
qc = QuantumCircuit(3, 2) Teleportation

qc.rx(0.9, 0) Prepare input state on qubit 0

qc.h(1) Prepare Bell state on qubits 1 and 2 qc.cx(1, 2)

qc.cx(0, 1) Perform teleportation
qc.h(0)
qc.measure(0, 0)
qc.measure(1, 1)

with qc.if_test((1, 1)): Perform first conditional
qc.x(2)


This circuit can be converted into PennyLane with the Qiskit measurements still accessible. For example, we can use those results as inputs to a mid-circuit measurement in PennyLane:

python
qml.qnode(dev)
def teleport():
m0, m1 = qml.from_qiskit(qc)()
qml.cond(m0, qml.Z)(2)
return qml.density_matrix(2)


pycon
>>> teleport()
tensor([[0.81080498+0.j , 0. +0.39166345j],
[0. -0.39166345j, 0.18919502+0.j ]], requires_grad=True)


* It is now more intuitive to handle and differentiate parametrized Qiskit circuits. Consider the following circuit:

python
from qiskit.circuit import Parameter
from pennylane import numpy as np

angle0 = Parameter("x") angle1 = Parameter("y")

qc = QuantumCircuit(2, 2)
qc.rx(angle0, 0)
qc.ry(angle1, 1)
qc.cx(1, 0)


We can convert this circuit into a QNode with two arguments, corresponding to `x` and `y`:

python
measurements = qml.expval(qml.PauliZ(0))
qfunc = qml.from_qiskit(qc, measurements)
qnode = qml.QNode(qfunc, dev)


The QNode can be evaluated and differentiated:

pycon
>>> x, y = np.array([0.4, 0.5], requires_grad=True)
>>> qnode(x, y)
tensor(0.80830707, requires_grad=True)

>>> qml.grad(qnode)(x, y)
(tensor(-0.34174675, requires_grad=True), tensor(-0.44158016, requires_grad=True))


This shows how easy it is to make a Qiskit circuit differentiable with PennyLane.

* In addition to circuits, it is also possible to convert operators from Qiskit to PennyLane with a new function called `qml.from_qiskit_op`. [(5251)](https://github.com/PennyLaneAI/pennylane/pull/5251)

A Qiskit [SparsePauliOp](https://docs.quantum.ibm.com/api/qiskit/qiskit.quantum_info.SparsePauliOp) can be converted to a PennyLane operator using `qml.from_qiskit_op`:

pycon
>>> from qiskit.quantum_info import SparsePauliOp
>>> qiskit_op = SparsePauliOp(["II", "XY"])
>>> qiskit_op SparsePauliOp(['II', 'XY'], coeffs=[1.+0.j, 1.+0.j])
>>> pl_op = qml.from_qiskit_op(qiskit_op)
>>> pl_op I(0) + X(1) Y(0)


Combined with `qml.from_qiskit`, it becomes easy to quickly calculate quantities like expectation values by converting the whole workflow to PennyLane:

python
qc = QuantumCircuit(2) Create circuit
qc.rx(0.785, 0)
qc.ry(1.57, 1)

measurements = qml.expval(pl_op) Create QNode
qfunc = qml.from_qiskit(qc, measurements)
qnode = qml.QNode(qfunc, dev)


pycon
>>> qnode() Evaluate!
tensor(0.29317504, requires_grad=True)


<h4>Native mid-circuit measurements on Default Qubit ๐Ÿ’ก</h4>

* Mid-circuit measurements can now be more scalable and efficient in finite-shots mode with `default.qubit` by simulating them in a similar way to what happens on quantum hardware. [(5088)](https://github.com/PennyLaneAI/pennylane/pull/5088) [(#5120)](https://github.com/PennyLaneAI/pennylane/pull/5120)

Previously, mid-circuit measurements (MCMs) would be automatically replaced with an additional qubit using the `qml.defer_measurements` transform. The circuit below would have required thousands of qubits to simulate.

Now, MCMs are performed in a similar way to quantum hardware with finite shots on `default.qubit`. For each shot and each time an MCM is encountered, the device evaluates the probability of projecting onto `|0>` or `|1>` and makes a random choice to collapse the circuit state. This approach works well when there are a lot of MCMs and the number of shots is not too high.

python
import pennylane as qml

dev = qml.device("default.qubit", shots=10)

qml.qnode(dev)
def f():
for i in range(1967):
qml.Hadamard(0)
qml.measure(0)
return qml.sample(qml.PauliX(0))


pycon
>>> f()
tensor([-1, -1, -1, 1, 1, -1, 1, -1, 1, -1], requires_grad=True)


<h4>Work easily and efficiently with operators ๐Ÿ”ง</h4>

* Over the past few releases, PennyLane's approach to operator arithmetic has been in the process of being overhauled. We have 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.

The updated operator arithmetic functionality is still being finalized, but can be activated using `qml.operation.enable_new_opmath()`. In the next release, the new behaviour will become the default, so we recommend enabling now to become familiar with the new system!

The following updates have been made in this version of PennyLane:

* You can now easily access Pauli operators via `I`, `X`, `Y`, and `Z`: [(5116)](https://github.com/PennyLaneAI/pennylane/pull/5116)

pycon
>>> from pennylane import I, X, Y, Z
>>> X(0) X(0)

The original long-form names `Identity`, `PauliX`, `PauliY`, and `PauliZ` remain available, but use of the short-form names is now recommended.

* A new `qml.commutator` function is now available that allows you to compute commutators between PennyLane operators. [(5051)](https://github.com/PennyLaneAI/pennylane/pull/5051) [(#5052)](https://github.com/PennyLaneAI/pennylane/pull/5052) [(#5098)](https://github.com/PennyLaneAI/pennylane/pull/5098)

pycon
>>> qml.commutator(X(0), Y(0))
2j * Z(0)


* Operators in PennyLane can have a backend Pauli representation, which can be used to perform faster operator arithmetic. Now, the Pauli representation will be automatically used for calculations when available. [(4989)](https://github.com/PennyLaneAI/pennylane/pull/4989) [(#5001)](https://github.com/PennyLaneAI/pennylane/pull/5001) [(#5003)](https://github.com/PennyLaneAI/pennylane/pull/5003) [(#5017)](https://github.com/PennyLaneAI/pennylane/pull/5017) [(#5027)](https://github.com/PennyLaneAI/pennylane/pull/5027)

The Pauli representation can be optionally accessed via `op.pauli_rep`:

pycon
>>> qml.operation.enable_new_opmath()
>>> op = X(0) + Y(0)
>>> op.pauli_rep
1.0 * X(0) + 1.0 * Y(0)


* Extensive improvements have been made to the string representations of PennyLane operators, making them shorter and possible to copy-paste as valid PennyLane code. [(5116)](https://github.com/PennyLaneAI/pennylane/pull/5116) [(#5138)](https://github.com/PennyLaneAI/pennylane/pull/5138)


>>> 0.5 * X(0)
0.5 * X(0)
>>> 0.5 * (X(0) + Y(1))
0.5 * (X(0) + Y(1))


Sums with many terms are broken up into multiple lines, but can still be copied back as valid code:


>>> 0.5 * (X(0) X(1)) + 0.7 * (X(1) X(2)) + 0.8 * (X(2) X(3))
(
0.5 * (X(0) X(1))
+ 0.7 * (X(1) X(2))
+ 0.8 * (X(2) X(3))
)


* Linear combinations of operators and operator multiplication via `Sum` and `Prod`, respectively, have been updated to reach feature parity with `Hamiltonian` and `Tensor`, respectively. This should minimize the effort to port over any existing code. [(5070)](https://github.com/PennyLaneAI/pennylane/pull/5070) [(#5132)](https://github.com/PennyLaneAI/pennylane/pull/5132) [(#5133)](https://github.com/PennyLaneAI/pennylane/pull/5133)

Updates include support for grouping via the `pauli` module:

pycon
>>> obs = [X(0) Y(1), Z(0), Y(0) Z(1), Y(1)]
>>> qml.pauli.group_observables(obs)
[[Y(0) Z(1)], [X(0) Y(1), Y(1)], [Z(0)]]


<h4>New Clifford device ๐Ÿฆพ</h4>

* A new `default.clifford` device enables efficient simulation of large-scale Clifford circuits defined in PennyLane through the use of [stim](https://github.com/quantumlib/Stim) as a backend. [(#4936)](https://github.com/PennyLaneAI/pennylane/pull/4936) [(#4954)](https://github.com/PennyLaneAI/pennylane/pull/4954) [(#5144)](https://github.com/PennyLaneAI/pennylane/pull/5144)

Given a circuit with only Clifford gates, one can use this device to obtain the usual range of PennyLane [measurements](https://docs.pennylane.ai/en/stable/introduction/measurements.html) as well as the state represented in the Tableau form of [Aaronson & Gottesman (2004)](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.70.052328):

python
import pennylane as qml

dev = qml.device("default.clifford", tableau=True)
qml.qnode(dev)
def circuit():
qml.CNOT(wires=[0, 1])
qml.PauliX(wires=[1])
qml.ISWAP(wires=[0, 1])
qml.Hadamard(wires=[0])
return qml.state()


pycon
>>> circuit()
array([[0, 1, 1, 0, 0],
[1, 0, 1, 1, 1],
[0, 0, 0, 1, 0],
[1, 0, 0, 1, 1]])


The `default.clifford` device also supports the `PauliError`, `DepolarizingChannel`, `BitFlip` and `PhaseFlip` [noise channels](https://docs.pennylane.ai/en/latest/introduction/operations.html#noisy-channels) when operating in finite-shot mode.

<h3>Improvements ๐Ÿ› </h3>

<h4>Faster gradients with VJPs and other performance improvements</h4>

* Vector-Jacobian products (VJPs) can result in faster computations when the output of your quantum Node has a low dimension. They can be enabled by setting `device_vjp=True` when loading a QNode. In the next release of PennyLane, VJPs are planned to be used by default, when available.

In this release, we have unlocked:

* Adjoint device VJPs can be used with `jax.jacobian`, meaning that `device_vjp=True` is always faster when using JAX with `default.qubit`. [(4963)](https://github.com/PennyLaneAI/pennylane/pull/4963)

* PennyLane can now use lightning-provided VJPs. [(4914)](https://github.com/PennyLaneAI/pennylane/pull/4914)

* VJPs can be used with TensorFlow, though support has not yet been added for `tf.Function` and Tensorflow Autograph. [(4676)](https://github.com/PennyLaneAI/pennylane/pull/4676)

* Measuring `qml.probs` is now faster due to an optimization in converting samples to counts. [(5145)](https://github.com/PennyLaneAI/pennylane/pull/5145)

* The performance of circuit-cutting workloads with large numbers of generated tapes has been improved. [(5005)](https://github.com/PennyLaneAI/pennylane/pull/5005)

* Queueing (`AnnotatedQueue`) has been removed from `qml.cut_circuit` and `qml.cut_circuit_mc` to improve performance for large workflows. [(5108)](https://github.com/PennyLaneAI/pennylane/pull/5108)

<h4>Community contributions ๐Ÿฅณ</h4>

* A new function called `qml.fermi.parity_transform` has been added for parity mapping of a fermionic Hamiltonian. [(4928)](https://github.com/PennyLaneAI/pennylane/pull/4928)

It is now possible to transform a fermionic Hamiltonian to a qubit Hamiltonian with parity mapping.

python
import pennylane as qml
fermi_ham = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'})

qubit_ham = qml.fermi.parity_transform(fermi_ham, n=6)


pycon
>>> print(qubit_ham)
-0.25j * Y(0) + (-0.25+0j) * (X(0) Z(1)) + (0.25+0j) * X(0) + 0.25j * (Y(0) Z(1))


* The transform `split_non_commuting` now accepts measurements of type `probs`, `sample`, and `counts`, which accept both wires and observables. [(4972)](https://github.com/PennyLaneAI/pennylane/pull/4972)

* The efficiency of matrix calculations when an operator is symmetric over a given set of wires has been improved. [(3601)](https://github.com/PennyLaneAI/pennylane/pull/3601)

* The `pennylane/math/quantum.py` module now has support for computing the minimum entropy of a density matrix. [(3959)](https://github.com/PennyLaneAI/pennylane/pull/3959/)

pycon
>>> x = [1, 0, 0, 1] / np.sqrt(2)
>>> x = qml.math.dm_from_state_vector(x)
>>> qml.math.min_entropy(x, indices=[0])
0.6931471805599455


* A function called `apply_operation` that applies operations to device-compatible states has been added to the new `qutrit_mixed` module found in `qml.devices`. [(5032)](https://github.com/PennyLaneAI/pennylane/pull/5032)

* A function called `measure` has been added to the new `qutrit_mixed` module found in `qml.devices` that measures device-compatible states for a collection of measurement processes. [(5049)](https://github.com/PennyLaneAI/pennylane/pull/5049)

* A `partial_trace` function has been added to `qml.math` for taking the partial trace of matrices. [(5152)](https://github.com/PennyLaneAI/pennylane/pull/5152)

<h4>Other operator arithmetic improvements</h4>

* The following capabilities have been added for Pauli arithmetic: [(4989)](https://github.com/PennyLaneAI/pennylane/pull/4989) [(#5001)](https://github.com/PennyLaneAI/pennylane/pull/5001) [(#5003)](https://github.com/PennyLaneAI/pennylane/pull/5003) [(#5017)](https://github.com/PennyLaneAI/pennylane/pull/5017) [(#5027)](https://github.com/PennyLaneAI/pennylane/pull/5027) [(#5018)](https://github.com/PennyLaneAI/pennylane/pull/5018)

* You can now multiply `PauliWord` and `PauliSentence` instances by scalars (e.g., `0.5 * PauliWord({0: "X"})` or `0.5 * PauliSentence({PauliWord({0: "X"}): 1.})`).

* You can now intuitively add and subtract `PauliWord` and `PauliSentence` instances and scalars together (scalars are treated implicitly as multiples of the identity, `I`). For example, `ps1 + pw1 + 1.` for some Pauli word `pw1 = PauliWord({0: "X", 1: "Y"})` and Pauli sentence `ps1 = PauliSentence({pw1: 3.})`.

* You can now element-wise multiply `PauliWord`, `PauliSentence`, and operators together with `qml.dot` (e.g., `qml.dot([0.5, -1.5, 2], [pw1, ps1, id_word])` with `id_word = PauliWord({})`).

* `qml.matrix` now accepts `PauliWord` and `PauliSentence` instances (e.g., `qml.matrix(PauliWord({0: "X"}))`).

* It is now possible to compute commutators with Pauli operators natively with the new `commutator` method.

pycon
>>> op1 = PauliWord({0: "X", 1: "X"})
>>> op2 = PauliWord({0: "Y"}) + PauliWord({1: "Y"})
>>> op1.commutator(op2) 2j * Z(0) X(1) + 2j * X(0) Z(1)


* Composite operations (e.g., those made with `qml.prod` and `qml.sum`) and scalar-product operations convert `Hamiltonian` and `Tensor` operands to `Sum` and `Prod` types, respectively. This helps avoid the mixing of incompatible operator types. [(5031)](https://github.com/PennyLaneAI/pennylane/pull/5031) [(#5063)](https://github.com/PennyLaneAI/pennylane/pull/5063)

* `qml.Identity()` can be initialized without wires. Measuring it is currently not possible, though. [(5106)](https://github.com/PennyLaneAI/pennylane/pull/5106)

* `qml.dot` now returns a `Sum` class even when all the coefficients match. [(5143)](https://github.com/PennyLaneAI/pennylane/pull/5143)

* `qml.pauli.group_observables` now supports grouping `Prod` and `SProd` operators. [(5070)](https://github.com/PennyLaneAI/pennylane/pull/5070)

* The performance of converting a `PauliSentence` to a `Sum` has been improved. [(5141)](https://github.com/PennyLaneAI/pennylane/pull/5141) [(#5150)](https://github.com/PennyLaneAI/pennylane/pull/5150)

* Akin to `qml.Hamiltonian` features, the coefficients and operators that make up composite operators formed via `Sum` or `Prod` can now be accessed with the `terms()` method. [(5132)](https://github.com/PennyLaneAI/pennylane/pull/5132) [(#5133)](https://github.com/PennyLaneAI/pennylane/pull/5133) [(#5164)](https://github.com/PennyLaneAI/pennylane/pull/5164)

python
>>> qml.operation.enable_new_opmath()
>>> op = X(0) (0.5 * X(1) + X(2))
>>> op.terms()
([0.5, 1.0],
[X(1) X(0),
X(2) X(0)])


* String representations of `ParametrizedHamiltonian` have been updated to match the style of other PL operators. [(5215)](https://github.com/PennyLaneAI/pennylane/pull/5215)

<h4>Other improvements</h4>

* The `pl-device-test` suite is now compatible with the `qml.devices.Device` interface. [(5229)](https://github.com/PennyLaneAI/pennylane/pull/5229)

* The `QSVT` operation now determines its `data` from the block encoding and projector operator data. [(5226)](https://github.com/PennyLaneAI/pennylane/pull/5226) [(#5248)](https://github.com/PennyLaneAI/pennylane/pull/5248)

* The `BlockEncode` operator is now JIT-compatible with JAX. [(5110)](https://github.com/PennyLaneAI/pennylane/pull/5110)

* The `qml.qsvt` function uses `qml.GlobalPhase` instead of `qml.exp` to define a global phase. [(5105)](https://github.com/PennyLaneAI/pennylane/pull/5105)

* The `tests/ops/functions/conftest.py` test has been updated to ensure that all operator types are tested for validity. [(4978)](https://github.com/PennyLaneAI/pennylane/pull/4978)

* A new `pennylane.workflow` module has been added. This module now contains `qnode.py`, `execution.py`, `set_shots.py`, `jacobian_products.py`, and the submodule `interfaces`. [(5023)](https://github.com/PennyLaneAI/pennylane/pull/5023)

* A more informative error is now raised when calling `adjoint_jacobian` with trainable state-prep operations. [(5026)](https://github.com/PennyLaneAI/pennylane/pull/5026)

* `qml.workflow.get_transform_program` and `qml.workflow.construct_batch` have been added to inspect the transform program and batch of tapes at different stages. [(5084)](https://github.com/PennyLaneAI/pennylane/pull/5084)

* All custom controlled operations such as `CRX`, `CZ`, `CNOT`, `ControlledPhaseShift` now inherit from `ControlledOp`, giving them additional properties such as `control_wire` and `control_values`. Calling `qml.ctrl` on `RX`, `RY`, `RZ`, `Rot`, and `PhaseShift` with a single control wire will return gates of types `CRX`, `CRY`, etc. as opposed to a general `Controlled` operator. [(5069)](https://github.com/PennyLaneAI/pennylane/pull/5069) [(#5199)](https://github.com/PennyLaneAI/pennylane/pull/5199)

* The CI will now fail if coverage data fails to upload to codecov. Previously, it would silently pass and the codecov check itself would never execute. [(5101)](https://github.com/PennyLaneAI/pennylane/pull/5101)

* `qml.ctrl` called on operators with custom controlled versions will now return instances of the custom class, and it will flatten nested controlled operators to a single multi-controlled operation. For `PauliX`, `CNOT`, `Toffoli`, and `MultiControlledX`, calling `qml.ctrl` will always resolve to the best option in `CNOT`, `Toffoli`, or `MultiControlledX` depending on the number of control wires and control values. [(5125)](https://github.com/PennyLaneAI/pennylane/pull/5125/)

* Unwanted warning filters have been removed from tests and no `PennyLaneDeprecationWarning`s are being raised unexpectedly. [(5122)](https://github.com/PennyLaneAI/pennylane/pull/5122)

* New error tracking and propagation functionality has been added [(5115)](https://github.com/PennyLaneAI/pennylane/pull/5115) [(#5121)](https://github.com/PennyLaneAI/pennylane/pull/5121)

* The method `map_batch_transform` has been replaced with the method `_batch_transform` implemented in `TransformDispatcher`. [(5212)](https://github.com/PennyLaneAI/pennylane/pull/5212)

* `TransformDispatcher` can now dispatch onto a batch of tapes, making it easier to compose transforms when working in the tape paradigm. [(5163)](https://github.com/PennyLaneAI/pennylane/pull/5163)

* `qml.ctrl` is now a simple wrapper that either calls PennyLane's built in `create_controlled_op` or uses the Catalyst implementation. [(5247)](https://github.com/PennyLaneAI/pennylane/pull/5247)

* Controlled composite operations can now be decomposed using ZYZ rotations. [(5242)](https://github.com/PennyLaneAI/pennylane/pull/5242)

* New functions called `qml.devices.modifiers.simulator_tracking` and `qml.devices.modifiers.single_tape_support` have been added to add basic default behavior onto a device class. [(5200)](https://github.com/PennyLaneAI/pennylane/pull/5200)

<h3>Breaking changes ๐Ÿ’”</h3>

* Passing additional arguments to a transform that decorates a QNode must now be done through the use of `functools.partial`. [(5046)](https://github.com/PennyLaneAI/pennylane/pull/5046)

* `qml.ExpvalCost` has been removed. Users should use `qml.expval()` moving forward. [(5097)](https://github.com/PennyLaneAI/pennylane/pull/5097)

* Caching of executions is now turned off by default when `max_diff == 1`, as the classical overhead cost outweighs the probability that duplicate circuits exists. [(5243)](https://github.com/PennyLaneAI/pennylane/pull/5243)

* The entry point convention registering compilers with PennyLane has changed. [(5140)](https://github.com/PennyLaneAI/pennylane/pull/5140)

To allow for packages to register multiple compilers with PennyLane, the `entry_points` convention under the designated group name `pennylane.compilers` has been modified.

Previously, compilers would register `qjit` (JIT decorator), `ops` (compiler-specific operations), and `context` (for tracing and program capture).

Now, compilers must register `compiler_name.qjit`, `compiler_name.ops`, and `compiler_name.context`, where `compiler_name` is replaced by the name of the provided compiler.

For more information, please see the [documentation on adding compilers](https://docs.pennylane.ai/en/stable/code/qml_compiler.html#adding-a-compiler).

* PennyLane source code is now compatible with the latest version of `black`. [(5112)](https://github.com/PennyLaneAI/pennylane/pull/5112) [(#5119)](https://github.com/PennyLaneAI/pennylane/pull/5119)

* `gradient_analysis_and_validation` has been renamed to `find_and_validate_gradient_methods`. Instead of returning a list, it now returns a dictionary of gradient methods for each parameter index, and no longer mutates the tape. [(5035)](https://github.com/PennyLaneAI/pennylane/pull/5035)

* Multiplying two `PauliWord` instances no longer returns a tuple `(new_word, coeff)` but instead `PauliSentence({new_word: coeff})`. The old behavior is still available with the private method `PauliWord._matmul(other)` for faster processing. [(5045)](https://github.com/PennyLaneAI/pennylane/pull/5054)

* `Observable.return_type` has been removed. Instead, you should inspect the type of the surrounding measurement process. [(5044)](https://github.com/PennyLaneAI/pennylane/pull/5044)

* `ClassicalShadow.entropy()` no longer needs an `atol` keyword as a better method to estimate entropies from approximate density matrix reconstructions (with potentially negative eigenvalues). [(5048)](https://github.com/PennyLaneAI/pennylane/pull/5048)

* Controlled operators with a custom controlled version decompose like how their controlled counterpart decomposes as opposed to decomposing into their controlled version. [(5069)](https://github.com/PennyLaneAI/pennylane/pull/5069) [(#5125)](https://github.com/PennyLaneAI/pennylane/pull/5125/)

For example:

pycon
>>> qml.ctrl(qml.RX(0.123, wires=1), control=0).decomposition()
[
RZ(1.5707963267948966, wires=[1]),
RY(0.0615, wires=[1]),
CNOT(wires=[0, 1]),
RY(-0.0615, wires=[1]),
CNOT(wires=[0, 1]),
RZ(-1.5707963267948966, wires=[1])
]


* `QuantumScript.is_sampled` and `QuantumScript.all_sampled` have been removed. Users should now validate these properties manually. [(5072)](https://github.com/PennyLaneAI/pennylane/pull/5072)

* `qml.transforms.one_qubit_decomposition` and `qml.transforms.two_qubit_decomposition` have been removed. Instead, you should use `qml.ops.one_qubit_decomposition` and `qml.ops.two_qubit_decomposition`. [(5091)](https://github.com/PennyLaneAI/pennylane/pull/5091)

<h3>Deprecations ๐Ÿ‘‹</h3>

* Calling `qml.matrix` without providing a `wire_order` on objects where the wire order could be ambiguous now raises a warning. In the future, the `wire_order` argument will be required in these cases. [(5039)](https://github.com/PennyLaneAI/pennylane/pull/5039)

* `Operator.validate_subspace(subspace)` has been relocated to the `qml.ops.qutrit.parametric_ops` module and will be removed from the Operator class in an upcoming release. [(5067)](https://github.com/PennyLaneAI/pennylane/pull/5067)

* Matrix and tensor products between `PauliWord` and `PauliSentence` instances are done using the `` operator, `*` will be used only for scalar multiplication. Note also the breaking change that the product of two `PauliWord` instances now returns a `PauliSentence` instead of a tuple `(new_word, coeff)`. [(4989)](https://github.com/PennyLaneAI/pennylane/pull/4989) [(#5054)](https://github.com/PennyLaneAI/pennylane/pull/5054)

* `MeasurementProcess.name` and `MeasurementProcess.data` are now deprecated, as they contain dummy values that are no longer needed. [(5047)](https://github.com/PennyLaneAI/pennylane/pull/5047) [(#5071)](https://github.com/PennyLaneAI/pennylane/pull/5071) [(#5076)](https://github.com/PennyLaneAI/pennylane/pull/5076) [(#5122)](https://github.com/PennyLaneAI/pennylane/pull/5122)

* `qml.pauli.pauli_mult` and `qml.pauli.pauli_mult_with_phase` are now deprecated. Instead, you should use `qml.simplify(qml.prod(pauli_1, pauli_2))` to get the reduced operator. [(5057)](https://github.com/PennyLaneAI/pennylane/pull/5057)

* The private functions `_pauli_mult`, `_binary_matrix` and `_get_pauli_map` from the `pauli` module have been deprecated, as they are no longer used anywhere and the same functionality can be achieved using newer features in the `pauli` module. [(5057)](https://github.com/PennyLaneAI/pennylane/pull/5057)

* `Sum.ops`, `Sum.coeffs`, `Prod.ops` and `Prod.coeffs` will be deprecated in the future. [(5164)](https://github.com/PennyLaneAI/pennylane/pull/5164)

<h3>Documentation ๐Ÿ“</h3>

* The module documentation for `pennylane.tape` now explains the difference between `QuantumTape` and `QuantumScript`. [(5065)](https://github.com/PennyLaneAI/pennylane/pull/5065)

* A typo in a code example in the `qml.transforms` API has been fixed. [(5014)](https://github.com/PennyLaneAI/pennylane/pull/5014)

* Documentation for `qml.data` has been updated and now mentions a way to access the same dataset simultaneously from multiple environments. [(5029)](https://github.com/PennyLaneAI/pennylane/pull/5029)

* A clarification for the definition of `argnum` added to gradient methods has been made. [(5035)](https://github.com/PennyLaneAI/pennylane/pull/5035)

* A typo in the code example for `qml.qchem.dipole_of` has been fixed. [(5036)](https://github.com/PennyLaneAI/pennylane/pull/5036)

* A development guide on deprecations and removals has been added. [(5083)](https://github.com/PennyLaneAI/pennylane/pull/5083)

* A note about the eigenspectrum of second-quantized Hamiltonians has been added to `qml.eigvals`. [(5095)](https://github.com/PennyLaneAI/pennylane/pull/5095)

* A warning about two mathematically equivalent Hamiltonians undergoing different time evolutions has been added to `qml.TrotterProduct` and `qml.ApproxTimeEvolution`. [(5137)](https://github.com/PennyLaneAI/pennylane/pull/5137)

* A reference to the paper that provides the image of the `qml.QAOAEmbedding` template has been added. [(5130)](https://github.com/PennyLaneAI/pennylane/pull/5130)

* The docstring of `qml.sample` has been updated to advise the use of single-shot expectations instead when differentiating a circuit. [(5237)](https://github.com/PennyLaneAI/pennylane/pull/5237)

* A quick start page has been added called "Importing Circuits". This explains how to import quantum circuits and operations defined outside of PennyLane. [(5281)](https://github.com/PennyLaneAI/pennylane/pull/5281)

<h3>Bug fixes ๐Ÿ›</h3>

* `QubitChannel` can now be used with jitting. [(5288)](https://github.com/PennyLaneAI/pennylane/pull/5288)

* Fixed a bug in the matplotlib drawer where the colour of `Barrier` did not match the requested style. [(5276)](https://github.com/PennyLaneAI/pennylane/pull/5276)

* `qml.draw` and `qml.draw_mpl` now apply all applied transforms before drawing. [(5277)](https://github.com/PennyLaneAI/pennylane/pull/5277)

* `ctrl_decomp_zyz` is now differentiable. [(5198)](https://github.com/PennyLaneAI/pennylane/pull/5198)

* `qml.ops.Pow.matrix()` is now differentiable with TensorFlow with integer exponents. [(5178)](https://github.com/PennyLaneAI/pennylane/pull/5178)

* The `qml.MottonenStatePreparation` template has been updated to include a global phase operation. [(5166)](https://github.com/PennyLaneAI/pennylane/pull/5166)

* Fixed a queuing bug when using `qml.prod` with a quantum function that queues a single operator. [(5170)](https://github.com/PennyLaneAI/pennylane/pull/5170)

* The `qml.TrotterProduct` template has been updated to accept scalar products of operators as an input Hamiltonian. [(5073)](https://github.com/PennyLaneAI/pennylane/pull/5073)

* Fixed a bug where caching together with JIT compilation and broadcasted tapes yielded wrong results `Operator.hash` now depends on the memory location, `id`, of a JAX tracer instead of its string representation. [(3917)](https://github.com/PennyLaneAI/pennylane/pull/3917)

* `qml.transforms.undo_swaps` can now work with operators with hyperparameters or nesting. [(5081)](https://github.com/PennyLaneAI/pennylane/pull/5081)

* `qml.transforms.split_non_commuting` will now pass the original shots along. [(5081)](https://github.com/PennyLaneAI/pennylane/pull/5081)

* If `argnum` is provided to a gradient transform, only the parameters specified in `argnum` will have their gradient methods validated. [(5035)](https://github.com/PennyLaneAI/pennylane/pull/5035)

* `StatePrep` operations expanded onto more wires are now compatible with backprop. [(5028)](https://github.com/PennyLaneAI/pennylane/pull/5028)

* `qml.equal` works well with `qml.Sum` operators when wire labels are a mix of integers and strings. [(5037)](https://github.com/PennyLaneAI/pennylane/pull/5037)

* The return value of `Controlled.generator` now contains a projector that projects onto the correct subspace based on the control value specified. [(5068)](https://github.com/PennyLaneAI/pennylane/pull/5068)

* `CosineWindow` no longer raises an unexpected error when used on a subset of wires at the beginning of a circuit. [(5080)](https://github.com/PennyLaneAI/pennylane/pull/5080)

* `tf.function` now works with `TensorSpec(shape=None)` by skipping batch size computation. [(5089)](https://github.com/PennyLaneAI/pennylane/pull/5089)

* `PauliSentence.wires` no longer imposes a false order. [(5041)](https://github.com/PennyLaneAI/pennylane/pull/5041)

* `qml.qchem.import_state` now applies the chemist-to-physicist sign convention when initializing a PennyLane state vector from classically pre-computed wavefunctions. That is, it interleaves spin-up/spin-down operators for the same spatial orbital index, as standard in PennyLane (instead of commuting all spin-up operators to the left, as is standard in quantum chemistry). [(5114)](https://github.com/PennyLaneAI/pennylane/pull/5114)

* Multi-wire controlled `CNOT` and `PhaseShift` are now be decomposed correctly. [(5125)](https://github.com/PennyLaneAI/pennylane/pull/5125/) [(#5148)](https://github.com/PennyLaneAI/pennylane/pull/5148)

* `draw_mpl` no longer raises an error when drawing a circuit containing an adjoint of a controlled operation. [(5149)](https://github.com/PennyLaneAI/pennylane/pull/5149)

* `default.mixed` no longer throws `ValueError` when applying a state vector that is not of type `complex128` when used with tensorflow. [(5155)](https://github.com/PennyLaneAI/pennylane/pull/5155)

* `ctrl_decomp_zyz` no longer raises a `TypeError` if the rotation parameters are of type `torch.Tensor` [(5183)](https://github.com/PennyLaneAI/pennylane/pull/5183)

* Comparing `Prod` and `Sum` objects now works regardless of nested structure with `qml.equal` if the operators have a valid `pauli_rep` property. [(5177)](https://github.com/PennyLaneAI/pennylane/pull/5177)

* Controlled `GlobalPhase` with non-zero control wires no longer throws an error. [(5194)](https://github.com/PennyLaneAI/pennylane/pull/5194)

* A `QNode` transformed with `mitigate_with_zne` now accepts batch parameters. [(5195)](https://github.com/PennyLaneAI/pennylane/pull/5195)

* The matrix of an empty `PauliSentence` instance is now correct (all-zeros). Further, matrices of empty `PauliWord` and `PauliSentence` instances can now be turned into matrices. [(5188)](https://github.com/PennyLaneAI/pennylane/pull/5188)

* `PauliSentence` instances can handle matrix multiplication with `PauliWord` instances. [(5208)](https://github.com/PennyLaneAI/pennylane/pull/5208)

* `CompositeOp.eigendecomposition` is now JIT-compatible. [(5207)](https://github.com/PennyLaneAI/pennylane/pull/5207)

* `QubitDensityMatrix` now works with JAX-JIT on the `default.mixed` device. [(5203)](https://github.com/PennyLaneAI/pennylane/pull/5203) [(#5236)](https://github.com/PennyLaneAI/pennylane/pull/5236)

* When a QNode specifies `diff_method="adjoint"`, `default.qubit` no longer tries to decompose non-trainable operations with non-scalar parameters such as `QubitUnitary`. [(5233)](https://github.com/PennyLaneAI/pennylane/pull/5233)

* The overwriting of the class names of `I`, `X`, `Y`, and `Z` no longer happens in the initialization after causing problems with datasets. This now happens globally. [(5252)](https://github.com/PennyLaneAI/pennylane/pull/5252)

* The `adjoint_metric_tensor` transform now works with `jax`. [(5271)](https://github.com/PennyLaneAI/pennylane/pull/5271)

<h3>Contributors โœ๏ธ</h3>

This release contains contributions from (in alphabetical order):

Abhishek Abhishek, Mikhail Andrenkov, Utkarsh Azad, Trenten Babcock, Gabriel Bottrill, Thomas Bromley, Astral Cai, Skylar Chan, Isaac De Vlugt, Diksha Dhawan, Lillian Frederiksen, Pietropaolo Frisoni, Eugenio Gigante, Diego Guala, David Ittah, Soran Jahangiri, Jacky Jiang, Korbinian Kottmann, Christina Lee, Xiaoran Li, Vincent Michaud-Rioux, Romain Moyard, Pablo Antonio Moreno Casares, Erick Ochoa Lopez, Lee J. O'Riordan, Mudit Pandey, Alex Preciado, Matthew Silverman, Jay Soni.

Page 1 of 11

ยฉ 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.