May 07, 2024
PennyLane v0.36 and Catalyst v0.6 released
.png)
Warmer weather, a cold beverage, birds chirping — it's not just spring, it's new versions of PennyLane and Catalyst 😎. PennyLane v0.36 and Catalyst v0.6 are here! Check out the new features below.
Contents
- Estimate errors in a quantum circuit 🧮
- Access an extended arsenal of quantum algorithms 🏹
- Catalyst qjit callback support 📞
- Make use of more methods to map from molecules 🗺️
- Qiskit 1.0 device support 🎉
- Calculate dynamical Lie algebras 👾
- Run Catalyst on Oxford Quantum Circuits' (OQC) superconducting hardware
- Improvements 🛠️
- Deprecations and breaking changes 💔
- Contributors ✍️
Estimate errors in a quantum circuit 🧮
How good is your approximation 🔮? PennyLane will tell you 🧙
This version of PennyLane lays the foundation for estimating the total error in a quantum circuit from the combination of individual gate errors. Two new user-facing classes enable calculating and propagating gate errors in PennyLane:
-
qml.resource.SpectralNormError
: the spectral norm error is defined as the distance, in spectral norm, between the true unitary we intend to apply and the approximate unitary that is actually applied. -
qml.resource.ErrorOperation
: a base class that inherits fromqml.operation.Operation
and represents quantum operations which carry some form of algorithmic error.
SpectralNormError
is the key tool to specify errors in larger quantum circuits:
-
For operations representing a major building block of an algorithm, we can create a custom operation that inherits from
ErrorOperation
. This child class must override theerror
method and should return aSpectralNormError
instance:import pennylane as qml from pennylane.resource import ErrorOperation, SpectralNormError class MyErrorOperation(ErrorOperation): def __init__(self, error_val, wires): self.error_val = error_val super().__init__(wires=wires) def error(self): return SpectralNormError(self.error_val)
In this toy example,
MyErrorOperation
introduces an arbitrarySpectralNormError
when called in a QNode. It does not require a decomposition or matrix representation when used withnull.qubit
(suggested for use with resource and error estimation since circuit executions are not required to calculate resources or errors).dev = qml.device("null.qubit") @qml.qnode(dev) def circuit(): MyErrorOperation(0.1, wires=0) MyErrorOperation(0.2, wires=1) return qml.state()
The total spectral norm error of the circuit can be calculated using
qml.specs
:>>> qml.specs(circuit)()['errors'] {'SpectralNormError': SpectralNormError(0.30000000000000004)}
-
PennyLane already includes a number of built-in building blocks for algorithms like
QuantumPhaseEstimation
andTrotterProduct
.TrotterProduct
now propagates errors based on the number of steps performed in the Trotter product.QuantumPhaseEstimation
now propagates errors based on the error of its input unitary.hamiltonian = qml.dot([1.0, 0.5, -0.25], [qml.X(0), qml.Y(0), qml.Z(0)]) @qml.qnode(dev) def circuit(): qml.TrotterProduct(hamiltonian, time=0.1, order=2) qml.QuantumPhaseEstimation( MyErrorOperation(0.01, wires=0), estimation_wires=[1, 2, 3] ) return qml.state()
Again, the total spectral norm error of the circuit can be calculated using
qml.specs
:>>> qml.specs(circuit)()["errors"] {'SpectralNormError': SpectralNormError(0.07616666666666666)}
Check out our error propagation demo to see how to use these new features in a real-world example!
Access an extended arsenal of quantum algorithms 🏹
Make some room on your tool belt for these new features 🧰
.png)
The last few releases have introduced several templates and operators that are useful subroutines to
have when working on quantum algorithms (e.g.,
qml.CosineWindow
and
qml.iterative_qpe
).
In this release, we've added a few new templates so that your prototyping and researching is
seamless in PennyLane.
-
qml.AmplitudeAmplification
: a high-level interface for amplitude amplification (based on arXiv:quant-ph/0005055).Given a state \vert \Psi \rangle = \alpha \vert \phi \rangle + \beta \vert \phi^{\perp} \rangle,
qml.AmplitudeAmplification
amplifies the amplitude of \vert \phi \rangle.Here's an example with a target state \vert \phi \rangle = \vert 2 \rangle = \vert 010 \rangle, an input state \vert \Psi \rangle = H^{\otimes 3} \vert 000 \rangle, and an oracle that flips the sign of \vert \phi \rangle and does nothing to \vert \phi^{\perp} \rangle, which can be achieved in this case through
qml.FlipSign
.import numpy as np @qml.prod def generator(wires): for wire in wires: qml.Hadamard(wires=wire) U = generator(wires=range(3)) O = qml.FlipSign(2, wires=range(3)) dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(): generator(wires=range(3)) # prepares |Psi> = U|0> qml.AmplitudeAmplification(U, O, iters=10) return qml.probs(wires=range(3))
>>> print(np.round(circuit(), 3)) [0.01 0.01 0.931 0.01 0.01 0.01 0.01 0.01 ]
As expected, we amplify the \vert 2 \rangle state. Dive deeper into how this works with our new amplitude amplification tutorial.
-
qml.Qubitization
: the qubitization subroutine encodes a Hamiltonian into a suitable unitary operator. When applied in conjunction with quantum phase estimation (QPE), it allows for computing the eigenvalue of an eigenvector of the given Hamiltonian. -
qml.FABLE
: the Fast Approximate BLock-Encodings (FABLE) algorithm for embedding a matrix into a quantum circuit (based on arXiv:2205.00081). -
qml.Reflection
: reflect about a given quantum state. This operation is very useful in the amplitude amplification algorithm and offers a generalization ofqml.FlipSign
, which only operates on basis states.
Catalyst qjit callback support 📞
Don't leave a voicemail, just callback 👏
.png)
Catalyst now supports externally hosted callbacks within qjit-compiled code. This provides the ability to insert native Python code into any qjit-compiled function! Use callbacks to enhance the debugging experience, or to include subroutines that do not yet support qjit-compilation.
@pure_callback def callback_fn(x) -> float: print("Value of x =", x) return np.sin(x)
Here, we call non-JAX-compatible code, such as standard NumPy and Python print statements. But we can still qjit!
@qjit def fn(x): return jnp.cos(callback_fn(x ** 2))
>>> fn(0.654) Value of x = 0.427716 array(0.9151995)
For more details, see the
catalyst.pure_callback
and
catalyst.debug.callback
function documentation.
Make use of more methods to map from molecules 🗺️
Jordan–Wigner or Bravyi–Kitaev? The choice is yours 👌
.png)
A new function called
qml.bravyi_kitaev
has been added to perform the Bravyi–Kitaev mapping of fermionic Hamiltonians
to qubit Hamiltonians. This function presents an alternative mapping to
qml.jordan_wigner
or
qml.parity_transform
which can help us measure expectation values more efficiently on hardware.
Simply provide a fermionic Hamiltonian (created from from_string
, FermiA
, FermiC
,
FermiSentence
, or FermiWord
) and the number of qubits or spin orbitals in the system, n
:
>>> fermi_ham = qml.fermi.from_string('0+ 1+ 1- 0-') >>> qubit_ham = qml.bravyi_kitaev(fermi_ham, n=6, tol=0.0) >>> print(qubit_ham) 0.25 * I(0) + -0.25 * Z(0) + -0.25 * (Z(0) @ Z(1)) + 0.25 * Z(1)
Still feeling a bit lost? Find your bearings with a new demonstration of mapping fermionic operators to qubit operators.
Qiskit 1.0 device support 🎉
Use PennyLane with your favourite Qiskit 1.0 devices and backends 💪

In our last release, we kicked off integration with Qiskit 1.0 by improving our circuit conversion functionality. Now, we're finishing the job by making our plugin devices compatible, so that you can now submit to the latest backends using Qiskit 1.0—all from the comfort of PennyLane 🛋️.
Simply pip install -U pennylane-qiskit
to access these new features! And stay tuned
for even more support in upcoming releases, where we'll be refreshing our integration
with runtimes and
primitives.
Calculate dynamical Lie algebras 👾
We're not Lie-ing about this new feature 🤠
.png)
The dynamical Lie algebra (DLA) of a set of operators captures the range of unitary evolutions that the operators can generate. In v0.36 of PennyLane, we have added support for calculating important DLA concepts:
qml.lie_closure
: computes the Lie closure of a list of operators, providing one way to obtain the DLA (see e.g. section IIB of arXiv:2308.01432).qml.structure_constants
: computes the structure constants of a DLA.qml.center
: computes the centre of a DLA withqml.center
.
Here's an example with
qml.lie_closure
.
For a list of operators ops = [op1, op2, op3, ..]
, one computes all nested commutators between
ops
until no new operators are generated from commutation.
>>> from pennylane import X, Y, Z >>> ops = [X(0) @ X(1), Z(0), Z(1)] >>> dla = qml.lie_closure(ops) >>> dla [1.0 * X(1) @ X(0), 1.0 * Z(0), 1.0 * Z(1), -1.0 * X(1) @ Y(0), -1.0 * Y(1) @ X(0), -1.0 * Y(1) @ Y(0)]
To help explain these concepts, check out the dynamical Lie algebras demo.
Run Catalyst on Oxford Quantum Circuits' (OQC) superconducting hardware
Catalyst now supports QNodes that execute on Oxford Quantum Circuits (OQC)
superconducting hardware, via OQC Cloud. To use OQC Cloud with Catalyst
and @qjit
, simply ensure your credentials are set as environment variables, and load the
oqc.cloud
device to be used within your qjit-compiled workflows.
import os import catalyst os.environ["OQC_EMAIL"] = "your_email" os.environ["OQC_PASSWORD"] = "your_password" os.environ["OQC_URL"] = "oqc_url" device = qml.device("oqc.cloud", backend="lucy", shots=2012, wires=2) @catalyst.qjit @qml.qnode(device=device) def circuit(a: float): qml.Hadamard(0) qml.CNOT(wires=[0, 1]) qml.RX(wires=0) return qml.counts(wires=[0, 1])
Improvements 🛠️
In addition to the new features listed above, the release contains a wide array of improvements and external contributions:
-
Mixed qutrit states can now be simulated with the
"default.qutrit.mixed"
device thanks to contributors from the University of British Columbia! This provides a noise-capable equivalent to"default.qutrit"
. However, there's one crucial ingredient that we still need to add: support for qutrit noise operations. Keep your eyes peeled for this to arrive in the coming releases! -
A new PennyLane-Snowflurry plugin is available. Developed by Calcul Québec in collaboration with École de technologie supérieure (ÉTS), the plugin allows you to run PennyLane circuits using the open-source and Julia-based Snowflurry package as a backend. Snowflurry is developed by Anyon and provides access to their hardware devices.
After following the set up instructions, you can load a device in the usual way:
dev = qml.device("snowflurry.qubit", wires=2)
This is a work-in-progress device, so stay tuned for a more advanced demonstration from the Calcul Québec team later in the year!
-
Native hardware-like mid-circuit measurements can now be carried out in
"lightning.qubit"
and"lightning.kokkos"
, following our recently-added support for"default.qubit"
in the last release.Learn more about mid-circuit measurements and dynamic circuits with our latest demos!
dev = qml.device("lightning.qubit", wires=2) @qml.qnode(dev) def circuit(): qml.Hadamard(0) m0 = qml.measure(0) qml.cond(m0 == 1, qml.RX)(np.pi / 4, wires=1) return qml.expval(qml.Z(1))
>>> circuit() array(0.85355339)
-
The
"lightning.qubit"
device now tries to calculate gradients using the adjoint differentiation method. This method has a similar runtime to backpropagation and a lower memory overhead, so you can rest assured that PennyLane and Lightning are running fast-by-default.Moreover, you can now request
"lightning.qubit"
to calculate vector-Jacobian products (VJPs) by settingdevice_vjp=True
when instantiating your QNode, which can result in even faster computations when the output of your calculation has a low dimension. -
You can now easily find the stable release news in the aptly-named "Release News" section in the sidebar of the documentation!
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:
-
This release completes the main phase of PennyLane's switchover to an updated approach for handling arithmetic operations between operators. The new approach is now enabled by default and is intended to realize a few objectives:
- To make it as easy to work with PennyLane operators as it would be with pen and paper.
- To improve the efficiency of operator arithmetic.
In many cases, this update should not break code. If issues do arise, check out the updated operator troubleshooting page and don't hesitate to reach out to us on the PennyLane Discussion Forum. As a last resort the old behaviour can be enabled by calling
qml.operation.disable_new_opmath()
, but this is not recommended because support will not continue in future PennyLane versions going forward. -
qml.matrix()
called on the following will now raise an error ifwire_order
is not specified:- Tapes with more than one wire;
- Quantum functions;
Operator
classes wherenum_wires
does not equal to 1;- QNodes if the device does not have wires specified;
PauliWord
s andPauliSentence
s with more than one wire.
-
single_tape_transform
,batch_transform
,qfunc_transform
,op_transform
,gradient_transform
andhessian_transform
have been removed. Instead, switch to using the newqml.transform
function. Please refer to the transform docs to see how this can be done.
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:
Tarun Kumar Allamsetty, Guillermo Alonso, Mikhail Andrenkov, Ali Asadi, Utkarsh Azad, Gabriel Bottrill, Thomas Bromley, Astral Cai, Diksha Dhawan, Isaac De Vlugt, Amintor Dusko, Tarik El-Khateeb, Pietropaolo Frisoni, Lillian M. A. Frederiksen, Thomas Germain, Diego Guala, Austin Huang, David Ittah, Soran Jahangiri, Korbinian Kottmann, Ivana Kurečić, Christina Lee, Vincent Michaud-Rioux, Sergei Mironov, Romain Moyard, Erick Ochoa Lopez, Lee James O'Riordan, Mudit Pandey, Kenya Sakka, Shuli Shu, Matthew Silverman, Jay Soni, Muzammiluddin Syed, David Wierichs.
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 🤠
Diego Guala
Diego is a quantum scientist at Xanadu. His work is focused on supporting the development of the datasets service and PennyLane features.
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.