Skip to content

Fix barrier unrolling to preserve multi-qubit barrier statements#295

Open
ryanhill1 wants to merge 5 commits intomainfrom
feat/composer
Open

Fix barrier unrolling to preserve multi-qubit barrier statements#295
ryanhill1 wants to merge 5 commits intomainfrom
feat/composer

Conversation

@ryanhill1
Copy link
Member

@ryanhill1 ryanhill1 commented Mar 5, 2026

Summary

  • Barriers now unroll as a single multi-qubit statement (e.g. barrier q[0], q[1], q[2]) instead of splitting into individual per-qubit barriers
  • Fixed physical qubit handling in the barrier consolidation path to iterate over all qubits instead of only the first

Summary by CodeRabbit

  • Bug Fixes
    • Barrier handling now preserves multi-qubit barrier statements as single directives (including ranges and mixed qubit specs) instead of splitting them into per-qubit barriers.
  • Tests
    • Updated and added tests to expect consolidated multi-qubit barrier output across QASM2/QASM3, device-qubit mapping, range unrolling, and visualization rendering.

ryanhill1 and others added 2 commits March 4, 2026 21:28
Support barrier merge/split operations in transformer, fix visitor
handling of physical qubits, and add corresponding tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: de5d2fba-5895-4db7-9709-5dfd5e4cec3e

📥 Commits

Reviewing files that changed from the base of the PR and between b11a92e and 65c00b4.

📒 Files selected for processing (2)
  • src/pyqasm/visitor.py
  • tests/visualization/test_mpl_draw.py

Walkthrough

Barrier unrolling now preserves multi‑qubit barrier directives as single statements. The visitor expands barrier ranges into explicit qubit indices; the transformer maps each qubit to device indices and rewrites qubit references. Tests and CHANGELOG updated to expect consolidated, comma‑separated barrier statements.

Changes

Cohort / File(s) Summary
Barrier Consolidation Logic
src/pyqasm/visitor.py, src/pyqasm/transformer.py
Visitor adds _expand_barrier_ranges and expands barrier ranges to explicit IndexedIdentifier entries; transformer now iterates all qubits in a barrier (Identifiers, RangeDefinitions, IndexedIdentifiers), maps each to device indices, and rewrites references to __PYQASM_QUBITS__[...], emitting a single multi‑qubit barrier instead of per‑qubit barriers.
Tests — QASM2 / QASM3
tests/qasm2/test_operations.py, tests/qasm3/test_barrier.py, tests/qasm3/test_device_qubits.py
Updated expected outputs from multiple single‑qubit barriers to consolidated comma‑separated barrier statements; added test_unrolled_barrier_with_range to validate range consolidation and device qubit mapping.
Visualization Tests
tests/visualization/test_mpl_draw.py
Added test_draw_barriers to verify rendering of consolidated barriers across multiple qubit patterns (individual, ranges, mixed registers).
Changelog
CHANGELOG.md
Added Unreleased entry noting barrier unrolling now preserves multi‑qubit barrier statements rather than splitting into per‑qubit barriers.

Sequence Diagram

