Tutorials
qcr:2606.49181.1

Introduction to Dynamic Circuits on Braket

Dynamic circuits extend the static quantum circuit model with two powerful capabilities, mid-circuit measurement and feedforward, and this Amazon Braket notebook introduces them on IQM's Garnet superconducting processor. In a conventional circuit, all measurements happen at the end; a dynamic circuit instead measures some qubits partway through and uses those classical outcomes to decide, in real time, which subsequent gates to apply (feedforward). This conditional, measurement-driven control unlocks capabilities that static circuits cannot express efficiently, and it is a prerequisite for quantum error correction, where syndrome measurements steer corrective operations. The notebook introduces the basic syntax Braket provides for mid-circuit measurement and classically-conditioned gates, shows how these primitives map onto IQM Garnet through Amazon Braket, and runs simple dynamic-circuit examples to illustrate the measure-then-act pattern. It explains the hardware and language constraints that come with this experimental capability and how results differ from purely unitary circuits. It is the entry point to the dynamic-circuit examples that follow and a hands-on introduction to one of the most important emerging features of near-term quantum hardware, presented with Amazon Braket.
Qubit
Circuit-based
Uploaded 3 days ago
12
Views
GitHub582
Citing this entry? Use this QCR ID
Uploaded by
QL
QCR Librarian

Overview

amazon-braket/amazon-braket-examples
582261
In [ ]:
# --- Setup cell added by QCR (not part of the original tutorial) ---
# Source: amazon-braket/amazon-braket-examples @ 0c0818f315479aab9deebed7e7ed7533ac581923, Apache License 2.0.
# Installs the example's dependencies. If a later cell still reports a missing
# package, restart the runtime/kernel and run again from the top.
%pip install -q amazon-braket-sdk==1.117.3

Introduction to Dynamic Circuits with Amazon Braket on IQM Garnet

In this notebook we introduce experimental dynamic circuit primitives on IQM Garnet through mid-circuit measurements (MCM) and feedforward (FF) techniques on Amazon Braket. We show the basic syntax supported on Amazon Braket and IQM Garnet, demonstrate active qubit reset and active bit flip protection experiments, detail ways to experiment with local simulators, and provide further details for using these capabilities on IQM Garnet.

What are Dynamic Circuits?

Dynamic circuits are quantum circuits involving mid-circuit measurements, qubit resets, and feedforward or classically conditioned gates. Over the last few years, most quantum devices have allowed for static quantum circuits, where all measurements are taken at the end of a quantum circuit. However, this often does not use qubits efficiently and does not allow for feedback within a circuit. One can show with the principle of deferred measurement, that the dynamic circuit and static circuit pictures are entirely equivalent.

A simple example is a bit-flip check operation on a data qubit that we would like to perform times using an ancilla. For static circuits, we require extra ancilla qubits, one per reset. However, with mid-circuit measurements and feedforward techniques we can realize the protocol with a single ancilla qubit.

A key identity for dynamic circuits is:

drawing

which we can verify by considering the effect of a unitary on an arbitrary state. Namely, for some states and we can apply a unitary such that:

drawing

and denotes taking the resulting state obtained by tracing over the measurement result.

Here it does not matter whether we apply the gate and then measure, or conditionally apply to the state given the measurement of the qubit. In other words, once we have specified a measurement, the probabilistic outcome is unaffected by whether or not it acted as a control, and so we can measure early, reuse the qubit and continue on.

  • You can verify this principle holds for density matrices as well.
  • Post-selection of a particular result can be used more generally to post-select pure states.

On real devices, this capability of measuring before the end of the circuit is known as mid-circuit measurement, and the experimental technique of feedforward allows us to condition quantum gates on the measurement outcome. These experimental operations are highly non-trivial, and their practical implementation can vary based on devices, software options, and qubit selection. Here we will focus on the implementation for IQM devices, namely IQM Garnet.

Access in Braket

