feat(gates): add RotXY in-plane single-qubit rotation (R gate)#170
Merged
Conversation
Add the `RotXY` trait to `ppvm-traits` and implement it for both
backends (`ppvm-tableau`, `ppvm-pauli-sum`), plus the `r(...)` Python
binding on the native PauliSum / tableau classes and the
`RotationsMixin` / `TruncatingRotationsMixin` wrappers.
`RotXY` is a single-qubit rotation about an arbitrary axis in the X/Y
plane:
R(axis_angle, θ) = exp(-i θ/2 · (cos(axis_angle)·X + sin(axis_angle)·Y))
= RZ(axis_angle)·RX(θ)·RZ(−axis_angle)
Pure addition alongside the existing `RotationOne` (RX/RY/RZ) rotations;
no new module wiring. Native type stubs (`.pyi`) for the whole module
are split into a separate follow-up PR. Snapshotted from #168, where the
R gate is a prerequisite for the circuit-component backends.
Merge order for the #168 split: single-qubit rotations (this) and core
tableau expectation/reset target `main` independently; native .pyi stubs
stack on this; then vihaco-circuit-isa (#169) -> circuit component ->
composite -> CLI/TUI (#166).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 8, 2026
|
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for an in-plane single-qubit rotation gate R(axis_angle, θ) across the Rust trait layer, both simulation backends (tableau + PauliSum), and the Python API surface, including targeted regression tests to ensure the intended Heisenberg/Schrödinger ordering semantics.
Changes:
- Introduces the
RotXYtrait inppvm-traitsand re-exports it for downstream consumers. - Implements
RotXY::rforGeneralizedTableau(Schrödinger picture viaRZ(-φ) → RX(θ) → RZ(φ)) and forPauliSum(Heisenberg picture ordering). - Exposes
r(...)in the native Python bindings and Python mixins, and adds Rust + Python tests validating key identities (e.g.,axis_angle=0 => RX,axis_angle=π/2 => RY).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| ppvm-python/test/test_basics.py | Adds PauliSum-level Python tests for r(...) matching rx/ry special cases. |
| ppvm-python/test/generalized_tableau/test_basics.py | Adds GeneralizedTableau Python tests confirming r(...) reduces to rx/ry at key axis angles. |
| ppvm-python/src/ppvm/mixins.py | Adds r(...) to RotationsMixin and TruncatingRotationsMixin with docstring math and truncation support. |
| crates/ppvm-traits/src/traits/mod.rs | Re-exports RotXY from the traits prelude. |
| crates/ppvm-traits/src/traits/branch/rot1.rs | Defines the new RotXY trait and documents the RZ(φ) RX(θ) RZ(-φ) decomposition. |
| crates/ppvm-traits/src/traits/branch/mod.rs | Re-exports RotXY from the branch module. |
| crates/ppvm-tableau/src/gates/rot1.rs | Implements RotXY for GeneralizedTableau and adds backend-level tests for identity/special cases/statistics equivalence. |
| crates/ppvm-python-native/src/interface.rs | Adds native PauliSum binding r(addr0, axis_angle, theta, truncate=True). |
| crates/ppvm-python-native/src/interface_tableau.rs | Adds native tableau binding r(addr0, axis_angle, theta). |
| crates/ppvm-pauli-sum/src/sum/rot1.rs | Implements RotXY for PauliSum and adds a test guarding the Heisenberg-order sign convention. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
david-pl
added a commit
that referenced
this pull request
Jul 8, 2026
## Merge order Part of splitting #168 into small, focused PRs. Full stack (independent items may merge in any relative order; dependents wait for their base): 1. single-qubit rotations (#170) → `main` 2. **core tableau expectation/reset (this PR)** → `main` 3. native `.pyi` type stubs (`feat/native-pyi-stubs`) → #170 4. vihaco-circuit-isa (#169) → `main` 5. circuit component (`david/42.2-circuit-component`) → #169 6. composite (`david/42.3-composite`) → #5 7. CLI + TUI (#166) → #6 Items 1, 2, and 4 are mutually independent off `main`. ## Summary Adds `expectation.rs` for `GeneralizedTableau`: - `expectation` — single-Pauli ⟨ψ|P|ψ⟩ for a `PauliWord`, conjugating P through the tableau and overlapping with the sparse coefficient vector. - `trace` — Σ over Paulis matching a `PauliPattern`. Supporting changes in `data.rs`: - `compute_decomposition_word` — multi-qubit conjugation used by `expectation`. - `reset_all` on both `Tableau` and `GeneralizedTableau` — reinitialise to |0…0⟩, clearing coefficients and loss state (refactors `new` via a shared `new_data` helper). - the rayon-nesting guard on the coefficient path (avoids nesting rayon inside shot-level parallelism; a no-op on the single-shot path). `lib.rs` gains `pub mod expectation`; `Cargo.toml` gains a `ppvm-pauli-word` dependency. Pure core addition, snapshotted from #168. ## Testing `cargo test -p ppvm-tableau` green (12 expectation tests + reset/noise). prek hooks all pass. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
david-pl
added a commit
that referenced
this pull request
Jul 8, 2026
## Merge order Part of the #168 split. **Stacked on #170** (base branch `feat/single-qubit-rotations`) because this stub file declares the native `r` binding that #170 adds. Merge #170 first, then this. Full stack: single-qubit rotations (#170) → **this** ; core tableau expectation/reset (`feat/tableau-expectation-reset`) → `main` ; vihaco-circuit-isa (#169) → `main` ; then circuit component → composite → CLI/TUI (#166). ## Summary Adds `ppvm_python_native.pyi` — the first type-stub file for the compiled `ppvm._core` module (none exists on `main`). It declares the macro-generated concrete classes (`PauliSumIndexMapFxHash{0..15}`, `PauliSumLossIndexMapFxHash{0..15}`, the `GeneralizedTableau{N}` family, `StimProgram`) via synthetic `_PauliSumBase` / `_PauliSumLossBase` / `_GeneralizedTableauBase` bases that hold the shared method signatures once. Pure additive typing surface; no runtime effect. Split out of #170 because the block covers the whole module — only `r` is new API; the rest describe pre-existing bindings. ## Provenance Snapshotted from the tip of #168. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 8, 2026
Roger-luo
added a commit
that referenced
this pull request
Jul 13, 2026
## Merge order Part of the #168 split. This PR targets **#169** (`david/42.1-vihaco-isa`), not `main`, and stacks on the core prerequisites: 1. RotXY / R gate (#170) → `main` ✅ merged 2. tableau expectation/reset (#172) → `main` ✅ merged 3. vihaco-circuit-isa (#169) → `main` (open; has `main` merged in, so it carries #170 + #172) 4. native `.pyi` stubs (#171) → `main` (open; independent of this line) 5. **circuit component (this PR)** → #169 6. composite (`david/42.3-composite`) → this PR 7. CLI + TUI (#166) → #6 ## Summary Introduces the `ppvm-vihaco` crate with just the **circuit component** slice — the piece that dispatches gates to a backend. The composite machine that drives it (VM, bytecode, syntax, shots) is the next PR. | File | What | |------|------| | `component.rs` | `Circuit` — dispatches `CircuitInstruction`s to a tableau / PauliSum / lossy-PauliSum backend, emitting measurement + trace effects (incl. the R gate and trace/reset, now that #170/#172 are in `main`) | | `measurements.rs` | measurement / trace effect + observer types | | `device_info.rs` | `PPVM_MAGIC`, `BackendKind`, `PPVMDeviceInfo` — **relocated** out of the composite so the component compiles standalone; the composite PR imports them from here | | `lib.rs` | component-only module wiring; composite-driven `load`/`run`/`dump`/`parse` helpers come with the composite | ## Notes - **`device_info.rs`**: the whole `PPVM_MAGIC` + `BackendKind` + `PPVMDeviceInfo` cluster moved (the struct can't compile without the other two). In #5, `composite.rs` imports these instead of defining them. - **machete ignore** for `chumsky` + `vihaco-parser-core` — pulled in only via the `vihaco_parser::Parse` derive on `BackendKind` (mirrors the isa crate). ## Testing `cargo test -p ppvm-vihaco` — 2 smoke tests (single-qubit flip + CNOT propagation through the component's dispatch). Fuller integration coverage arrives with the composite's `.sst` fixtures. Full workspace builds; clippy + machete clean. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Xiu-zhe (Roger) Luo <rluo@quera.com>
david-pl
added a commit
that referenced
this pull request
Jul 14, 2026
## Merge order Part of the #168 split. This PR targets **#173** (`david/42.2-circuit-component`) and sits at the top of the vihaco line: 1. RotXY / R gate (#170) → `main` ✅ merged 2. tableau expectation/reset (#172) → `main` ✅ merged 3. vihaco-circuit-isa (#169) → `main` (open; carries #170 + #172 via a `main` merge) 4. native `.pyi` stubs (#171) → `main` (open; independent) 5. circuit component (#173) → #169 6. **composite machine + VM (this PR)** → #173 7. CLI + TUI (#166) → this PR ## Summary Completes the `ppvm-vihaco` crate on top of the circuit component (#173) — the composite machine that drives it plus the surrounding VM. | File | What | |------|------| | `composite.rs` | the `PPVM` composite: vihaco machine (CPU + program loader) driving the circuit component, measurement/trace observers, backend selection from the device header, reset, single-instruction stepping | | `syntax.rs` | `.sst` header parse / lower (`PPVMHeader`, `PPVMResolver`) | | `bytecode.rs` | `.ssb` bytecode emit / load (magic-tagged) | | `observable.rs` | observable-header parsing for the PauliSum backends | | `shots.rs` | multi-shot execution (serial + optional `rayon`) | | `lib.rs` | full module wiring + `load`/`run`/`dump`/`compile`/`parse` helpers + `PPVMModule` | | `Cargo.toml` | adds `vihaco-cpu`, `log`, optional `rayon` feature | | `tests/*.sst` + `sst_fixtures.rs` | 28 integration fixtures | ## `device_info` relocation resolves here `composite.rs` no longer defines `PPVM_MAGIC` / `BackendKind` / `PPVMDeviceInfo` — it imports them from `device_info` (introduced in #173) and `pub use`-re-exports them, so the existing `crate::composite::{…}` paths in `lib.rs` / `bytecode.rs` / `syntax.rs` keep resolving with no other edits. The machete-ignore added in #173 is dropped here — the full crate uses `chumsky` / `vihaco-parser-core` directly. ## Testing `cargo test -p ppvm-vihaco` — **111 unit + 28 integration** tests, green with and without `--features rayon`. Full workspace builds; clippy + machete clean. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
david-pl
added a commit
that referenced
this pull request
Jul 14, 2026
## Merge order Part of the #168 split. This PR targets **#174** (`david/42.3-composite`) and adds the CLI binary the TUI PR builds on: 1. RotXY / R gate (#170) → `main` ✅ merged 2. tableau expectation/reset (#172) → `main` ✅ merged 3. vihaco-circuit-isa (#169) → `main` (open) 4. native `.pyi` stubs (#171) → `main` (open; independent) 5. circuit component (#173) → #169 6. composite machine + VM (#174) → #173 7. **ppvm-cli binary (this PR)** → #174 8. ratatui TUI (#166) → this PR ## Summary Extracts the `ppvm-cli` crate — the `ppvm` binary — from #168 onto the composite. This is the **base CLI without the TUI**: clap-based `run` / `dump` / `parse` / `debug` subcommands over `ppvm-vihaco`, plus example `.sst` programs. The ratatui TUI that layers on top of it is the follow-up PR (#166), which modifies this crate. `ppvm-cli` was part of #168's implementation but had no extraction step of its own — the original split plan conflated it with the TUI PR. It slots in here between the composite and the TUI. - Depends on `ppvm-vihaco` (with `rayon`), `clap`, `eyre`. - **Excluded from the wasm32 CI build** (terminal binary, forces `rayon`), mirroring #168's exclusion — `ppvm-vihaco` itself still builds for wasm, so only `ppvm-cli` is excluded; the reusable engine stays covered. ## Testing `cargo test -p ppvm-cli` — 23 pass. `ppvm run examples/ghz.sst` runs. clippy + machete clean; full workspace builds; `ppvm-vihaco` still builds for `wasm32-unknown-unknown`. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.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.
Merge order
Part of splitting #168 into small, focused PRs. Full stack (independent items may merge in any relative order; dependents wait for their base):
mainfeat/tableau-expectation-reset) →main.pyitype stubs (feat/native-pyi-stubs) → this PR (declares the nativeradded here)maindavid/42.2-circuit-component) → feat(vihaco-circuit-isa): add standalone circuit ISA crate #169david/42.3-composite) → PauliSum printing should properly display small floating points #5Items 1, 2, and 4 are mutually independent off
main.Summary
Adds the
RotXYtrait toppvm-traitsand implements it for both backends (ppvm-tableau,ppvm-pauli-sum), plus ther(...)Python binding on the native PauliSum / tableau classes and theRotationsMixin/TruncatingRotationsMixinwrappers.RotXYis a single-qubit rotation about an arbitrary axis in the X/Y plane:Pure addition alongside the existing
RotationOne(RX/RY/RZ) rotations; no new module wiring. Likeu3,ris single-qubit (scalaraddr0), not batched overtargets.Provenance
Snapshotted from the tip of #168 (not cherry-picked); the R gate is a prerequisite for the circuit-component backends there.
Testing
cargo test -p ppvm-traits -p ppvm-tableau -p ppvm-pauli-sumgreen (incl.test_rx/ry/rz/r). Python:maturin develop+pytest test/test_basics.py test/generalized_tableau/test_basics.py→ 37 passed. prek hooks (fmt, check, clippy, machete, ruff, ty, license) all pass.