sequenceDiagram
    participant Parser as Visitor / Parser
    participant Barrier as Barrier Statement
    participant Transformer as Transformer
    participant Emitter as Emitter / Output

    Parser->>Barrier: parse barrier (identifiers, ranges, indexed ids)
    Barrier-->>Parser: expanded qubit list (ranges -> explicit indices)
    Parser->>Transformer: pass single expanded_barrier
    Transformer->>Transformer: iterate qubits -> map to device indices
    Transformer->>Transformer: rewrite qubit refs to __PYQASM_QUBITS__[…]
    Transformer-->>Emitter: emit single consolidated barrier statement
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: preserving multi-qubit barrier statements instead of splitting them into per-qubit barriers, which is reflected across the code changes in transformer.py, visitor.py, and test files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/composer

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ryanhill1 ryanhill1 marked this pull request as ready for review March 5, 2026 05:25
@ryanhill1 ryanhill1 requested a review from TheGupta2012 as a code owner March 5, 2026 05:25
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pyqasm/transformer.py`:
- Line 508: The long call that passes _qubit_str.name, ind.value,
qubit_register_offsets, global_qreg_size_map exceeds the line-length limit;
split the arguments across multiple lines (or assign a temporary
tuple/list/kwargs) so each line stays under the formatter max length, e.g.,
break the argument list into one-per-line inside the enclosing parentheses where
this call occurs (look for the call site involving _qubit_str.name and ind.value
in transformer.py) and ensure you keep proper commas and indentation to satisfy
the linter.
- Around line 495-499: The current code mutates Identifier.name to embed slice
syntax (the block setting _qubit_id.name to "__PYQASM_QUBITS__[...]" when
handling barrier ranges), which breaks downstream consumers; instead, replace
that mutation by constructing an IndexedIdentifier whose index is a
RangeDefinition built from IntegerLiteral nodes (use IndexedIdentifier,
RangeDefinition, IntegerLiteral) so the AST retains a proper range node; modify
the branch that handles consolidate_qubits=True and unroll_barriers=False (the
branches that set _qubit_id.name for the three cases: full slice, open-ended
slice, and start:end slice) to create and assign an IndexedIdentifier containing
a RangeDefinition with appropriate IntegerLiteral start/end (or omitted for
open-ended), rather than changing Identifier.name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8e92d3f6-bf8b-4503-9dbc-a450dc116df4

📥 Commits

Reviewing files that changed from the base of the PR and between a8736e7 and 66764e3.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • src/pyqasm/transformer.py
  • src/pyqasm/visitor.py
  • tests/qasm2/test_operations.py
  • tests/qasm3/test_barrier.py
  • tests/qasm3/test_device_qubits.py

@codecov-commenter
Copy link

codecov-commenter commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ryanhill1 ryanhill1 linked an issue Mar 5, 2026 that may be closed by this pull request
@ryanhill1
Copy link
Member Author

ryanhill1 commented Mar 5, 2026

Building circuit composer on account. This update is needed from pyqasm to support the backend. So linking that issue here. This PR will close the issue because the bulk of the issue is being actively worked on elsewhere, and this is the only pyqasm related change needed (as far as I can tell)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pyqasm/transformer.py`:
- Around line 503-511: The loop that remaps indices (iterating _qubit_ind and
then ind) assumes each ind is an IntegerLiteral and accesses ind.value, which
fails for RangeDefinition nodes (e.g., q[0:2]); update the logic in
consolidate_qubit_registers (used when consolidate_qubits=True and
unroll_barriers=False) to guard against non-literal nodes: before accessing
ind.value, check the node type (e.g., isinstance(ind, IntegerLiteral)); if it's
an IntegerLiteral, call _get_pyqasm_device_qubit_index(_qubit_str.name,
ind.value, qubit_register_offsets, global_qreg_size_map) and assign back to
ind.value; if it's a RangeDefinition (or other range node), explicitly handle it
by remapping its bounds/contained indices to device indices (iterate its
start..end or child indices and replace those elements with remapped
IntegerLiteral nodes or update the range representation accordingly) instead of
directly accessing .value; apply the same guarded handling to the equivalent
loops used for measurement and reset remapping that call
_get_pyqasm_device_qubit_index.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fa6f2d82-5d5f-4134-b1f0-6c1bedea8b5d

📥 Commits

Reviewing files that changed from the base of the PR and between 66764e3 and dcd3ce8.

📒 Files selected for processing (2)
  • src/pyqasm/transformer.py
  • src/pyqasm/visitor.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pyqasm/visitor.py`:
- Around line 782-799: The consolidation logic incorrectly expands barrier
operands by comparing register names in barrier_qubits (using eq.name.name and
_global_qreg_size_map) which collapses aliases and over-consumes adjacent
operands; instead, for each original operand (op_qubit) call the expansion
routine (_get_op_bits or equivalent used upstream) and append that operand's
concrete list of qubit bits to consolidated_qubits, advancing expanded_idx by
the number of bits produced for that operand rather than scanning by name;
update the loop around expanded_idx/op_qubit to use the per-operand expanded
list and remove name-based comparisons (eq.name.name and qubit_name) so
constructs like "let a = q; barrier a;" and mixed slices "barrier q[0:2], q[3]"
expand correctly.

In `@tests/visualization/test_mpl_draw.py`:
- Around line 132-134: The test uses _check_fig(circ, fig) which only inspects
ax.texts and therefore misses barrier rendering (barriers are drawn as
collections/patches in src/pyqasm/printer.py); update the test to assert
directly on the Matplotlib artists created by mpl_draw by checking
fig.axes[0].collections and fig.axes[0].patches for the expected barrier artists
(or modify _check_fig to include those checks), or alternatively convert this
test into an mpl_image_compare style test to verify the rendered barrier
visually.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 904f7298-2e15-472c-9773-6ebdab088724

📥 Commits

Reviewing files that changed from the base of the PR and between dcd3ce8 and b11a92e.

📒 Files selected for processing (3)
  • src/pyqasm/visitor.py
  • tests/qasm3/test_device_qubits.py
  • tests/visualization/test_mpl_draw.py

Replace name-based comparisons in _expand_barrier_ranges with per-operand
expansion counting via _get_op_bits, fixing incorrect behavior for aliases
and mixed same-register slices. Add barrier-specific artist assertions to
test_draw_barriers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Minimal QASM-based circuit composer

2 participants