Pennylane

Latest version: v0.35.1

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

Scan your dependencies

Page 1 of 11

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.

0.34.0.post1

This postfix release pins additional requirements in `doc/requirements.txt` for building the website documentation. This allows the website to be rebuilt to show the "Getting involved" section.

0.34.0

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

<h4>Statistics and drawing for mid-circuit measurements 🎨</h4>

* It is now possible to return statistics of composite mid-circuit measurements. [(4888)](https://github.com/PennyLaneAI/pennylane/pull/4888)

Mid-circuit measurement results can be composed using basic arithmetic operations and then statistics can be calculated by putting the result within a PennyLane [measurement](https://docs.pennylane.ai/en/stable/introduction/measurements.html) like `qml.expval()`. For example:

python
import pennylane as qml

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

qml.qnode(dev)
def circuit(phi, theta):
qml.RX(phi, wires=0)
m0 = qml.measure(wires=0)
qml.RY(theta, wires=1)
m1 = qml.measure(wires=1)
return qml.expval(~m0 + m1)

print(circuit(1.23, 4.56))


1.2430187928114291


Another option, for ease-of-use when using `qml.sample()`, `qml.probs()`, or `qml.counts()`, is to provide a simple list of mid-circuit measurement results:

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

qml.qnode(dev)
def circuit(phi, theta):
qml.RX(phi, wires=0)
m0 = qml.measure(wires=0)
qml.RY(theta, wires=1)
m1 = qml.measure(wires=1)
return qml.sample(op=[m0, m1])

print(circuit(1.23, 4.56, shots=5))



[[0 1]
[0 1]
[0 0]
[1 0]
[0 1]]


Composite mid-circuit measurement statistics are supported on `default.qubit` and `default.mixed`. To learn more about which measurements and arithmetic operators are supported, [refer to the measurements page](https://docs.pennylane.ai/en/stable/introduction/measurements.html) and the [documentation for qml.measure](https://docs.pennylane.ai/en/stable/code/api/pennylane.measure.html).

* Mid-circuit measurements can now be visualized with the text-based `qml.draw()` and the graphical `qml.draw_mpl()` methods. [(4775)](https://github.com/PennyLaneAI/pennylane/pull/4775) [(#4803)](https://github.com/PennyLaneAI/pennylane/pull/4803) [(#4832)](https://github.com/PennyLaneAI/pennylane/pull/4832) [(#4901)](https://github.com/PennyLaneAI/pennylane/pull/4901) [(#4850)](https://github.com/PennyLaneAI/pennylane/pull/4850) [(#4917)](https://github.com/PennyLaneAI/pennylane/pull/4917) [(#4930)](https://github.com/PennyLaneAI/pennylane/pull/4930) [(#4957)](https://github.com/PennyLaneAI/pennylane/pull/4957)

Drawing of mid-circuit measurement capabilities including qubit reuse and reset, postselection, conditioning, and collecting statistics is now supported. Here is an all-encompassing example:

python
def circuit():
m0 = qml.measure(0, reset=True)
m1 = qml.measure(1, postselect=1)
qml.cond(m0 - m1 == 0, qml.S)(0)
m2 = qml.measure(1)
qml.cond(m0 + m1 == 2, qml.T)(0)
qml.cond(m2, qml.PauliX)(1)


The text-based drawer outputs:

pycon
>>> print(qml.draw(circuit)())
0: ───↗│ β”‚0βŸ©β”€β”€β”€β”€β”€β”€β”€β”€S───────T─────
1: β”€β”€β”€β•‘β”€β”€β”€β”€β”€β”€β”€β”€β”€β†—β‚β”œβ”€β”€β•‘β”€β”€β”€β†—β”œβ”€β”€β•‘β”€β”€X──
β•šβ•β•β•β•β•β•β•β•β•β•‘β•β•β•β•β•¬β•β•β•β•‘β•β•β•β•£ β•‘
β•šβ•β•β•β•β•©β•β•β•β•‘β•β•β•β• β•‘
β•šβ•β•β•β•β•β•β•


The graphical drawer outputs:

pycon
>>> print(qml.draw_mpl(circuit)())


<img src="https://raw.githubusercontent.com/PennyLaneAI/pennylane/master/doc/_static/mid-circuit-measurement.png" width=70%/>

<h4>Catalyst is seamlessly integrated with PennyLane βš—οΈ</h4>

* Catalyst, our next-generation compilation framework, is now accessible within PennyLane, allowing you to more easily benefit from hybrid just-in-time (JIT) compilation.

To access these features, simply install `pennylane-catalyst`:


pip install pennylane-catalyst


The [qml.compiler](https://docs.pennylane.ai/en/latest/code/qml_compiler.html) module provides support for hybrid quantum-classical compilation. [(#4692)](https://github.com/PennyLaneAI/pennylane/pull/4692) [(#4979)](https://github.com/PennyLaneAI/pennylane/pull/4979)

Through the use of the `qml.qjit` decorator, entire workflows can be JIT compiled β€” including both quantum and classical processing β€” down to a machine binary on first-function execution. Subsequent calls to the compiled function will execute the previously-compiled binary, resulting in significant performance improvements.

python
import pennylane as qml

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

qml.qjit
qml.qnode(dev)
def circuit(theta):
qml.Hadamard(wires=0)
qml.RX(theta, wires=1)
qml.CNOT(wires=[0,1])
return qml.expval(qml.PauliZ(wires=1))


pycon
>>> circuit(0.5) the first call, compilation occurs here array(0.)
>>> circuit(0.5) the precompiled quantum function is called
array(0.)


Currently, PennyLane supports the [Catalyst hybrid compiler](https://github.com/pennylaneai/catalyst) with the `qml.qjit` decorator. A significant benefit of Catalyst is the ability to preserve complex control flow around quantum operations β€” such as `if` statements and `for` loops, and including measurement feedback β€” during compilation, while continuing to support end-to-end autodifferentiation.

* The following functions can now be used with the `qml.qjit` decorator: `qml.grad`, `qml.jacobian`, `qml.vjp`, `qml.jvp`, and `qml.adjoint`. [(4709)](https://github.com/PennyLaneAI/pennylane/pull/4709) [(#4724)](https://github.com/PennyLaneAI/pennylane/pull/4724) [(#4725)](https://github.com/PennyLaneAI/pennylane/pull/4725) [(#4726)](https://github.com/PennyLaneAI/pennylane/pull/4726)

When `qml.grad` or `qml.jacobian` are used with `qml.qjit`, they are patched to [catalyst.grad](https://docs.pennylane.ai/projects/catalyst/en/stable/code/api/catalyst.grad.html) and [catalyst.jacobian](https://docs.pennylane.ai/projects/catalyst/en/stable/code/api/catalyst.jacobian.html), respectively.

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

qml.qjit
def workflow(x):

qml.qnode(dev)
def circuit(x):
qml.RX(np.pi * x[0], wires=0)
qml.RY(x[1], wires=0)
return qml.probs()

g = qml.jacobian(circuit)

return g(x)


pycon
>>> workflow(np.array([2.0, 1.0]))
array([[ 3.48786850e-16, -4.20735492e-01],
[-8.71967125e-17, 4.20735492e-01]])


* JIT-compatible functionality for control flow has been added via `qml.for_loop`, `qml.while_loop`, and `qml.cond`. [(4698)](https://github.com/PennyLaneAI/pennylane/pull/4698)

`qml.for_loop` and `qml.while_loop` can be deployed as decorators on functions that are the body of the loop. The arguments to both follow typical conventions:


qml.for_loop(lower_bound, upper_bound, step)



qml.while_loop(cond_function)


Here is a concrete example with `qml.for_loop`:

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

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

qml.for_loop(0, n, 1)
def loop_rx(i, x):
perform some work and update (some of) the arguments
qml.RX(x, wires=0)

update the value of x for the next iteration
return jnp.sin(x)

apply the for loop
final_x = loop_rx(x)

return qml.expval(qml.PauliZ(0)), final_x


pycon
>>> circuit(7, 1.6)
(array(0.97926626), array(0.55395718))


<h4>Decompose circuits into the Clifford+T gateset 🧩</h4>

* The new `qml.clifford_t_decomposition()` transform provides an approximate breakdown of an input circuit into the [Clifford+T gateset](https://en.wikipedia.org/wiki/Clifford_gates). Behind the scenes, this decomposition is enacted via the `sk_decomposition()` function using the Solovay-Kitaev algorithm. [(#4801)](https://github.com/PennyLaneAI/pennylane/pull/4801) [(#4802)](https://github.com/PennyLaneAI/pennylane/pull/4802)

The Solovay-Kitaev algorithm *approximately* decomposes a quantum circuit into the Clifford+T gateset. To account for this, a desired total circuit decomposition error, `epsilon`, must be specified when using `qml.clifford_t_decomposition`:

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

qml.qnode(dev)
def circuit():
qml.RX(1.1, 0)
return qml.state()

circuit = qml.clifford_t_decomposition(circuit, epsilon=0.1)


pycon
>>> print(qml.draw(circuit)())
0: ──T†──H──T†──H──T──H──T──H──T──H──T──H──T†──H──T†──T†──H──T†──H──T──H──T──H──T──H──T──H──T†──H

───T†──H──T──H──GlobalPhase(0.39)──


The resource requirements of this circuit can also be evaluated:

pycon
>>> with qml.Tracker(dev) as tracker:
... circuit()
>>> resources_lst = tracker.history["resources"]
>>> resources_lst[0]
wires: 1
gates: 34
depth: 34
shots: Shots(total=None)
gate_types: {'Adjoint(T)': 8, 'Hadamard': 16, 'T': 9, 'GlobalPhase': 1}
gate_sizes: {1: 33, 0: 1}


<h4>Use an iterative approach for quantum phase estimation πŸ”„</h4>

* [Iterative Quantum Phase Estimation](https://arxiv.org/pdf/quant-ph/0610214.pdf) is now available with `qml.iterative_qpe`. [(#4804)](https://github.com/PennyLaneAI/pennylane/pull/4804)

The subroutine can be used similarly to mid-circuit measurements:

python
import pennylane as qml

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

qml.qnode(dev)
def circuit():

Initial state
qml.PauliX(wires=[0])

Iterative QPE
measurements = qml.iterative_qpe(qml.RZ(2., wires=[0]), ancilla=[1], iters=3)

return [qml.sample(op=meas) for meas in measurements]


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


The $i$-th element in the list refers to the 5 samples generated by the $i$-th measurement of the algorithm.

<h3>Improvements πŸ› </h3>

<h4>Community contributions πŸ₯³</h4>

* The `+=` operand can now be used with a `PauliSentence`, which has also provides a performance boost. [(4662)](https://github.com/PennyLaneAI/pennylane/pull/4662)

* The Approximate Quantum Fourier Transform (AQFT) is now available with `qml.AQFT`. [(4715)](https://github.com/PennyLaneAI/pennylane/pull/4715)

* `qml.draw` and `qml.draw_mpl` now render operator IDs. [(4749)](https://github.com/PennyLaneAI/pennylane/pull/4749)

The ID can be specified as a keyword argument when instantiating an operator:

pycon
>>> def circuit():
... qml.RX(0.123, id="data", wires=0)
>>> print(qml.draw(circuit)())
0: ──RX(0.12,"data")──


* Non-parametric operators such as `Barrier`, `Snapshot`, and `Wirecut` have been grouped together and moved to `pennylane/ops/meta.py`. Additionally, the relevant tests have been organized and placed in a new file, `tests/ops/test_meta.py`. [(4789)](https://github.com/PennyLaneAI/pennylane/pull/4789)

* The `TRX`, `TRY`, and `TRZ` operators are now differentiable via backpropagation on `default.qutrit`. [(4790)](https://github.com/PennyLaneAI/pennylane/pull/4790)

* The function `qml.equal` now supports `ControlledSequence` operators. [(4829)](https://github.com/PennyLaneAI/pennylane/pull/4829)

* XZX decomposition has been added to the list of supported single-qubit unitary decompositions. [(4862)](https://github.com/PennyLaneAI/pennylane/pull/4862)

* `==` and `!=` operands can now be used with `TransformProgram` and `TransformContainers` instances. [(4858)](https://github.com/PennyLaneAI/pennylane/pull/4858)

* A `qutrit_mixed` module has been added to `qml.devices` to store helper functions for a future qutrit mixed-state device. A function called `create_initial_state` has been added to this module that creates device-compatible initial states. [(4861)](https://github.com/PennyLaneAI/pennylane/pull/4861)

* The function `qml.Snapshot` now supports arbitrary state-based measurements (i.e., measurements of type `StateMeasurement`). [(4876)](https://github.com/PennyLaneAI/pennylane/pull/4908)

* `qml.equal` now supports the comparison of `QuantumScript` and `BasisRotation` objects. [(4902)](https://github.com/PennyLaneAI/pennylane/pull/4902) [(#4919)](https://github.com/PennyLaneAI/pennylane/pull/4919)

* The function `qml.draw_mpl` now accept a keyword argument `fig` to specify the output figure window. [(4956)](https://github.com/PennyLaneAI/pennylane/pull/4956)

<h4>Better support for batching</h4>

* `qml.AmplitudeEmbedding` now supports batching when used with Tensorflow. [(4818)](https://github.com/PennyLaneAI/pennylane/pull/4818)

* `default.qubit` can now evolve already batched states with `qml.pulse.ParametrizedEvolution`. [(4863)](https://github.com/PennyLaneAI/pennylane/pull/4863)

* `qml.ArbitraryUnitary` now supports batching. [(4745)](https://github.com/PennyLaneAI/pennylane/pull/4745)

* Operator and tape batch sizes are evaluated lazily, helping run expensive computations less frequently and an issue with Tensorflow pre-computing batch sizes. [(4911)](https://github.com/PennyLaneAI/pennylane/pull/4911)

<h4>Performance improvements and benchmarking</h4>

* Autograd, PyTorch, and JAX can now use vector-Jacobian products (VJPs) provided by the device from the new device API. If a device provides a VJP, this can be selected by providing `device_vjp=True` to a QNode or `qml.execute`. [(4935)](https://github.com/PennyLaneAI/pennylane/pull/4935) [(#4557)](https://github.com/PennyLaneAI/pennylane/pull/4557) [(#4654)](https://github.com/PennyLaneAI/pennylane/pull/4654) [(#4878)](https://github.com/PennyLaneAI/pennylane/pull/4878) [(#4841)](https://github.com/PennyLaneAI/pennylane/pull/4841)

pycon
>>> dev = qml.device('default.qubit')
>>> qml.qnode(dev, diff_method="adjoint", device_vjp=True)
>>> def circuit(x):
... qml.RX(x, wires=0)
... return qml.expval(qml.PauliZ(0))
>>> with dev.tracker:
... g = qml.grad(circuit)(qml.numpy.array(0.1))
>>> dev.tracker.totals
{'batches': 1, 'simulations': 1, 'executions': 1, 'vjp_batches': 1, 'vjps': 1}
>>> g
-0.09983341664682815


* `qml.expval` with large `Hamiltonian` objects is now faster and has a significantly lower memory footprint (and constant with respect to the number of `Hamiltonian` terms) when the `Hamiltonian` is a `PauliSentence`. This is due to the introduction of a specialized `dot` method in the `PauliSentence` class which performs `PauliSentence`-`state` products. [(4839)](https://github.com/PennyLaneAI/pennylane/pull/4839)

* `default.qubit` no longer uses a dense matrix for `MultiControlledX` for more than 8 operation wires. [(4673)](https://github.com/PennyLaneAI/pennylane/pull/4673)

* Some relevant Pytests have been updated to enable its use as a suite of benchmarks. [(4703)](https://github.com/PennyLaneAI/pennylane/pull/4703)

* `default.qubit` now applies `GroverOperator` faster by not using its matrix representation but a custom rule for `apply_operation`. Also, the matrix representation of `GroverOperator` now runs faster. [(4666)](https://github.com/PennyLaneAI/pennylane/pull/4666)

* A new pipeline to run benchmarks and plot graphs comparing with a fixed reference has been added. This pipeline will run on a schedule and can be activated on a PR with the label `ci:run_benchmarks`. [(4741)](https://github.com/PennyLaneAI/pennylane/pull/4741)

* `default.qubit` now supports adjoint differentiation for arbitrary diagonal state-based measurements. [(4865)](https://github.com/PennyLaneAI/pennylane/pull/4865)

* The benchmarks pipeline has been expanded to export all benchmark data to a single JSON file and a CSV file with runtimes. This includes all references and local benchmarks. [(4873)](https://github.com/PennyLaneAI/pennylane/pull/4873)

<h4>Final phase of updates to transforms</h4>

* `qml.quantum_monte_carlo` and `qml.simplify` now use the new transform system. [(4708)](https://github.com/PennyLaneAI/pennylane/pull/4708/) [(#4949)](https://github.com/PennyLaneAI/pennylane/pull/4949)

* The formal requirement that type hinting be provided when using the `qml.transform` decorator has been removed. Type hinting can still be used, but is now optional. Please use a type checker such as [mypy](https://github.com/python/mypy) if you wish to ensure types are being passed correctly. [(#4942)](https://github.com/PennyLaneAI/pennylane/pull/4942/)

<h4>Other improvements</h4>

* PennyLane now supports Python 3.12. [(4985)](https://github.com/PennyLaneAI/pennylane/pull/4985)

* `SampleMeasurement` now has an optional method `process_counts` for computing the measurement results from a counts dictionary. [(4941)](https://github.com/PennyLaneAI/pennylane/pull/4941/)

* A new function called `ops.functions.assert_valid` has been added for checking if an `Operator` class is defined correctly. [(4764)](https://github.com/PennyLaneAI/pennylane/pull/4764)

* `Shots` objects can now be multiplied by scalar values. [(4913)](https://github.com/PennyLaneAI/pennylane/pull/4913)

* `GlobalPhase` now decomposes to nothing in case devices do not support global phases. [(4855)](https://github.com/PennyLaneAI/pennylane/pull/4855)

* Custom operations can now provide their matrix directly through the `Operator.matrix()` method without needing to update the `has_matrix` property. `has_matrix` will now automatically be `True` if `Operator.matrix` is overridden, even if `Operator.compute_matrix` is not. [(4844)](https://github.com/PennyLaneAI/pennylane/pull/4844)

* The logic for re-arranging states before returning them has been improved. [(4817)](https://github.com/PennyLaneAI/pennylane/pull/4817)

* When multiplying `SparseHamiltonian`s by a scalar value, the result now stays as a `SparseHamiltonian`. [(4828)](https://github.com/PennyLaneAI/pennylane/pull/4828)

* `trainable_params` can now be set upon initialization of a `QuantumScript` instead of having to set the parameter after initialization. [(4877)](https://github.com/PennyLaneAI/pennylane/pull/4877)

* `default.qubit` now calculates the expectation value of `Hermitian` operators in a differentiable manner. [(4866)](https://github.com/PennyLaneAI/pennylane/pull/4866)

* The `rot` decomposition now has support for returning a global phase. [(4869)](https://github.com/PennyLaneAI/pennylane/pull/4869)

* The `"pennylane_sketch"` MPL-drawer style has been added. This is the same as the `"pennylane"` style, but with sketch-style lines. [(4880)](https://github.com/PennyLaneAI/pennylane/pull/4880)

* Operators now define a `pauli_rep` property, an instance of `PauliSentence`, defaulting to `None` if the operator has not defined it (or has no definition in the Pauli basis). [(4915)](https://github.com/PennyLaneAI/pennylane/pull/4915)

* `qml.ShotAdaptiveOptimizer` can now use a multinomial distribution for spreading shots across the terms of a Hamiltonian measured in a QNode. Note that this is equivalent to what can be done with `qml.ExpvalCost`, but this is the preferred method because `ExpvalCost` is deprecated. [(4896)](https://github.com/PennyLaneAI/pennylane/pull/4896)

* Decomposition of `qml.PhaseShift` now uses `qml.GlobalPhase` for retaining the global phase information. [(4657)](https://github.com/PennyLaneAI/pennylane/pull/4657) [(#4947)](https://github.com/PennyLaneAI/pennylane/pull/4947)

* `qml.equal` for `Controlled` operators no longer returns `False` when equivalent but differently-ordered sets of control wires and control values are compared. [(4944)](https://github.com/PennyLaneAI/pennylane/pull/4944)

* All PennyLane `Operator` subclasses are automatically tested by `ops.functions.assert_valid` to ensure that they follow PennyLane `Operator` standards. [(4922)](https://github.com/PennyLaneAI/pennylane/pull/4922)

* Probability measurements can now be calculated from a `counts` dictionary with the addition of a `process_counts` method in the `ProbabilityMP` class. [(4952)](https://github.com/PennyLaneAI/pennylane/pull/4952)

* `ClassicalShadow.entropy` now uses the algorithm outlined in [1106.5458](https://arxiv.org/abs/1106.5458) to project the approximate density matrix (with potentially negative eigenvalues) onto the closest valid density matrix. [(#4959)](https://github.com/PennyLaneAI/pennylane/pull/4959)

* The `ControlledSequence.compute_decomposition` default now decomposes the `Pow` operators, improving compatibility with machine learning interfaces. [(4995)](https://github.com/PennyLaneAI/pennylane/pull/4995)

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

* The functions `qml.transforms.one_qubit_decomposition`, `qml.transforms.two_qubit_decomposition`, and `qml.transforms.sk_decomposition` were moved to `qml.ops.one_qubit_decomposition`, `qml.ops.two_qubit_decomposition`, and `qml.ops.sk_decomposition`, respectively. [(4906)](https://github.com/PennyLaneAI/pennylane/pull/4906)

* The function `qml.transforms.classical_jacobian` has been moved to the gradients module and is now accessible as `qml.gradients.classical_jacobian`. [(4900)](https://github.com/PennyLaneAI/pennylane/pull/4900)

* The transforms submodule `qml.transforms.qcut` is now its own module: `qml.qcut`. [(4819)](https://github.com/PennyLaneAI/pennylane/pull/4819)

* The decomposition of `GroverOperator` now has an additional global phase operation. [(4666)](https://github.com/PennyLaneAI/pennylane/pull/4666)

* `qml.cond` and the `Conditional` operation have been moved from the `transforms` folder to the `ops/op_math` folder. `qml.transforms.Conditional` will now be available as `qml.ops.Conditional`. [(4860)](https://github.com/PennyLaneAI/pennylane/pull/4860)

* The `prep` keyword argument has been removed from `QuantumScript` and `QuantumTape`. `StatePrepBase` operations should be placed at the beginning of the `ops` list instead. [(4756)](https://github.com/PennyLaneAI/pennylane/pull/4756)

* `qml.gradients.pulse_generator` is now named `qml.gradients.pulse_odegen` to adhere to paper naming conventions. [(4769)](https://github.com/PennyLaneAI/pennylane/pull/4769)

* Specifying `control_values` passed to `qml.ctrl` as a string is no longer supported. [(4816)](https://github.com/PennyLaneAI/pennylane/pull/4816)

* The `rot` decomposition will now normalize its rotation angles to the range `[0, 4pi]` for consistency [(4869)](https://github.com/PennyLaneAI/pennylane/pull/4869)

* `QuantumScript.graph` is now built using `tape.measurements` instead of `tape.observables` because it depended on the now-deprecated `Observable.return_type` property. [(4762)](https://github.com/PennyLaneAI/pennylane/pull/4762)

* The `"pennylane"` MPL-drawer style now draws straight lines instead of sketch-style lines. [(4880)](https://github.com/PennyLaneAI/pennylane/pull/4880)

* The default value for the `term_sampling` argument of `ShotAdaptiveOptimizer` is now `None` instead of `"weighted_random_sampling"`. [(4896)](https://github.com/PennyLaneAI/pennylane/pull/4896)

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

* `single_tape_transform`, `batch_transform`, `qfunc_transform`, and `op_transform` are deprecated. Use the new `qml.transform` function instead. [(4774)](https://github.com/PennyLaneAI/pennylane/pull/4774)

* `Observable.return_type` is deprecated. Instead, you should inspect the type of the surrounding measurement process. [(4762)](https://github.com/PennyLaneAI/pennylane/pull/4762) [(#4798)](https://github.com/PennyLaneAI/pennylane/pull/4798)

* All deprecations now raise a `qml.PennyLaneDeprecationWarning` instead of a `UserWarning`. [(4814)](https://github.com/PennyLaneAI/pennylane/pull/4814)

* `QuantumScript.is_sampled` and `QuantumScript.all_sampled` are deprecated. Users should now validate these properties manually. [(4773)](https://github.com/PennyLaneAI/pennylane/pull/4773)

* With an algorithmic improvement to `ClassicalShadow.entropy`, the keyword `atol` becomes obsolete and will be removed in v0.35. [(4959)](https://github.com/PennyLaneAI/pennylane/pull/4959)

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

* Documentation for unitaries and operations' decompositions has been moved from `qml.transforms` to `qml.ops.ops_math`. [(4906)](https://github.com/PennyLaneAI/pennylane/pull/4906)

* Documentation for `qml.metric_tensor` and `qml.adjoint_metric_tensor` and `qml.transforms.classical_jacobian` is now accessible via the gradients API page `qml.gradients` in the documentation. [(4900)](https://github.com/PennyLaneAI/pennylane/pull/4900)

* Documentation for `qml.specs` has been moved to the `resource` module. [(4904)](https://github.com/PennyLaneAI/pennylane/pull/4904)

* Documentation for QCut has been moved to its own API page: `qml.qcut`. [(4819)](https://github.com/PennyLaneAI/pennylane/pull/4819)

* The documentation page for `qml.measurements` now links top-level accessible functions (e.g., `qml.expval`) to their top-level pages rather than their module-level pages (e.g., `qml.measurements.expval`). [(4750)](https://github.com/PennyLaneAI/pennylane/pull/4750)

* Information for the documentation of `qml.matrix` about wire ordering has been added for using `qml.matrix` on a QNode which uses a device with `device.wires=None`. [(4874)](https://github.com/PennyLaneAI/pennylane/pull/4874)

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

* `TransformDispatcher` now stops queuing when performing the transform when applying it to a qfunc. Only the output of the transform will be queued. [(4983)](https://github.com/PennyLaneAI/pennylane/pull/4983)

* `qml.map_wires` now works properly with `qml.cond` and `qml.measure`. [(4884)](https://github.com/PennyLaneAI/pennylane/pull/4884)

* `Pow` operators are now picklable. [(4966)](https://github.com/PennyLaneAI/pennylane/pull/4966)

* Finite differences and SPSA can now be used with tensorflow-autograph on setups that were seeing a bus error. [(4961)](https://github.com/PennyLaneAI/pennylane/pull/4961)

* `qml.cond` no longer incorrectly queues operators used arguments. [(4948)](https://github.com/PennyLaneAI/pennylane/pull/4948)

* `Attribute` objects now return `False` instead of raising a `TypeError` when checking if an object is inside the set. [(4933)](https://github.com/PennyLaneAI/pennylane/pull/4933)

* Fixed a bug where the parameter-shift rule of `qml.ctrl(op)` was wrong if `op` had a generator that has two or more eigenvalues and is stored as a `SparseHamiltonian`. [(4899)](https://github.com/PennyLaneAI/pennylane/pull/4899)

* Fixed a bug where trainable parameters in the post-processing of finite-differences were incorrect for JAX when applying the transform directly on a QNode. [(4879)](https://github.com/PennyLaneAI/pennylane/pull/4879)

* `qml.grad` and `qml.jacobian` now explicitly raise errors if trainable parameters are integers. [(4836)](https://github.com/PennyLaneAI/pennylane/pull/4836)

* JAX-JIT now works with shot vectors. [(4772)](https://github.com/PennyLaneAI/pennylane/pull/4772/)

* JAX can now differentiate a batch of circuits where one tape does not have trainable parameters. [(4837)](https://github.com/PennyLaneAI/pennylane/pull/4837)

* The decomposition of `GroverOperator` now has the same global phase as its matrix. [(4666)](https://github.com/PennyLaneAI/pennylane/pull/4666)

* The `tape.to_openqasm` method no longer mistakenly includes interface information in the parameter string when converting tapes using non-NumPy interfaces. [(4849)](https://github.com/PennyLaneAI/pennylane/pull/4849)

* `qml.defer_measurements` now correctly transforms circuits when terminal measurements include wires used in mid-circuit measurements. [(4787)](https://github.com/PennyLaneAI/pennylane/pull/4787)

* Fixed a bug where the adjoint differentiation method would fail if an operation that has a parameter with `grad_method=None` is present. [(4820)](https://github.com/PennyLaneAI/pennylane/pull/4820)

* `MottonenStatePreparation` and `BasisStatePreparation` now raise an error when decomposing a broadcasted state vector. [(4767)](https://github.com/PennyLaneAI/pennylane/pull/4767)

* Gradient transforms now work with overridden shot vectors and `default.qubit`. [(4795)](https://github.com/PennyLaneAI/pennylane/pull/4795)

* Any `ScalarSymbolicOp`, like `Evolution`, now states that it has a matrix if the target is a `Hamiltonian`. [(4768)](https://github.com/PennyLaneAI/pennylane/pull/4768)

* In `default.qubit`, initial states are now initialized with the simulator's wire order, not the circuit's wire order. [(4781)](https://github.com/PennyLaneAI/pennylane/pull/4781)

* `qml.compile` will now always decompose to `expand_depth`, even if a target basis set is not specified. [(4800)](https://github.com/PennyLaneAI/pennylane/pull/4800)

* `qml.transforms.transpile` can now handle measurements that are broadcasted onto all wires. [(4793)](https://github.com/PennyLaneAI/pennylane/pull/4793)

* Parametrized circuits whose operators do not act on all wires return PennyLane tensors instead of NumPy arrays, as expected. [(4811)](https://github.com/PennyLaneAI/pennylane/pull/4811) [(#4817)](https://github.com/PennyLaneAI/pennylane/pull/4817)

* `qml.transforms.merge_amplitude_embedding` no longer depends on queuing, allowing it to work as expected with QNodes. [(4831)](https://github.com/PennyLaneAI/pennylane/pull/4831)

* `qml.pow(op)` and `qml.QubitUnitary.pow()` now also work with Tensorflow data raised to an integer power. [(4827)](https://github.com/PennyLaneAI/pennylane/pull/4827)

* The text drawer has been fixed to correctly label `qml.qinfo` measurements, as well as `qml.classical_shadow` `qml.shadow_expval`. [(4803)](https://github.com/PennyLaneAI/pennylane/pull/4803)

* Removed an implicit assumption that an empty `PauliSentence` gets treated as identity under multiplication. [(4887)](https://github.com/PennyLaneAI/pennylane/pull/4887)

* Using a `CNOT` or `PauliZ` operation with large batched states and the Tensorflow interface no longer raises an unexpected error. [(4889)](https://github.com/PennyLaneAI/pennylane/pull/4889)

* `qml.map_wires` no longer fails when mapping nested quantum tapes. [(4901)](https://github.com/PennyLaneAI/pennylane/pull/4901)

* Conversion of circuits to openqasm now decomposes to a depth of 10, allowing support for operators requiring more than 2 iterations of decomposition, such as the `ApproxTimeEvolution` gate. [(4951)](https://github.com/PennyLaneAI/pennylane/pull/4951)

* `MPLDrawer` does not add the bonus space for classical wires when no classical wires are present. [(4987)](https://github.com/PennyLaneAI/pennylane/pull/4987)

* `Projector` now works with parameter-broadcasting. [(4993)](https://github.com/PennyLaneAI/pennylane/pull/4993) * The jax-jit interface can now be used with float32 mode. [(#4990)](https://github.com/PennyLaneAI/pennylane/pull/4990)

* Keras models with a `qnn.KerasLayer` no longer fail to save and load weights properly when they are named "weights". [(5008)](https://github.com/PennyLaneAI/pennylane/pull/5008)

<h3>Contributors ✍️</h3>

This release contains contributions from (in alphabetical order):

Guillermo Alonso, Ali Asadi, Utkarsh Azad, Gabriel Bottrill, Thomas Bromley, Astral Cai, Minh Chau, Isaac De Vlugt, Amintor Dusko, Pieter Eendebak, Lillian Frederiksen, Pietropaolo Frisoni, Josh Izaac, Juan Giraldo, Emiliano Godinez Ramirez, Ankit Khandelwal, Korbinian Kottmann, Christina Lee, Vincent Michaud-Rioux, Anurav Modak, Romain Moyard, Mudit Pandey, Matthew Silverman, Jay Soni, David Wierichs, Justin Woodring.

0.33.1

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

* Fix gradient performance regression due to expansion of VJP products. [(4806)](https://github.com/PennyLaneAI/pennylane/pull/4806)

* `qml.defer_measurements` now correctly transforms circuits when terminal measurements include wires used in mid-circuit measurements. [(4787)](https://github.com/PennyLaneAI/pennylane/pull/4787)

* Any `ScalarSymbolicOp`, like `Evolution`, now states that it has a matrix if the target is a `Hamiltonian`. [(4768)](https://github.com/PennyLaneAI/pennylane/pull/4768)

* In `default.qubit`, initial states are now initialized with the simulator's wire order, not the circuit's wire order. [(4781)](https://github.com/PennyLaneAI/pennylane/pull/4781)

<h3>Contributors ✍️</h3>

This release contains contributions from (in alphabetical order):

Christina Lee, Lee James O'Riordan, Mudit Pandey

0.33.0

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

<h4>Postselection and statistics in mid-circuit measurements πŸ“Œ</h4>

* It is now possible to request postselection on a mid-circuit measurement. [(4604)](https://github.com/PennyLaneAI/pennylane/pull/4604)

This can be achieved by specifying the `postselect` keyword argument in `qml.measure` as either `0` or `1`, corresponding to the basis states.

python
import pennylane as qml

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

qml.qnode(dev, interface=None)
def circuit():
qml.Hadamard(wires=0)
qml.CNOT(wires=[0, 1])
qml.measure(0, postselect=1)
return qml.expval(qml.PauliZ(1)), qml.sample(wires=1)

This circuit prepares the $| \Phi^{+} \rangle$ Bell state and postselects on measuring $|1\rangle$ in wire `0`. The output of wire `1` is then also $|1\rangle$ at all times:

pycon
>>> circuit(shots=10)
(-1.0, array([1, 1, 1, 1, 1, 1]))

Note that the number of shots is less than the requested amount because we have thrown away the samples where $|0\rangle$ was measured in wire `0`.

* Measurement statistics can now be collected for mid-circuit measurements. [(4544)](https://github.com/PennyLaneAI/pennylane/pull/4544)

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

qml.qnode(dev)
def circ(x, y):
qml.RX(x, wires=0)
qml.RY(y, wires=1)
m0 = qml.measure(1)
return qml.expval(qml.PauliZ(0)), qml.expval(m0), qml.sample(m0)


pycon
>>> circ(1.0, 2.0, shots=10000)
(0.5606, 0.7089, array([0, 1, 1, ..., 1, 1, 1]))

Support is provided for both [finite-shot and analytic modes](https://docs.pennylane.ai/en/stable/introduction/circuits.html#shots) and devices default to using the [deferred measurement](https://docs.pennylane.ai/en/stable/code/api/pennylane.defer_measurements.html) principle to enact the mid-circuit measurements.

<h4>Exponentiate Hamiltonians with flexible Trotter products πŸ–</h4>

* Higher-order Trotter-Suzuki methods are now easily accessible through a new operation called `TrotterProduct`. [(4661)](https://github.com/PennyLaneAI/pennylane/pull/4661)

Trotterization techniques are an affective route towards accurate and efficient Hamiltonian simulation. The Suzuki-Trotter product formula allows for the ability to express higher-order approximations to the matrix exponential of a Hamiltonian, and it is now available to use in PennyLane via the `TrotterProduct` operation. Simply specify the `order` of the approximation and the evolution `time`.

python
coeffs = [0.25, 0.75]
ops = [qml.PauliX(0), qml.PauliZ(0)]
H = qml.dot(coeffs, ops)

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

qml.qnode(dev)
def circuit():
qml.Hadamard(0)
qml.TrotterProduct(H, time=2.4, order=2)
return qml.state()


pycon
>>> circuit()
[-0.13259524+0.59790098j 0. +0.j -0.13259524-0.77932754j 0. +0.j ]


* Approximating matrix exponentiation with random product formulas, qDrift, is now available with the new `QDrift` operation. [(4671)](https://github.com/PennyLaneAI/pennylane/pull/4671)

As shown in [1811.08017](https://arxiv.org/pdf/1811.08017.pdf), qDrift is a Markovian process that can provide a speedup in Hamiltonian simulation. At a high level, qDrift works by randomly sampling from the Hamiltonian terms with a probability that depends on the Hamiltonian coefficients. This method for Hamiltonian simulation is now ready to use in PennyLane with the `QDrift` operator. Simply specify the evolution `time` and the number of samples drawn from the Hamiltonian, `n`:
python
coeffs = [0.25, 0.75]
ops = [qml.PauliX(0), qml.PauliZ(0)]
H = qml.dot(coeffs, ops)

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

qml.qnode(dev)
def circuit():
qml.Hadamard(0)
qml.QDrift(H, time=1.2, n = 10)
return qml.probs()


pycon
>>> circuit()
array([0.61814334, 0. , 0.38185666, 0. ])


<h4>Building blocks for quantum phase estimation 🧱</h4>

* A new operator called `CosineWindow` has been added to prepare an initial state based on a cosine wave function. [(4683)](https://github.com/PennyLaneAI/pennylane/pull/4683)

As outlined in [2110.09590](https://arxiv.org/pdf/2110.09590.pdf), the cosine tapering window is part of a modification to quantum phase estimation that can provide a cubic improvement to the algorithm's error rate. Using `CosineWindow` will prepare a state whose amplitudes follow a cosinusoidal distribution over the computational basis.

python
import matplotlib.pyplot as plt

dev = qml.device('default.qubit', wires=4)

qml.qnode(dev)
def example_circuit():
qml.CosineWindow(wires=range(4))
return qml.state()

output = example_circuit()

plt.style.use("pennylane.drawer.plot")
plt.bar(range(len(output)), output)
plt.show()


<img src="https://docs.pennylane.ai/en/stable/_images/cosine_window.png" width=50%/>

* Controlled gate sequences raised to decreasing powers, a sub-block in quantum phase estimation, can now be created with the new `ControlledSequence` operator. [(4707)](https://github.com/PennyLaneAI/pennylane/pull/4707/)

To use `ControlledSequence`, specify the controlled unitary operator and the control wires, `control`:

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

qml.qnode(dev)
def circuit():
for i in range(3):
qml.Hadamard(wires = i)
qml.ControlledSequence(qml.RX(0.25, wires = 3), control = [0, 1, 2])
qml.adjoint(qml.QFT)(wires = range(3))
return qml.probs(wires = range(3))


pycon
>>> print(circuit())
[0.92059345 0.02637178 0.00729619 0.00423258 0.00360545 0.00423258 0.00729619 0.02637178]


<h4>New device capabilities, integration with Catalyst, and more! βš—οΈ</h4>

* `default.qubit` now uses the new `qml.devices.Device` API and functionality in `qml.devices.qubit`. If you experience any issues with the updated `default.qubit`, please let us know by [posting an issue](https://github.com/PennyLaneAI/pennylane/issues/new/choose). The old version of the device is still accessible by the short name `default.qubit.legacy`, or directly via `qml.devices.DefaultQubitLegacy`. [(#4594)](https://github.com/PennyLaneAI/pennylane/pull/4594) [(#4436)](https://github.com/PennyLaneAI/pennylane/pull/4436) [(#4620)](https://github.com/PennyLaneAI/pennylane/pull/4620) [(#4632)](https://github.com/PennyLaneAI/pennylane/pull/4632)

This changeover has a number of benefits for `default.qubit`, including:

* The number of wires is now optional β€” simply having `qml.device("default.qubit")` is valid! If wires are not provided at instantiation, the device automatically infers the required number of wires for each circuit provided for execution.

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

qml.qnode(dev)
def circuit():
qml.PauliZ(0)
qml.RZ(0.1, wires=1)
qml.Hadamard(2)
return qml.state()


pycon
>>> print(qml.draw(circuit)())
0: ──Z───────── State
1: ──RZ(0.10)── State
2: ──H───────── State


* `default.qubit` is no longer silently swapped out with an interface-appropriate device when the backpropagation differentiation method is used. For example, consider:

python
import jax

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

qml.qnode(dev, diff_method="backprop")
def f(x):
qml.RX(x, wires=0)
return qml.expval(qml.PauliZ(0))
f(jax.numpy.array(0.2))

In previous versions of PennyLane, the device will be swapped for the JAX equivalent:

pycon
>>> f.device
<DefaultQubitJax device (wires=1, shots=None) at 0x7f8c8bff50a0>
>>> f.device == dev
False

Now, `default.qubit` can itself dispatch to all the interfaces in a backprop-compatible way and hence does not need to be swapped:

pycon
>>> f.device
<default.qubit device (wires=1) at 0x7f20d043b040>
>>> f.device == dev
True


* A QNode that has been decorated with `qjit` from PennyLane's [Catalyst](https://docs.pennylane.ai/projects/catalyst) library for just-in-time hybrid compilation is now compatible with `qml.draw`. [(#4609)](https://github.com/PennyLaneAI/pennylane/pull/4609)

python
import catalyst

catalyst.qjit
qml.qnode(qml.device("lightning.qubit", wires=3))
def circuit(x, y, z, c):
"""A quantum circuit on three wires."""

catalyst.for_loop(0, c, 1)
def loop(i):
qml.Hadamard(wires=i)

qml.RX(x, wires=0)
loop()
qml.RY(y, wires=1)
qml.RZ(z, wires=2)
return qml.expval(qml.PauliZ(0))

draw = qml.draw(circuit, decimals=None)(1.234, 2.345, 3.456, 1)

pycon
>>> print(draw)
0: ──RX──H─── <Z>
1: ──H───RY──
2: ──RZ──────


<h3>Improvements πŸ› </h3>

<h4>More PyTrees!</h4>

* `MeasurementProcess` and `QuantumScript` objects are now registered as JAX PyTrees. [(4607)](https://github.com/PennyLaneAI/pennylane/pull/4607) [(#4608)](https://github.com/PennyLaneAI/pennylane/pull/4608)

It is now possible to JIT-compile functions with arguments that are a `MeasurementProcess` or a `QuantumScript`:

python import jax

tape0 = qml.tape.QuantumTape([qml.RX(1.0, 0), qml.RY(0.5, 0)], [qml.expval(qml.PauliZ(0))])
dev = qml.device('lightning.qubit', wires=5)

execute_kwargs = {"device": dev, "gradient_fn": qml.gradients.param_shift, "interface":"jax"}

jitted_execute = jax.jit(qml.execute, static_argnames=execute_kwargs.keys())
jitted_execute((tape0, ), **execute_kwargs)


<h4>Improving QChem and existing algorithms</h4>

* Computationally expensive functions in `integrals.py`, `electron_repulsion` and `_hermite_coulomb`, have been modified to replace indexing with slicing for better compatibility with JAX. [(4685)](https://github.com/PennyLaneAI/pennylane/pull/4685)

* `qml.qchem.import_state` has been extended to import more quantum chemistry wavefunctions, from MPS, DMRG and SHCI classical calculations performed with the Block2 and Dice libraries. [4523](https://github.com/PennyLaneAI/pennylane/pull/4523) [#4524](https://github.com/PennyLaneAI/pennylane/pull/4524) [#4626](https://github.com/PennyLaneAI/pennylane/pull/4626) [#4634](https://github.com/PennyLaneAI/pennylane/pull/4634)

Check out our [how-to guide](https://pennylane.ai/qml/demos/tutorial_initial_state_preparation) to learn more about how PennyLane integrates with your favourite quantum chemistry libraries.

* The qchem `fermionic_dipole` and `particle_number` functions have been updated to use a `FermiSentence`. The deprecated features for using tuples to represent fermionic operations are removed. [(4546)](https://github.com/PennyLaneAI/pennylane/pull/4546) [(#4556)](https://github.com/PennyLaneAI/pennylane/pull/4556)

* The tensor-network template `qml.MPS` now supports changing the `offset` between subsequent blocks for more flexibility. [(4531)](https://github.com/PennyLaneAI/pennylane/pull/4531)

* Builtin types support with `qml.pauli_decompose` have been improved. [(4577)](https://github.com/PennyLaneAI/pennylane/pull/4577)

* `AmplitudeEmbedding` now inherits from `StatePrep`, allowing for it to not be decomposed when at the beginning of a circuit, thus behaving like `StatePrep`. [(4583)](https://github.com/PennyLaneAI/pennylane/pull/4583)

* `qml.cut_circuit` is now compatible with circuits that compute the expectation values of Hamiltonians with two or more terms. [(4642)](https://github.com/PennyLaneAI/pennylane/pull/4642)

<h4>Next-generation device API</h4>

* `default.qubit` now tracks the number of equivalent qpu executions and total shots when the device is sampling. Note that `"simulations"` denotes the number of simulation passes, whereas `"executions"` denotes how many different computational bases need to be sampled in. Additionally, the new `default.qubit` tracks the results of `device.execute`. [(4628)](https://github.com/PennyLaneAI/pennylane/pull/4628) [(#4649)](https://github.com/PennyLaneAI/pennylane/pull/4649)

* `DefaultQubit` can now accept a `jax.random.PRNGKey` as a `seed` to set the key for the JAX pseudo random number generator when using the JAX interface. This corresponds to the `prng_key` on `default.qubit.jax` in the old API. [(4596)](https://github.com/PennyLaneAI/pennylane/pull/4596)

* The `JacobianProductCalculator` abstract base class and implementations `TransformJacobianProducts` `DeviceDerivatives`, and `DeviceJacobianProducts` have been added to `pennylane.interfaces.jacobian_products`. [(4435)](https://github.com/PennyLaneAI/pennylane/pull/4435) [(#4527)](https://github.com/PennyLaneAI/pennylane/pull/4527) [(#4637)](https://github.com/PennyLaneAI/pennylane/pull/4637)

* `DefaultQubit` dispatches to a faster implementation for applying `ParametrizedEvolution` to a state when it is more efficient to evolve the state than the operation matrix. [(4598)](https://github.com/PennyLaneAI/pennylane/pull/4598) [(#4620)](https://github.com/PennyLaneAI/pennylane/pull/4620)

* Wires can be provided to the new device API. [(4538)](https://github.com/PennyLaneAI/pennylane/pull/4538) [(#4562)](https://github.com/PennyLaneAI/pennylane/pull/4562)

* `qml.sample()` in the new device API now returns a `np.int64` array instead of `np.bool8`. [(4539)](https://github.com/PennyLaneAI/pennylane/pull/4539)

* The new device API now has a `repr()` method. [(4562)](https://github.com/PennyLaneAI/pennylane/pull/4562)

* `DefaultQubit` now works as expected with measurement processes that don't specify wires. [(4580)](https://github.com/PennyLaneAI/pennylane/pull/4580)

* Various improvements to measurements have been made for feature parity between `default.qubit.legacy` and the new `DefaultQubit`. This includes not trying to squeeze batched `CountsMP` results and implementing `MutualInfoMP.map_wires`. [(4574)](https://github.com/PennyLaneAI/pennylane/pull/4574)

* `devices.qubit.simulate` now accepts an interface keyword argument. If a QNode with `DefaultQubit` specifies an interface, the result will be computed with that interface. [(4582)](https://github.com/PennyLaneAI/pennylane/pull/4582)

* `ShotAdaptiveOptimizer` has been updated to pass shots to QNode executions instead of overriding device shots before execution. This makes it compatible with the new device API. [(4599)](https://github.com/PennyLaneAI/pennylane/pull/4599)

* `pennylane.devices.preprocess` now offers the transforms `decompose`, `validate_observables`, `validate_measurements`, `validate_device_wires`, `validate_multiprocessing_workers`, `warn_about_trainable_observables`, and `no_sampling` to assist in constructing devices under the new device API. [(4659)](https://github.com/PennyLaneAI/pennylane/pull/4659)

* Updated `qml.device`, `devices.preprocessing` and the `tape_expand.set_decomposition` context manager to bring `DefaultQubit` to feature parity with `default.qubit.legacy` with regards to using custom decompositions. The `DefaultQubit` device can now be included in a `set_decomposition` context or initialized with a `custom_decomps` dictionary, as well as a custom `max_depth` for decomposition. [(4675)](https://github.com/PennyLaneAI/pennylane/pull/4675)

<h4>Other improvements</h4>

* The `StateMP` measurement now accepts a wire order (e.g., a device wire order). The `process_state` method will re-order the given state to go from the inputted wire-order to the process's wire-order. If the process's wire-order contains extra wires, it will assume those are in the zero-state. [(4570)](https://github.com/PennyLaneAI/pennylane/pull/4570) [(#4602)](https://github.com/PennyLaneAI/pennylane/pull/4602)

* Methods called `add_transform` and `insert_front_transform` have been added to `TransformProgram`. [(4559)](https://github.com/PennyLaneAI/pennylane/pull/4559)

* Instances of the `TransformProgram` class can now be added together. [(4549)](https://github.com/PennyLaneAI/pennylane/pull/4549)

* Transforms can now be applied to devices following the new device API. [(4667)](https://github.com/PennyLaneAI/pennylane/pull/4667)

* All gradient transforms have been updated to the new transform program system. [(4595)](https://github.com/PennyLaneAI/pennylane/pull/4595)

* Multi-controlled operations with a single-qubit special unitary target can now automatically decompose. [(4697)](https://github.com/PennyLaneAI/pennylane/pull/4697)

* `pennylane.defer_measurements` will now exit early if the input does not contain mid circuit measurements. [(4659)](https://github.com/PennyLaneAI/pennylane/pull/4659)

* The density matrix aspects of `StateMP` have been split into their own measurement process called `DensityMatrixMP`. [(4558)](https://github.com/PennyLaneAI/pennylane/pull/4558)

* `StateMeasurement.process_state` now assumes that the input is flat. `ProbabilityMP.process_state` has been updated to reflect this assumption and avoid redundant reshaping. [(4602)](https://github.com/PennyLaneAI/pennylane/pull/4602)

* `qml.exp` returns a more informative error message when decomposition is unavailable for non-unitary operators. [(4571)](https://github.com/PennyLaneAI/pennylane/pull/4571)

* Added `qml.math.get_deep_interface` to get the interface of a scalar hidden deep in lists or tuples. [(4603)](https://github.com/PennyLaneAI/pennylane/pull/4603)

* Updated `qml.math.ndim` and `qml.math.shape` to work with built-in lists or tuples that contain interface-specific scalar dat (e.g., `[(tf.Variable(1.1), tf.Variable(2.2))]`). [(4603)](https://github.com/PennyLaneAI/pennylane/pull/4603)

* When decomposing a unitary matrix with `one_qubit_decomposition` and opting to include the `GlobalPhase` in the decomposition, the phase is no longer cast to `dtype=complex`. [(4653)](https://github.com/PennyLaneAI/pennylane/pull/4653)

* `_qfunc_output` has been removed from `QuantumScript`, as it is no longer necessary. There is still a `_qfunc_output` property on `QNode` instances. [(4651)](https://github.com/PennyLaneAI/pennylane/pull/4651)

* `qml.data.load` properly handles parameters that come after `'full'` [(4663)](https://github.com/PennyLaneAI/pennylane/pull/4663)

* The `qml.jordan_wigner` function has been modified to optionally remove the imaginary components of the computed qubit operator, if imaginary components are smaller than a threshold. [(4639)](https://github.com/PennyLaneAI/pennylane/pull/4639)

* `qml.data.load` correctly performs a full download of the dataset after a partial download of the same dataset has already been performed. [(4681)](https://github.com/PennyLaneAI/pennylane/pull/4681) * The performance of `qml.data.load()` has been improved when partially loading a dataset [(#4674)](https://github.com/PennyLaneAI/pennylane/pull/4674)

* Plots generated with the `pennylane.drawer.plot` style of `matplotlib.pyplot` now have black axis labels and are generated at a default DPI of 300. [(4690)](https://github.com/PennyLaneAI/pennylane/pull/4690)

* Shallow copies of the `QNode` now also copy the `execute_kwargs` and transform program. When applying a transform to a `QNode`, the new qnode is only a shallow copy of the original and thus keeps the same device. [(4736)](https://github.com/PennyLaneAI/pennylane/pull/4736)

* `QubitDevice` and `CountsMP` are updated to disregard samples containing failed hardware measurements (record as `np.NaN`) when tallying samples, rather than counting failed measurements as ground-state measurements, and to display `qml.counts` coming from these hardware devices correctly. [(4739)](https://github.com/PennyLaneAI/pennylane/pull/4739)

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

* `qml.defer_measurements` now raises an error if a transformed circuit measures `qml.probs`, `qml.sample`, or `qml.counts` without any wires or observable, or if it measures `qml.state`. [(4701)](https://github.com/PennyLaneAI/pennylane/pull/4701)

* The device test suite now converts device keyword arguments to integers or floats if possible. [(4640)](https://github.com/PennyLaneAI/pennylane/pull/4640)

* `MeasurementProcess.eigvals()` now raises an `EigvalsUndefinedError` if the measurement observable does not have eigenvalues. [(4544)](https://github.com/PennyLaneAI/pennylane/pull/4544)

* The `__eq__` and `__hash__` methods of `Operator` and `MeasurementProcess` no longer rely on the object's address in memory. Using `==` with operators and measurement processes will now behave the same as `qml.equal`, and objects of the same type with the same data and hyperparameters will have the same hash. [(4536)](https://github.com/PennyLaneAI/pennylane/pull/4536)

In the following scenario, the second and third code blocks show the previous and current behaviour of operator and measurement process equality, determined by `==`:

python
op1 = qml.PauliX(0)
op2 = qml.PauliX(0)
op3 = op1


Old behaviour:

pycon
>>> op1 == op2
False
>>> op1 == op3
True


New behaviour:

pycon
>>> op1 == op2
True
>>> op1 == op3
True


The `__hash__` dunder method defines the hash of an object. The default hash of an object is determined by the objects memory address. However, the new hash is determined by the properties and attributes of operators and measurement processes. Consider the scenario below. The second and third code blocks show the previous and current behaviour.

python
op1 = qml.PauliX(0)
op2 = qml.PauliX(0)


Old behaviour:

pycon
>>> print({op1, op2})
{PauliX(wires=[0]), PauliX(wires=[0])}


New behaviour:

pycon
>>> print({op1, op2})
{PauliX(wires=[0])}


* The old return type and associated functions `qml.enable_return` and `qml.disable_return` have been removed. [(4503)](https://github.com/PennyLaneAI/pennylane/pull/4503)

* The `mode` keyword argument in `QNode` has been removed. Please use `grad_on_execution` instead. [(4503)](https://github.com/PennyLaneAI/pennylane/pull/4503)

* The CV observables `qml.X` and `qml.P` have been removed. Please use `qml.QuadX` and `qml.QuadP` instead. [(4533)](https://github.com/PennyLaneAI/pennylane/pull/4533)

* The `sampler_seed` argument of `qml.gradients.spsa_grad` has been removed. Instead, the `sampler_rng` argument should be set, either to an integer value, which will be used to create a PRNG internally, or to a NumPy pseudo-random number generator (PRNG) created via `np.random.default_rng(seed)`. [(4550)](https://github.com/PennyLaneAI/pennylane/pull/4550)

* The `QuantumScript.set_parameters` method and the `QuantumScript.data` setter have been removed. Please use `QuantumScript.bind_new_parameters` instead. [(4548)](https://github.com/PennyLaneAI/pennylane/pull/4548)

* The method `tape.unwrap()` and corresponding `UnwrapTape` and `Unwrap` classes have been removed. Instead of `tape.unwrap()`, use `qml.transforms.convert_to_numpy_parameters`. [(4535)](https://github.com/PennyLaneAI/pennylane/pull/4535)

* The `RandomLayers.compute_decomposition` keyword argument `ratio_imprivitive` has been changed to `ratio_imprim` to match the call signature of the operation. [(4552)](https://github.com/PennyLaneAI/pennylane/pull/4552)

* The private `TmpPauliRot` operator used for `SpecialUnitary` no longer decomposes to nothing when the theta value is trainable. [(4585)](https://github.com/PennyLaneAI/pennylane/pull/4585)

* `ProbabilityMP.marginal_prob` has been removed. Its contents have been moved into `process_state`, which effectively just called `marginal_prob` with `np.abs(state) ** 2`. [(4602)](https://github.com/PennyLaneAI/pennylane/pull/4602)

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

* The following decorator syntax for transforms has been deprecated and will raise a warning: [(4457)](https://github.com/PennyLaneAI/pennylane/pull/4457/)

python
transform_fn(**transform_kwargs)
qml.qnode(dev)
def circuit():
...

If you are using a transform that has supporting `transform_kwargs`, please call the transform directly using `circuit = transform_fn(circuit, **transform_kwargs)`, or use `functools.partial`:

python
functools.partial(transform_fn, **transform_kwargs)
qml.qnode(dev)
def circuit():
...


* The `prep` keyword argument in `QuantumScript` has been deprecated and will be removed from `QuantumScript`. `StatePrepBase` operations should be placed at the beginning of the `ops` list instead. [(4554)](https://github.com/PennyLaneAI/pennylane/pull/4554)

* `qml.gradients.pulse_generator` has been renamed to `qml.gradients.pulse_odegen` to adhere to paper naming conventions. During v0.33, `pulse_generator` is still available but raises a warning. [(4633)](https://github.com/PennyLaneAI/pennylane/pull/4633)

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

* A warning section in the docstring for `DefaultQubit` regarding the start method used in multiprocessing has been added. This may help users circumvent issues arising in Jupyter notebooks on macOS for example. [(4622)](https://github.com/PennyLaneAI/pennylane/pull/4622)

* Documentation improvements to the new device API have been made. The documentation now correctly states that interface-specific parameters are only passed to the device for backpropagation derivatives. [(4542)](https://github.com/PennyLaneAI/pennylane/pull/4542)

* Functions for qubit-simulation to the `qml.devices` sub-page of the "Internal" section have been added. Note that these functions are unstable while device upgrades are underway. [(4555)](https://github.com/PennyLaneAI/pennylane/pull/4555)

* A documentation improvement to the usage example in the `qml.QuantumMonteCarlo` page has been made. An integral was missing the differential $dx$. [(4593)](https://github.com/PennyLaneAI/pennylane/pull/4593)

* A documentation improvement for the use of the `pennylane` style of `qml.drawer` and the `pennylane.drawer.plot` style of `matplotlib.pyplot` has been made by clarifying the use of the default font. [(4690)](https://github.com/PennyLaneAI/pennylane/pull/4690)

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

* Jax jit now works when a probability measurement is broadcasted onto all wires. [(4742)](https://github.com/PennyLaneAI/pennylane/pull/4742)

* Fixed `LocalHilbertSchmidt.compute_decomposition` so that the template can be used in a QNode. [(4719)](https://github.com/PennyLaneAI/pennylane/pull/4719)

* Fixes `transforms.transpile` with arbitrary measurement processes. [(4732)](https://github.com/PennyLaneAI/pennylane/pull/4732)

* Providing `work_wires=None` to `qml.GroverOperator` no longer interprets `None` as a wire. [(4668)](https://github.com/PennyLaneAI/pennylane/pull/4668)

* Fixed an issue where the `__copy__` method of the `qml.Select()` operator attempted to access un-initialized data. [(4551)](https://github.com/PennyLaneAI/pennylane/pull/4551)

* Fixed the `skip_first` option in `expand_tape_state_prep`. [(4564)](https://github.com/PennyLaneAI/pennylane/pull/4564)

* `convert_to_numpy_parameters` now uses `qml.ops.functions.bind_new_parameters`. This reinitializes the operation and makes sure everything references the new NumPy parameters. [(4540)](https://github.com/PennyLaneAI/pennylane/pull/4540)

* `tf.function` no longer breaks `ProbabilityMP.process_state`, which is needed by new devices. [(4470)](https://github.com/PennyLaneAI/pennylane/pull/4470)

* Fixed unit tests for `qml.qchem.mol_data`. [(4591)](https://github.com/PennyLaneAI/pennylane/pull/4591)

* Fixed `ProbabilityMP.process_state` so that it allows for proper Autograph compilation. Without this, decorating a QNode that returns an `expval` with `tf.function` would fail when computing the expectation. [(4590)](https://github.com/PennyLaneAI/pennylane/pull/4590)

* The `torch.nn.Module` properties are now accessible on a `pennylane.qnn.TorchLayer`. [(4611)](https://github.com/PennyLaneAI/pennylane/pull/4611)

* `qml.math.take` with Pytorch now returns `tensor[..., indices]` when the user requests the last axis (`axis=-1`). Without the fix, it would wrongly return `tensor[indices]`. [(4605)](https://github.com/PennyLaneAI/pennylane/pull/4605)

* Ensured the logging `TRACE` level works with gradient-free execution. [(4669)](https://github.com/PennyLaneAI/pennylane/pull/4669)

<h3>Contributors ✍️</h3>

This release contains contributions from (in alphabetical order):

Guillermo Alonso, Utkarsh Azad, Thomas Bromley, Isaac De Vlugt, Jack Brown, Stepan Fomichev, Joana Fraxanet, Diego Guala, Soran Jahangiri, Edward Jiang, Korbinian Kottmann, Ivana KurečiΔ‡ Christina Lee, Lillian M. A. Frederiksen, Vincent Michaud-Rioux, Romain Moyard, Daniel F. Nino, Lee James O'Riordan, Mudit Pandey, Matthew Silverman, Jay Soni.

Page 1 of 11

Β© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.