PennyLane
Install
Install

Related materials

  • Related contentIntro to Quantum Phase Estimation
  • Related contentBasic arithmetic with the quantum Fourier transform (QFT)
  • Related contentHow to use quantum arithmetic operators

Contents

  1. How to create a wire register
  2. A simple example
  3. An advanced example
  4. Conclusion
  5. About the author

Downloads

  • Download Python script
  • Download Notebook
  • View on GitHub
  1. Demos/
  2. Getting Started/
  3. How to use wire registers

How to use wire registers

Austin Huang

Austin Huang

Published: September 04, 2024. Last updated: September 22, 2025.

A register of wires represents a collection of wires that serve a purpose (e.g., an “estimation” register in quantum phase estimation) and abstract away the finer details of running quantum algorithms. In this tutorial, we will explore how you can construct and use wire registers in PennyLane.

How to create a wire register

The way to construct a wire register is simple — just use registers(). We need to pass a dictionary where the keys are the register names and the values are the number of wires in each register:

import pennylane as qml

register = qml.registers({"alice": 1, "bob": 2, "charlie": 3})
print(register)
{'alice': Wires([0]), 'bob': Wires([1, 2]), 'charlie': Wires([3, 4, 5])}

The output is a dictionary where the keys are the names of the registers and the values are Wires instances.

You can also pass in a dictionary that has nested dictionaries as its values.

nested_register = qml.registers(
    {
        "all_registers": {
            "alice": 1,
            "bob": {"bob1": {"bob1a": 1, "bob1b": 2}, "bob2": 1},
            "charlie": 1,
        }
    }
)
print(nested_register)
{'alice': Wires([0]), 'bob1a': Wires([1]), 'bob1b': Wires([2, 3]), 'bob1': Wires([1, 2, 3]), 'bob2': Wires([4]), 'bob': Wires([1, 2, 3, 4]), 'charlie': Wires([5]), 'all_registers': Wires([0, 1, 2, 3, 4, 5])}

Note that registers() flattens any nested dictionaries, and the order of the elements is based on the order of appearance and the level of nestedness. For more details on ordering, refer to the documentation for registers().

Accessing a particular register is the same as accessing any element in a dictionary…

print(nested_register["alice"], nested_register["bob1a"])
Wires([0]) Wires([1])

…and you can access a specific wire index via its index in a register.

print(nested_register["all_registers"][2], nested_register["bob1a"][0])
2 1

You can also combine registers using set operations. Here, we use the pipe operator | to perform the union operation on the alice register and the charlie register.

new_register = nested_register["alice"] | nested_register["charlie"]
print(new_register)
Wires([0, 5])

For more details on what set operations are supported, refer to the documentation of Wires.

A simple example

In this example, we demonstrate how one can implement the swap test with registers. The swap test is an algorithm that calculates the squared inner product of two input states. It requires one auxiliary qubit and takes two input states \(|\psi\rangle\) and \(|\phi\rangle.\) We can think of these components as three registers. Suppose states \(|\psi\rangle\) and \(|\phi\rangle\) are each represented with 3 wires. In PennyLane code, that would be:

import numpy as np

swap_register = qml.registers({"auxiliary": 1, "psi": 3, "phi": 3})

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

@qml.qnode(dev)
def swap_test():
    # Make "psi" and "phi" state orthogonal to each other
    qml.RX(np.pi/2, swap_register["phi"][0])

    qml.Hadamard(swap_register["auxiliary"])
    for i in range(len(swap_register["psi"])):
        # We can use the union operation to assemble our registers on the fly
        qml.CSWAP(
            swap_register["auxiliary"]
            | swap_register["psi"][i]
            | swap_register["phi"][i]
        )
    qml.Hadamard(swap_register["auxiliary"])
    return qml.expval(qml.Z(wires=swap_register["auxiliary"]))


print(swap_test())
0.4999999999999999

An advanced example

Using registers can greatly streamline the process of modifying a workflow by simplifying wire management. In this example, we use quantum phase estimation (QPE) to calculate the eigenvalues of a Hamiltonian. Generally, QPE is described with two sets of registers. One register is known as the “estimation” or “measurement” register, and the other is the state register where we apply our unitary operators \(U.\) We can define these registers in PennyLane code:

register = qml.registers({"state": 4, "estimation": 6})

To build our unitary operator \(U,\) there are a variety of options. We can opt to use a straight-forward block encoding, or choose to use a subroutine like qubitization. Let’s opt for Qubitization, which means we have to define another preparation register. Our registers now look like this:

register = qml.registers({"state": 4, "estimation": 6, "prep": 4})

Finally, let’s define our Hamiltonian. We’ll use the transverse-field Ising model from PennyLane Datasets, but feel free to try this with any other Hamiltonian.

[dataset] = qml.data.load(
    "qspin", sysname="Ising", periodicity="open", lattice="chain", layout="1x4"
)
H = dataset.hamiltonians[0]
print(H)
-1.0 * (Z(0) @ Z(1)) + -1.0 * (Z(1) @ Z(2)) + -1.0 * (Z(2) @ Z(3)) + 0.0 * X(0) + 0.0 * X(1) + 0.0 * X(2) + 0.0 * X(3)

For QPE to work, we need to initialize the “state” register with an initial state that has good overlap with the eigenstate we want the eigenvalue of.

initial_state = dataset.ground_states[0]

With this, we can now define our QPE circuit:

dev = qml.device("lightning.qubit", wires=14)

@qml.qnode(dev)
def circuit():
    # Initialize state register to initial state
    qml.StatePrep(initial_state, wires=register["state"])

    # Apply Hadamard gate to all wires in estimation register
    for wire in register["estimation"]:
        qml.Hadamard(wires=wire)

    qml.ControlledSequence(
        qml.Qubitization(H, register["prep"]),
        control=register["estimation"],
    )

    qml.adjoint(qml.QFT)(wires=register["estimation"])

    return qml.probs(wires=register["estimation"])

We’ll run our circuit and do some post-processing to get the energy eigenvalue:

output = circuit()
lamb = sum([abs(c) for c in H.terms()[0]])
print("Eigenvalue: ", lamb * np.cos(2 * np.pi * (np.argmax(output)) / 2 ** len(register["estimation"])))
Eigenvalue:  -3.0

Changing the number of wires in your estimation register is very easy with registers. The complexity of wire management only gets more difficult as you start working with more and more registers. As you start building bigger and more complex algorithms, this can quickly become a serious issue!

Conclusion

In this demo, we showed how to construct wire registers and use them to implement quantum algorithms. Wire registers provide an elegant way of organizing and managing wires. Often, algorithms are described as acting upon registers and sub-registers; using wire registers can greatly streamline the implementation from theory to code.

About the author

Austin Huang
Austin Huang

Austin Huang

Pennylane Algorithms Team

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

Share demo

Ask a question on the forum

Related Demos

Intro to Quantum Phase Estimation

Basic arithmetic with the quantum Fourier transform (QFT)

How to use quantum arithmetic operators

How to use Qualtran with PennyLane

Intro to qubitization

Intro to Amplitude Amplification

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

Linear combination of unitaries and block encodings

Intro to quantum read-only memory (QROM)

How to track algorithmic error using PennyLane

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