In Braket, mid-circuit measurements are (as of June 2025) supported as an Experimental feature. We first specify the experimental capability context:

from braket.experimental_capabilities import EnableExperimentalCapability

We can enable this context with a with statement, and then use the Circuit().measure_ff and Circuit().cc_prx gates to specify that our measurement is being used in a dynamic circuit context. Later in the notebooks we will simplify these operations to cc_x and cc_z, which effectively combine these operations.

Configuring the Notebook

First, let's handle relevant imports and configure the notebook. If you do not want to run these on the actual hardware, don't execute the second cell, and continue until the Local Simulation section.

In [1]:
from math import pi

from braket.circuits import Circuit
from braket.experimental_capabilities import EnableExperimentalCapability
from braket.tracking import Tracker

track = Tracker().start()
In [2]:
use_qpu = True

if use_qpu:
    import iqm_config
    qd = iqm_config.qd

Hello Reset!

Here we detail a simple active reset protocol. Namely, we prepare some state, measure it, and apply a rotation conditioned on the measurement outcome. This allows us to realize the following circuit structure:

drawing

Here we classically condition a operation on the result of the qubit measurement, which effectively prepares the zero state.

In [3]:
with EnableExperimentalCapability():
    circuit = Circuit()
    circuit.prx(1, pi/2, 0.0)
    circuit.measure_ff(1, 1)
    circuit.cc_prx(1, pi, .0, 1)
    circuit = Circuit().add_verbatim_box(circuit)

    print(circuit)

    if use_qpu:
        res0 = qd.run(circuit, shots=100).result()
        print(res0.measurement_counts)
T  : │        0        │         1         │    2    │           3           │       4       │
                        ┌─────────────────┐ ┌───────┐ ┌─────────────────────┐                 
q1 : ───StartVerbatim───┤ PRx(1.57, 0.00) ├─┤ MFF→1 ├─┤ 1→CCPRx(3.14, 0.00) ├───EndVerbatim───
                        └─────────────────┘ └───────┘ └─────────────────────┘                 
T  : │        0        │         1         │    2    │           3           │       4       │
Counter({'0': 95, '1': 5})

And we have effectively reset the circuit using a dynamic circuit primitive!

Multi-Qubit Dynamic Circuits

The next step involves multi-qubit feedback, which we demonstrate with a simple bitflip protection circuit. First, we construct a non-zero state as a data qubit, and then use a measured ancilla to reset it. In the device case, we use an ancilla qubit with MCM and a classically conditioned X gate to correct the qubit.

In [4]:
qreg = [1,2]

with EnableExperimentalCapability():
    qc = Circuit()
    qc.prx(qreg[0], pi/2,pi/2).prx(qreg[0], pi, 0) # H gate

    qc.prx(qreg[1], pi/2,pi/2).prx(qreg[1], pi, 0) # H gate
    qc.cz(qreg[0],qreg[1])
    qc.prx(qreg[1], -pi, 0).prx(qreg[1], -pi/2,pi/2) # H+ gate
    qc.measure_ff(qreg[1],0)
    qc.cc_prx(qreg[0], pi, 0, 0)
    qc.cc_prx(qreg[1], pi, 0, 0)

    qc = Circuit().add_verbatim_box(qc)
    print(qc)

if use_qpu:
    res1 = qd.run(qc, shots=100).result()
    print('Shots with reset: ')
    print(res1.measurement_counts)
T  : │        0        │         1         │       2        │  3  │         4          │         5          │    6    │         7          │       8       │
                        ┌─────────────────┐ ┌──────────────┐       ┌──────────────────┐                                                                     
q1 : ───StartVerbatim───┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├───●───┤ 0→CCPRx(3.14, 0) ├───────────────────────────────────────────────────────EndVerbatim───
              ║         └─────────────────┘ └──────────────┘   │   └──────────────────┘                                                            ║        
              ║         ┌─────────────────┐ ┌──────────────┐ ┌─┴─┐  ┌───────────────┐   ┌──────────────────┐ ┌───────┐ ┌──────────────────┐        ║        
