{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tutorial 6) Asynchronous Control\n",
"\n",
"This tutorial covers **asynchronous control** in arbok-driver, executing parts of a\n",
"sequence *conditionally* and *independently* of the main parameter sweep, rather\n",
"than running every repetition through an identical, strictly linear set of steps.\n",
"\n",
"Many experiments need this. Slow drifts in qubit frequency or microwave power can\n",
"be tracked between sweep points, or a quantum state can be prepared by\n",
"measurement in a **repeat-until-success** protocol, where the sequence only\n",
"continues once a desired outcome has been obtained.\n",
"\n",
"arbok-driver supports this through a **step requirement** mechanism. Any\n",
"sub-sequence can register a step requirement (a boolean QUA variable) on its\n",
"parent `Measurement`. This variable is evaluated at runtime before each sequence\n",
"iteration:\n",
"\n",
"- While the step requirement is **not satisfied**, no data is saved to the\n",
" stream-processing buffers.\n",
"- Sub-sequences defined with `check_step_requirements=True` are **not executed**\n",
" while the requirement is unmet.\n",
"\n",
"This lets asynchronous logic such as feedback loops or heralding protocols run\n",
"continuously alongside the main sequence, without a separate program or manual\n",
"host/FPGA coordination.\n",
"\n",
"We demonstrate this with a **heralded quantum state initialization** protocol,\n",
"building directly on the parity initialization from Tutorial 3.\n",
"\n",
"This tutorial assumes you have completed Tutorials 1–3."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 1. The Idea: Heralded Initialization\n",
"\n",
"In Tutorial 3 the measurement flowed strictly linearly:\n",
"\n",
"```\n",
"parity_init → control → parity_read\n",
"```\n",
"\n",
"Every repetition initialized the qubit pair, applied control, and read out —\n",
"regardless of whether the initialization actually produced the desired state.\n",
"\n",
"**Heralded initialization** inserts a verification layer. We measure the state\n",
"*before* accepting it for quantum control:\n",
"\n",
"```\n",
" ┌─────────────────────────── repeat until success ──┐\n",
" │ │\n",
" parity_init (heralded) → control → parity_read ───────────┘\n",
" (skipped once (only (heralds the state AND,\n",
" heralded) when once accepted, is the\n",
" heralded) actual measurement)\n",
"```\n",
"\n",
"The sequence keeps re-initializing and reading out until the readout reports the\n",
"**target state**. Only then does it accept the state, run the quantum control,\n",
"and save the measurement data. This has a nice physical bonus: the heralding\n",
"measurement itself **collapses the wavefunction** into the correct state.\n",
"\n",
"Real-time heralding of this kind is widely used in silicon spin-qubit\n",
"experiments to prepare high-fidelity initial states by measurement\n",
"[[1]](#ref-1)[[2]](#ref-2)[[3]](#ref-3).\n",
"\n",
"Three features make this cheap to build in arbok-driver, and we highlight each\n",
"below:\n",
"\n",
"1. **Heralding is added by inheritance** — `ParityInitHeralded` simply subclasses\n",
" the `ParityInit` of Tutorial 3.\n",
"2. **One readout does both jobs** — the same `ParityRead` heralds the state *and*\n",
" serves as the final measurement. The control section is toggled on/off\n",
" depending on heralding success.\n",
"3. **Data is saved conditionally** — measurement results are only streamed on\n",
" iterations where control was actually executed.\n",
"\n",
"### References\n",
"\n",
"[1] Huang, J.Y., Su, R.Y., Lim, W.H. *et al.* High-fidelity spin\n",
"qubit operation and algorithmic initialization above 1 K. *Nature* **627**,\n",
"772–777 (2024). https://doi.org/10.1038/s41586-024-07160-2\n",
"\n",
"[2] Nickl, A., Dumoulin Stuyck, N., Steinacker, P. *et al.*\n",
"Eight-qubit operation of a 300 mm SiMOS foundry-fabricated device.\n",
"*Nature Communications* **17**, 5878 (2026). https://doi.org/10.1038/s41467-026-74597-6\n",
"\n",
"[3] Steinacker, P., Dumoulin Stuyck, N., Lim, W.H. *et al.*\n",
"Industry-compatible silicon spin-qubit unit cells exceeding 99% fidelity.\n",
"*Nature* **646**, 81–87 (2025). https://doi.org/10.1038/s41586-025-09531-9"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 2. Heralding by Inheritance\n",
"\n",
"The heralded initialization lives in\n",
"[`parity_initialization_heralded.py`](../arbok_driver/examples/sequences/parity_initialization_heralded.py).\n",
"It is a thin subclass of the `ParityInit` from Tutorial 3 — the actual voltage\n",
"ramps that prepare the qubit pair are inherited unchanged. All the subclass adds\n",
"is the repeat-until-success bookkeeping.\n",
"\n",
"The essential logic is compact enough to show in full:\n",
"\n",
"```python\n",
"class ParityInitHeralded(ParityInit):\n",
"\n",
" def qua_declare(self):\n",
" # remembers the previous readout outcome\n",
" self.successful_init = qua.declare(bool, value=False)\n",
" # the step requirement gating everything downstream\n",
" self.step_requirement = qua.declare(bool, value=False)\n",
" self.measurement.add_step_requirement(self.step_requirement)\n",
" ...\n",
"\n",
" def qua_sequence(self):\n",
" # resolve the readout result we herald on\n",
" self.feedback_var = self.measurement.find_parameter_from_sub_sequence(\n",
" self.feedback_result)\n",
" with qua.if_(self.successful_init):\n",
" # already heralded -> allow downstream stages, skip re-init\n",
" qua.assign(self.step_requirement, True)\n",
" qua.wait(self.arbok_params.t_wait_post_init.qua, *self.elements)\n",
" with qua.else_():\n",
" # not yet heralded -> block downstream stages, re-initialize\n",
" qua.assign(self.step_requirement, False)\n",
" super().qua_sequence() # <- the inherited ParityInit ramps\n",
"\n",
" def qua_after_sequence(self):\n",
" # update the flag from the latest readout for the next iteration\n",
" with qua.if_(~self.successful_init):\n",
" qua.assign(self.successful_init, self.feedback_var) # target_state = 1\n",
" with qua.else_():\n",
" qua.assign(self.successful_init, False)\n",
"```\n",
"\n",
"Two things are worth noting:\n",
"\n",
"- `super().qua_sequence()` re-runs the **entire** parity initialization inherited\n",
" from Tutorial 3. Adding heralding did not require re-implementing any of the\n",
" physics.\n",
"- `add_step_requirement(...)` registers the boolean on the `Measurement`. Every\n",
" sub-sequence marked `check_step_requirements=True`, and all data saving, is\n",
" gated on it."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2.1 A config for the heralded initialization\n",
"\n",
"The heralded sequence reuses every voltage point and timing of the bare parity\n",
"initialization and adds a single new parameter: `t_wait_post_init`, the settle\n",
"time applied once initialization has been heralded. The config\n",
"[`parity_init_heralded_conf`](../arbok_driver/examples/configurations/sequence/parity_init_heralded_config.py)\n",
"is therefore just a copy of `parity_init_conf` with that one parameter added and\n",
"the sequence class swapped to `ParityInitHeralded`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-23T01:05:34.171047Z",
"iopub.status.busy": "2026-07-23T01:05:34.170395Z",
"iopub.status.idle": "2026-07-23T01:05:37.439117Z",
"shell.execute_reply": "2026-07-23T01:05:37.438257Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2026-07-23 01:05:36,054 - qm - INFO - Starting session: 6f3cfa78-54fc-437e-ad00-c8e193e76ca6\n"
]
}
],
"source": [
"from arbok_driver import ArbokDriver, Device, Measurement\n",
"from arbok_driver.examples.configurations.hardware import opx1000_config\n",
"from arbok_driver.examples.configurations.sequence import (\n",
" device_config,\n",
" parity_init_heralded_conf,\n",
" parity_read_conf,\n",
")\n",
"from arbok_driver.examples.sequences import Xstrict\n",
"\n",
"# The device master_config provides shared parameters such as the qubit\n",
"# elements used by the control sub-sequence (see Tutorial 3).\n",
"device = Device(\n",
" 'device_8q',\n",
" opx_config=opx1000_config,\n",
" divider_config={},\n",
" master_config=device_config,\n",
")\n",
"my_driver = ArbokDriver('my_driver', device)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 3. Composing the Heralded Measurement\n",
"\n",
"We build the measurement with the dictionary-based composition from Tutorial 3.\n",
"Compared to the linear CPMG example, only two things change:\n",
"\n",
"1. The initialization stage uses the heralded config and receives two extra\n",
" `kwargs`:\n",
" - `feedback_result`: the path to the readout gettable that heralds the state.\n",
" Here `'parity_read.p1p2.state__p1p2.qua_result_var'` points at the\n",
" thresholded state of the `p1p2` signal produced by the readout stage.\n",
" - `target_state`: the readout outcome that satisfies the protocol (`1`).\n",
"2. The control stage is marked `check_step_requirements=True`, so it is only\n",
" executed once the initialization has been heralded.\n",
"\n",
"As the **quantum control** we use the simplest possible operation: a single\n",
"`Xstrict` gate playing one `control_pi` pulse on `Q1`."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-23T01:05:37.441140Z",
"iopub.status.busy": "2026-07-23T01:05:37.440775Z",
"iopub.status.idle": "2026-07-23T01:05:37.453207Z",
"shell.execute_reply": "2026-07-23T01:05:37.451390Z"
}
},
"outputs": [],
"source": [
"heralded_conf = {\n",
" # Initialization stage — heralded, repeat-until-success\n",
" 'parity_init': {\n",
" 'config': parity_init_heralded_conf,\n",
" 'kwargs': {\n",
" # readout result used to herald the initialized state\n",
" 'feedback_result': 'parity_read.p1p2.state__p1p2.qua_result_var',\n",
" # accept the state once the readout reports a 1\n",
" 'target_state': 1,\n",
" },\n",
" },\n",
" # Quantum control stage — a single X gate, toggled by heralding success\n",
" 'spin_control': {\n",
" 'sub_sequences': {\n",
" 'x_gate': {\n",
" 'sequence': Xstrict,\n",
" 'kwargs': {\n",
" 'target_qubit': 'Q1',\n",
" 'control_pulse': 'control_pi',\n",
" },\n",
" },\n",
" },\n",
" # only execute this stage once the step requirement is satisfied\n",
" 'kwargs': {'check_step_requirements': True},\n",
" },\n",
" # Readout stage — heralds the state AND is the actual measurement\n",
" 'parity_read': {'config': parity_read_conf},\n",
"}\n",
"\n",
"heralded_meas = Measurement(my_driver, 'heralded_meas')\n",
"heralded_meas.add_subsequences_from_dict(heralded_conf)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.1 One readout, two jobs\n",
"\n",
"Notice that `parity_read` appears **once** in the dictionary, yet it plays two\n",
"roles:\n",
"\n",
"- **Heralding measurement.** On every iteration it measures the state. Its\n",
" thresholded `state__p1p2` result is what `ParityInitHeralded` reads through\n",
" `feedback_result` to decide whether the target state was reached.\n",
"- **Actual measurement.** On the iteration where the state has been heralded and\n",
" control has been applied, the very same readout provides the measurement data\n",
" we care about.\n",
"\n",
"The readout runs unconditionally every iteration — but its **data saving** is\n",
"gated on the step requirement (this is handled inside `ParityRead`, which wraps\n",
"its `save_variables` in `measurement.qua_check_step_requirements`). So results\n",
"are only streamed on iterations where control was executed."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 4. Compiling to QUA\n",
"\n",
"Everything compiles to a standard QUA program. Let's generate it and inspect the\n",
"key parts of the loop body."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2026-07-23T01:05:37.456875Z",
"iopub.status.busy": "2026-07-23T01:05:37.456579Z",
"iopub.status.idle": "2026-07-23T01:05:38.038251Z",
"shell.execute_reply": "2026-07-23T01:05:38.036946Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"# Single QUA script generated at 2026-07-23 01:05:38.031989\n",
"# QUA library version: 1.2.5\n",
"\n",
"\n",
"from qm import CompilerOptionArguments\n",
"from qm.qua import *\n",
"\n",
"with program() as prog:\n",
" v1 = declare(int, value=0)\n",
" v2 = declare(bool, value=False)\n",
" v3 = declare(bool, value=False)\n",
" v4 = declare(int, value=0)\n",
" v5 = declare(fixed, )\n",
" v6 = declare(fixed, )\n",
" v7 = declare(fixed, )\n",
" v8 = declare(fixed, )\n",
" v9 = declare(fixed, )\n",
" v10 = declare(fixed, )\n",
" v11 = declare(bool, )\n",
" v12 = declare(bool, )\n",
" with infinite_loop_():\n",
" pause()\n",
" assign(v1, 0)\n",
" with if_(v2):\n",
" assign(v3, True)\n",
" r2 = declare_stream()\n",
" save(v4, r2)\n",
" assign(v4, 0)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(250, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" with else_():\n",
" assign(v3, False)\n",
" assign(v4, (v4+1))\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" play(\"unit_ramp\"*amp(0.06), \"P1\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.085), \"J1\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.06), \"P2\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.07), \"P7\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.05), \"J7\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.07), \"P8\", duration=250)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(50000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" play(\"unit_ramp\"*amp(-0.0165), \"P1\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.035), \"J1\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.0165), \"P2\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.099), \"P7\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.117), \"J7\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.099), \"P8\", duration=250)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(9571, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" play(\"unit_ramp\"*amp(-0.03), \"P1\", duration=141)\n",
" play(\"unit_ramp\"*amp(0.03), \"P2\", duration=141)\n",
" play(\"unit_ramp\"*amp(-0.02), \"P7\", duration=141)\n",
" play(\"unit_ramp\"*amp(0.02), \"P8\", duration=141)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(250, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" ramp_to_zero(\"P1\")\n",
" ramp_to_zero(\"J1\")\n",
" ramp_to_zero(\"P2\")\n",
" ramp_to_zero(\"P7\")\n",
" ramp_to_zero(\"J7\")\n",
" ramp_to_zero(\"P8\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" with if_(v3):\n",
" play(\"control_pi\", \"Q1\")\n",
" align()\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" wait(25000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" play(\"unit_ramp\"*amp(0.023), \"P1\", duration=6250)\n",
" play(\"unit_ramp\"*amp(-0.02), \"J1\", duration=6250)\n",
" play(\"unit_ramp\"*amp(-0.023), \"P2\", duration=6250)\n",
" play(\"unit_ramp\"*amp(-0.0325), \"P7\", duration=6250)\n",
" play(\"unit_ramp\"*amp(0.005), \"J7\", duration=6250)\n",
" play(\"unit_ramp\"*amp(0.0325), \"P8\", duration=6250)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(25000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" measure(\"measure\", \"SET1\", integration.full(\"x_const\", v5, \"\"))\n",
" measure(\"measure\", \"SET2\", integration.full(\"x_const\", v6, \"\"))\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" wait(5000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" play(\"unit_ramp\"*amp(0.0020000000000000018), \"P1\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.0020000000000000018), \"P2\", duration=250)\n",
" play(\"unit_ramp\"*amp(-0.0025000000000000022), \"P7\", duration=250)\n",
" play(\"unit_ramp\"*amp(0.0025000000000000022), \"P8\", duration=250)\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(25000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" measure(\"measure\", \"SET1\", integration.full(\"x_const\", v7, \"\"))\n",
" measure(\"measure\", \"SET2\", integration.full(\"x_const\", v8, \"\"))\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align()\n",
" assign(v9, (v5-v7))\n",
" assign(v10, (v6-v8))\n",
" assign(v11, (v9>0.001))\n",
" assign(v12, (v10>-0.001))\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" wait(5000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" ramp_to_zero(\"P1\")\n",
" ramp_to_zero(\"J1\")\n",
" ramp_to_zero(\"P2\")\n",
" ramp_to_zero(\"P7\")\n",
" ramp_to_zero(\"J7\")\n",
" ramp_to_zero(\"P8\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\")\n",
" wait(1000, \"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align(\"P1\", \"J1\", \"P2\", \"P7\", \"J7\", \"P8\", \"SET1\", \"SET2\")\n",
" align()\n",
" with if_((v2^True)):\n",
" assign(v2, v11)\n",
" with else_():\n",
" assign(v2, False)\n",
" with if_(v3):\n",
" r3 = declare_stream()\n",
" save(v5, r3)\n",
" r4 = declare_stream()\n",
" save(v6, r4)\n",
" r5 = declare_stream()\n",
" save(v7, r5)\n",
" r6 = declare_stream()\n",
" save(v8, r6)\n",
" r7 = declare_stream()\n",
" save(v9, r7)\n",
" r8 = declare_stream()\n",
" save(v10, r8)\n",
" r9 = declare_stream()\n",
" save(v11, r9)\n",
" r10 = declare_stream()\n",
" save(v12, r10)\n",
" align()\n",
" with if_(v3):\n",
" assign(v1, (v1+1))\n",
" r1 = declare_stream()\n",
" save(v1, r1)\n",
" align()\n",
" with stream_processing():\n",
" r1.buffer(1).save(\"my_driver_heralded_meas_shots\")\n",
" r2.save_all(\"heralded_attempts\")\n",
" r3.buffer(1).save(\"my_driver_heralded_meas_parity_read_ref__p1p2\")\n",
" r4.buffer(1).save(\"my_driver_heralded_meas_parity_read_ref__p7p8\")\n",
" r5.buffer(1).save(\"my_driver_heralded_meas_parity_read_read__p1p2\")\n",
" r6.buffer(1).save(\"my_driver_heralded_meas_parity_read_read__p7p8\")\n",
" r7.buffer(1).save(\"my_driver_heralded_meas_parity_read_diff__p1p2\")\n",
" r8.buffer(1).save(\"my_driver_heralded_meas_parity_read_diff__p7p8\")\n",
" r9.buffer(1).save(\"my_driver_heralded_meas_parity_read_state__p1p2\")\n",
" r10.buffer(1).save(\"my_driver_heralded_meas_parity_read_state__p7p8\")\n",
"\n",
"config = None\n",
"\n",
"loaded_config = None\n",
"\n",
"\n"
]
}
],
"source": [
"qua_str = heralded_meas.get_qua_program_as_str()\n",
"print(qua_str)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.1 Reading the compiled program\n",
"\n",
"Look for the following structures in the output above — they are the direct\n",
"consequences of the step requirement mechanism. (`v2` is `successful_init`, `v3`\n",
"is `step_requirement`.)\n",
"\n",
"**Repeat-until-success initialization.** The heralding flag chooses between\n",
"skipping re-init and running the full inherited parity initialization:\n",
"\n",
"```python\n",
"with if_(v2): # already heralded\n",
" assign(v3, True) # -> raise the step requirement\n",
" wait(250, \"P1\", \"J1\", ...) # -> just settle\n",
"with else_(): # not yet heralded\n",
" assign(v3, False) # -> lower the step requirement\n",
" play(\"unit_ramp\"*amp(0.06), \"P1\", duration=250) # full ParityInit ramps\n",
" ...\n",
"```\n",
"\n",
"**Control gated by heralding success.** The single X gate is wrapped in the step\n",
"requirement, so it only fires once the state has been accepted:\n",
"\n",
"```python\n",
"with if_(v3):\n",
" play(\"control_pi\", \"Q1\")\n",
"```\n",
"\n",
"**Conditional data saving.** The readout runs unconditionally, but the streams\n",
"are only written — and the shot counter only advanced — when control ran:\n",
"\n",
"```python\n",
"with if_(v3):\n",
" save(v5, r3) # readout results\n",
" save(v6, r4)\n",
" ...\n",
"with if_(v3):\n",
" assign(v1, (v1+1)) # shot counter\n",
" save(v1, r1)\n",
"```\n",
"\n",
"**Flag update for the next iteration.** After the readout, the heralding flag is\n",
"refreshed from the latest thresholded state (`v11`):\n",
"\n",
"```python\n",
"with if_((v2^True)): # if this iteration was an init attempt\n",
" assign(v2, v11) # herald from the fresh readout\n",
"with else_(): # control ran this iteration\n",
" assign(v2, False) # reset -> re-initialize next shot\n",
"```\n",
"\n",
"This is a complete repeat-until-success feedback loop running entirely on the\n",
"FPGA, expressed as a handful of QUA `if_`/`else_` blocks driven by one boolean."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## 5. Summary\n",
"\n",
"Asynchronous control in arbok-driver rests on a single, simple primitive: a\n",
"boolean **step requirement** registered on the `Measurement`.\n",
"\n",
"| Concern | How it is handled |\n",
"|---|---|\n",
"| Conditional execution | Sub-sequences with `check_step_requirements=True` run only when the requirement is satisfied |\n",
"| Conditional data saving | Stream writes and the shot counter are gated on the requirement automatically |\n",
"| Feedback / heralding logic | A sub-sequence sets the requirement based on a readout result resolved via `feedback_result` |\n",
"\n",
"The heralded initialization showcased all three highlights:\n",
"\n",
"- **Inheritance made heralding cheap** — `ParityInitHeralded` subclasses\n",
" `ParityInit` and reuses its physics via `super().qua_sequence()`.\n",
"- **One readout served two purposes** — heralding the state and, once accepted,\n",
" acting as the actual measurement, with the control section toggled by\n",
" heralding success.\n",
"- **Data was saved conditionally** — only on iterations where control executed.\n",
"\n",
"Because this all lives in ordinary QUA control flow, the same pattern extends to\n",
"richer feedback protocols: drift tracking between sweep points, adaptive\n",
"calibration, or multi-stage repeat-until-success routines — all running\n",
"continuously alongside the main parameter sweep."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}