PennyLane
Install
Install
  1. Blog/
  2. Releases/
  3. Assemble meaningful algorithms with PennyLane v0.45 and Catalyst v0.15

May 13, 2026

Assemble meaningful algorithms with PennyLane v0.45 and Catalyst v0.15

Anton Naim Ibrahim

Anton Naim Ibrahim

Isaac De Vlugt

Isaac De Vlugt

Gabriela Sanchez Diaz

Gabriela Sanchez Diaz

v0.45

PennyLane v0.45 and Catalyst v0.15 have arrived to help you assemble your fault-tolerant quantum algorithms ๐Ÿช›

With this release, you can plan out your workflow with ease via application-focused state preparations and operations, put your compilation pipeline together using various transforms and pre-defined gate sets, and admire your finished creation through comprehensive workflow inspection tools! We'll take you through an end-to-end example where we build an algorithm for quantum arithmetic.

If you want to put yourself to the test with our newest tools, take our release Coding Challenge all about resource estimation โ€” a versatile tool powering the latest research in quantum computing! Complete the challenge and receive an exclusive badge on your PennyLane profile.

If exploring these new features and tackling the coding challenges has you eager for more, make sure you never miss an update. We're launching the official PennyLane newsletter! Sign up here to stay in the loop, and weโ€™ll keep you posted whenever we have something special in the works โ€” whether it's cutting-edge features, fresh research results, or new events.

Contents

  • Planning out your algorithm ๐Ÿ“‹
  • Putting the pieces together ๐Ÿ”ง
  • Admiring the final product ๐Ÿ“ท
  • Deprecations and breaking changes โค๏ธโ€๐Ÿฉน
  • Community Contributions ๐Ÿซถ
  • Contributors โœ๏ธ

Planning out your algorithm ๐Ÿ“‹

Just got all the materials... but where do you even start? ๐Ÿ˜ต

Planning out your algorithm

Building up a useful algorithm isn't easy, and the first things you'll be looking for are the right building blocks. If you want to quickly get an idea of your algorithm's cost before writing the whole thing, our resource estimation tools are just what you need. You can now easily estimate the resources of BasisEmbedding, SelectOnlyQRAM, and HybridQRAM, with our qp.estimator module.

Here's an example showing how to estimate the resources of HybridQRAM and SelectOnlyQRAM, where the data we wish to read and access is a list of length-3 bitstrings:

import pennylane as qp
import pennylane.estimator as qre

num_select_wires = 2
num_control_wires = 3

data = ["010", "111", "110", "000", "010", "111", "110", "000"]
bitstring_size = 3

gate_set = {"T", "CNOT", "S", "Hadamard", "RZ", "GlobalPhase", "MidMeasure"}

select_qram_res = qre.estimate(
    qre.SelectOnlyQRAM(data, num_wires=bitstring_size+num_control_wires, num_control_wires=num_control_wires, num_select_wires=num_select_wires), gate_set=gate_set
)
hybrid_qram_res = qre.estimate(
    qre.HybridQRAM(data, num_wires=bitstring_size+num_control_wires, num_control_wires=num_control_wires, num_select_wires=num_select_wires), gate_set=gate_set
)
>>> print("SelectOnlyQRAM:", select_qram_res.total_gates, "\nHybridQRAM:", hybrid_qram_res.total_gates)
SelectOnlyQRAM: 1256 
HybridQRAM: 6058

With these particular parameters, SelectOnlyQRAM is the more efficient option ๐Ÿ‘.

When you're ready to write your algorithm, we have plenty of new application-focused functionality at your disposal. For algorithms requiring a high quality initial state, like in quantum chemistry applications, a new state of the art state preparation method qp.SumOfSlatersPrep is now available, which is introduced in Fomichev et al., PRX Quantum 5, 040339 (see the related demo). This state preparation technique is shown to lower resource costs by several orders of magnitude when compared with the best single product state ansatz.

Another versatile tool is the Quantum Singular Value Transformation (QSVT), known for its broad applicability from Hamiltonian simulation to solving linear systems of equations. If you're repeatedly computing the angles needed for QSVT with high-degree polynomials, you can now leverage the new iterative-optax angle solver in qp.qsvt and qp.poly_to_angles for a significant performance boost.

Putting the pieces together ๐Ÿ”ง

I hope you're starting to see the vision ๐Ÿง

Putting the pieces together