q2 : ─────────╨─────────┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├─┤ Z ├──┤ PRx(-3.14, 0) ├───┤ PRx(-1.57, 1.57) ├─┤ MFF→0 ├─┤ 0→CCPRx(3.14, 0) ├────────╨────────
                        └─────────────────┘ └──────────────┘ └───┘  └───────────────┘   └──────────────────┘ └───────┘ └──────────────────┘                 
T  : │        0        │         1         │       2        │  3  │         4          │         5          │    6    │         7          │       8       │
Shots with reset: 
Counter({'00': 87, '01': 10, '10': 3})

We can also probe the result without the active reset:

In [5]:
qreg = [1,2]

with EnableExperimentalCapability():
    qc = Circuit()
    qc.prx(qreg[0], pi/2,pi/2).prx(qreg[0], pi, 0) # H gate
    qc.prx(qreg[1], pi/2,pi/2).prx(qreg[1], pi, 0) # H gate
    qc.cz(qreg[0],qreg[1])
    qc.prx(qreg[1], pi/2,pi/2).prx(qreg[1], pi, 0) # H gate
    qc.measure_ff(qreg[1],0)
    qc.cc_prx(qreg[0], pi, 0, 0)
    # qc.cc_prx(qreg[1], pi, 0, 0)

    qc = Circuit().add_verbatim_box(qc)
    print(qc)

if use_qpu:
    res2 = qd.run(qc, shots=100).result()
    print('Shots with reset: ')
    print(res2.measurement_counts)
T  : │        0        │         1         │       2        │  3  │         4          │       5        │    6    │       7       │
                        ┌─────────────────┐ ┌──────────────┐       ┌──────────────────┐                                            
q1 : ───StartVerbatim───┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├───●───┤ 0→CCPRx(3.14, 0) ├──────────────────────────────EndVerbatim───
              ║         └─────────────────┘ └──────────────┘   │   └──────────────────┘                                   ║        
              ║         ┌─────────────────┐ ┌──────────────┐ ┌─┴─┐ ┌─────────────────┐  ┌──────────────┐ ┌───────┐        ║        
q2 : ─────────╨─────────┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├─┤ Z ├─┤ PRx(1.57, 1.57) ├──┤ PRx(3.14, 0) ├─┤ MFF→0 ├────────╨────────
                        └─────────────────┘ └──────────────┘ └───┘ └─────────────────┘  └──────────────┘ └───────┘                 
T  : │        0        │         1         │       2        │  3  │         4          │       5        │    6    │       7       │
Shots with reset: 
Counter({'00': 56, '01': 34, '10': 5, '11': 5})

And we have successfully applied our first multi-qubit reset operations!

Local Simulation

The measurement and classically controlled feedforward heres allow us to effectively implement an if style logic, which for many applications can be aggregated into a single gate, a classical controlled , or cc_x gate.

Here, we use a form which concatenates the measurement, control, and qubit reset in one gate. We then can use the local Braket backends (braket_dm) to carry out these simulations. To simplify notation as well, we will move from the native gates to standard Clifford gates.

  • Note, cc_x is a custom, user-defined gate, defined in local_config.py. Use the reset keyword to specify an active reset.
In [6]:
import local_config

qd = local_config.qd

Importing local_config registers the correct set of gates, and adds the cc_x gate.

In [7]:
circuit = Circuit()
circuit.h(0)
circuit.cc_x([0])

print(circuit)
res3 =  qd.run(circuit, shots=100).result()
print(res3.measurement_counts)
T  : │         0         │           1           │
      ┌─────────────────┐ ┌──────────────┐ ┌────┐ 
q0 : ─┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├─┤ KR ├─
      └─────────────────┘ └──────────────┘ └────┘ 
T  : │         0         │           1           │
Counter({'0': 100})

