PennyLane
  • Why PennyLane
  • Getting Started
  • Documentation
  • Ecosystem
Install
Install
  1. Blog/
  2. Releases/
  3. PennyLane v0.36 and Catalyst v0.6 released

May 07, 2024

PennyLane v0.36 and Catalyst v0.6 released

Isaac De Vlugt

Isaac De Vlugt

Thomas Bromley

Thomas Bromley

Diego Guala

Diego Guala

Josh Izaac

Josh Izaac

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 🧙

PL0.36_ErrorAnimation_(blog)

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 from qml.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 the error method and should return a SpectralNormError 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 arbitrary SpectralNormError when called in a QNode. It does not require a decomposition or matrix representation when used with null.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 and TrotterProduct. 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 🧰

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 of qml.FlipSign, which only operates on basis states.

Catalyst qjit callback support 📞

Don't leave a voicemail, just callback 👏

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 👌

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 🤠

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 with qml.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 setting device_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:

    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.

    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 if wire_order is not specified:

    • Tapes with more than one wire;
    • Quantum functions;
    • Operator classes where num_wires does not equal to 1;
    • QNodes if the device does not have wires specified;
    • PauliWords and PauliSentences with more than one wire.
  • single_tape_transform, batch_transform, qfunc_transform, op_transform, gradient_transform and hessian_transform have been removed. Instead, switch to using the new qml.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
Isaac De Vlugt

Isaac De Vlugt

My job is to help manage the PennyLane and Catalyst feature roadmap... and spam lots of emojis in the chat 🤠

Thomas Bromley
Thomas Bromley

Thomas Bromley

Diego Guala
Diego Guala

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 Izaac

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.

Last modified: August 14, 2024

Related Blog Posts

PennyLane

PennyLane is an open-source software framework for quantum machine learning, quantum chemistry, and quantum computing, with the ability to run on all hardware. Built with ❤️ by Xanadu.

Stay updated with our newsletter

For researchers

  • Research
  • Features
  • Demos
  • Compilation
  • Datasets
  • Performance
  • Learn
  • Videos
  • Documentation
  • Teach

For learners

  • Learn
  • Codebook
  • Teach
  • Videos
  • Challenges
  • Demos
  • Compilation
  • Glossary

For developers

  • Features
  • Documentation
  • API
  • GitHub
  • Datasets
  • Demos
  • Compilation
  • Performance
  • Devices
  • Catalyst

© Copyright 2025 | Xanadu | All rights reserved

TensorFlow, the TensorFlow logo and any related marks are trademarks of Google Inc.

Privacy Policy|Terms of Service|Cookie Policy|Code of Conduct