Skip to content

Add mid-circuit measurement and classical feedforward - #5

Merged
jascal merged 6 commits into
mainfrom
mid-circuit-measurement
Apr 14, 2026
Merged

Add mid-circuit measurement and classical feedforward#5
jascal merged 6 commits into
mainfrom
mid-circuit-measurement

Conversation

@jascal

@jascal jascal commented Apr 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • AST: New QEffectMeasure and QEffectConditional dataclasses; QActionSignature gains mid_circuit_measure and conditional_gate optional fields
  • Parser: Recognises measure(qs[N]) -> bits[M] and if bits[M] == val: Gate(qs[K]) effect syntax; list<bit> context fields are parsed as QTypeList(element_type="bit")
  • Qiskit compiler: Uses QuantumCircuit(n_qubits, n_bits) when classical bits are present; emits qc.measure() mid-circuit and with qc.if_test((qc.clbits[M], val)): feedforward blocks; BFS traversal no longer halts at mid-circuit measurement events
  • QASM compiler: Emits c[M] = measure q[N]; inline in the gate sequence and if(c==val) gate q[K]; for conditional gates; suppresses redundant terminal measurement block when mid-circuit measurements are present
  • Verifier: check_mid_circuit_coherence (error if unitary gate applied to already-measured qubit); check_feedforward_completeness (warning if measurement result is never consumed); _has_rule now also matches custom_name so custom rule names activate the new checks
  • Examples: active-teleportation.q.orca.md (3-qubit active teleportation with X/Z feedforward), bit-flip-syndrome.q.orca.md (5-qubit syndrome extraction with mid-circuit ancilla measurement)
  • Tests: 21 new tests in tests/test_mid_circuit_measurement.py — full suite is 331 passed, 1 skipped, 0 failures

Test plan

  • pytest tests/test_mid_circuit_measurement.py — 21/21 pass
  • pytest (full suite) — 331 passed, 1 skipped, no regressions
  • Reviewer: check Qiskit qc.if_test emission for correctness against IBM Dynamic Circuits docs
  • Reviewer: verify QASM if(c==val) clause is accepted by target simulators

🤖 Generated with Claude Code

Allan Scott and others added 6 commits April 14, 2026 05:17
Implements the mid-circuit-measurement OpenSpec change:

- AST: QEffectMeasure, QEffectConditional dataclasses; new optional fields on
  QActionSignature (mid_circuit_measure, conditional_gate)
- Parser: recognize measure(qs[N]) -> bits[M] and if bits[M] == val: Gate(qs[K])
  effect syntax; list<bit> context fields parsed as QTypeList(element_type="bit")
- Qiskit compiler: QuantumCircuit(n_qubits, n_bits) for classical registers;
  emit qc.measure() mid-circuit and with qc.if_test() feedforward blocks;
  BFS no longer halts at mid-circuit measurement events
- QASM compiler: emit c[M] = measure q[N]; inline and if(c==val) gate q[K];
  terminal measurement block suppressed when mid-circuit measurements are present
- Verifier: check_mid_circuit_coherence (errors on unitary gate after measured
  qubit) and check_feedforward_completeness (warns on unused measurement result);
  _has_rule now matches custom_name for custom rules
- Examples: active-teleportation.q.orca.md, bit-flip-syndrome.q.orca.md
- Tests: 21 new tests covering parser, Qiskit, QASM, and verifier paths
  (331 passed, 1 skipped — no regressions)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace if(c==val) (OpenQASM 2, whole-register comparison) with
if (c[M] == val) { gate; } (OpenQASM 3.0, per-bit), consistent with
the OPENQASM 3.0; declaration at the top of every emitted file.

The old form gave wrong results for multi-bit classical registers:
if(c==1) on a 2-bit register tests c==01 in binary, not bit 0 alone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SUPERPOSITION_LEAK was firing for measure_alice_x/measure_s0 events
because the check only looked at event names, not whether the action
was a mid-circuit measurement (intentional, coherence-preserving) vs
a terminal collapse. Add an action-level guard: skip the leak check
when the transition's action has mid_circuit_measure set.

Also fix check_mid_circuit_coherence BFS to continue past mid-circuit
measurement transitions rather than stopping at them (terminal-only
halt), enabling correct qubit reuse detection across the full circuit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'done' was declared in the events list but had no transitions, causing
an ORPHAN_EVENT strict verify failure in CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Qiskit's QASM 3.0 importer requires single-bit conditions to be
'bit == bool' not 'bit == int'. Switch from:
  if (c[M] == 1) { gate; }
to:
  if (c[M]) { gate; }   (value == 1)
  if (!c[M]) { gate; }  (value == 0)

Verified round-trip: both examples parse successfully through
qiskit.qasm3.loads() with depth and clbit counts intact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jascal
jascal merged commit 13e0ef5 into main Apr 14, 2026
6 checks passed
@jascal
jascal deleted the mid-circuit-measurement branch April 14, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant