Pre-existing defect, independent of PR #547 (measured identical on dev be5a2ead4 and on that branch).
rz_apply_direct (exp/pecos-stab-tn/src/stab_mps.rs) applies the tableau-frame Pauli decomposition to the stored MPS without conjugating by the pending lazy-measurement frame V. With lazy_measure(true), any sequence of measurement then Clifford then non-Clifford rotation therefore evolves the wrong state.
Measured: 24 seeds, circuits of the shape lazy mz -> Clifford -> rz, compared against a dense state-vector oracle: 24/24 fail, fidelity 0.71-0.87, byte-identical results on both commits. Inserting an explicit flush() after the measurement improves this to 4/24 (worst 0.98) — also identical on both — so the defect is the missing conjugation, not the fix under review.
Consequences:
lazy_measure(true) is currently unsound for any circuit that continues with non-Clifford rotations while the deferred queue is pending, though it is documented and recommended as the exact-state option.
- It also masks a related invariant question: while the queue is pending, stored-frame proofs (
disent_flags) and effective-frame state disagree, which is why numerical flag redetection is already gated off in that regime.
Suggested direction: conjugate the decomposition through the deferred queue before applying it (the measurement path already has conjugate_pauli_by_deferred_ops), or flush before non-Clifford application and document the cost. Either way the falsifier above should become a regression test.
Pre-existing defect, independent of PR #547 (measured identical on
devbe5a2ead4and on that branch).rz_apply_direct(exp/pecos-stab-tn/src/stab_mps.rs) applies the tableau-frame Pauli decomposition to the stored MPS without conjugating by the pending lazy-measurement frameV. Withlazy_measure(true), any sequence of measurement then Clifford then non-Clifford rotation therefore evolves the wrong state.Measured: 24 seeds, circuits of the shape lazy
mz-> Clifford ->rz, compared against a dense state-vector oracle: 24/24 fail, fidelity 0.71-0.87, byte-identical results on both commits. Inserting an explicitflush()after the measurement improves this to 4/24 (worst 0.98) — also identical on both — so the defect is the missing conjugation, not the fix under review.Consequences:
lazy_measure(true)is currently unsound for any circuit that continues with non-Clifford rotations while the deferred queue is pending, though it is documented and recommended as the exact-state option.disent_flags) and effective-frame state disagree, which is why numerical flag redetection is already gated off in that regime.Suggested direction: conjugate the decomposition through the deferred queue before applying it (the measurement path already has
conjugate_pauli_by_deferred_ops), or flush before non-Clifford application and document the cost. Either way the falsifier above should become a regression test.