PennyLane
Install
Install

Related materials

  • Related contentHow to create dynamic circuits with mid-circuit measurements
  • Related contentHow to collect statistics of mid-circuit measurements
  • Related contentMeasurement-based quantum computation

Contents

  1. Measurements in quantum mechanics
    1. Mathematical description
    2. Measuring a single qubit
    3. Measuring a Bell pair
    4. Qubit reset
  2. Dynamically controlling a quantum circuit
    1. T-gadget in PennyLane
  3. Conclusion
  4. References
  5. About the author

Downloads

  • Download Python script
  • Download Notebook
  • View on GitHub
  1. Demos/
  2. Getting Started/
  3. Introduction to mid-circuit measurements

Introduction to mid-circuit measurements

David Wierichs

David Wierichs

Published: May 09, 2024. Last updated: November 05, 2024.

Mid-circuit measurements are an important building block in quantum algorithms and quantum error correction, and with measurement-based quantum computing, they even power a complete quantum computing paradigm. In this tutorial, we will dive into the basics of mid-circuit measurements with PennyLane. You will learn about

  • basic measurement processes in quantum mechanics,

  • the impact of a measurement on one- and two-qubit systems,

  • postselection and qubit reset, and

  • dynamic quantum circuits powered by conditional operations.

demos/_static/demonstration_assets/mcm_introduction/socialthumbnail_mcm_introduction.png

We also have dedicated learning material if you want to know how to collect statistics of mid-circuit measurements or how to create dynamic circuits with mid-circuit measurements.

Measurements in quantum mechanics

Measurements are the subject of important questions in quantum mechanics: What is a measurement? How does it affect the measured system? And how can we describe a measurement process mathematically? Given how fundamental those question are, there is a plethora of learning resources on this topic, from textbooks 1 and (video) lectures 2, 3 to interactive studying material like the PennyLane Codebook or Ref. 4. Furthermore, discussing measurements quickly leads to questions about the interpretation of quantum mechanics and philosophical, if not metaphysical, discourse. For these reasons, we will not aim at discussing those deep question in great detail, but focus on understanding the basics that will help us understand measurements performed within quantum circuits, i.e., mid-circuit measurements, and how to realize them in PennyLane.

Bear with us, we will briefly look at a mathematicaly definition for measurements but then turn to practical examples and hands-on calculations.

Mathematical description

We will go with the following definition: A measurement \(M\) is a process that maps a valid quantum state \(\rho\) to a classical probabilistic mixture

\[M[\rho]=\sum_{i=1}^n p_i \rho_i\]

of post-measurement quantum states \(\rho_i\) that are specified by \(M.\) Here, \(n\) is the number of possible measurement outcomes and \(p_i\) is the probability to measure the outcome \(i\) associated to \(\rho_i,\) given the input state \(\rho.\) For a qubit in the \(|+\rangle=(|0\rangle + |1\rangle)/\sqrt{2}\) state measured in the \(Z\) basis, we find

\[M[|+\rangle\langle +|]=\frac{1}{2}|0\rangle\langle 0|+\frac{1}{2}|1\rangle\langle 1|,\]

because the probability to measure \(0\) or \(1\) is \(50\%\) each. We will explore this example in more detail below.

The expression above describes the probabilistic mixture after the quantum mechanical measurement if we do not record the measurement outcome. If we do record the measurement outcome and only keep those samples that match a specific postselection rule, we no longer have a probabilistic mixture, but find the state \(\rho_i\) for the filtered outcome \(i.\)

For the rest of this tutorial, we will restrict ourselves to standard measurements commonly found in mid-circuit measurements, using so-called projective measurements. In this setting, the measurement comes with one projector \(\Pi_i\) per measurement outcome, and all projectors sum to the identity. The post-measurement states are given by

\[\rho_i = \frac{\Pi_i \rho \Pi_i}{\operatorname{tr}[\Pi_i \rho]}\]

