Skip to content

feat(stim-parser)!: require *pi in rotation/U3 tag angles (no bare rotation gates)#163

Open
david-pl wants to merge 4 commits into
mainfrom
david/require-pi-tag-angles
Open

feat(stim-parser)!: require *pi in rotation/U3 tag angles (no bare rotation gates)#163
david-pl wants to merge 4 commits into
mainfrom
david/require-pi-tag-angles

Conversation

@david-pl

Copy link
Copy Markdown
Collaborator

Supersedes #159

This PR replaces #159 (david/parse-bare-rotations). It keeps only the tag-parsing tightening from that PR and drops the bare rotation-gate support, matching tsim semantics rather than clifft's bare half-turn shorthand.

#159 should be closed in favor of this one.

What changes

  • No bare R_X / R_Y / R_Z / U3 gates. The bare clifft-style mnemonics (R_Z(0.5) 0, U3(a,b,c) 0) are not registered, so they are rejected as unknown instruction — the same as on main. Only tsim's canonical tagged form is accepted.
  • *pi is strictly required in rotation/U3 tag angles. Mirroring tsim's parametric-tag convention, angles must be written in half-turns as <n>*pi (e.g. I[R_Z(theta=0.5*pi)]). A bare number (I[R_Z(theta=0.5)]) is now rejected with an invalid-tag diagnostic rather than silently read as radians.
  • Printer re-emits the clean <c>*pi form with the shortest exact coefficient (no 0.7599999999999999*pi rounding tail), keeping parse → print a byte-for-byte fixpoint.
  • T / T_DAG bare gates now reject tags (T[foo] 0 previously parsed and silently dropped the tag) — an orthogonal tightening included here.

Behavior

Input Result
I[R_Z(theta=0.5*pi)] 0 ✅ accepted, round-trips
I[R_Z(theta=0.5)] 0 parameter 'theta' must be written as <n>*pi (half-turns)
R_Z(0.5) 0 unknown instruction 'R_Z'
U3(0.5, 1.0, 1.5) 0 unknown instruction 'U3'
I[U3(theta=0.3*pi, …)] 0 ✅ accepted, round-trips

Commits

  1. feat(stim-parser)!: require *pi in rotation/U3 tag angles
  2. fix(stim-parser): reject tags on bare T/T_DAG gates
  3. fix(stim-parser): print shortest exact *pi coefficient (no rounding tail)
  4. test(ppvm-stim): U3 with all angles nonzero exercises phi/lambda half-turns

Testing

  • cargo test -p stim-parser -p ppvm-stim — all green.
  • pytest test/test_stim_api.py — 22 passed (native module rebuilt).

🤖 Generated with Claude Code

david-pl and others added 4 commits June 26, 2026 10:40
Mirror tsim's parametric-tag convention: rotation and U3 tag angles
must be written in half-turns as `<n>*pi` (e.g. `I[R_Z(theta=0.5*pi)]`),
and a bare number (`I[R_Z(theta=0.5)]`) is now rejected with an
`invalid-tag` diagnostic. tsim's tag parser requires the `*pi` literal
(`core/parse.py`, regex `^\w+=<float>\*pi$`) and treats the coefficient
as half-turns; ppvm now refuses the ambiguous bare form rather than
silently reading it as radians.

Mechanics:
- `TagParam::Named` gains a `had_pi` flag, captured by a new
  `pi_expr_flagged` grammar rule (pi_expr is now defined in terms of it).
- `exact_named_params` rejects any rotation/U3 angle written without `*pi`.
- The printer re-emits the half-turn form (`theta={theta/pi}*pi`); since
  every parser-produced rotation angle is a `<n>*pi` multiple, theta/pi
  recovers the coefficient exactly (verified for the relevant float set),
  so print -> parse stays a fixpoint.

Tests across extended/roundtrip/proptest suites move to the `*pi` form;
the proptest AST generator now produces `coeff*pi` angles (the only
parser-producible shape). The ppvm-python fixpoint test is updated too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The native T / T_DAG arms dropped any tag the same way the gate body is
lowered (e.g. `T[foo] 0` parsed and silently lost `[foo]`). A tag has no
meaning on the bare mnemonics — the tagged form is S[T] / S_DAG[T] — so
reject a non-empty tag list with an `invalid-tag` diagnostic that points
at the canonical tagged spelling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ail)

