If this release was in Fahrenheit, it'd be cool enough to freeze water 🧊. PennyLane v0.32 is out today! Check out the exciting new functionality below.
Contents
- Datasets, datasets, datasets! 💾
- Encode matrices using a linear combination of unitaries ⛓️
- Inspect PennyLane's inner workings with logging 📃
- More input states for quantum chemistry calculations ⚛️
- Reuse and reset qubits after mid-circuit measurements ♻️
- Improvements 🛠️
- Deprecations and breaking changes 💔
- Contributors ✍️
Datasets, datasets, datasets! 💾

Several releases back, we introduced our very own curated datasets module.
Initially accessible only through qml.data
methods in Python, we are pleased
to announce a brand new online library that
makes it easier to browse available datasets, and find exactly what you are
looking for; complementing our
existing datasets functionality in PennyLane.
This welcome addition to PennyLane is deserving of its own blog post — go check it out!
Encode matrices using a linear combination of unitaries ⛓️
PREPpin', SELECTin', and block-encodin' — it's all possible with these new features in v0.32 🤓
It is now possible to encode an operator A
into a quantum circuit by
decomposing it into a linear combination of unitaries and using the
qml.StatePrep
and
qml.Select
operations to input the coefficients and unitaries, respectively.
Consider an operator A
composed of a linear combination of Pauli terms:
>>> A = qml.PauliX(2) + 2 * qml.PauliY(2) + 3 * qml.PauliZ(2)
A decomposable block-encoding circuit can be created:
def block_encode(A, control_wires): probs = A.coeffs / np.sum(A.coeffs) state = np.pad(np.sqrt(probs, dtype=complex), (0, 1)) unitaries = A.ops qml.StatePrep(state, wires=control_wires) qml.Select(unitaries, control=control_wires) qml.adjoint(qml.StatePrep)(state, wires=control_wires)
>>> print(qml.draw(block_encode, show_matrices=False)(A, control_wires=[0, 1])) 0: ─╭|Ψ⟩─╭Select─╭|Ψ⟩†─┤ 1: ─╰|Ψ⟩─├Select─╰|Ψ⟩†─┤ 2: ──────╰Select───────┤
This circuit can be used as a building block within a larger QNode to perform algorithms such as the quantum singular value transformation or Hamiltonian simulation.
Inspect PennyLane's inner workings with logging 📃
Does debugging look like "print('this')
, print('that')
" for you? Try
PennyLane's logging support! Take a peak under the hood to see what makes the
PennyLane engine chug 🚂
Python-native logging can now be enabled with qml.logging.enable_logging()
.
Consider the following code that is contained in my_code.py
:
import pennylane as qml qml.logging.enable_logging() # enables logging dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def f(x): qml.RX(x, wires=0) return qml.state() f(0.5)
Executing my_code.py
with logging enabled will detail every step in
PennyLane's pipeline that gets used to run your code.
$ python my_code.py [1967-02-13 15:18:38,591][DEBUG][<PID 8881:MainProcess>] - pennylane.qnode.__init__():: “Creating QNode(func=<function f at 0x7faf2a6fbaf0>, device=<DefaultQubit device (wires=2, shots=None) at 0x7faf2a689b50>, interface=auto, diff_method=best, expansion_strategy=gradient, max_expansion=10, grad_on_execution=best, mode=None, cache=True, cachesize=10000, max_diff=1, gradient_kwargs={}” ...
Additional logging configuration settings can be specified by modifying the
contents of the logging configuration file, which can be located by running
qml.logging.config_path()
.
More input states for quantum chemistry calculations ⚛️
We aim to make it easy to integrate PennyLane with existing libraries far and wide, including popular quantum chemistry libraries. Importing entities like PySCF solver objects and returning the corresponding circuit state vector is now possible!

The qml.qchem.import_state
function can be used to import a PySCF solver
object and return the corresponding state vector.
>>> from pyscf import gto, scf, ci >>> mol = gto.M(atom=[['H', (0, 0, 0)], ['H', (0,0,0.71)]], basis='sto6g') >>> myhf = scf.UHF(mol).run() >>> myci = ci.UCISD(myhf).run() >>> wf_cisd = qml.qchem.import_state(myci, tol=1e-1) >>> print(wf_cisd) [ 0. +0.j 0. +0.j 0. +0.j 0.1066467 +0.j 1. +0.j 0. +0.j 0. +0.j 0. +0.j 2. +0.j 0. +0.j 0. +0.j 0. +0.j -0.99429698+0.j 0. +0.j 0. +0.j 0. +0.j]
The currently supported objects are RCISD, UCISD, RCCSD, and UCCSD, which correspond to restricted (R) and unrestricted (U) configuration interaction (CI) and coupled cluster (CC) calculations with single and double (SD) excitations.
Reuse and reset qubits after mid-circuit measurements ♻️
Reuse, reset, and recycle qubits ♻ — do your part to make the quantum world more sustainable 🌱

PennyLane now allows you to define circuits that reuse a qubit after a mid-circuit measurement has taken place. Optionally, the wire can also be reset to the |0\rangle state.
Post-measurement reset can be activated by setting reset=True
when calling
qml.measure.
In this v0.32 of PennyLane, executing circuits where a qubit is being reused
will result in the
qml.defer_measurements
transform being applied. This transform replaces each reused wire with an
additional qubit. However, future releases of PennyLane will explore
device-level support for qubit reuse without consuming additional qubits.
Qubit reuse and reset is also fully differentiable:
dev = qml.device("default.qubit", wires=4) @qml.qnode(dev) def circuit(p): qml.RX(p, wires=0) m = qml.measure(0, reset=True) qml.cond(m, qml.Hadamard)(1) qml.RX(p, wires=0) m = qml.measure(0) qml.cond(m, qml.Hadamard)(1) return qml.expval(qml.PauliZ(1))
>>> jax.grad(circuit)(0.4) Array(-0.35867804, dtype=float32, weak_type=True)
Stay tuned for more mid-circuit measurement support in the next few releases!
Improvements 🛠️
In addition to the new features listed above, the release contains a wide array of improvements and optimizations:
-
Circuit drawings and plots can now be created following the beloved PennyLane style.
The
qml.draw_mpl
function accepts astyle='pennylane'
argument to create PennyLane-themed circuit diagrams:def circuit(x, z): qml.QFT(wires=(0,1,2,3)) qml.Toffoli(wires=(0,1,2)) qml.CSWAP(wires=(0,2,3)) qml.RX(x, wires=0) qml.CRZ(z, wires=(3,0)) return qml.expval(qml.PauliZ(0)) qml.draw_mpl(circuit, style="pennylane")(1, 1)
PennyLane-styled plots can also be drawn by passing
"pennylane.drawer.plot"
to Matplotlib'splt.style.use
function:import matplotlib.pyplot as plt plt.style.use("pennylane.drawer.plot") for i in range(3): plt.plot(np.random.rand(10))
If the font Quicksand Bold isn't available, an available default font is used instead.
-
Any class inheriting from
Operator
is now automatically registered as a pytree with JAX. This unlocks the ability to JIT functions ofOperator
.>>> op = qml.adjoint(qml.RX(1.0, wires=0)) >>> jax.jit(qml.matrix)(op) Array([[0.87758255-0.j , 0. +0.47942555j], [0. +0.47942555j, 0.87758255-0.j ]], dtype=complex64, weak_type=True) >>> jax.tree_util.tree_map(lambda x: x+1, op) Adjoint(RX(2.0, wires=[0]))
-
qml.pulse.transmon_drive
has been updated in accordance with this paper. In particular, the functional form has been changed from \Omega(t)(\cos(\omega_d t + \phi) X - \sin(\omega_d t + \phi) Y) to \Omega(t) \sin(\omega_d t + \phi) Y. -
The
qchem
module has been upgraded to use the fermionic operators of thefermi
module. -
qml.pauli_decompose
is now exponentially faster and differentiable. -
The calculation of
Sum
,Prod
,SProd
,PauliWord
, andPauliSentence
sparse matrices are orders of magnitude faster.
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:
-
Support for Python 3.8 has been dropped.
-
qml.StatePrep
has been renamed toqml.StatePrepBase
andqml.QubitStateVector
has been renamed toqml.StatePrep
.qml.operation.StatePrep
andqml.QubitStateVector
are still accessible. -
The CV observables
qml.X
andqml.P
have been deprecated. Useqml.QuadX
andqml.QuadP
instead. -
qml.enable_return
andqml.disable_return
have been deprecated. Please avoid callingdisable_return
, as the old return system has been deprecated along with these switch functions. -
qml.qchem.jordan_wigner
has been deprecated. Useqml.jordan_wigner
instead. List input to define the fermionic operator has also been deprecated; the fermionic operators in theqml.fermi
module should be used instead.
These highlights are just scratching the surface — check out the full release notes for more details.
Contributors ✍️
As always, this release would not have been possible without the hard work of our development team and contributors:
Juan Miguel Arrazola, Utkarsh Azad, Thomas Bromley, Jack Brown, David Clark, Isaac De Vlugt, Amintor Dusko, Tarik El-Khateeb, Stepan Fomichev, Lillian M. A. Frederiksen, Andrew Gardhouse, Diego Guala, Josh Izaac, Ant Hayes, Soran Jahangiri, Edward Jiang, Korbinian Kottmann, Ivana Kurečić, Christina Lee, Vincent Michaud-Rioux, Romain Moyard, Lee James O'Riordan, Mudit Pandey, Borja Requena, Shuli Shu, Lucas Silbernagel, Matthew Silverman, Jay Soni, David Wierichs, and Frederik Wilde
About the authors
Isaac De Vlugt
My job is to help manage the PennyLane and Catalyst feature roadmap... and spam lots of emojis in the chat 🤠