Now, we can implement the same two-qubit experiment as well.

In [8]:
circuit = Circuit()
circuit.h(0)
circuit.cnot(0,1)
circuit.cc_x([1,0], reset=False)
print(circuit)
res4 =  qd.run(circuit, shots=100).result()
print(res4.measurement_counts)
T  : │         0         │       1        │  2  │        3        │             4             │
      ┌─────────────────┐ ┌──────────────┐                                              ┌────┐ 
q0 : ─┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├───●──────────────────────────────────────────┤ KR ├─
      └─────────────────┘ └──────────────┘   │                                          └─┬──┘ 
      ┌─────────────────┐ ┌──────────────┐ ┌─┴─┐ ┌───────────────┐ ┌──────────────────┐ ┌─┴──┐ 
q1 : ─┤ PRx(1.57, 1.57) ├─┤ PRx(3.14, 0) ├─┤ Z ├─┤ PRx(-3.14, 0) ├─┤ PRx(-1.57, 1.57) ├─┤ KR ├─
      └─────────────────┘ └──────────────┘ └───┘ └───────────────┘ └──────────────────┘ └────┘ 
T  : │         0         │       1        │  2  │        3        │             4             │
Counter({'01': 51, '00': 49})

And we have demonstrated our classical controlled measurement and feedback for qubit and data reset operations!

Predicted Costs

The local example can be run at no cost. The QPU costs are given below:

In [10]:
print("Quantum Task Summary")
print(track.quantum_tasks_statistics())
print(
    "\nNote: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage.\nEstimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits,\nand you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2).",
)
print(
    f"\nEstimated cost to run this example: {track.qpu_tasks_cost()} USD",
)
Quantum Task Summary
{<_IQM.Garnet: 'arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet'>: {'shots': 300, 'tasks': {'COMPLETED': 3}}}

Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage.
Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits,
and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2).

Estimated cost to run this example: 1.3350000000 USD

Notes on IQM Devices and Usage in Braket

For IQM's Garnet, there are a few notes on dynamic circuit creation for practical use. These are summarized here and further detailed in the Braket Developer Guide.

  1. Current systems only allow a surjective mapping from control qubits to target qubits; each channel can listen to only a single qubit source.
    • All feedback qubits should only have one source!
  2. The device layout for IQM Garnet has two "groups", which limit the measurement and feed forward applications. Make sure your qubits and operations are in these groups.
drawing
  1. The measure_ff gate does not implement active qubit reset, so cc_x has an optional reset flag (with default reset=True).
  2. Use of verbatim boxes requires pre-transpilation to IQM-native gates.
  3. Some Braket ResultType instances may not be supported, and so basic measurement instructions are recommended.

Conclusions

In this notebook we began our exploration of dynamic circuits using IQM's Garnet with Amazon Braket. Dynamic circuits represent a powerful tool beyond static circuit structures which will be essential for future quantum computing applications, and which we explore in the next notebooks.

References:

  1. Zhou, Leung, Chuang. Methodology for quantum logic construction. (2000) arXiv:0002039.
  2. Corcoles, Takia, Inoue et al. Exploiting dynamic quantum circuits in a quantum algorithm with superconducting qubits. (2021) Phys. Rev. Lett. 127, 100501, arXiv
  3. Explore Experimental Capabilities. Amazon Braket Developer Guide (June 2025) https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html

Join the Discussion

Comments (0)

No comments yet. Be the first to share your thoughts!

Indexed by QCR Librarian

This entry was created automatically from publicly available records. QCR links to public sources and only stores repository content where the license permits redistribution.

Versions

v1 Latest
Jun 16, 2026
qcr:2606.49181.1

Cite all versions? Use the base QCR ID to always reference the latest version of this entry.

Tools used

Amazon Braket SDK

Keywords

dynamic-circuits
mid-circuit-measurement
feedforward
braket
iqm

You may also like5