use ppvm_pauli_sum::config::indexmap::ByteFxHashF64;
use ppvm_tableau::prelude::*;
type Tab = GeneralizedTableau<ByteFxHashF64<8>, usize>;
const FNV_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
const FNV_PRIME: u64 = 0x0000_0100_0000_01b3;
fn fnv1a_update(mut h: u64, byte: u8) -> u64 {
h ^= byte as u64;
h = h.wrapping_mul(FNV_PRIME);
h
}
fn build_rot2_brickwork(n: usize, layers: usize) -> Tab {
let mut tab: Tab = GeneralizedTableau::new_with_seed(n, 1e-10, 1);
for q in (0..n).step_by(2) {
tab.h(q);
}
for layer in 0..layers {
for a in (0..n.saturating_sub(1)).step_by(2) {
tab.rxx(a, a + 1, 0.3 * std::f64::consts::PI);
tab.ryy(a, a + 1, 0.4 * std::f64::consts::PI);
}
for a in (1..n.saturating_sub(1)).step_by(2) {
tab.rzz(a, a + 1, 0.25 * std::f64::consts::PI);
tab.rxx(a, a + 1, 0.15 * std::f64::consts::PI);
}
if layer % 2 == 0 {
for q in (1..n).step_by(2) {
tab.h(q);
}
}
}
tab
}
fn measure_record_digest(tab: &Tab, n: usize, seeds: u64) -> u64 {
let mut h = FNV_OFFSET;
for seed in 0..seeds {
let mut forked = tab.fork(Some(seed));
for q in 0..n {
let bit = forked.measure(q).expect("no lost qubits in this circuit");
h = fnv1a_update(h, bit as u8);
}
}
h
}
#[test]
fn rot2_apply_path_measurement_digest_is_stable() {
let n = 8;
let tab = build_rot2_brickwork(n, 3);
assert!(
tab.coefficients.len() > 8,
"expected a branchy superposition, got {} coefficients",
tab.coefficients.len()
);
let digest = measure_record_digest(&tab, n, 256);
println!("rot2_apply_path digest = {digest:#018x}");
assert_eq!(
digest, 0x2401_e08e_70e6_ecc8,
"measurement record changed — apply-path refactor is not behaviour-preserving"
);
}