and the probabilities are dictated by the Born rule, \(p_i=\operatorname{tr}[\Pi_i \rho].\) This means that if we do not record the measurement outcome, the system simply ends up in the state

\[M[\rho] = \sum_{i=1}^n \Pi_i \rho \Pi_i.\]

To understand this abstract description better, let’s look at three simple examples; measuring a single qubit, measuring a Bell state, and resetting qubits.

Measuring a single qubit

Consider a single qubit in the state \(|+\rangle,\) i.e., in the equal superposition of \(|0\rangle\) and \(|1\rangle.\) To get started, let’s first implement this state in PennyLane and compute some expectation values that will be insightful later on. We follow these steps:

  • Import PennyLane and define a device using device(). The built-in "default.qubit" Python statevector simulator will suffice for our purposes, however PennyLane provides a wide array of additional high-performance and hardware devices.

  • Write a quantum function that first creates the \(|+\rangle\) state using a Hadamard gate, and then measures the expectation values \(\langle X\rangle\) and \(\langle Z\rangle\) in this state, using expval().

  • Specify the device on which the quantum function should be executed, using the qnode() decorator.

  • Run the quantum node and show the computed expectation values!

If you’d like more guidance on any of these steps, also have a look at our tutorial on qubit rotation explaining them in detail.

import pennylane as qml

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

@qml.qnode(dev)
def before():
    qml.Hadamard(0)  # Create |+> state
    return qml.expval(qml.X(0)), qml.expval(qml.Z(0))

b = before()
print(f"Expectation values before any measurement: {b[0]:.1f}, {b[1]:.1f}")
Expectation values before any measurement: 1.0, 0.0

The result is not surprising: \(|+\rangle\) is the eigenstate of \(X\) for the eigenvalue \(+1,\) and it has the well-known expectation value \(\langle +|Z|+\rangle=0.\)

Now we bring in a mid-circuit measurement in the computational, or Pauli-\(Z,\) basis. It comes with the projections \(\Pi_i=|i\rangle\langle i|,\) \(i\in\{0, 1\},\) onto the computational basis states. If we execute the measurement process but do not record the outcome, we find the state

\[\begin{split}M[\rho] &= \Pi_0 \rho_0 \Pi_0 + \Pi_1\rho_1 \Pi_1\\ &= |0\rangle\langle 0|+\rangle\langle +|0\rangle\langle 0| \ +\ |1\rangle\langle 1|+\rangle\langle +|1\rangle\langle 1|\\ &= \frac{1}{2}\mathbb{I}.\end{split}\]

where we used the overlaps \(\langle +|i\rangle=1/\sqrt{2}\) and the decomposition \(\mathbb{I} = |0\rangle\langle 0| + |1\rangle\langle 1|\) of the identity. This means that the measurement sends the qubit from a pure state into a mixed state, i.e., it not only affects the state but even the class of states it is in. And this is because we did not even record the measurement outcome!

Let’s look at this example in PennyLane. We repeat the steps from above but additionally include a mid-circuit measurement, calling measure() on the qubit 0. Note that we just perform the measurement and do not assign any variable to its outcome.

@qml.qnode(dev)
def after():
    qml.Hadamard(0)  # Create |+> state
    qml.measure(0)  # Measure without recording the outcome
    return qml.expval(qml.X(0)), qml.expval(qml.Z(0))

a = after()
print(f"Expectation value after the measurement:  {a[0]:.1f}, {a[1]:.1f}")
Expectation value after the measurement:  0.0, 0.0

The measurement moved the qubit from the \(|+\rangle\) eigenstate of the Pauli-\(X\) operator into a mixed state with expectation value zero for all Pauli operators, explaining the values we just observed.

Now if we filter for one measurement outcome, say \(0,\) we find the state

\[M[\rho]=\rho_0 =\frac{|0\rangle\langle 0|+\rangle\langle +|0\rangle\langle 0|}{\operatorname{tr}[|0\rangle\langle 0|+\rangle\langle +|]} =|0\rangle\langle 0|,\]

that is, the qubit is in a new, pure state. In PennyLane, we can postselect on the case where we measured a \(0\) using the postselect keyword argument of qml.measure:

@qml.qnode(dev)
def after():
    qml.Hadamard(0)  # Create |+> state
    qml.measure(0, postselect=0)  # Measure and only accept 0 as outcome
    return qml.expval(qml.X(0)), qml.expval(qml.Z(0))

a = after()
print(f"Expectation value after the postselected measurement:  {a[0]:.1f}, {a[1]:.1f}")
Expectation value after the postselected measurement:  0.0, 1.0

As expected, we find the that the measured, postselected qubit is in the \(|0\rangle\) eigenstate of the Pauli-\(Z\) operator with eigenvalue \(+1,\) yielding \(\langle X\rangle=0\) and \(\langle Z\rangle=1.\) For postselect=1, we would have obtained the \(|1\rangle\) eigenstate of \(Z\) with eigenvalue \(-1,\) instead.

Measuring a Bell pair

Next, we consider a pair of qubits, entangled in a Bell state:

\[|\phi\rangle = \frac{1}{\sqrt{2}} (|00\rangle + |11\rangle).\]

This is a pure state with density matrix

\[|\phi\rangle\langle \phi | = \frac{1}{2}\left(|00\rangle\langle 00| + |00\rangle\langle 11| + |11\rangle\langle 00| + |11\rangle\langle 11|\right).\]

We will again measure only the first qubit. We code this circuit up similar to the one above, using an additional CNOT gate to create the Bell state. We also include optional hyperparameters such as postselect as keyword arguments to our quantum function and pass them on to qml.measure. Note that we can’t complete the quantum function yet, because we still need to discuss what to return from it!

def bell_pair_preparation(**kwargs):
    qml.Hadamard(0)
    qml.CNOT([0, 1])  # Create a Bell pair
    qml.measure(0, **kwargs)  # Measure first qubit, using keyword arguments

Without recording the outcome, i.e., postselect=None, we obtain the state

\[M[\rho] = \frac{1}{2}\left(|00\rangle\langle 00| + |11\rangle\langle 11|\right),\]

which again could be described by a classical mixture as well. If we instead postselect on measuring, say, a \(1,\) we find \(M[\rho] = |11\rangle\langle 11|.\)

There are two striking differences between whether we record the measurement outcome or not: the state of the qubits changes from a mixed to a pure state, as witnessed by the state’s purity; and its entanglement changes, too, as witnessed by the von Neumann entanglement entropy. We can compute both quantities easily in PennyLane, using purity() and vn_entropy(), respectively. And those will be the return types to complete our quantum function:

@qml.qnode(dev)
def bell_pair(postselect):
    bell_pair_preparation(postselect=postselect)
    return qml.purity([0, 1]), qml.vn_entropy(0)

So let’s compare the purities and von Neumann entropies of the Bell state after measurement:

without_ps = bell_pair(None)
with_ps = bell_pair(1)
print(f"                     | without ps | with ps ")
print(f"Purity               |     {without_ps[0]:.1f}    |   {with_ps[0]:.1f}")
print(f"Entanglement entropy |     {without_ps[1]:.2f}   |  {with_ps[1]:.1f}")
| without ps | with ps
Purity               |     0.5    |   1.0
Entanglement entropy |     0.69   |  -0.0

We indeed see a change in the purity and entanglement entropy based on postselection.

Qubit reset

