Add mid-circuit measurement and classical feedforward - #5
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
QEffectMeasureandQEffectConditionaldataclasses;QActionSignaturegainsmid_circuit_measureandconditional_gateoptional fieldsmeasure(qs[N]) -> bits[M]andif bits[M] == val: Gate(qs[K])effect syntax;list<bit>context fields are parsed asQTypeList(element_type="bit")QuantumCircuit(n_qubits, n_bits)when classical bits are present; emitsqc.measure()mid-circuit andwith qc.if_test((qc.clbits[M], val)):feedforward blocks; BFS traversal no longer halts at mid-circuit measurement eventsc[M] = measure q[N];inline in the gate sequence andif(c==val) gate q[K];for conditional gates; suppresses redundant terminal measurement block when mid-circuit measurements are presentcheck_mid_circuit_coherence(error if unitary gate applied to already-measured qubit);check_feedforward_completeness(warning if measurement result is never consumed);_has_rulenow also matchescustom_nameso custom rule names activate the new checksactive-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/test_mid_circuit_measurement.py— full suite is 331 passed, 1 skipped, 0 failuresTest plan
pytest tests/test_mid_circuit_measurement.py— 21/21 passpytest(full suite) — 331 passed, 1 skipped, no regressionsqc.if_testemission for correctness against IBM Dynamic Circuits docsif(c==val)clause is accepted by target simulators🤖 Generated with Claude Code