Skip to content

Support classically controlled gates in Stim#3417

Open
joao-boechat wants to merge 6 commits into
joaoboechat/support-prepare-blockfrom
joaoboechat/classically-controlled-gates
Open

Support classically controlled gates in Stim#3417
joao-boechat wants to merge 6 commits into
joaoboechat/support-prepare-blockfrom
joaoboechat/classically-controlled-gates

Conversation

@joao-boechat

Copy link
Copy Markdown
Contributor

Support classically-controlled gates (rec targets) in the Stim → QIR compiler

What this is (in Stim)

Stim lets certain two-qubit controlled gates take a measurement record target
(rec[-k]) in place of a qubit control. This turns the gate into a
classically-controlled (feed-forward) operation: if the recorded measurement
bit is set, apply the target Pauli to the target qubit.

M 0
CX rec[-1] 1    # if the last measurement was 1, apply X to qubit 1
CZ 0 rec[-1]    # CZ is symmetric, so the rec may go on either side
XCZ 1 rec[-1]   # reversed order: rec on the 2nd target, X applied to qubit 1

A rec is only valid where the gate has a Z-basis control, which limits it to:

Gate (+ aliases) rec allowed on Classical action
CX / CNOT / ZCX 1st (control) X on target
CY / ZCY 1st (control) Y on target
CZ / ZCZ either (symmetric) Z on the other qubit
XCZ 2nd (the Z side) X on the 1st qubit
YCZ 2nd (the Z side) Y on the 1st qubit

Docs: Stim gate reference
(see the CX,
CZ, and
XCZ entries).

What changed

Previously these gates went through broadcast_pair, which assumes both targets
are qubits and rejects a rec as an unsupported target. The changes:

  • broadcast_controlled — a new dispatch for controlled gates. For each target
    pair it either emits the fully-quantum decomposition (both qubits) or, when a
    target is a rec, emits a classically-controlled operation.
  • classical_control — emits the feed-forward pattern (reusing the existing
    REQUIRE machinery): read the measurement result, branch, apply the gate's
    single-qubit Pauli to the target, then rejoin.
  • AllowedRecPosition (First / Second / Either) — encodes which side of a
    gate may carry a rec, so CX accepts it only on the control, XCZ only on the
    second target, and CZ on either.
  • Call sitesCX/CY/CZ/XCZ/YCZ now call broadcast_controlled, each
    supplying its quantum decomposition and its single-qubit classical action.
  • Dedicated diagnostics for the invalid cases, instead of a generic
    "unsupported target":
    • MisplacedMeasurementRecordrec on a side the gate doesn't allow.
    • NegatedMeasurementRecord — a negated control (!rec[-1]).
    • MeasurementRecordWithoutQubit — both targets are records (no qubit to act on).
  • Testsqir/tests/measurement_record_targets.rs covers every gate and every
    error case.

@joao-boechat joao-boechat marked this pull request as draft July 2, 2026 21:21
@joao-boechat joao-boechat changed the base branch from main to joaoboechat/support-prepare-block July 2, 2026 21:22
@joao-boechat joao-boechat marked this pull request as ready for review July 2, 2026 21:22
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