Conversation
Implement the global-phase-tracking generalization of outcome-complete
stabilizer simulation (KBP, arXiv:2309.08676 Alg. 5.3), following the
phased-simulation algorithm of arXiv:2603.24717.
paulimer:
- New `PhasedCliffordUnitary` primitive (clifford/phased_clifford.rs): a
`CliffordUnitary` plus an exact global-phase tracker for the encoder state
`Co|0…0>`, with phase-aware left-multiplication of elementary generators,
Pauli, Pauli-exp and Clifford, and an exact stabilizer-amplitude helper.
Global phases are tracked entirely as exact integer ζ₈ exponents (mod 8):
amplitude sums reduce to pure integer logic (separations d ∈ {0,2,6}, or
cancellation at d = 4), with no floating-point or complex arithmetic.
- Dense statevector validation harness (tests/phased_clifford_dense.rs).
pauliverse:
- New `PhasedOutcomeCompleteSimulation` implementing the `Simulation` trait,
mirroring `OutcomeCompleteSimulation` and additionally tracking the
quadratic phase matrix B and the linear i/-1 phase vectors p, s, so the
output state is i^<p,r> (-1)^<Br+s,r> R|Ar>.
- Exhaustive dense-statevector test enumerating every random-bit assignment r
and comparing phase-exactly against a brute-force reference
(tests/phased_outcome_complete_dense.rs).
Python bindings:
- `PhasedOutcomeCompleteSimulation` exposed through paulimer/bindings/python,
with phase accessors (sign/quadratic-phase/outcome matrices, outcome shift,
linear i/-1 phase vectors, output_phase_exponent), .pyi stubs and tests.
Docs: pauliverse crate docs and README updated to a fifth simulation mode,
citing arXiv:2603.24717.
The §4.5 auxiliary-qubit separation and §4.1 verification application are
deferred as follow-ups.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Demonstrates `PhasedOutcomeCompleteSimulation` (arXiv:2603.24717) using only the exposed phase data — no state vector is ever formed. Prepares |++>, measures Y on each qubit, and shows the four branch phases 1, i, i, -1, where the two i factors interfere to -1 (captured exactly by the quadratic phase matrix B since the linear i-phase p is tracked mod 2). Reconstructs the zeta8 exponent from A, B, p, s with exact integer arithmetic and asserts it against output_phase_exponent, contrasts with the phaseless OutcomeCompleteSimulation, and explains the §4.1 verification application. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Demonstrates applying a symbolic rotation exp(iαP) to PhasedOutcomeCompleteSimulation by conditioning the Pauli P on a fresh allocate_random_bit(), following §4.1 of arXiv:2603.24717. Shows the two branches (cos α / i·sin α weights), verifies that H·exp(iαZ)·H and exp(iαX) have identical exact phase signatures, and catches a buggy exp(iαY) variant that the phaseless OutcomeCompleteSimulation cannot distinguish from exp(iαX) (the two differ only by a relative branch phase). Statevector-free and self-verifying via asserts; executed with outputs committed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…ython
Augments the circuit-action machinery with an exact-global-phase analog of
`action_of`/`CircuitAction` for verifying symbolic-rotation circuits as
operators (Choi states / channel-state duality).
- pauliverse: refactor `build_action` to share a post-simulation
`action_from_simulation` core; add `phased_action_of` (Circuit path),
`phased_action_from_simulation` (simulator-native path), and
`PhasedCircuitAction` with `is_equivalent` / `is_equivalent_up_to_signs`.
Equality is up to a single global phase; relative branch phases (which
distinguish e.g. e^{+iaZ} from e^{-iaZ}) are compared via the degree-<=2
phase polynomial phi(r) = 2<p,r> + 4<Br+s,r> mod 8.
- bindings: expose `PhasedOutcomeCompleteSimulation.phased_action(...)` and
the `PhasedCircuitAction` class; update the `.pyi` stub and `__all__`.
- tests: Rust `phased_action_test.rs` (Circuit + simulator-native paths) and
Python `TestPhasedCircuitAction`.
- example: rewrite `verifying-symbolic-rotations.ipynb` to use the principled
`phased_action` API instead of raw-field comparison.
Each random bit is currently treated as a symbolic rotation angle matched
one-to-one between circuits; distinguishing virtual angle bits from true
measurement randomness (affine remapping) is a tracked follow-up.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…d actions
Introduce a first-class `allocate_symbolic_angle()` allocation that tags a
random bit as a *virtual* rotation angle, distinct from a *true* measurement
random bit. The phased Choi-action equivalence now enforces the distinction:
symbolic angles must correspond one-to-one (in allocation order) between two
compared circuits, while true measurement bits may be marginalized/affinely
remapped. The two kinds are never mixed (guarded by SymbolicAngleCount /
SymbolicAngleMixed inequivalence reasons).
Core fix: `relative_phase_matches` now compares the degree-<=2 branch-phase
polynomial only over the symbolic-angle bits (true bits zeroed). Symbolic
angles model coherent `e^{i a P}` superpositions whose relative phase is
observable; true measurement bits label incoherent, traced-out branches whose
per-branch global phase is unobservable. This makes the phased equivalence
reduce exactly to the phaseless `CircuitAction` equivalence when no angles are
present, and lets measurement-based "ejection" gadgets compare equal to the
operation they implement directly.
Provenance is plumbed through the `Simulation` trait (default defers to
`allocate_random_bit`; `PhasedOutcomeCompleteSimulation` overrides to tag the
bit), the `Circuit`/`CircuitBuilder` replay (`Instruction::AllocateRandomBit`
gains a `symbolic_angle` flag), and the Python bindings (+ `.pyi`).
Tests: Z-basis ejection of symbolic Z-rotations vs the direct rotation (Rust +
Python), a miscorrected-ejection detection test, and an angle-free Z-diagonal
Clifford ejection proving phased == phaseless without symbolic angles. The
`verifying-symbolic-rotations.ipynb` notebook gains an ejection section and is
migrated to `allocate_symbolic_angle`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Add the X-basis dual of the measurement-based ejection gadget: ancillas in |+>, CNOTs reversed (control = ancilla, target = system), an X-diagonal operation on the ancillas, destructive Z-basis ancilla measurement, and a conditional X correction per `1` outcome. This whole gadget is the conjugation of the (already verified) Z-basis gadget by a transversal Hadamard, so it must equal applying the same X-diagonal operation directly to the system qubits. - phased_action_test.rs: symbolic X-rotation ejection (`x_ejection_channel` etc.) with single/two/three-qubit and repeated-angle cases, mirroring the Z-basis helpers and asserting symmetric phase-aware equivalence. - action_test.rs: the angle-free `OutcomeCompleteSimulation` case as a proptest ejecting a random X-diagonal Clifford, obtained by Hadamard-conjugating the existing `arbitrary_diagonal_clifford` generator, and compared to the direct unitary action exactly like the Z-basis `diagonal_unitary_ejection_proptest`. Tests only; no library changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Add ejection tests for diagonal channels that mix symbolic rotations (virtual bits) with non-destructive stabilizer measurements (true observed bits), exercising all three provenance classes at once (virtual angles, observed measurements, marginalized readouts). - phased_action_test.rs: Z- and X-basis channel ejection with non-destructive measurements, compared via the default `is_equivalent` (angle bits 1:1, measurement bits identity-by-order, readout bits projected). - action_test.rs: `diagonal_measure_x_ejection_proptest`, the X-basis dual of the existing Z-basis measurement-ejection proptest, via Hadamard duality (`x_paulis_from_z_paulis`). Tests only; no library behaviour changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…ation Section 4.1 of arXiv:2603.24717 reduces verifying C1 exp(iα Z) C2|0> == D1 exp(iα Z) D2|0> (for all α) to a single exact stabilizer-state equality C1 Z^a C2|0> == D1 Z^a D2|0> with a symbolic exponent. This needs no dedicated API: the check is `phased_action_of` + `PhasedCircuitAction::is_equivalent`, the phased analog of how OutcomeCompleteSimulation does phaseless equality checking. - phased_action_test.rs: state-preparation (inputs = []) verification tests for the C1 Z^a C2|0> construction -- equal factorizations (CNOT-conjugated ZZ rotation), a phase-only difference detected as exactly one RelativePhase, and the multi-angle generalization. - examples/verifying-circuit-equivalence.ipynb: a focused notebook illustrating the Python verification workflow (allocate_symbolic_angle -> conditional Z -> phased_action -> is_equivalent), float-free. Tests + notebook only; no library or binding changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Introduce `Simulation::symbolic_pauli_exp` (Rust) and `apply_symbolic_pauli_exp` (Python) so users express `exp(iα P)` directly instead of conditioning a Pauli on an allocated angle. The name mirrors the existing fixed-angle `pauli_exp` / `apply_pauli_exp`. The new method is a thin default over `conditional_pauli`, so no core simulator behaviour changes. User-facing docs no longer mention the virtual-bit / conditional-Pauli plumbing: `allocate_symbolic_angle` is documented purely as "allocate a rotation angle" with the cross-circuit one-to-one allocation-order correspondence that makes equivalence checks meaningful. Notebooks: - verifying-symbolic-rotations.ipynb: use the high-level `apply_symbolic_pauli_exp` throughout (terminology is "Pauli exponent", not "rotation"); use the explicit `prepare_bell_pairs` Choi convention (matching zz-measurement-verification.ipynb) instead of a custom `choi_action` wrapper; drop all "virtual/true bit" framing; and finish with a richer ejection example -- a three-qubit Z-diagonal channel (three overlapping Z-Pauli exponents plus a non-destructive three-qubit parity measurement) ejected through ancillas. - verifying-circuit-equivalence.ipynb: remove stray implementation-detail wording. Tests: migrate genuine rotation call sites in phased_action_test.rs to `symbolic_pauli_exp`; measurement corrections stay as `conditional_pauli`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Previously `allocate_symbolic_angle` (Python) returned a raw `int` outcome id, and two circuits' angles were said to correspond "in allocation order". That coupling was implicit and brittle, and the integer leaked an internal representation (it is a random-bit index, not the angle's logical subscript). Expose symbolic angles in Python as an opaque `SymbolicAngle` handle instead. Its only observable feature is `index` -- the subscript k in alpha_k, fixed by allocation order -- which is exactly what the phased equivalence check pairs between two circuits. New ergonomics: - `allocate_symbolic_angle() -> SymbolicAngle` - `allocate_symbolic_angles(count) -> list[SymbolicAngle]` to allocate a circuit's angles up front - `symbolic_angles` property to retrieve all allocated angles, so `angles[k]` is alpha_k - `apply_symbolic_pauli_exp(observable, angle: SymbolicAngle)` Because the handle is opaque it can only be consumed by `apply_symbolic_pauli_exp`, not fed back into `apply_conditional_pauli`, which keeps symbolic-angle provenance flowing through the symbolic API. The Rust core is unchanged: it keeps the uniform `OutcomeId = usize` model (shared by measurements, random bits and angles, and used by the `Circuit`/`Instruction` replay machinery); the opaque handle is a Python-binding concern, consistent with the repo's "Pythonic, not 1:1" binding guidance. - simulation.rs: add `SymbolicAngle` pyclass (frozen, with `index`/`__eq__`/`__hash__`/ `__repr__`) and the allocation/accessor/apply methods above. - paulimer.pyi: stub `SymbolicAngle` and the new signatures; add to `__all__`. - verifying-symbolic-rotations.ipynb: the ejection example now allocates its angles with `allocate_symbolic_angles(3)` and refers to them by index, making the cross-circuit correspondence explicit; prose describes angles as opaque, index-identified handles. - simulation_test.py: pass symbolic angles through `apply_symbolic_pauli_exp` (measurement corrections keep `apply_conditional_pauli`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…logy) M1: Correct the user-facing docstrings for phased_action / PhasedCircuitAction / is_equivalent in paulimer.pyi to state that only symbolic-angle bits are matched one-to-one by index, while genuine measurement (true) random bits are marginalized (not "every random bit mapped one-to-one"). Reword a stale "rotations" mention. M2: apply_clifford on PhasedOutcomeCompleteSimulation previously panicked across the FFI boundary (the phased simulator's Rust clifford is unimplemented! because a phaseless CliffordUnitary does not determine the exact global phase it tracks). Thread a clifford_supported flag through the impl_simulation! macro so the phased binding raises a clean NotImplementedError instead, directing users to apply_unitary / apply_pauli / apply_pauli_exp. Document the behavior in the .pyi stub. L1: Scrub residual "rotation" / "true bit" terminology from the example notebooks in favor of "Pauli exponent" / "measurement outcome"; re-execute both notebooks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Add sign-flip and angle-permutation negative tests plus proptest/hypothesis randomization for PhasedCircuitAction equivalence. Flipping any subset of symbolic Pauli-exponent signs leaves the phaseless action unchanged but must yield exactly RelativePhase; permuting the symbolic-angle allocation order over distinct Paulis must be detected as inequivalent (identity permutation stays equivalent). Mirrored in Python via hypothesis. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Make the repository's user-facing docs aware of the phased outcome-complete
simulator and its symbolic-angle circuit-verification workflow:
- Top-level README: note exact global-phase tracking in the pauliverse bullet
and add a "Stabilizer Simulation (pauliverse)" Rust quick-start showing
PhasedOutcomeCompleteSimulation with a higher-weight symbolic exponent
e^{i alpha Z0 Z1}.
- Python bindings README: add a "Verifying parameterised circuits with symbolic
angles" quick-start, a PhasedOutcomeCompleteSimulation feature bullet, and a
use-case sentence.
- verifying-symbolic-rotations.ipynb: add a mixed-basis (non-Z), higher-weight
Pauli-exponent example (e^{i alpha X0 Z1} == H0 e^{i alpha Z0 Z1} H0) to make
the "arbitrary Pauli of any weight" capability unambiguous.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Rename terse/single-letter variables and parameters (n, q, c, t, a, b, m, x, z, ab, bb, cb, tb, p, p1, p2, sp1, sp2, u, o, ...) to descriptive names (qubit_count, qubit, control, target, first_qubit, second_qubit, matrix, x_bits, z_bits, pauli, first_pauli, second_pauli, ...) in the dense-statevector oracle tests for PhasedCliffordUnitary and PhasedOutcomeCompleteSimulation, matching the naming conventions used elsewhere in the test suite (e.g. pauliverse/tests/action_test.rs). No behavioral changes; cargo test confirms all 12 affected tests still pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…ation tests Add PhasedOutcomeCompleteSimulation to SIMULATION_CLASSES so it gets the same generic parametrized coverage as the other three simulator classes (apply_permutation, is_stabilizer, measure with hint, allocate_random_bit, reserve_qubits, reserve_outcomes, etc.), which it was previously missing entirely. apply_clifford genuinely cannot work on this class: CliffordUnitary only encodes how a unitary conjugates the Pauli group, discarding the absolute global phase information PhasedOutcomeCompleteSimulation must track, so the binding raises NotImplementedError for it (simulation.rs). Introduce CLIFFORD_CAPABLE_SIMULATION_CLASSES, scoped to the three classes that do support apply_clifford, and use it only for the two apply_clifford tests. Verified with maturin develop --release + pytest: 329 passed (up from 146 in simulation_test.py alone, now including 30 new phased-class cases). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Owner
Author
|
Superseded by microsoft#115, targeting the upstream repository. |
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.
Summary
PhasedOutcomeCompleteSimulationwith exact integer ζ₈ global-phase tracking.PhasedCircuitActionfor phase-aware Choi-state equivalence and opaque symbolic-angle support.Reference
Implements Algorithm 4.2 of arXiv:2603.24717, the phase-exact counterpart of the existing outcome-complete stabilizer simulation. The tests also exercise the §4.1 circuit-verification workflow.
Stack
Stack A, PR 1 of 3. Base:
main. Review and merge this PR first;masilv/clifford-pauli-exp-decompand thenmasilv/phased-aux-separationare stacked on it.