You've got the pieces laid out, now it's time to grab your tools and put them all together. Quantum compilation is a key component of algorithm development, taking your workflow from a high-level representation to one that can actually be passed to hardware. The CompilePipeline class allows you to sequentially and functionally define the sequence of transforms to apply to your circuit, and assembling one is now easier than ever. You can add a marker directly using the add_marker function, and the CompilePipeline now better displays your transforms and markers, so you can keep track of exactly what's happening to your program during compilation.

And if you're interested in optimizing your algorithm, our graph-based decomposition system (enabled via enable_graph()) is able to find the most resource-efficient decompositions available for your target gate set. You can find pre-defined gate sets in the recently added gate_sets module to start experimenting.

Let's put some of these features to the test! First, let's create a CompilePipeline that we'll use later on to compile a circuit comprising SelectOnlyQRAM and arithmetic operations.

qp.decomposition.enable_graph()

pipeline = qp.CompilePipeline()
pipeline += qp.decompose(gate_set=gate_set, minimize_work_wires=True)
pipeline += qp.transforms.combine_global_phases
pipeline.add_marker("after decomp + global phase")
pipeline += (qp.transforms.cancel_inverses(recursive=True) + qp.transforms.merge_rotations) * 2
pipeline.add_marker("after cancel + merge")
>>> pipeline
CompilePipeline(
  [1] decompose(gate_set=..., minimize_work_wires=True),
  [2] combine_global_phases(),
   โ”œโ”€โ–ถ after decomp + global phase
  [3] cancel_inverses(recursive=True),
  [4] merge_rotations(),
  [5] cancel_inverses(recursive=True),
  [6] merge_rotations()
   โ””โ”€โ–ถ after cancel + merge
)

Now let's set up some arithmetic operations. We're going to prepare two integers, x and y, and perform x \times (x + y) \texttt{ mod } 8. To perform addition we'll use SemiAdder, and for multiplication we'll use OutMultiplier. In this example, we'll set x = 3 and y = 4. The end result should be 21 \texttt{ mod } 8 = 5.

To represent x and y in a quantum circuit, we will need 2 and 3 wires, respectively.

x = 3 # |11>
y = 4 # |100>
mod = 8

wires = qp.registers({
    "x": 2,
    "y": 3,
    "intermediate_result": num_control_wires, # will store |x + y>
    "final_result": bitstring_size, # will store |21 mod 8 = 5>
    "work_wires": 2,
})

def add_mult():

    qp.SemiAdder(wires["x"], wires["y"], wires["work_wires"]) # |x> |y> --> |x> |x+y> = |3> |7>
    qp.OutMultiplier(
        wires["x"],
        wires["y"],
        wires["intermediate_result"],
        mod,
        wires["work_wires"] # only needs 2 work wires
    ) # |x> |x+y> |0> --> |x> |x+y> |0 + x * (x + y) mod 8> = |3> |7> |5>

We're trusting the decompose transform to optimize the resources of the circuit, but how can we understand what it's doing? You can now easily inspect decompositions with the new decomp_inspector() function, which analyzes the decomposition graph and tells you how your algorithm was decomposed, and why particular decompositions were chosen for your operators!

Let's see how SemiAdder will be decomposed with the gate_set used in the previous code snippet using the decomp_inspector ๐Ÿ‘€:

>>> inspector = qp.decomp_inspector(add_mult, gate_set=gate_set, minimize_work_wires=True)()
>>> inspector.inspect_decomps(qp.SemiAdder(wires["x"], wires["y"], wires["work_wires"]))
CHOSEN: Decomposition 0 (name: _semiadder)
 0: โ”€โ”€โ”€โ”€โ•ญXโ”€โ”€โ”€โ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ—โ•ฎโ”€โ•ญXโ”€โ•ญโ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
 1: โ”€โ•ญโ—โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ—โ•ฎโ”€โ•ญโ—โ”€โ”ค
 2: โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ•ญXโ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”‚โ”€โ”‚โ”€โ”€โ”ค
 3: โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ•ญXโ”€โ”œโ—โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ—โ”คโ”€โ”‚โ”€โ”€โ•ฐXโ”€โ”€โ”€โ”‚โ”€โ”‚โ”€โ”€โ”ค
 4: โ”€โ”œโ—โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ—โ”คโ”€โ•ฐXโ”€โ”ค
11: โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ”‚โ”€โ”€โ•ฐโŠ•โ”€โ•ญXโ”€โ•ฐโ—โ”€โ•ญXโ”€โ”€โŠ•โ•ฏโ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”ค
12: โ”€โ•ฐโŠ•โ”€โ•ฐโ—โ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ”€โ•ฐโ—โ”€โ”€โ”€โ”€โ”€โŠ•โ•ฏโ”€โ”€โ”€โ”€โ”ค
First-Level Expansion Gates: {TemporaryAND: 2, Adjoint(TemporaryAND): 2, CNOT: 8}
Full Expansion Gates: {CNOT: 16, MidMeasure: 2, Hadamard: 26, GlobalPhase: 14, RZ: 14, T: 4}
Weighted Cost: 76.0

Here we also used the inspect_decomps() function, which displays how an operator would be decomposed using available decomposition rules. We can see both the structure and the resource cost of the chosen decomposition.

Admiring the final product ๐Ÿ“ท

All in an honest day's work ๐Ÿคฉ

Admiring the final product

Now that you've built up your algorithm, it's time to take a close look at how it turned out, and make sure everything lines up as expected.

specs is your go-to for analyzing the resources of your compiled program. With specs, you can:

  • Easily step in at any stage of compilation with the level argument, which also conveniently accepts the markers you added to your CompilePipeline.
  • For qjit-d circuits you can now easily see how the resources of your program evolved throughout compilation with a tabular display, showing resources of each level side-by-side. To try it out, use pass-by-pass mode by setting level="all" for your qjit-d circuit.

You'll also enjoy significant speedups for large workflows (we've seen up to 10x!), as the implementation behind specs has been improved for better integration with Catalyst.

Let's put everything together! We can take the result of the arithmetic operations, 5, to access the fifth (zero-indexed) entry of the data in the previous code snippet: "111".

def state_prep(): # |x> |y> = |3> |4>
    qp.BasisState(x, wires=wires["x"])
    qp.BasisState(y, wires=wires["y"])

dev = qp.device("default.qubit")

@qp.set_shots(1)
@pipeline
@qp.qnode(dev)
def circuit():

    state_prep()
    add_mult()

    qp.SelectOnlyQRAM(
        data,
        control_wires=wires["intermediate_result"],
        target_wires=wires["final_result"],
    )

    return qp.sample(wires=wires["final_result"])
>>> circuit()
array([[1, 1, 1]])
>>> qp.specs(circuit, level="after decomp + global phase")().resources.gate_counts
{'Hadamard': 234, 'RZ': 792, 'T': 100, 'CNOT': 950, 'MidMeasureMP': 2, 'Conditional(Hadamard)': 4, 'Conditional(CNOT)': 2, 'GlobalPhase': 1}
>>> qp.specs(circuit, level="after cancel + merge")().resources.gate_counts
{'Hadamard': 194, 'RZ': 783, 'T': 100, 'CNOT': 800, 'MidMeasureMP': 2, 'Conditional(Hadamard)': 4, 'Conditional(CNOT)': 2, 'GlobalPhase': 1}

As we can see, we recover the fifth entry in data, where we can see the final gate-count tally with specs.

Resources are one thing, but the structure of your algorithm another. draw and draw_mpl let you see how your circuit is wired up at any level. You can now also access Catalyst's draw_graph from PennyLane for a different mode of visualization โ€” a graphical representation which preserves the structure of your program.

Let's draw our circuit to see what we've built:

>>> print(qp.draw(circuit, level="top", show_matrices=False)())
 0: โ”€โ•ญ|ฮจโŸฉโ”€โ•ญSemiAdderโ”€โ•ญOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
 1: โ”€โ•ฐ|ฮจโŸฉโ”€โ”œSemiAdderโ”€โ”œOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
 2: โ”€โ•ญ|ฮจโŸฉโ”€โ”œSemiAdderโ”€โ”œOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
 3: โ”€โ”œ|ฮจโŸฉโ”€โ”œSemiAdderโ”€โ”œOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
 4: โ”€โ•ฐ|ฮจโŸฉโ”€โ”œSemiAdderโ”€โ”œOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
 5: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œOutMultiplierโ”€โ•ญSelectOnlyQRAM(M0)โ”€โ”ค        
 6: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œOutMultiplierโ”€โ”œSelectOnlyQRAM(M0)โ”€โ”ค        
 7: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œOutMultiplierโ”€โ”œSelectOnlyQRAM(M0)โ”€โ”ค        
 8: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œSelectOnlyQRAM(M0)โ”€โ”ค โ•ญSample
 9: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”œSelectOnlyQRAM(M0)โ”€โ”ค โ”œSample
10: โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐSelectOnlyQRAM(M0)โ”€โ”ค โ•ฐSample
11: โ”€โ”€โ”€โ”€โ”€โ”€โ”œSemiAdderโ”€โ”œOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
12: โ”€โ”€โ”€โ”€โ”€โ”€โ•ฐSemiAdderโ”€โ•ฐOutMultiplierโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค

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 NumPy 1.x has been dropped entirely following its end-of-life. NumPy 2.0 or higher is now required.
  • The custom_decomps keyword argument to qp.device has been removed. Instead, with the graph decomposition system, new decomposition rules can be defined as quantum functions with registered resources. See the pennylane.decomposition module for more details.
  • The gate_set argument in qp.decompose no longer takes a function and only expects a sequence of operator types and/or names. Functions should be passed to the stopping_condition argument instead.

These highlights are just scratching the surface โ€” check out the full release notes for PennyLane and Catalyst for more details.

Community Contributions ๐Ÿซถ

A lot of great contributions to PennyLane have come from our community recently (that's you)!

Here are just a few of them:

  • Various contributions to our open-source software from Olivia Di Matteo, Oumarou Oumarou, Roberto Turrado Camblor, Nate Stemen, Omkar Sarkar, huhu37, and jk20342!
  • A demo by Andrew Nader: Before you train: Pre-screening quantum kernels with geometric difference!
  • Three new Community Demos on quantum signal processing, quantum error correction, and quantum re-uploading!
  • Artistic unitaryDESIGN contributions โ€” see our unitaryDESIGN blog post highlighting them!

Contributors โœ๏ธ

As always, this release would not have been possible without the hard work of our development team and contributors:

Runor Agbaire, Guillermo Alonso, Ali Asadi, Astral Cai, Joey Carter, Yushao Chen, Isaac De Vlugt, Diksha Dhawan, Olivia Di Matteo, Marcus Edwards, Tarik El-Khateeb, Ashley Enman, Lillian Frederiksen, Thomas Germain, Diego Guala, Sengthai Heng, David Ittah, Josh Izaac, Jeffrey Kam, Ashish Kanwar Singh, Jacob Kitchen, Korbinian Kottmann, Christina Lee, Joseph Lee, Mehrdad Malekmohammadi, River McCubbin, Sofia Mosina, Anton Naim Ibrahim, Luis Alfredo Nuรฑez Meneses, Lee J. O'Riordan, Oumarou Oumarou, Mudit Pandey, Andrija Paurevic, Alex Preciado, David D.W. Ren, Gabriela Sanchez Diaz, Omkar Sarkar, Shuli Shu, Jay Soni, Nate Stemen, Paul Haochen Wang, David Wierichs, Fuyuan Xia, Jake Zaia, Hong-Sheng Zheng.

Remember to try out our Coding Challenge for an exclusive badge, and sign up for our newsletter to stay in-the-know all things PennyLane!

About the authors

Anton Naim Ibrahim
Anton Naim Ibrahim

Anton Naim Ibrahim

Physicist and Product Manager. Exploring uncharted territory.

Isaac De Vlugt
Isaac De Vlugt

Isaac De Vlugt

Isaac is a computational physicist and black-belt emoji spammer. At Xanadu, he devises strategies and roadmaps for future and current PennyLane & Catalyst features.

Gabriela Sanchez Diaz
Gabriela Sanchez Diaz

Gabriela Sanchez Diaz

Last modified:ย May 13, 2026

Related Blog Posts

PennyLane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Built by researchers, for research. Created with โค๏ธ by Xanadu.

Research

  • Research
  • Performance
  • Hardware & Simulators
  • Demos
  • Compilation Hub
  • Quantum Datasets

Education

  • Teach
  • Learn
  • Codebook
  • Coding Challenges
  • Videos
  • Glossary

Software

  • Install PennyLane
  • Features
  • Documentation
  • Catalyst Compilation Docs
  • Development Guide
  • API
  • GitHub
Stay updated with our newsletter

ยฉ Copyright 2026 | 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