feat(tableau): add Pauli expectation/trace and reset_all#172
Merged
Conversation
Add `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` (generalizes the single-qubit `compute_decomposition`). - `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. Merge order for the #168 split: this and single-qubit rotations target `main` independently; native .pyi stubs stack on rotations; then vihaco-circuit-isa (#169) -> circuit component -> composite -> CLI/TUI (#166). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds expectation/trace utilities to the ppvm-tableau backend by introducing Pauli-word conjugation + overlap evaluation on GeneralizedTableau, alongside state-wide reset helpers and supporting tableau decomposition logic.
Changes:
- Add
GeneralizedTableau::expectation(single Pauli ⟨ψ|P|ψ⟩) andGeneralizedTableau::trace(pattern-summed expectations) via a newexpectationmodule. - Add
reset_allfor bothTableauandGeneralizedTableau, plus a shared tableau initializer helper and a multi-qubitcompute_decomposition_word. - Add
ppvm-pauli-worddependency forPauliPattern/PauliWordsupport.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/ppvm-tableau/src/lib.rs | Exposes the new expectation module. |
| crates/ppvm-tableau/src/expectation.rs | Implements expectation/trace and adds focused tests (Bell/GHZ/rotations/noise cross-check). |
| crates/ppvm-tableau/src/data.rs | Adds reset_all, factors tableau initialization, adds compute_decomposition_word, and guards a rayon path against nested usage. |
| crates/ppvm-tableau/Cargo.toml | Adds ppvm-pauli-word dependency. |
| Cargo.lock | Records the new dependency in the workspace lockfile. |
Comments suppressed due to low confidence (1)
crates/ppvm-tableau/src/data.rs:84
- The doc comment for the public constructor
Tableau::newwas removed during thenew_datarefactor. Since this is part of the public API (and the type itself is documented), it’s better to keep the constructor documented as well.
pub fn new(n_qubits: usize) -> Self {
let data = Tableau::<T>::new_data(n_qubits);
Self {
n_qubits,
data,
rng: rand::make_rng(),
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
- `expectation` now iterates `self.coefficients` by reference (mirroring `z_expectation`) instead of cloning the whole sparse vector and collecting it up front. The map path builds directly from `.iter()`, dropping an intermediate `Vec`. `trace` calls `expectation` per matching Pauli, so this removes a per-call clone. Numerically identical (all expectation/trace tests unchanged). - `GeneralizedTableau::reset_all` now clears `measurement_record`, so `current_measurement_record()` no longer returns stale outcomes after a full reset. - Restore the `Tableau::new` doc comment dropped in the `new_data` refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`component.rs` and `measurements.rs` were staged for the circuit-component PR (#4) and got committed into d43fda1 by accident when the index was carried across a branch switch. They belong on `david/42.2-circuit-component`, not this PR. They were never wired into the workspace so they had no build effect; removing them keeps #172 scoped to the tableau changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover `GeneralizedTableau::reset_all` and `Tableau::reset_all`: - restores a fresh |0…0⟩ tableau (rows + single identity coefficient) after non-Clifford branching, - clears the measurement record (regression guard for the review fix), - clears per-qubit loss flags, - `Tableau::reset_all` restores the fresh identity rows. 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>
Comment on lines
+60
to
+62
| pub fn expectation<W: PauliWordTrait>(&self, word: &W) -> f64 { | ||
| let (phase, stab_anticomm, destab_anticomm) = self.compute_decomposition_word(word); | ||
| if stab_anticomm == I::zero() { |
Comment on lines
+699
to
+701
| for l in self.is_lost.iter_mut() { | ||
| *l &= false; | ||
| } |
Comment on lines
+891
to
+893
| let mut phase = 0u8; | ||
| let mut stab_anticomm = I::zero(); | ||
| let mut destab_anticomm = I::zero(); |
| coefficients.unsafe_insert(I::zero(), complex_one); | ||
| self.coefficients = coefficients; | ||
| for l in self.is_lost.iter_mut() { | ||
| *l &= false; |
This was referenced Jul 8, 2026
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):
mainmain.pyitype stubs (feat/native-pyi-stubs) → feat(gates): add RotXY in-plane single-qubit rotation (R gate) #170maindavid/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
expectation.rsforGeneralizedTableau:expectation— single-Pauli ⟨ψ|P|ψ⟩ for aPauliWord, conjugating P through the tableau and overlapping with the sparse coefficient vector.trace— Σ over Paulis matching aPauliPattern.Supporting changes in
data.rs:compute_decomposition_word— multi-qubit conjugation used byexpectation.reset_allon bothTableauandGeneralizedTableau— reinitialise to |0…0⟩, clearing coefficients and loss state (refactorsnewvia a sharednew_datahelper).lib.rsgainspub mod expectation;Cargo.tomlgains appvm-pauli-worddependency. Pure core addition, snapshotted from #168.Testing
cargo test -p ppvm-tableaugreen (12 expectation tests + reset/noise). prek hooks all pass.