Add exact Clifford-to-Pauli-exponent decomposition - #116
Open
Marcus P S (marcusps) wants to merge 54 commits into
Open
Add exact Clifford-to-Pauli-exponent decomposition#116Marcus P S (marcusps) wants to merge 54 commits into
Marcus P S (marcusps) wants to merge 54 commits into
Conversation
Catch up
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>
Introduce `clifford_to_pauli_exponents` in `paulimer::clifford`: an exact decomposition of a `CliffordUnitary` into an ordered product of pi/4 Pauli exponents `exp(i pi/4 P)`. The reconstruction reproduces the full tableau, including Pauli-image signs, so replaying the factors on a phased operator (`PhasedCliffordUnitary::left_mul_pauli_exp`) yields a well-defined global phase. This is the primitive needed to recover the absolute global phase in the auxiliary-qubit separation of arXiv:2603.24717 (Sec 4.5). The algorithm reduces a working copy of the Clifford to the identity by left-multiplying pi/4 exponents (per-qubit column reduction of the X and Z images), then returns the inverse exponents in reverse order. - New module `paulimer/src/clifford/decomposition.rs`, re-exported from `clifford.rs`. - Rust tests in `clifford_test.rs`: identity-is-empty, fixed examples, and a proptest roundtrip over random Cliffords (n in 0..6). - Python binding `CliffordUnitary.to_pauli_exponents()` with `.pyi` stub and tests; stubtest clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Surface clifford_to_pauli_exponents / CliffordUnitary.to_pauli_exponents in the user-facing docs: - paulimer/README.md: add a Clifford feature bullet, a Quick-Start snippet that decomposes a Clifford and rebuilds it via left_mul_pauli_exp, and a documentation entry pointing at src/clifford/decomposition.rs. - Python bindings README: add a "Decomposing a Clifford into pi/4 Pauli exponents" quick-start and mention to_pauli_exponents in the CliffordUnitary feature bullet. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Restore the standalone dense-Pauli controlled-operation test header so pytest collects it independently from the Pauli-exponent round-trip test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: GPT-5.6 Sol <noreply@openai.com>
Cite section 4.3, where auxiliary-qubit separation is defined, rather than section 4.5. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: GPT-5.6 Sol <noreply@openai.com>
This was referenced Jul 17, 2026
Marcus P S (marcusps)
marked this pull request as ready for review
July 17, 2026 04:32
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d Clifford Add trailing semicolons in the left_mul_x/y/z closures to match the sibling gate methods and unblock the -D clippy::pedantic CI step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-sim' into masilv/clifford-pauli-exp-decomp
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…jection test Add the two symbolic-rotation notebook scenarios that lacked a Rust test: HZH = X-exp, and mixed-basis X0Z1 = H0.ZZ.H0 (distinct from bare ZZ). Refactor the core Z-ejection helpers in place for readability: document the three ejection phases (entangle, rotate remotely, measure-and-correct), state the ejection invariant on check_z_ejection, and clarify the local-vs-support indexing of the shared helpers. No test coverage removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d-pauli-exp-decomp
Address review feedback that the phased-outcome-simulation tests and the pre-existing phased-Clifford tests each carried a near-identical hand-rolled full state vector simulator. Extract the shared oracle (C, zeta8, Dense, gate_matrix, statevector, pauli_arrays, close) into a new private, unpublished `dense-oracle` crate and have both test suites reuse it. The change is additive to non-test code: no crate's src/ is touched, only the two test files, their dev-dependencies, and the workspace member list. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
…hints A review pointed out that `PhasedOutcomeCompleteSimulation::measure_with_hint` produced the wrong post-measurement state and outcome sign whenever the anti-commuting hint carried a negative sign (the `(-1)^alpha` branch of case 5 of Algorithm 4.2). Generalize the reviewer's reproduction into a property-based (proptest) test and add it to the suite: over random Clifford states it measures the destabilizer `image_x(q)` while hinting with the (optionally negated) stabilizer `image_z(q)`, and asserts the measured observable stays a stabilizer whose conditional sign matches the reported outcome. This test fails on the old code (shrinking to measuring X on |0> with hint -Z) and its minimal counterexample is pinned via the checked-in .proptest-regressions file. Adopt the reviewer's proposed fix: instead of applying a global `(-1)^alpha` phase, relabel the reported outcome (`m = r XOR alpha`) via `outcome_shift`, which makes the tracked stabilizer sign and the reported outcome agree. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
…outcome-complete-sim
…outcome-complete-sim # Conflicts: # pauliverse/Cargo.toml
…plete-sim' into masilv/phased-outcome-complete-sim # Conflicts: # pauliverse/Cargo.toml
Co-authored-by: Juan M. Bello-Rivas <jmbr@superadditive.com>
Co-authored-by: Juan M. Bello-Rivas <jmbr@superadditive.com>
Addresses jmbr's review: move the shared statevector oracle under test-utils/, set version 0.0.0, and use num-complex instead of a bespoke complex type. microsoft#115 (comment) microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: build `difference` via map/collect and iterate the Pauli's x/z bit supports directly instead of materializing helper vectors. microsoft#115 (comment) microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: replace the hand-rolled RNG loop with a proptest Gate strategy tracking the dense statevector. microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: share a phased_action helper, collect symbolic angles inline, and drop the now-unused indicator_to_bitvec. microsoft#115 (comment) microsoft#115 (comment) microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: delegate the branch-phase computation to the identical PhaseData routine in action.rs rather than duplicating it. microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: use enumerate().take() with the bound bit so the clippy-suggested pattern stays warning-clean. microsoft#115 (comment) microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: generate the preparation circuit with a proptest Gate strategy mirroring phased_clifford_dense. microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: remove the phased_action and measure_with_hint proptest-regressions files. microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr's review: revert the references/ addition. microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Pass Complex::norm_sqr directly instead of wrapping it in a closure, fixing a clippy::pedantic error surfaced by CI's newer toolchain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Addresses jmbr: replace the allocating PhaseData round-trip in output_phase_exponent with a closure-based phase_form_exponent shared by the simulator and PhaseData, evaluating the phase form directly over self. microsoft#115 (comment) microsoft#115 (comment) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
…uli-exp-decomp Bring the fully-reviewed phased outcome-complete simulation branch up the stack. This carries all of jmbr's PR microsoft#115 review fixes: dense-oracle relocated under test-utils/ with num-complex, deduplicated phased action + shared phase_form_exponent helper, idiomatic bit iteration in phased_clifford, proptest Gate-strategy tests, and dropped proptest-regressions seeds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Preempts jmbr-style review notes on the Clifford->pi/4 decomposition: - drop the redundant `Reduction.qubit_count` field and derive it from `working.num_qubits()` at each use, removing duplicated state; - fold the reduction-math explanation from an inline comment into the `clifford_to_pauli_exponents` doc comment under a `# Algorithm` heading. Behavior-preserving; roundtrip proptest and examples still pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Marcus P S (marcusps)
pushed a commit
to marcusps/qdk-ec
that referenced
this pull request
Jul 24, 2026
Apply the conventions established while addressing @jmbr's review on the phased-outcome / decomposition stack (PRs microsoft#115/microsoft#116) to the transvection decomposition, anticipating the same feedback here: - Replace the seed + internal-RNG proptests (`seed in any::<u64>()` feeding `CliffordUnitary::random`) with a `Gate`-sequence `Strategy`, mirroring phased_clifford_dense.rs and measure_with_hint_sign_test.rs, so a failing input shrinks to a minimal gate sequence instead of an opaque seed. The deterministic sweep (which needs no shrinking) keeps using a seeded RNG. - Derive `qubit_count` inside `next_transvection` from `working.num_qubits()` instead of threading it as a parameter, matching the earlier "derive qubit count" tidy on the Gaussian-elimination decomposition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
Marcus P S (marcusps)
pushed a commit
to marcusps/qdk-ec
that referenced
this pull request
Jul 25, 2026
…inimal Update the minimal-decomposition rung with the latest from the lower rung clifford-to-pauli-exp-unphased (79c66e3): the Gate-strategy proptests and the param-less next_transvection tidy, applying the @jmbr review conventions from PRs microsoft#115/microsoft#116/microsoft#117 to this branch too. Also align the branch's own minimal-decomposition tests with those conventions: convert the remaining seed + internal-RNG proptests (minimal_reproduces_symplectic_action, minimal_is_r_or_r_plus_one_and_at_most_greedy) to the shared Gate strategy so they shrink to a minimal gate sequence, and drop the committed transvection_test.proptest-regressions seed file. The deterministic seeded sweeps (which need no shrinking) keep using random_clifford. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 16f923fe-a72a-4430-97b0-b7677f48dfb7
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
Published reference
This decomposition is the phase-exact building block used by §4.3 of Phased outcome-complete simulation (arXiv:2603.24717): Clifford factors are decomposed and replayed while tracking their ζ₈ phase.
Review series
This is the second of three dependent PRs. It is stacked on #115 and should be reviewed and merged after it. Until #115 merges and this branch is rebased, GitHub shows the preceding PR’s commits as part of this draft; the new review scope is the Clifford decomposition, its bindings, tests, and documentation.