July 15, 2025
PennyLane v0.42 and Catalyst v0.12 released

Does quantum computing give you butterflies π¦? PennyLane v0.42 and Catalyst v0.12 will leave you buzzin' π!
Contents
- Improved Select implementation π
- New QSVT/QSP angle solver π·οΈ
- Send PennyLane circuits to Qualtran π
- More efficient Clifford + T decomposition π
- Compile directly to Pauli Product Measurements πͺ²
- Deprecations and breaking changes π
- Contributors βοΈ
Improved Select implementation π
Bee selective with your quantum programming! A new decomposition for qml.Select significantly reduces the number of T gates required for multiplexing. Try it in your block encodings!

In PennyLane v0.41, we introduced a
graph-based decomposition system
that offers better resource efficiency. With this release, we've added a state-of-the-art
decomposition for qml.Select
that leverages this new decomposition system. Based on unary iteration from
arXiv:1805.03662, this decomposition leads to significantly fewer
T gates and uses c-1 auxiliary wires, where c is the number of control wires
of the qml.Select
operator.
The unary-iterator decomposition also uses a new template called
qml.TemporaryAND, which
is equivalent to a logical AND
operation (or a reversible
qml.Toffoli gate).
This operation stores intermediate values of the auxiliary wires for reuse among the different
multi-controlled operators.
To use the unary iterator decomposition for qml.Select
,
enable the graph-based decomposition
system with qml.decomposition.enable_graph()
:
import pennylane as qml
qml.decomposition.enable_graph()
To demonstrate the resource-efficiency of this new decomposition, we can decompose
an instance of
qml.Select
and further decompose these gates into the Clifford + T gate set using
qml.clifford_t_decomposition
so that we can count the number of T gates required:
from functools import partial
reg = qml.registers({"targ": 2, "control": 2, "work": 1})
targ, control, work = (reg[k] for k in reg.keys())
dev = qml.device('default.qubit')
ops = [qml.X(targ[0]), qml.X(targ[1]), qml.Y(targ[0]), qml.SWAP(targ)]
@qml.clifford_t_decomposition
@partial(qml.transforms.decompose, gate_set={
"X", "CNOT", "TemporaryAND", "Adjoint(TemporaryAND)", "CY", "CSWAP"
}
)
@qml.qnode(dev)
def circuit():
qml.Select(ops, control=control, work_wires=work)
return qml.state()
>>> unary_specs = qml.specs(circuit)()
>>> print(unary_specs['resources'].gate_types["T"])
16
>>> print(unary_specs['resources'].gate_types["Adjoint(T)"])
13
Go check out the Unary iterator decomposition section
in the
qml.Select
documentation for
more information!
New QSVT/QSP angle solver π·οΈ
Don't let computing phase angles get you caught in a webβa new contribution from our collaborator Oumarou Oumarou at Covestro allows you to generate QSVT and QSP phase angles for even the largest of polynomials!

Effortlessly perform QSVT and QSP with polynomials of large degrees using our new iterative angle solver.
A new iterative angle solver for QSVT and QSP is available in the qml.poly_to_angles function, designed for angle computation for polynomials with degrees larger than 1000.
Simply set angle_solver="iterative"
in poly_to_angles
to use it.
import numpy as np
# P(x) = x - 0.5 x^3 + 0.25 x^5
poly = np.array([0, 1.0, 0, -1/2, 0, 1/4])
qsvt_angles = qml.poly_to_angles(poly, "QSVT", angle_solver="iterative")
>>> print(qsvt_angles)
[-4.72195208 1.59759022 1.12953398 1.12953403 1.59759046 -0.00956271]
This functionality can also be accessed directly from qml.qsvt with the same keyword argument:
# P(x) = -x + 0.5 x^3 + 0.5 x^5
poly = np.array([0, -1, 0, 0.5, 0, 0.5])
hamiltonian = qml.dot([0.3, 0.7], [qml.Z(1), qml.X(1) @ qml.Z(2)])
dev = qml.device("default.qubit")
@qml.qnode(dev)
def circuit():
qml.qsvt(
hamiltonian,
poly,
encoding_wires=[0],
block_encoding="prepselprep",
angle_solver="iterative"
)
return qml.state()
matrix = qml.matrix(circuit, wire_order=[0, 1, 2])()
>>> print(matrix[:4, :4].real)
[[-0.16253996 0. -0.37925991 0. ]
[ 0. -0.16253996 0. 0.37925991]
[-0.37925991 0. 0.16253996 0. ]
[ 0. 0.37925991 0. 0.16253996]]
Send PennyLane circuits to Qualtran π
A brilli-ant new collaboration with our partners at Google! It's now possible to convert PennyLane circuits to Qualtran Bloqs, unlocking a new way to do quantum resource estimation with PennyLane.

