Fix gate broadcasting over multiple registers (#384) - #403
Conversation
Argus reviewAuto-review is off for this repo. Tick the box below to run a review on this PR.
Estimated cost
Tip: you can also comment |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
db4a6a1 to
902ad15
Compare
`cx q, r` with two same-size registers used to emit the linear chunk `cx q[0],q[1]; cx q[2],q[3]; cx r[0],r[1]; cx r[2],r[3]` because `_get_op_bits` flattened operand boundaries in `_visit_generic_gate_operation` before `_unroll_multiple_target_qubits` sliced the resolved qubits by gate arity. It now zips element-wise per the OpenQASM 3 spec, emitting `cx q[i], r[i]`; single-qubit operands (e.g. `cx q, r[0]`) repeat unchanged. Implementation: - Add `_get_op_bits_per_operand` returning per-operand qubit groups; keep `_get_op_bits` as a flattening wrapper for existing callers. - Preserve operand boundaries end-to-end from `_visit_generic_gate_operation` through the basic/external/custom gate visits via a new `operand_groups` parameter. - Peel `ctrl @` qubits by flat index while splitting the affected group, so `ctrl @ x q2` (qubit[2]) still works and `ctrl @ cx cq, a, b` (a, b registers) broadcasts. - Add `_broadcast_operand_groups` implementing spec element-wise broadcasting with a clear register-mismatch error naming both operands. - Extend `_visit_custom_gate_operation` to iterate once per application. - Dispatch rules in `_unroll_multiple_target_qubits`: flat_count == arity → one application; group_count == arity → spec broadcast; all-single operands with matching total → pyqasm legacy chunking; else raise. Ambiguous shapes such as `cx q, r, s` (three registers, arity 2) now raise instead of silently linear-chunking to the wrong circuit. Two existing tests encoded the old "Invalid number of qubits" message for shapes that now hit the richer new dispatch error; regexes updated. Fixes #384 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
902ad15 to
033e173
Compare
Fixes #384
Problem
Broadcasting is element-wise: every register operand must have the same length
n, the gate is applied once per index pairing operands positionally, and single-qubit operands are repeated.pyqasm flattened every operand into one list and sliced it into consecutive chunks, so
cx q, ron twoqubit[4]registers emitted the wrong circuit with no error:cx q, r[0]and the spec'sg4 qr0[0], qr1, qr2[0], qr3were rejected outright.The boundary was lost earlier than the issue suggested:
_visit_generic_gate_operationoverwroteoperation.qubitswith the flat list from_get_op_bitsbefore_unroll_multiple_target_qubitsever ran.Fix
New
_get_op_bits_per_operandreturnslist[list[...]], one inner list per source-level operand;_get_op_bitsbecomes a wrapper over it. The grouped shape threads through the basic / external / custom gate visits asoperand_groups.ctrl @peeling keeps its flat-index semantics but splits the affected group, so a ctrl boundary landing mid-register still works.Dispatch is ordered so one input matches at most one rule: exact-fit single application, then spec broadcast, then the legacy all-single-qubit chunking, else a
ValidationError.Behaviour change
Deliberate.
cx q[0], q[1], q[2], q[3](all single-qubit operands) still chunks as a pyqasm extension. Mismatched register lengths now raise naming both operands, and an ambiguous shape such ascx q, r, s(three registers, arity 2) is rejected rather than silently chunked.Two rejection tests in
tests/qasm3/resources/gates.pyhad their message regex updated — the same shapes are still rejected, with a clearer message. No test was removed.Tests
New
tests/qasm3/test_gate_broadcasting.py: two-registercx, mixed register/single-qubit, the specg4example, the size mismatch,ctrl @, and the ambiguous multi-register case.808 passed, 3 skipped.
pylint10.00/10,black+isortclean.🤖 Generated with Claude Code