PennyLane
Install
Install

Related materials

  • Related contentIntro to QSVT
  • Related contentHow to estimate the resource requirements of quantum algorithms
  • Related contentQSVT in Practice

Contents

  1. Estimating the cost of QSVT
    1. Resources from an Executable Workflow
    2. Resources from an Estimator Workflow
  2. Conclusion
  3. References
  4. About the author

Downloads

  • Download Python script
  • Download Notebook
  • View on GitHub
  1. Demos/
  2. Algorithms/
  3. How to use PennyLane’s quantum resource estimator module for QSVT

How to use PennyLane’s quantum resource estimator module for QSVT

Jay Soni

Jay Soni

Published: January 30, 2026. Last updated: January 30, 2026.

The Quantum Singular Value Transformation (QSVT) is a versatile algorithm, applicable to a wide range of problems including unstructured search, Hamiltonian simulation, matrix inversion and many more [1]. PennyLane makes it easy to build circuits and experiment with QSVT using the qsvt() function. For more information on how to use PennyLane’s QSVT functionality checkout our other demos:

  • Intro to QSVT

  • QSVT in Practice

  • How to implement QSVT on hardware

However, simulations can only take us so far, and industrially relevant system sizes are often too large to meaningfully simulate. Fortunately, PennyLane’s resource estimator module can help us gather meaningful insights in this regime. If you are new to resource estimation in PennyLane or need a quick refresher, checkout this demo on how to use PennyLane for Resource Estimation.

In this demo, you will learn how to use PennyLane’s estimator module to estimate the cost of a QSVT workflow.

Estimating the cost of QSVT

The logical cost of QSVT depends primarily on two factors, the block encoding operator and the degree of the polynomial transformation. For example let’s estimate the cost of performing a quintic (5th degree) polynomial transformation to the matrix \(A\):

\[\begin{split}A = \begin{bmatrix} 0.1 & 0.0 & 0.3 & 0.2 \\ 0.0 & -0.1 & 0.2 & -0.3 \\ 0.3 & 0.2 & -0.1 & 0.0 \\ 0.2 & -0.3 & 0.0 & 0.1 \\ \end{bmatrix},\end{split}\]

This particular matrix can be expressed as a linear combination of unitaries (LCU) \(A = 0.1 \cdot \hat{Z}_{0}\hat{Z}_{1} + 0.2 \cdot \hat{X}_{0}\hat{X}_{1} + 0.3 \cdot \hat{X}_{0}\hat{Z}_{1}\). The LCU representation is crucial for building the block encoding operator using the standard method of LCUs. For a recap on this technique, see our demo on linear combination of unitaries and block encodings.

import pennylane as qml

A = 0.1 * (qml.Z(0) @ qml.Z(1)) + 0.2 * (qml.X(0) @ qml.X(1)) + 0.3 * (qml.X(0) @ qml.Z(1))

print(qml.matrix(A, wire_order=[0, 1]))
[[ 0.1+0.j  0. +0.j  0.3+0.j  0.2+0.j]
 [ 0. +0.j -0.1+0.j  0.2+0.j -0.3+0.j]
 [ 0.3+0.j  0.2+0.j -0.1+0.j  0. +0.j]
 [ 0.2+0.j -0.3+0.j  0. +0.j  0.1+0.j]]

Resources from an Executable Workflow

Suppose we already had a PennyLane circuit which used QSVT to apply the quintic polynomial transformation to \(A\). Here we can use estimate() on the circuit directly to obtain the resource estimate.

import pennylane.numpy as qnp
import pennylane.estimator as qre

num_terms = len(A)
num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms)))
encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)]

poly = (0, 0, 0, 0, 0, 1)  # f(x) = x^5


def circ():
    qml.qsvt(A, poly, encoding_wires=encoding_wires)
    return


gs = {"X", "Y", "Z", "S", "T", "Hadamard", "CNOT", "Toffoli"}
resources = qre.estimate(circ, gate_set=gs)()
print(resources)
--- Resources: ---
 Total wires: 5
   algorithmic wires: 4
   allocated wires: 1
     zero state: 1
     any state: 0
 Total gates : 2.968E+3
   'Toffoli': 10,
   'T': 2.772E+3,
   'CNOT': 82,
   'X': 44,
   'Hadamard': 60

This works great for small systems and toy models. However, it suffers from performance bottlenecks when we scale to larger system sizes. In this case we can use some of the other functionality from the estimator module to estimate the cost of QSVT.

Resources from an Estimator Workflow

First we use the PauliHamiltonian class to efficiently capture the LCU representation of \(A\). This produces a compact object specifically for resource estimation.

First we build the block encoding operator by efficiently capturing the LCU representation of \(A\) using the PauliHamiltonian class. This produces a compact object specifically for resource estimation. The block encoding operator is built with the ChangeOpBasis class which uses the compute-uncompute pattern to implement the \(\text{Prep}^{\dagger} \circ \text{Select} \circ \text{Prep}\) operator.

The resources for QSVT can then be obtained using this block encoding:

lcu_A = qre.PauliHamiltonian(
    num_qubits=2,
    pauli_terms={"ZZ": 1, "XX": 1, "XZ": 1},
)  # represents A = 0.1*ZZ + 0.2*XX + 0.3*XZ
num_terms = lcu_A.num_terms
num_qubits = lcu_A.num_qubits

num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms)))
encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)]
lcu_wires = [f"t_{i}" for i in range(num_qubits)]

Prep = qre.QubitUnitary(
    num_encoding_wires,
    wires=encoding_wires,
)  # Prep the coeffs of the LCU
Select = qre.SelectPauli(
    lcu_A,
    wires=lcu_wires + encoding_wires,
)  # Select over ops in the LCU
BlockEncoding = qre.ChangeOpBasis(Prep, Select)  # Prep ○ Sel Prep^t


qsvt_op = qre.QSVT(
    block_encoding=BlockEncoding,
    encoding_dims=(4, 4),  # The shape of matrix A
    poly_deg=5,  # quintic
)

resources = qre.estimate(qsvt_op, gate_set=gs)
print(resources)
--- Resources: ---
 Total wires: 5
   algorithmic wires: 4
   allocated wires: 1
     zero state: 1
     any state: 0
 Total gates : 2.620E+3
   'Toffoli': 10,
   'T': 2.420E+3,
   'CNOT': 90,
   'X': 40,
   'Z': 0,
   'S': 0,
   'Hadamard': 60

Representing the QSVT workflow like this allows us to easily upscale it to larger system sizes without any computational overheads. Let’s extend this example to a 50 qubit system with an LCU of 2000 terms and a 100th degree polynomial transformation. Notice how simple it is to update the code and obtain the cost of this larger system:

lcu_A = qre.PauliHamiltonian(
    num_qubits=50,
    pauli_terms={"ZZ": 250, "XX": 750, "XZ": 1000},
)  # 2000 terms !
num_terms = lcu_A.num_terms
num_qubits = lcu_A.num_qubits

num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms)))
encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)]
lcu_wires = [f"t_{i}" for i in range(num_qubits)]

Prep = qre.QROMStatePreparation(
    num_encoding_wires,
    wires=encoding_wires,
)  # More efficient Prep
Select = qre.SelectPauli(
    lcu_A,
    wires=lcu_wires + encoding_wires,
)  # Select over ops in the LCU
BlockEncoding = qre.ChangeOpBasis(Prep, Select)  #  Prep ○ Sel Prep^t

qsvt_op = qre.QSVT(
    block_encoding=BlockEncoding,
    encoding_dims=(2**50, 2**50),  # The shape of matrix A
    poly_deg=100,
)

resources = qre.estimate(qsvt_op, gate_set=gs)
print(resources)
--- Resources: ---
 Total wires: 124
   algorithmic wires: 61
   allocated wires: 63
     zero state: 63
     any state: 0
 Total gates : 3.025E+7
   'Toffoli': 1.979E+6,
   'T': 1.320E+4,
   'CNOT': 1.823E+7,
   'X': 3.674E+6,
   'Z': 6.400E+3,
   'S': 1.280E+4,
   'Hadamard': 6.332E+6

With PennyLane’s resource estimation functionality we can analyze the cost of QSVT workflows for large system sizes consisting of hundreds of qubits and millions of gates!

Conclusion

In this demo, you learned how to use PennyLane’s estimator module to determine the resource requirements for QSVT. Now that you are armed with these tools for resource estimation, I challenge you to find another problem where polynomial transformations may be helpful, and figure out: what are the logical resource requirements of solving this on a quantum computer?

References

[1]

John M. Martyn, Zane M. Rossi, Andrew K. Tan, and Isaac L. Chuang, “A Grand Unification of Quantum Algorithms” arxiv.2105.02859, 2021.

About the author

Jay Soni
Jay Soni

Jay Soni

Jay completed his BSc. in Mathematical Physics from the University of Waterloo and currently works as a Quantum Software Developer at Xanadu. Fun fact, you will often find him sipping on a Tim Horton's IceCapp while he is working.

Total running time of the script: (0 minutes 0.042 seconds)

Share demo

Ask a question on the forum

Related Demos

Intro to QSVT

How to estimate the resource requirements of quantum algorithms

QSVT in Practice

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
  • Quantum Compilation
  • 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