The new qml.to_bloq function translates PennyLane QNodes, functions, and operations into equivalent Qualtran Bloqs, allowing you to use Qualtran's abstractions and tools to analyze PennyLane circuits without rewriting them.
qml.to_bloq
can be used in the following ways:
-
Use smart default mapping of PennyLane circuits and operations to Qualtran Bloqs by setting
map_ops=True
(the default value):>>> PL_op = qml.X(0) >>> qualtran_op = qml.to_bloq(PL_op) >>> type(qualtran_op) qualtran.bloqs.basic_gates.x_basis.XGate
-
Alternatively, wrap PennyLane circuits and operations to preserve PennyLane's definition of the circuit/operator while still enabling Qualtran features like bloq_counts or drawing a call_graph. This is done by setting
map_ops=False
, which instead wraps operations as aToBloq
object:>>> def circuit(): ... qml.X(0) ... qml.Y(1) ... qml.Z(2) ... >>> cbloq = qml.to_bloq(circuit, map_ops=False) >>> type(cbloq) pennylane.io.qualtran_io.ToBloq >>> cbloq.bloq_counts() {XGate(): 1, ZGate(): 1, YGate(): 1}
More efficient Clifford + T decomposition π
This new decomposition will leaf you in awe. Building circuits in the Clifford + T gate set now requires fewer gates!

The Ross-Selinger algorithm (arXiv:1403.2975),
also known as 'gridsynth', can now be accessed in the
qml.clifford_t_decomposition
transform by setting method="gridsynth"
. This is a newer Clifford + T decomposition method that can produce
orders of magnitude fewer gates than the Solovay-Kitaev algorithm (method="sk"
).
In the following example, decomposing with method="gridsynth"
instead of method="sk"
gives a
significant reduction in overall gate counts, specifically the T-count:
@qml.qnode(qml.device("lightning.qubit", wires=2))
def circuit():
qml.RX(0.12, 0)
qml.CNOT([0, 1])
qml.RY(0.34, 0)
return qml.expval(qml.Z(0))
gridsynth_circuit = qml.clifford_t_decomposition(circuit, method="gridsynth")
sk_circuit = qml.clifford_t_decomposition(circuit, method="sk")
We can inspect the gate counts resulting from both decomposition methods with qml.specs:
>>> gridsynth_specs = qml.specs(gridsynth_circuit)()["resources"]
>>> sk_specs = qml.specs(sk_circuit)()["resources"]
>>> print(gridsynth_specs.num_gates, sk_specs.num_gates)
239 47942
>>> print(gridsynth_specs.gate_types['T'], sk_specs.gate_types['T'])
90 8044
Compile directly to Pauli Product Measurements πͺ²
Roll your circuits downhill into instructions meant for FTQC architectures π