Another commonly used feature with mid-circuit measurements is to reset the measured qubit, i.e., if we measured a \(1,\) we flip it back into to the \(|0\rangle\) state with a Pauli \(X\) operation. If there is just one qubit, this is the same as if we never measured it but reset it directly to the initial state \(|0\rangle,\) as long as we do not use the measurement outcome for anything. For the Bell pair example from above, resetting the measured qubit means that we flip the first bit if it is a \(1.\) Alternatively, we can trace out the first qubit and re-initialize it in the state \(|0\rangle.\) Denoting the reset step explicitly as \(R,\) this leads to the post-measurement state

\[\begin{split}R[M[\rho]] &=|0\rangle\langle 0|\otimes \operatorname{tr}_1[M[\rho]]\\ &=|0\rangle\langle 0|\otimes \left[\frac{1}{2}\left(|0\rangle\langle 0| + |1\rangle\langle 1|\right)\right]\\ &= |0\rangle\langle 0|\otimes \frac{1}{2}\mathbb{I}.\end{split}\]

We see that the qubits are no longer entangled, even if we do not postselect. Let’s compute some exemplary expectation values in this state with PennyLane. We recycle the state preparation subroutine from above, to which we can simply pass the keyword argument reset to activate the qubit reset:

@qml.qnode(dev)
def bell_pair_with_reset(reset):
    bell_pair_preparation(reset=reset)
    return qml.expval(qml.Z(0)), qml.expval(qml.Z(1)), qml.expval(qml.Z(0) @ qml.Z(1))

no_reset = bell_pair_with_reset(reset=False)
reset = bell_pair_with_reset(reset=True)

print(f"              | <Z₀> | <Z₁> | <Z₀Z₁> ")
print(f"Without reset |  {no_reset[0]:.1f} |  {no_reset[1]:.1f} |   {no_reset[2]:.1f}")
print(f"With reset    |  {reset[0]:.1f} |  {reset[1]:.1f} |   {reset[2]:.1f}")
| <Z₀> | <Z₁> | <Z₀Z₁>
Without reset |  0.0 |  0.0 |   1.0
With reset    |  1.0 |  0.0 |   0.0

Resetting the qubit changed the expectation values of the local observable \(Z_0\) and the global observable \(Z_0Z_1.\)

Dynamically controlling a quantum circuit

So far we’ve only talked about mid-circuit measurements that directly affect the state of qubits, about postselection, and about qubit reset as an additional step after performing the measurement. However, the outcomes of a measurement can not only be used to decide whether or not to discard a circuit execution. More importantly, as mid-circuit measurements are performed while the quantum circuit is up and running, their outcomes can be used to modify the circuit structure itself dynamically.

This technique is widely used to improve quantum algorithms or to trade off classical and quantum computing resources. It also is an elementary building block for quantum error correction, as the corrections need to happen while the circuit is running.

Here we look at a simple yet instructive example subroutine called a T-gadget, a technique related to quantum teleportation.

T-gadget in PennyLane

In fault-tolerant quantum computing, a standard way to describe a quantum circuit is to separate Clifford gates (which map Pauli operators to Pauli operators) from T gates. Clifford gates, including X, Hadamard, S, and CNOT, alone can not express arbitrary quantum circuits, but it’s enough to add the T gate to this set 5!

Applying a T gate on an error-corrected quantum computer is usually hard. A T-gadget 6 allows us to replace a T gate by Clifford gates, provided we have an auxiliary qubit in the right initial state, a so-called magic state. The gadget then consists of the following steps:

  • Prepare an auxiliary qubit in a magic state \((|0\rangle + e^{i\pi/4} |1\rangle)/\sqrt{2},\) for example using magic state distillation;

  • Entangle the auxiliary and target qubit with a CNOT;

  • Measure the auxiliary qubit with measure and record the outcome;

  • If the measurement outcome was \(1,\) apply an S gate to the target qubit. The conditional is realized with cond().

import numpy as np

magic_state = np.array([1, np.exp(1j * np.pi / 4)]) / np.sqrt(2)

def t_gadget(wire, aux_wire):
    qml.StatePrep(magic_state, aux_wire)
    qml.CNOT([wire, aux_wire])
    mcm = qml.measure(aux_wire, reset=True)  # Resetting disentangles aux qubit
    qml.cond(mcm, qml.S)(wire)  # Apply qml.S(wire) if mcm was 1

We will not derive why this works (see, e.g., 6 instead), but illustrate that this gadget implements a T gate by combining it with an adjoint T† gate and looking at the resulting action on the eigenstates of X. For this, we

  • prepare a \(|+\rangle\) or \(|-\rangle\) state, chosen by an input;

  • apply the T-gadget from above;

  • apply T†, using adjoint();

  • return the expectation value \(\langle X_0\rangle.\)

@qml.qnode(dev)
def test_t_gadget(init_state):
    qml.Hadamard(0)  # Create |+> state
    if init_state == "-":
        qml.Z(0)  # Flip to |-> state

    t_gadget(0, 1)  # Apply T-gadget
    qml.adjoint(qml.T)(0)  # Apply T^† to undo the gadget

    return qml.expval(qml.X(0))

print(f"<X₀> with initial state |+>: {test_t_gadget('+'):4.1f}")
print(f"<X₀> with initial state |->: {test_t_gadget('-'):4.1f}")
<X₀> with initial state |+>:  1.0
<X₀> with initial state |->: -1.0

The T-gadget indeed performs a T gate, which is being reversed by T†. As a result, the expectation values match those of the initial states \(|\pm\rangle.\)

How can we understand the above circuit intuitively? We did not postselect the measurement outcome, but we did record (and use) it to modify the circuit structure. For a single measurement, or shot, this would have led to exactly one of the events “measure \(0,\) do not apply S” or “measure \(1,\) apply S”, with equal probability for either one. The state on wire 0 is \(T|\pm\rangle\) in either case!

For scenarios in which the different events lead to distinct states, one has to pay attention to whether a single shot or a collection of shots is used, and to the computed measurement statistics.

Conclusion

This concludes our introduction to mid-circuit measurements. We saw how quantum mechanical measurements affect qubit systems and how postselection affects the state after measurement and validated the theoretical examples with short PennyLane examples. Then we looked into dynamic circuits powered by operations conditioned on mid-circuit measurements.

For more detailed material also check out the dedicated how-tos on mid-circuit measurement statistics and dynamic circuits, as well as the measurements quickstart page and the documentation of measure().

Happy measuring!

References

1

Michael Nielsen, Isaac Chuang “Quantum computation and quantum information”, Cambridge university press, Book website, 2010.

2

Richard P. Feynman “Feynman lectures on physics”, volume 3, open access at Caltech, 1963.

3

Barton Zwiebach “Quantum Physics II”, MIT OpenCourseWare, 2013.

4

Toeno van der Sar, Gary Steele “Open Quantum Sensing and Measurement”, open access at TUDelft, 2023.

5

Daniel Gottesman “Theory of fault-tolerant quantum computation”, Physical Review A, 57, 127, open acces at Caltech, 1998.

6(1,2)

Xinlan Zhou, Debbie W. Leung, Isaac L. Chuang “Methodology for quantum logic gate constructions”, Physical Review A, 62, 052316, arXiv quant-ph/0002039, 2000

About the author

David Wierichs
David Wierichs

David Wierichs

I like to think about differentiation and representations of quantum programs, and I enjoy coding up research ideas and useful features for anyone to use in PennyLane.

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

Share demo

Ask a question on the forum

Related Demos

How to create dynamic circuits with mid-circuit measurements

How to collect statistics of mid-circuit measurements

Measurement-based quantum computation

Quantum Teleportation

Constant-depth preparation of matrix product states with dynamic circuits

The KAK decomposition

How to use noise models in PennyLane

Noisy circuits

Stabilizer codes for quantum error correction

Pauli Propagation: Classically estimating expectation values from parametrized quantum circuits

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