PennyLane
Install
Install

Related materials

  • Related contentHow to use Qualtran with PennyLane
  • Related contentFunction Fitting using Quantum Signal Processing
  • Related contentIntro to QSVT

Contents

  1. Quantum Krylov Subspace Diagonalization
  2. Using QSP to directly create the QKSD ground-state
    1. Measuring the reduced density matrices
    2. Defining the QSP circuit
  3. Analyzing with Qualtran
  4. Conclusion
  5. References
  6. About the author
  7. About the authors

Downloads

  • Download Python script
  • Download Notebook
  • View on GitHub
  1. Demos/
  2. Quantum Computing/
  3. Using PennyLane and Qualtran to analyze how QSP can improve measurements of molecular properties

Using PennyLane and Qualtran to analyze how QSP can improve measurements of molecular properties

Diego Guala

Diego Guala

Oumarou Oumarou

Oumarou Oumarou

Anton Naim Ibrahim

Anton Naim Ibrahim

Austin Huang

Austin Huang

Published: August 28, 2025. Last updated: August 28, 2025.

Want to efficiently measure molecular properties using quantum computers? In this demo, we outline a powerful workflow for measuring molecular properties on future fault-tolerant quantum computers. We demonstrate how to construct the Quantum Krylov Subspace Diagonalization (QKSD) ground state of the water molecule, represented as a sum of Chebyshev polynomials, using a Quantum Signal Processing (QSP) circuit in PennyLane. This direct state preparation approach is highly efficient, enabling the measurement of properties like reduced density matrices with a constant number of circuit executions and thereby avoiding the quadratic scaling costs of other methods. We then use the integration between PennyLane and Qualtran to perform a detailed resource analysis.

demos/_static/demo_thumbnails/opengraph_demo_thumbnails/pennylane-demo-qualtran-covestro-krylov-subspace-paper-open-graph.png

This demo is based on some of the techniques and results of the paper titled Molecular Properties from Quantum Krylov Subspace Diagonalization 2. In the following sections we will follow this paper and:

  • Introduce QKSD briefly.

  • Build a circuit that uses QSP to prepare the QKSD ground-state.

  • Simulate circuits that estimate the one-particle reduced density matrix of a molecular system from the QKSD ground-state.

  • Use the PennyLane-Qualtran integration to count relevant circuit resources and demonstrate linear resource scaling with respect to the Krylov dimension, \(D\).

Quantum Krylov Subspace Diagonalization

QKSD is a notable candidate algorithm for fault-tolerant quantum computing that approximates the low-lying eigenvalues and eigenstates of a large Hamiltonian by focusing on a smaller subspace of the same Hamiltonian 3. The general steps to perform QKSD are:

  • Obtain the Hamiltonian, \(\hat{H}\), describing a system of interest, e.g., a molecule.

  • Define a Krylov subspace \(\mathcal{K}\) defined by the span of quantum states \(| \psi_{k = 0, \dots, D-1} \rangle\), where \(D\) is the Krylov dimension and \(| \psi_k \rangle\) can be efficiently prepared on a quantum computer.

  • Project \(\hat{H}\) into the Krylov subspace with a quantum computer, resulting in a new, “smaller” Hamiltonian \(\tilde{H}\) whose eigenvalues and eigenstates approximate those of \(\hat{H}\).

  • Calculate the overlap matrix, \(\tilde{S}\), defined by the inner-products of each element of the Krylov subspace.

  • Solve the generalized eigenvalue problem: \(\tilde{H}c^m = E_m \tilde{S}c^m\) on a classical computer, where \(c^m\) are the eigenstates of \(\tilde{H}\).

The result of this generalized eigenvalue problem gives approximations of the low-lying eigenenergies and eigenstates of the Hamiltonian 3, including the Krylov ground-state, \(|\Psi_0\rangle = \sum_k c^0_k | \psi_k \rangle\). Such an eigenstate is a linear combination of the states spanning the Krylov subspace and can be prepared with QSP, as we will see shortly.

Let’s now apply the above formalism to a familiar example: the \(H_2O\) molecule. We will use the Jordan-Wigner mapping of the \(H_2O\) Hamiltonian with an active space of 4 electrons in 4 molecular orbitals in the cc-pVDZ basis. To save time on this computationally-expensive basis, we provide pre-calculated coefficients and Pauli words for this Hamiltonian below. It is also possible to obtain these values for other molecules and basis sets using either PennyLane Datasets or the pennylane.qchem module. We use the pre-calculated results below to create a Hamiltonian object.

import pennylane as qml
import numpy as np

coeffs = [-2.6055398817649027, 0.4725512342017669, 0.06908378485045799, 0.06908378485045799, 0.42465877221739423, 0.040785962774025165, 0.02016371425557293, 0.33650704944175736, 0.059002396986463035, 0.059002396986463035, 0.2401948108687125, 0.2696430914655511, 0.04971997220167805, 0.04971997220167805, 0.2751875205710399, 0.30033122257656397, 0.22551650339251875]
paulis = [qml.GlobalPhase(0, 0), qml.Z(0), qml.Y(0) @ qml.Z(1) @ qml.Y(2), qml.X(0) @ qml.Z(1) @ qml.X(2), qml.Z(1), qml.Z(2), qml.Z(3), qml.Z(0) @ qml.Z(1), qml.Y(0) @ qml.Y(2), qml.X(0) @ qml.X(2), qml.Z(0) @ qml.Z(2), qml.Z(0) @ qml.Z(3), qml.Y(0) @ qml.Z(1) @ qml.Y(2) @ qml.Z(3), qml.X(0) @ qml.Z(1) @ qml.X(2) @ qml.Z(3), qml.Z(1) @ qml.Z(2), qml.Z(1) @ qml.Z(3), qml.Z(2) @ qml.Z(3)]
hamiltonian = qml.Hamiltonian(coeffs, paulis)

Next, we will define the Krylov subspace, \(\mathcal{K}\). We first define the states that span \(\mathcal{K}\):

\[\ket{\psi_k} = T_k(H)\ket{\psi_0},\]

where \(T_k\) is the \(k\)-th Chebyshev polynomial and \(|\psi_0\rangle\) is the Hartree-Fock state. The Chebyshev polynomials are defined by:

\[T_0(\hat{H}) = \mathbb{1}\]
\[T_1(\hat{H}) = \hat{H}\]
\[T_{n+1}(\hat{H}) = 2 \hat{H} T_n(\hat{H}) - T_{n-1}(\hat{H})\]

Other subspace definitions are possible 3, but we choose Chebyshev polynomials for convenience. The reason for this is that we plan to prepare the Krylov ground-state using QSP, which directly implements Chebyshev polynomials. Other types of functions or polynomials would first need to be converted into Chebyshev polynomials, adding more complexity to our program.

With the states defined, the Krylov subspace of dimension \(D\) is then:

\[\mathcal{K} = \text{span}(\{\ket{\psi_k}\}_{k=0}^{D-1}).\]

After projecting \(\hat{H}\) into \(\mathcal{K}\) and solving the generalized eigenvalue problem described above, we obtain the Krylov ground-state 3,

\[\ket{\Psi_0} = \sum_{k=0}^{D-1} c^0_k \ket{\psi_k} = \sum_{k=0}^{D-1} c_k^0 T_k(H) \ket{\psi_0},\]

where \(c_k^m\) is the \(k\)-th coefficient of the \(m\)-th eigenstate of \(\tilde{H}\). We pre-calculate these coefficients and use them to obtain the QSP rotation angles that prepare the QKSD ground-state in the section below.

Using QSP to directly create the QKSD ground-state

Only using QKSD to calculate one-particle or two-particle reduced density matrices results in a quadratic scaling of the number of expectation values that need to be measured with respect to the Krylov dimension, \(D\) 2. Instead, reference 2 shows that it is possible to reduce this to constant scaling by preparing \(|\Psi_0\rangle\) via QSP and measuring individual terms of the Hamiltonian. The QSP circuit we will use, \(U_\text{QSP}\), is defined as a series of alternating block-encoding, \(U_\text{BE}\), and rotation operators, \(S\), such that 1 2 :

\[U_\text{QSP} = S(\phi_0)\prod_k^{d-1}{U_\text{BE}(\hat{H})S(\phi_k)}.\]

This QSP circuit prepares a Chebyshev polynomial of the block-encoded Hamiltonian:

\[U_\text{QSP} \ket{\psi_0} \ket{0}_a = \sum_{i=0}^{D-1} c_i T_i(H) \ket{\psi_0} \ket{0}_a + \beta\ket{\perp}.\]

With specific rotation angles, \(\phi\), \(U_\text{QSP}\) implements the Chebyshev polynomial corresponding to the Krylov ground-state:

\[U_\text{QSP}|\psi_0\rangle|0\rangle = \ket{\Psi_0}\ket{0}_a + \beta\ket{\perp}\]

For more details about implementing polynomials of block-encoded Hamiltonians, block-encoding operators, and rotation operators, see the Intro to QSVT demo.

Measuring the reduced density matrices

The elements of the one-particle reduced density matrix, \(\gamma_{pq}\), are obtained by measuring the expectation value of the fermionic one-particle excitation operators acting on the Krylov ground-state 2. That is,

\[\gamma_{pq} = \langle\Psi_0 | a^{\dagger}_p a_q | \Psi_0\rangle,\]

where \(a^{\dagger}\) and \(a\) are the creation and annihilation operators, respectively. The indices \(p\) and \(q\) determine in which orbital particles are added or removed.

We can obtain these expectation values by measuring the right observables and post-processing the result according to reference 2. Specifically, we use the Jordan-Wigner mapping of the fermionic one-particle excitation operators and measure the resulting Pauli word observables. By measuring each Pauli word, \(P\) and a product of the Pauli word and a reflection around 0, \(R_0P\), we obtain:

\[o_1 = \bra{\psi_0}\bra{0}_aU_\text{QSP}^{*}P U_\text{QSP}\ket{0}_a\ket{\psi_0}\]
\[o_2 = \bra{\psi_0}\bra{0}_aU_\text{QSP}^{*}R_0 PU_\text{QSP}\ket{0}_a\ket{\psi_0}\]

These measurements can then be combined according to 2

\[2\langle \Psi_0 |P|\Psi_0\rangle = \eta^2(o_1 + o_2),\]

giving the value of \(\gamma_{pq}\) for the Hamiltonian in the Jordan-Wigner mapping. Note that it is also possible to obtain the two-particle reduced density matrix, \(\Gamma_{pqrs}\), by following the same protocol for fermionic two-particle excitation operators, \(a^{\dagger}_p a^{\dagger}_q a_r a_s\).

Now let’s see how to build the QSP circuit and measurements in PennyLane.

Defining the QSP circuit

To define the QSP circuit, we first create a function to implement the rotations, \(S\). The block-encoding, \(U_\text{BE}\), will be implemented via the PrepSelPrep class. We then create a QSP template to alternate between \(U_\text{BE}\) and \(S\). Alternating between these operations will prepare a Chebyshev polynomial of the input block-encoded matrix.

def rotation_about_reflection_axis(angle, wires):
    """Rotation operation, S(phi_k)"""
    qml.ctrl(qml.PauliX(wires[0]), wires[1:], (0,) * len(wires[1:]))
    qml.RZ(angle, wires[0])
    qml.ctrl(qml.PauliX(wires[0]), wires[1:], (0,) * len(wires[1:]))

def qsp(lcu, angles, rot_wires, prep_wires):
    """Applies QSP by alternating between S(phi_k) and U_{QSP}"""
    for angle in angles[::-1][:-1]:
        rotation_about_reflection_axis(angle, rot_wires)
        qml.PrepSelPrep(lcu, control=prep_wires)
    rotation_about_reflection_axis(angles[0], rot_wires)

Since QSP can only produce fixed-parity real Chebyshev polynomials 1 and our QKSD ground-state has complex polynomials, we also create a template that combines the real and imaginary parts of the polynomial.

def qsp_poly_complex(lcu, angles_real, angles_imag, ctrl_wire, rot_wires, prep_wires):
    qml.H(ctrl_wire)
    qml.ctrl(qsp, ctrl_wire, 0)(lcu, angles_real, rot_wires, prep_wires)
    qml.ctrl(qsp, ctrl_wire, 1)(lcu, angles_imag, rot_wires, prep_wires)
    qml.H(ctrl_wire)

Additionally, we require a template to perform the \(R_0\) reflection for our measurements.

def reflection(wire, ctrl_wires):
    """Reflection operator, R_0"""
    qml.ctrl(qml.X(wire), ctrl_wires, [0] * len(ctrl_wires))
    qml.Z(wire)
    qml.ctrl(qml.X(wire), ctrl_wires, [0] * len(ctrl_wires))

We will also need to split even- and odd-parity polynomial terms, which is captured in the final circuit below. Since we have split the polynomial and implemented each part via a separate QSP circuit, we will also need to split the rotation angles that implement each of these polynomials. The final circuit below accepts a separate argument for odd/even and real/imaginary angles: odd_real, odd_imag, even_real, and even_imag.

We also define an argument for an input observable, obs, and an argument defining whether to measure the reflection of the observable, measure_reflection.

With these building blocks in place, we can now define the overarching QNode that will apply the QSP circuit to the reference state \(|\psi_0\rangle\) and return measurements of the elements of the one-particle reduced density matrix:

dev = qml.device("lightning.qubit")
ref_state = qml.qchem.hf_state(electrons=4, orbitals=4)

@qml.qnode(dev)
def krylov_qsp(lcu, even_real, even_imag, odd_real, odd_imag, obs, measure_reflection=False):
    """Prepares the Krylov ground-state by applying QSP with the input angles.
    Then measures the expectation value of the desired observable.
    """
    num_aux = int(np.log(len(lcu.operands)) / np.log(2)) + 1

    start_wire = hamiltonian.wires[-1] + 1
    rot_wires = list(range(start_wire, start_wire + num_aux + 1))
    prep_wires = rot_wires[1:]
    ctrl_wires = [prep_wires[-1] + 1, prep_wires[-1] + 2]
    rdm_ctrl_wire = ctrl_wires[-1] + 1

    #prepare the reference state
    for i in hamiltonian.wires:
        qml.X(i)

    if measure_reflection: # preprocessing for reflection measurement
        qml.X(rdm_ctrl_wire)

    qml.H(ctrl_wires[0])
    qml.ctrl(qsp_poly_complex, ctrl_wires[0], 0)(lcu, even_real, even_imag, ctrl_wires[1],
                                                 rot_wires, prep_wires)
    qml.ctrl(qsp_poly_complex, ctrl_wires[0], 1)(lcu, odd_real, odd_imag, ctrl_wires[1],
                                                 rot_wires, prep_wires)
    qml.H(ctrl_wires[0])

    # measurements
    if measure_reflection:
        return qml.expval(qml.prod(reflection)(rdm_ctrl_wire, set(ctrl_wires+prep_wires))@obs)
    return qml.expval(obs)

We can now use this circuit to build one-particle and two- particle reduced density matrices. We can obtain the Jordan-Wigner mapping of the fermionic operators via PennyLane using the from_string() and jordan_wigner() functions as follows:

Epq = qml.fermi.from_string('0+ 0-')
obs = qml.jordan_wigner(Epq)

For this demo, we used a Krylov subspace dimension of \(D=15\) and pre-computed QSP angles that implement the corresponding sum of Chebyshev polynomials \(\sum_{k=0}^{D-1}c_k^0 T_k(\hat{H})\). For a given polynomial it is possible to obtain the QSP angles using poly_to_angles().

The angles below will produce the QKSD ground-state \(|\Psi_0\rangle\) via QSP. Since QSP can only produce fixed-parity real Chebyshev polynomials 1 and our QKSD ground-state has mixed-parity complex polynomials, we split them and apply separately.

even_real = np.array([3.11277458, 2.99152757, 3.15307452, 3.40611024, 3.00166196, 3.03597059, 3.25931224, 3.04073693, 3.25931224, 3.03597059, 3.00166196, 3.40611024, 3.15307452, 2.99152757, -40.86952257])
even_imag = np.array([3.17041073, 3.29165774, 3.13011078, 2.87707507, 3.28152334, 3.24721472, 3.02387307, 3.24244837, 3.02387307, 3.24721472, 3.28152334, 2.87707507, 3.13011078, 3.29165774, -47.09507173])
odd_real = np.array([3.26938242, 3.43658284, 3.17041296, 3.10158929, 3.22189574, 2.93731798, 3.25959312, 3.25959312, 2.93731798, 3.22189574, 3.10158929, 3.17041296, 3.43658284, -37.57132208])
odd_imag = np.array([3.01380289, 2.84660247, 3.11277234, 3.18159601, 3.06128956, 3.34586733, 3.02359219, 3.02359219, 3.34586733, 3.06128956, 3.18159601, 3.11277234, 2.84660247, -44.11008691])

We then measure the QSP circuit using these angles and post-process according to the equations above:

P = krylov_qsp(hamiltonian, even_real, even_imag, odd_real, odd_imag, obs=obs)
RP = krylov_qsp(hamiltonian, even_real, even_imag, odd_real, odd_imag, obs=obs,
                measure_reflection=True)

print("P:", P)
print("RP:", RP)

lambda_lcu = np.sum(np.abs(coeffs))
coherent_result = 2*lambda_lcu*(P+RP)
print("Coherent result:", coherent_result)
/home/runner/work/qml/qml/.venv-build/lib/python3.10/site-packages/pennylane_lightning/lightning_base/_serialize.py:359: ComplexWarning: Casting complex values to real discards the imaginary part
  coeffs = np.array(coeffs).astype(self.rtype)
P: 0.9677972215519083
RP: -0.6875560272165191
Coherent result: 3.120032869288977

Analyzing with Qualtran

We can analyze the resources and flow of this program by using the Qualtran call graph. We first convert the PennyLane circuit to a Qualtran bloq using to_bloq() and then use the call graph to count the required gates:

bloq = qml.to_bloq(krylov_qsp, map_ops=False,
    even_real=even_real, even_imag=even_imag,
    odd_real=odd_real, odd_imag=odd_imag,
    lcu=hamiltonian, obs=obs)

We can then use Qualtran tools to analyze and process the gate counts of the circuit. Below, we use the call_graph to obtain a breakdown of the gates used, applying the generalize_rotation_angle generalizer to neatly group all rotations for clearer viewing:

from qualtran.resource_counting.generalizers import generalize_rotation_angle

graph, sigma = bloq.call_graph(generalizer=generalize_rotation_angle)
print("--- Gate counts ---")
for gate, count in sigma.items():
    print(f"{gate}: {count}")
--- Gate counts ---
CNOT: 28856
And: 5398
XGate: 2326
And†: 5398
Z**\phi: 972
CZ: 1188
CYGate: 324
Z**\phi: 26684
Toffoli: 11232
CHadamard: 4
H: 2

As explained in 2, increasing \(D\) improves the accuracy of the Krylov minimal energy compared to the true ground state energy. This extra accuracy is paid for by requiring additional gates. Let’s see how the number of gates increases with increasing Krylov subspace dimension. We can increase the Krylov subspace dimension by increasing the number of terms in our Chebyshev polynomial, captured in this demo via the angles variables. Let’s try \(D=20\) by setting the number of terms in these angles to 20. As the resource estimation is independent of the exact angle values, we are able to set them randomly instead of recomputing the formally:

even_real = even_imag = odd_real = odd_imag = np.random.random(20)

We then repeat the gate counts and see they have increased:

bloq = qml.to_bloq(krylov_qsp, map_ops=False, even_real=even_real,
                   even_imag=even_imag, odd_real=odd_real,
                   odd_imag=odd_imag, lcu=hamiltonian, obs=obs)

graph, sigma = bloq.call_graph(generalizer=generalize_rotation_angle)
print("--- Gate counts ---")
for gate, count in sigma.items():
    print(f"{gate}: {count}")
--- Gate counts ---
CNOT: 40604
Z**\phi: 37552
And: 7576
And†: 7576
XGate: 3206
Z**\phi: 1368
CZ: 1672
CYGate: 456
Toffoli: 15808
CHadamard: 4
H: 2

We can plot how the number of gates increases with the Krylov dimension to see if it is linear as described in reference 2. Below we plot how the Toffoli, CNOT, and X gate count increase with the Krylov dimension:

import matplotlib.pyplot as plt
from qualtran.bloqs.basic_gates import Toffoli, CNOT, XGate

def count_cnots(krylov_dimension):
    even_real = even_imag = odd_real = odd_imag = np.random.random(krylov_dimension)
    bloq = qml.to_bloq(krylov_qsp, map_ops=False, even_real=even_real,
                       even_imag=even_imag, odd_real=odd_real,
                       odd_imag=odd_imag, lcu=hamiltonian, obs=obs)
    _, sigma = bloq.call_graph(generalizer=generalize_rotation_angle)
    return sigma

Ds = [10, 20, 30, 40, 50]
sigmas = [count_cnots(D) for D in Ds]

plt.style.use("pennylane.drawer.plot")
plt.scatter(Ds, [sigma[CNOT()] for sigma in sigmas], label='CNOTs')
plt.scatter(Ds, [sigma[Toffoli()] for sigma in sigmas], label = 'Toffolis')
plt.scatter(Ds, [sigma[XGate()] for sigma in sigmas], label = 'X Gates')
plt.xlabel('Krylov Subspace Dimension, D')
plt.ylabel('Number of Gates')
plt.legend()
plt.show()
tutorial qksd qsp qualtran

As expected, the gate counts increase linearly with the Krylov subspace dimension.

We can also show the call graph of the circuit, a diagrammatic representation of how each operation in the circuit calls other operations. This can be useful to understand how a circuit works or which sections are resource-intensive.

The first layer of this circuit, before decomposing the operations, contains many RZ gates controlled on two qubits with different angles. As we saw above, we can group similar operations together and simplify the view. To this end, we first write a custom Qualtran generalizer that will combine controlled-RZ gates:

import attrs
import sympy

from qualtran.resource_counting.generalizers import _ignore_wrapper

PHI = sympy.Symbol(r'\phi')

def generalize_ccrz(b):
    from qualtran.bloqs.basic_gates import Rz
    from qualtran.bloqs.mcmt.controlled_via_and import ControlledViaAnd

    if isinstance(b, ControlledViaAnd) and isinstance(b.subbloq, Rz):
        return attrs.evolve(b, subbloq = Rz(angle=PHI))

    return _ignore_wrapper(generalize_ccrz, b)

We can then use this generalizer to draw our call graph using Qualtran’s show_call_graph

from qualtran.drawing import show_call_graph

graph, sigma = bloq.call_graph(generalizer=generalize_ccrz)
show_call_graph(qpe_bloq, max_depth=1)
demos/_static/demonstration_assets/qksd_qsp_qualtran/generalize_ccrz_call_graph.svg

Conclusion

This demo demonstrated how to use PennyLane to measure the one-particle reduced density matrix of the water molecule with a linearly-scaling number of operations and how to integrate with Qualtran to demonstrate these resource requirements. This was done by using Quantum Krylov Subspace Diagonalization techniques to compress a complicated molecular Hamiltonian, finding its ground-state classically, and then using Quantum Signal Processing to efficiently measure its one-particle reduced density matrix.

We then used the integration between PennyLane and Qualtran to perform a detailed resource analysis. By converting our PennyLane QNode into a Qualtran Bloq, we precisely counted the required quantum gates and confirmed that the number of gates scales linearly with the Krylov subspace dimension, a crucial result from the source paper 2. This favorable scaling highlights the potential of QSP-based techniques for tackling meaningful quantum chemistry problems and provides a practical framework for bridging the gap between theoretical algorithms and their implementation on future quantum hardware.

References

1(1,2,3)

Guang Hao Low, Isaac L. Chuang “Hamiltonian Simulation by Qubitization”, arXiv:1610.06546, 2019.

2(1,2,3,4,5,6,7,8,9,10)

Oumarou Oumarou, Pauline J. Ollitrault, Cristian L. Cortes, Maximilian Scheurer, Robert M. Parrish, Christian Gogolin “Molecular Properties from Quantum Krylov Subspace Diagonalization” arXiv:2501.05286, 2025.

3(1,2,3,4)

Nobuyuki Yoshioka, Mirko Amico, William Kirby, Petar Jurcevic, Arkopal Dutt, Bryce Fuller, Shelly Garion, Holger Haas, Ikko Hamamura, Alexander Ivrii, Ritajit Majumdar, Zlatko Minev, Mario Motta, Bibek Pokharel, Pedro Rivero, Kunal Sharma, Christopher J. Wood, Ali Javadi-Abhari, and Antonio Mezzacapo “Diagonalization of large many-body Hamiltonians on a quantum processor”, arXiv:2407.14431, 2024.

About the authors

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.

Oumarou Oumarou
Oumarou Oumarou

Oumarou Oumarou

Quantum Computing scientist focusing on its application in Quantum Chemistry problems

Anton Naim Ibrahim
Anton Naim Ibrahim

Anton Naim Ibrahim

Exploring uncharted territory.

Austin Huang
Austin Huang

Austin Huang

Pennylane Algorithms Team

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

Share demo

Ask a question on the forum

Related Demos

How to use Qualtran with PennyLane

Function Fitting using Quantum Signal Processing

Intro to QSVT

How to implement QSVT on hardware

Intro to qubitization

QSVT in Practice

Using PennyLane with PySCF and OpenFermion

How to build compressed double-factorized Hamiltonians

Differentiable Hartree-Fock

How to quantum just-in-time compile VQE with Catalyst

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 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