The rotation/U3 printer emitted `theta/PI` directly, so the division's
rounding leaked into the output: `theta=0.76*pi` printed as
`theta=0.7599999999999999*pi`. Roughly 10% of ordinary decimal angles
were affected.

`pi_coeff` now returns the shortest decimal `c` whose `c * PI` recovers
the stored radians bit-for-bit, falling back to `value / PI` when no exact
short form exists. Because acceptance requires exact equality, this both
prints cleanly and keeps `parse → print` lossless and the printer a
byte-for-byte fixpoint — verified by a new property test over arbitrary
decimal coefficients (exact theta recovery + fixpoint + no rounding tail)
plus a unit test covering rotation and U3 tags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-turns

The only U3 execution test used phi=lambda=0, so the half-turn scaling of
phi/lambda was never exercised end-to-end (flagged in review). Add a test
using U3(theta=pi, phi=pi/2, lambda=pi/2) == Y, framed as H·U3·H so the
qubit flips to |1> deterministically. The H frame makes the outcome
sensitive to phi *and* lambda: dropping or mis-scaling either collapses
P(1) to ~0.5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 26, 2026 08:55
@david-pl david-pl requested a review from Roger-luo June 26, 2026 08:58
@david-pl

Copy link
Copy Markdown
Collaborator Author

FYI, @Roger-luo I checked again and these are the semantics as emitted by bloqade and parsed by tsim.

@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://QuEraComputing.github.io/ppvm/pr-preview/pr-163/

Built to branch gh-pages at 2026-06-26 08:59 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens stim-parser’s extended-dialect rotation/U3 tag parsing to match tsim semantics: rotation/U3 tag angles must be written in half-turns as "<n>*pi", and the printer re-emits a canonical *pi form that round-trips without floating-point “rounding tail” artifacts. It also tightens parsing of bare T/T_DAG by rejecting (previously ignored) tags.

Changes:

  • Require *pi in I[R_X(...)] / I[R_Y(...)] / I[R_Z(...)] / I[U3(...)] tag parameters (bare numbers now produce invalid-tag).
  • Track whether pi appeared in named tag parameters (had_pi) and print rotation/U3 angles as the shortest exact <c>*pi coefficient to preserve parse→print fixpoints.
  • Add/adjust tests across stim-parser, ppvm-stim, and Python API tests to reflect the stricter grammar and canonical printing.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ppvm-python/test/test_stim_api.py Updates Python stim API test input to use theta=…*pi syntax.
crates/stim-parser/tests/tags.rs Updates tag parsing test to assert had_pi is captured.
crates/stim-parser/tests/roundtrip.rs Updates the fixed round-trip corpus to the *pi form for rotations/U3.
crates/stim-parser/tests/proptest_roundtrip.rs Updates proptest fragments to *pi and adds property coverage for clean *pi coefficient printing and exact round-trips.
crates/stim-parser/tests/proptest_ast.rs Adjusts AST generators to produce rotation/U3 radians as coefficient * PI (aligned with new tag requirements).
crates/stim-parser/tests/extended.rs Updates extended parsing/lowering tests to expect radians scaled by PI.
crates/stim-parser/src/syntax/grammar.rs Adds pi_expr_flagged and records had_pi for named parameters.
crates/stim-parser/src/print/mod.rs Prints rotation/U3 tags in canonical <c>*pi form and adds pi_coeff recovery to avoid rounding tails.
crates/stim-parser/src/pipeline/validate.rs Updates validation tests to include had_pi in constructed TagParam::Named.
crates/stim-parser/src/pipeline/lower.rs Enforces had_pi for rotation/U3 required params and rejects tags on bare T/T_DAG.
crates/stim-parser/src/ast/shared.rs Extends TagParam::Named with the had_pi flag (syntax provenance).
crates/ppvm-stim/tests/executor.rs Updates U3 test inputs to *pi and adds coverage that exercises nonzero phi/lambda.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants