
PennyLane v0.33 just dropped in time for Halloween, and itβs scary good πΉ! Check out the terrifyingly terrific new functionality below.
Contents
- Postselection and statistics in mid-circuit measurements π
- Flexible Trotter products π
- Pulse programming with OQC hardware βοΈπ¬
- Modular Quantum Phase Estimation π§©
- New device capabilities, Catalyst integration, and more! βοΈ
- Improvements π οΈ
- Deprecations and breaking changes π
- Contributors βοΈ
Postselection and statistics in mid-circuit measurements π
Trick or treat? You decide ππ¬. Postselecting qubits and gathering statistics of mid-circuit measurements are now available in v0.33 π

In the last release, we introduced reusing and resetting qubits after a mid-circuit measurement. With this release, we've added more features to mid-circuit measurements:
-
Postselection after mid-circuit measurements can now be performed by specifying
thepostselect
keyword argument inqml.measure
as either0
or1
, corresponding to the basis states.import pennylane as qml dev = qml.device("default.qubit", wires=1) @qml.qnode(dev) def circuit(): qml.Hadamard(0) m = qml.measure(0, postselect=1) return qml.probs(wires=0)
>>> circuit() tensor([0., 1.], requires_grad=True)
-
Mid-circuit measurement statistics can be obtained from QNode returns:
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)
>>> 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 and devices default to using the deferred measurement principle to enact the mid-circuit measurements.
In future releases, we will be exploring the ability to combine and manipulate mid-circuit
measurements such as qml.expval(m0 @ m1)
or qml.expval(m0 @ qml.PauliZ(0))
.
Stay tuned!
Flexible Trotter products π
Want better Trotter decomposition functionality? Fright this way π±

With this release, we're putting some points into Hamiltonian simulation techniques that are based on Trotterization.
-
Higher-order SuzukiβTrotter methods are now easily accessible through a new operation called
TrotterProduct
. The SuzukiβTrotter product formula allows for the ability to express higher-order approximations to the matrix exponential of a Hamiltonian, letting you use Trotterization techniques as an effective route towards accurate and efficient Hamiltonian simulation. Simply specify theorder
of the approximation and the evolutiontime
: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()
>>> circuit() [-0.13259524+0.59790098j 0. +0.j -0.13259524-0.77932754j 0. +0.j ]
-
The quantum stochastic drift protocol for approximating matrix exponentiation with random product formulas, qDrift, is now available with the new
QDrift
operation. As shown in 1811.08017, 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 theQDrift
operator. Simply specify the evolutiontime
and the number of samples drawn from the Hamiltonian,n
: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()
>>> circuit() array([0.61814334, 0. , 0.38185666, 0. ])
Pulse programming with OQC hardware βοΈπ¬
PennyLane-Braket is creepinβ it real π

Now you can run pulse-level circuits on the 8-qubit Lucy device from Oxford Quantum Circuits (OQC). This new hardware support is provided through the Amazon Braket service, so you'll need to install the PennyLane-Braket plugin to get it up and running. Once you're ready, head on over to our hot-off-the-press Pulse programming demo to learn more!
This release of PennyLane concludes our year-long push to add pulse-level support to PennyLane π. We started in v0.29 with pulse-based circuits and simulation and then unlocked hardware support on QuEra in v0.30. Have you enjoyed working with pulse programs in PennyLane or has it been a nightmare? π± Would you like to see more pulse support in 2024? Let us know by filling out our PennyLane user survey!
Modular Quantum Phase Estimation π§©
Create zombified QPE algorithms by stitching together these new features π§

Quantum phase estimation (QPE) is a staple quantum algorithm, and recent research has delivered some new ways of looking at it by way of modifications to bits and pieces of the algorithm at large. Motivated by these advancements, we've added two new operators that facilitate the modularization of QPE and more!
-
Controlled gate sequences raised to decreasing powers, a sub-block in QPE, can now be created with the new
ControlledSequence
operator. Applying sequences of controlled unitary operations raised to decreasing powers is a key part in QPE. The newControlledSequence
operator allows for the ability to create just this part of the algorithm.To use
ControlledSequence
, specify the controlled unitary operator and the control wires,control
: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))
>>> print(circuit()) [0.92059345 0.02637178 0.00729619 0.00423258 0.00360545 0.00423258 0.00729619 0.02637178]
-
A new operator called
CosineWindow
has been added to prepare an initial state based on a cosine wave function. As outlined in 2110.09590, the cosine tapering window is part of a modification to QPE that can provide a cubic improvement to the algorithm's error rate. UsingCosineWindow
will prepare a state whose amplitudes follow a cosinusoidal distribution over the computational basis.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()
New device capabilities, Catalyst integration, and more! βοΈ
We think these new device changes are fang-tastic π¦·
With this v0.33 release, default.qubit
has been totally revamped to use our new qml.devices.Device
API
and functionality in qml.devices.qubit
. This change has several benefits, most
notably that 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.
dev = qml.device("default.qubit") # no wires specified! @qml.qnode(dev) def circuit(): qml.PauliZ(0) qml.RZ(0.1, wires=1) qml.Hadamard(2) return qml.state()
>>> print(qml.draw(circuit)()) 0: ββZβββββββββ€ State 1: ββRZ(0.10)ββ€ State 2: ββHβββββββββ€ State
If you experience any issues with the updated default.qubit
, please let us
know by posting an issue.
The old version of the device is still accessible by the short name default.qubit.legacy
,
or directly via qml.devices.DefaultQubitLegacy
.
Improvements π οΈ
In addition to the new features listed above, the release contains a wide array of improvements and optimizations:
-
A QNode that has been decorated with
qjit
from PennyLane's Catalyst library for just-in-time hybrid compilation is now compatible withqml.draw
. -
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.Check out our how-to guide to learn more about how PennyLane integrates with your favourite quantum chemistry libraries.
-
MeasurementProcess
andQuantumScript
objects are now registered as JAX PyTrees. It is now possible to JIT-compile functions with arguments that are aMeasurementProcess
or aQuantumScript
. -
qml.cut_circuit
is now compatible with circuits that compute the expectation values of Hamiltonians with two or more terms.
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:
-
The old return type and associated functions
qml.enable_return
andqml.disable_return
have been removed. -
qml.defer_measurements
now raises an error if a transformed circuit measuresqml.probs
,qml.sample
, orqml.counts
without any wires or observable, or if it measuresqml.state
. -
Using
==
with operators and measurement processes will now behave the same asqml.equal
.op1 = qml.PauliX(0) op2 = qml.PauliX(0) op3 = op1
>>> op1 == op2 True >>> op1 == op3 True
These highlights are just scratching the surface β check out the full release notes for more details, and let us know how you're liking the new release in the PennyLane v0.33 survey.
Contributors βοΈ
As always, this release would not have been possible without the hard work of our development team and contributors:
Guillermo Alonso, Ali Asadi, Utkarsh Azad, Thomas Bromley, Isaac De Vlugt, Jack Brown, Amintor Dusko, Tarik El-Khateeb, 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, Shuli Shu, Matthew Silverman, Jay Soni.
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 π€