Catalyst has a new compilation pass called catalyst.passes.ppm_compilation, which compiles Clifford + T circuits down to Pauli product measurements (PPMs) based on concepts and theory from A Game of Surface Codes (arXiv:1808.02892). PPMs are just one facet of compiling logical circuits down to instructions for FTQC architectures, but they represent an important paradigm in full-stack logical quantum compilation.
Alongside this feature, explore and learn about representations of your programs in terms of PPMs and Pauli product rotations (PPRs: \exp(-iP_{\{x, y, z\}} \theta)) with catalyst.passes.get_ppm_specs, which allows inspection of your Clifford + T circuit for the following quantities:
num_pi2_gates
,num_pi4_gates
,num_pi8_gates
: number of PPRs with \theta = \tfrac{\pi}{2} (classical), \tfrac{\pi}{4} (Clifford), \tfrac{\pi}{8} (non-Clifford)max_weight_pi2
,max_weight_pi4
,max_weight_pi8
: maximum weight of each type of PPRnum_logical_qubits
: number of logical qubitsnum_of_ppm
: number of PPMs
import catalyst
from catalyst.passes import ppm_compilation, get_ppm_specs
pipeline = [("pipe", ["enforce-runtime-invariants-pipeline"])]
@qml.qjit(pipelines=pipeline, target="mlir")
@ppm_compilation
@qml.qnode(qml.device("null.qubit", wires=2))
def circuit():
qml.CNOT([0, 1])
qml.CNOT([1, 0])
qml.adjoint(qml.T)(0)
qml.T(1)
return catalyst.measure(0), catalyst.measure(1)
>>> ppm_specs = get_ppm_specs(circuit)
>>> print(ppm_specs)
{'circuit_0': {'max_weight_pi2': 2, 'num_logical_qubits': 2, 'num_of_ppm': 8, 'num_pi2_gates': 2}}
Check out the documentation of ppm_compilation and get_ppm_specs for more information, as well as the PPM page in our Quantum Compilation Wiki!
Deprecations and breaking changes π
As new things are added, outdated features are removed. To keep track of things in the deprecation pipeline, check out the deprecations page.
Here's a summary of what has changed in this release:
-
Python 3.10 is deprecated and support will be removed in v0.43. Please upgrade to Python 3.11 or newer.
-
Support for Mac x86 has been removed. This includes Macs running on Intel processors. This is because JAX has also dropped support for it since 0.5.0, with the rationale being that such machines are becoming increasingly scarce. If support for Mac x86 platforms is still desired, please install Catalyst v0.11.0, PennyLane v0.41.0, PennyLane-Lightning v0.41.0, and JAX v0.4.28.
-
The
KerasLayer
class inqml.qnn.keras
has been removed because Keras 2 is no longer actively maintained. Please consider using a different machine learning framework, like PyTorch or JAX.
These highlights are just scratching the surface β check out the full release notes for PennyLane and Catalyst for more details.
Contributors βοΈ
As always, this release would not have been possible without the hard work of our development team and contributors:
Runor Agbaire, Guillermo Alonso-Linaje, Ali Asadi, Utkarsh Azad, Astral Cai, Joey Carter, Yushao Chen, Isaac De Vlugt, Diksha Dhawan, Marcus Edwards, Tarik El-Khateeb, Lillian Frederiksen, Pietropaolo Frisoni, Simone Gasperini, Diego Guala, Sengthai Heng, Austin Huang, David Ittah, Soran Jahangiri, Tzung-Han Juang, Korbinian Kottmann, Christina Lee, Joseph Lee, Erick Ochoa Lopez, Anton Naim Ibrahim, Mehrdad Malekmohammadi, William Maxwell, Luis Alfredo NuΓ±ez Meneses, Oumarou Oumarou, Lee J. O'Riordan, Mudit Pandey, Andrija Paurevic, Justin Pickering, Shuli Shu, Jay Soni, Kalman Szenes, Ritu Thombre, Raul Torres, Marc Vandelle, Paul Haochen Wang, David Wierichs, Jake Zaia.
About the authors
Diego Guala
Diego is a quantum scientist at Xanadu. His work is focused on supporting the development of the datasets service and PennyLane features.
Isaac De Vlugt
My job is to help manage the PennyLane and Catalyst feature roadmap... and spam lots of emojis in the chat π€
Anton Naim Ibrahim
Exploring uncharted territory.
Josh Izaac
Josh is a theoretical physicist, software tinkerer, and occasional baker. At Xanadu, he contributes to the development and growth of Xanaduβs open-source quantum software products.