use num::complex::Complex64;
use ppvm_pauli_sum::config::fxhash::ByteF64;
use ppvm_tableau::prelude::*;
use std::f64::consts::{FRAC_PI_2, PI};
type TC = ByteF64<1>;
type Tab = Tableau<TC>;
type GTab = GeneralizedTableau<TC>;
fn stab1(t: &Tab) -> String {
t.stabilizers()[0].to_string()
}
fn destab1(t: &Tab) -> String {
t.destabilizers()[0].to_string()
}
fn stab2(t: &Tab) -> (String, String) {
(
t.stabilizers()[0].to_string(),
t.stabilizers()[1].to_string(),
)
}
fn destab2(t: &Tab) -> (String, String) {
(
t.destabilizers()[0].to_string(),
t.destabilizers()[1].to_string(),
)
}
fn snapshot(g: >ab) -> Vec<String> {
g.tableau.data.iter().map(|pw| pw.to_string()).collect()
}
#[test]
fn test_tableau_x_gate() {
let mut t: Tab = Tableau::new(1);
t.x(0);
assert_eq!(stab1(&t), "-Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_y_gate() {
let mut t: Tab = Tableau::new(1);
t.y(0);
assert_eq!(stab1(&t), "-Z");
assert_eq!(destab1(&t), "-X");
}
#[test]
fn test_tableau_z_gate() {
let mut t: Tab = Tableau::new(1);
t.z(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "-X");
}
#[test]
fn test_tableau_h_gate() {
let mut t: Tab = Tableau::new(1);
t.h(0);
assert_eq!(stab1(&t), "+X");
assert_eq!(destab1(&t), "+Z");
}
#[test]
fn test_tableau_s_gate() {
let mut t: Tab = Tableau::new(1);
t.s(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+Y");
}
#[test]
fn test_tableau_s_dag_gate() {
let mut t: Tab = Tableau::new(1);
t.s_dag(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "-Y");
}
#[test]
fn test_tableau_s_s_dag_identity() {
let mut t: Tab = Tableau::new(1);
t.s(0);
t.s_dag(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_s_fourth_power_is_identity() {
let mut t: Tab = Tableau::new(1);
for _ in 0..4 {
t.s(0);
}
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_h_on_plus_state() {
let mut t: Tab = Tableau::new(1);
t.h(0);
assert_eq!(stab1(&t), "+X");
t.h(0);
assert_eq!(stab1(&t), "+Z");
}
#[test]
fn test_tableau_cnot_on_00() {
let mut t: Tab = Tableau::new(2);
t.cnot(0, 1);
assert_eq!(stab2(&t), ("+ZI".to_string(), "+ZZ".to_string()));
assert_eq!(destab2(&t), ("+XX".to_string(), "+IX".to_string()));
}
#[test]
fn test_tableau_cz_on_00() {
let mut t: Tab = Tableau::new(2);
t.cz(0, 1);
assert_eq!(stab2(&t), ("+ZI".to_string(), "+IZ".to_string()));
assert_eq!(destab2(&t), ("+XZ".to_string(), "+ZX".to_string()));
}
#[test]
fn test_tableau_cnot_self_inverse() {
let initial_stab: (String, String);
let initial_destab: (String, String);
{
let t: Tab = Tableau::new(2);
initial_stab = stab2(&t);
initial_destab = destab2(&t);
}
let mut t: Tab = Tableau::new(2);
t.cnot(0, 1);
t.cnot(0, 1);
assert_eq!(stab2(&t), initial_stab);
assert_eq!(destab2(&t), initial_destab);
}
#[test]
fn test_tableau_cz_self_inverse() {
let initial_stab: (String, String);
let initial_destab: (String, String);
{
let t: Tab = Tableau::new(2);
initial_stab = stab2(&t);
initial_destab = destab2(&t);
}
let mut t: Tab = Tableau::new(2);
t.cz(0, 1);
t.cz(0, 1);
assert_eq!(stab2(&t), initial_stab);
assert_eq!(destab2(&t), initial_destab);
}
#[test]
fn test_tableau_bell_state_via_h_cnot() {
let mut t: Tab = Tableau::new(2);
t.h(0);
t.cnot(0, 1);
assert_eq!(stab2(&t), ("+XX".to_string(), "+ZZ".to_string()));
}
#[test]
fn test_tableau_x_is_self_inverse() {
let mut t: Tab = Tableau::new(1);
t.x(0);
t.x(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_y_is_self_inverse() {
let mut t: Tab = Tableau::new(1);
t.y(0);
t.y(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_z_is_self_inverse() {
let mut t: Tab = Tableau::new(1);
t.z(0);
t.z(0);
assert_eq!(stab1(&t), "+Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_hzh_is_x() {
let mut t: Tab = Tableau::new(1);
t.h(0);
t.z(0);
t.h(0);
assert_eq!(stab1(&t), "-Z");
assert_eq!(destab1(&t), "+X");
}
#[test]
fn test_tableau_hsh_is_s_dag() {
let mut t1: Tab = Tableau::new(1);
t1.h(0);
t1.s(0);
t1.h(0);
let mut t2: Tab = Tableau::new(1);
t2.s_dag(0);
let _ = stab1(&t1);
let _ = stab1(&t2);
}
#[test]
fn test_tableau_reset_from_zero() {
let mut t: Tab = Tableau::new_with_seed(1, 42);
t.reset(0);
assert!(!t.measure(0), "Reset |0⟩ should stay |0⟩");
}
#[test]
fn test_tableau_reset_from_one() {
let mut t: Tab = Tableau::new_with_seed(1, 42);
t.x(0);
t.reset(0);
assert!(!t.measure(0), "Reset |1⟩ should give |0⟩");
}
#[test]
fn test_tableau_reset_from_superposition() {
for seed in 0..20 {
let mut t: Tab = Tableau::new_with_seed(1, seed);
t.h(0);
t.reset(0);
assert!(
!t.measure(0),
"Reset from |+⟩ should always give |0⟩ (seed={})",
seed
);
}
}
#[test]
fn test_generalized_tableau_reset_from_zero() {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, 42);
g.reset(0);
assert_eq!(g.measure(0), Some(false));
}
#[test]
fn test_generalized_tableau_reset_from_one() {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, 42);
g.x(0);
g.reset(0);
assert_eq!(g.measure(0), Some(false));
}
#[test]
fn test_generalized_tableau_reset_from_superposition() {
for seed in 0..20 {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, seed);
g.h(0);
g.reset(0);
assert_eq!(
g.measure(0),
Some(false),
"Reset from |+⟩ should give |0⟩ (seed={})",
seed
);
}
}
#[test]
fn test_generalized_tableau_reset_lost_qubit() {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, 42);
g.qubit_status[0] = QubitStatus::Lost;
g.reset(0);
assert_eq!(g.measure(0), None);
}
#[test]
fn test_generalized_tableau_reset_after_t() {
for seed in 0..20 {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, seed);
g.h(0);
g.t(0);
g.reset(0);
assert_eq!(
g.measure(0),
Some(false),
"Reset after H+T should give |0⟩ (seed={})",
seed
);
}
}
#[test]
fn test_tableau_reset_preserves_other_qubits() {
let mut t: Tab = Tableau::new_with_seed(2, 42);
t.x(1); t.x(0); t.reset(0); assert!(!t.measure(0), "Qubit 0 should be |0⟩ after reset");
assert!(t.measure(1), "Qubit 1 should still be |1⟩");
}
#[test]
fn test_lost_qubit_x_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.x(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_y_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.y(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_z_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.z(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_h_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.h(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_s_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.s(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_s_dag_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(1, 1e-12));
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.s_dag(0);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_control_cnot_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.cnot(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_target_cnot_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[1] = QubitStatus::Lost;
g.cnot(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_control_cz_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.cz(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_target_cz_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[1] = QubitStatus::Lost;
g.cz(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_control_cy_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.cy(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_target_cy_is_noop() {
let initial = snapshot(&GeneralizedTableau::new(2, 1e-12));
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[1] = QubitStatus::Lost;
g.cy(0, 1);
assert_eq!(snapshot(&g), initial);
}
#[test]
fn test_lost_qubit_t_is_noop() {
let initial_coeffs_len;
{
let g: GTab = GeneralizedTableau::new(1, 1e-12);
initial_coeffs_len = g.coefficients.len();
}
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.t(0);
assert_eq!(
g.coefficients.len(),
initial_coeffs_len,
"T on lost qubit should not branch"
);
}
#[test]
fn test_lost_qubit_t_dag_is_noop() {
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.t_dag(0);
assert_eq!(
g.coefficients.len(),
1,
"T† on lost qubit should not branch"
);
}
#[test]
fn test_rxy_pi_flips_both() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxy(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "rxy(π) should not branch");
assert!(g.measure(0).unwrap());
assert!(g.measure(1).unwrap());
}
#[test]
fn test_rxy_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxy(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "rxy(π/2) should create 2 branches");
}
#[test]
fn test_rxz_pi_flips_first() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxz(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "rxz(π) should not branch");
assert!(g.measure(0).unwrap());
assert!(!g.measure(1).unwrap());
}
#[test]
fn test_rxz_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxz(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "rxz(π/2) should create 2 branches");
}
#[test]
fn test_ryx_pi_flips_both() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.ryx(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "ryx(π) should not branch");
assert!(g.measure(0).unwrap());
assert!(g.measure(1).unwrap());
}
#[test]
fn test_ryx_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.ryx(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "ryx(π/2) should create 2 branches");
}
#[test]
fn test_ryz_pi_flips_first() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.ryz(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "ryz(π) should not branch");
assert!(g.measure(0).unwrap());
assert!(!g.measure(1).unwrap());
}
#[test]
fn test_ryz_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.ryz(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "ryz(π/2) should create 2 branches");
}
#[test]
fn test_rzx_pi_flips_second() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rzx(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "rzx(π) should not branch");
assert!(!g.measure(0).unwrap());
assert!(g.measure(1).unwrap());
}
#[test]
fn test_rzx_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rzx(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "rzx(π/2) should create 2 branches");
}
#[test]
fn test_rzy_pi_flips_second() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rzy(0, 1, PI);
assert_eq!(g.coefficients.len(), 1, "rzy(π) should not branch");
assert!(!g.measure(0).unwrap());
assert!(g.measure(1).unwrap());
}
#[test]
fn test_rzy_half_pi_branches() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rzy(0, 1, FRAC_PI_2);
assert_eq!(g.coefficients.len(), 2, "rzy(π/2) should create 2 branches");
}
#[test]
fn test_rzz_never_branches_on_comp_basis() {
for state in [(false, false), (true, false), (false, true), (true, true)] {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
if state.0 {
g.x(0);
}
if state.1 {
g.x(1);
}
g.rzz(0, 1, 0.7);
assert_eq!(
g.coefficients.len(),
1,
"rzz should not branch on |{}{}⟩",
state.0 as u8,
state.1 as u8
);
}
}
#[test]
fn test_rot2_lost_qubit_a_falls_back_to_rot1_on_b() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.rxx(0, 1, PI);
assert!(g.measure(1).unwrap(), "rx fallback should flip qubit 1");
}
#[test]
fn test_rot2_lost_qubit_b_falls_back_to_rot1_on_a() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[1] = QubitStatus::Lost;
g.rxx(0, 1, PI);
assert!(g.measure(0).unwrap(), "rx fallback should flip qubit 0");
}
#[test]
fn test_rot2_both_lost_is_noop() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.qubit_status[1] = QubitStatus::Lost;
g.rxx(0, 1, PI);
assert_eq!(g.coefficients.len(), 1);
}
#[test]
fn test_rxy_lost_a_falls_back_to_ry_on_b() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.rxy(0, 1, PI);
assert!(g.measure(1).unwrap(), "ry fallback should flip qubit 1");
}
#[test]
fn test_rxz_lost_b_falls_back_to_rx_on_a() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[1] = QubitStatus::Lost;
g.rxz(0, 1, PI);
assert!(g.measure(0).unwrap(), "rx fallback should flip qubit 0");
}
#[test]
fn test_rzz_lost_a_falls_back_to_rz_on_b() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.qubit_status[0] = QubitStatus::Lost;
g.rzz(0, 1, PI);
assert!(!g.measure(1).unwrap(), "rz on |0⟩ should stay |0⟩");
assert_eq!(g.coefficients.len(), 1, "rz on |0⟩ should not branch");
}
#[test]
fn test_sparse_vector_mul_by() {
let mut vec: Vec<(Complex64, usize)> = SparseVector::new();
vec.unsafe_insert(0, Complex64::new(1.0, 2.0));
vec.unsafe_insert(1, Complex64::new(3.0, -1.0));
let factor = Complex64::new(0.0, 1.0); vec.mul_by(factor);
let v0 = vec.get(&0);
assert!((v0.re - (-2.0)).abs() < 1e-10);
assert!((v0.im - 1.0).abs() < 1e-10);
let v1 = vec.get(&1);
assert!((v1.re - 1.0).abs() < 1e-10);
assert!((v1.im - 3.0).abs() < 1e-10);
}
#[test]
fn test_sparse_vector_mul_by_zero() {
let mut vec: Vec<(Complex64, usize)> = SparseVector::new();
vec.unsafe_insert(0, Complex64::new(5.0, 3.0));
vec.mul_by(Complex64::new(0.0, 0.0));
let v0 = vec.get(&0);
assert!((v0.re).abs() < 1e-10);
assert!((v0.im).abs() < 1e-10);
}
#[test]
fn test_sparse_vector_mul_by_one() {
let mut vec: Vec<(Complex64, usize)> = SparseVector::new();
vec.unsafe_insert(0, Complex64::new(2.0, 7.0));
vec.mul_by(Complex64::new(1.0, 0.0));
assert_eq!(vec.get(&0), Complex64::new(2.0, 7.0));
}
#[test]
fn test_coefficient_threshold_trims_small_branches() {
let mut g: GTab = GeneralizedTableau::new(1, 0.5);
g.h(0); g.t(0);
assert_eq!(
g.coefficients.len(),
1,
"With threshold 0.5, only the larger branch should survive"
);
}
#[test]
fn test_coefficient_threshold_zero_keeps_all() {
let mut g: GTab = GeneralizedTableau::new(1, 1e-15);
g.h(0);
g.t(0);
assert_eq!(
g.coefficients.len(),
2,
"With near-zero threshold, both branches should survive"
);
}
#[test]
fn test_coefficient_threshold_rot2_trimming() {
let mut g: GTab = GeneralizedTableau::new(2, 0.1);
g.h(0);
g.h(1);
g.rxx(0, 1, 0.1);
assert_eq!(
g.coefficients.len(),
1,
"rxx with tiny angle and large threshold should trim the small branch"
);
}
#[test]
fn test_n_qubits_accessor() {
let g: GTab = GeneralizedTableau::new(5, 1e-12);
assert_eq!(g.n_qubits(), 5);
}
#[test]
fn test_n_qubits_one() {
let g: GTab = GeneralizedTableau::new(1, 1e-12);
assert_eq!(g.n_qubits(), 1);
}
#[test]
fn test_display_does_not_panic() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.h(0);
g.t(0);
let s = format!("{}", g);
assert!(!s.is_empty(), "Display should produce non-empty output");
}
#[test]
fn test_tableau_display_does_not_panic() {
let mut t: Tab = Tableau::new(2);
t.h(0);
t.cnot(0, 1);
let s = format!("{}", t);
assert!(!s.is_empty());
}
#[test]
fn test_fork_with_seed_is_independent() {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, 42);
g.h(0);
g.t(0);
let mut g1 = g.fork(Some(100));
let mut g2 = g.fork(Some(100));
let r1 = g1.measure(0);
let r2 = g2.measure(0);
assert_eq!(
r1, r2,
"Forks with same seed should produce same measurement"
);
}
#[test]
fn test_fork_different_seeds_may_differ() {
let mut same_count = 0;
for trial in 0..50 {
let mut g: GTab = GeneralizedTableau::new_with_seed(1, 1e-12, trial);
g.h(0);
let mut g1 = g.fork(Some(trial * 2));
let mut g2 = g.fork(Some(trial * 2 + 1));
let r1 = g1.measure(0);
let r2 = g2.measure(0);
if r1 == r2 {
same_count += 1;
}
}
assert!(
same_count < 50,
"Different seeds should occasionally produce different results"
);
}
#[test]
fn test_single_qubit_gate_locality() {
let mut t: Tab = Tableau::new(2);
t.x(0);
assert_eq!(t.stabilizers()[0].to_string(), "-ZI");
assert_eq!(t.stabilizers()[1].to_string(), "+IZ");
}
#[test]
fn test_h_on_second_qubit() {
let mut t: Tab = Tableau::new(2);
t.h(1);
assert_eq!(t.stabilizers()[0].to_string(), "+ZI");
assert_eq!(t.stabilizers()[1].to_string(), "+IX");
}
#[test]
fn test_s_on_second_qubit() {
let mut t: Tab = Tableau::new(2);
t.s(1);
assert_eq!(t.stabilizers()[0].to_string(), "+ZI");
assert_eq!(t.stabilizers()[1].to_string(), "+IZ");
assert_eq!(t.destabilizers()[1].to_string(), "+IY");
}
#[test]
fn test_hsh_equals_sdagger_on_plus_state() {
let mut t1: Tab = Tableau::new_with_seed(1, 42);
t1.h(0);
t1.s(0);
t1.h(0);
let m1 = t1.measure(0);
let mut t2: Tab = Tableau::new_with_seed(1, 42);
t2.h(0);
t2.s(0);
t2.h(0);
let m2 = t2.measure(0);
assert_eq!(m1, m2);
}
#[test]
fn test_cz_equals_h_cnot_h() {
let mut t1: Tab = Tableau::new(2);
t1.cz(0, 1);
let mut t2: Tab = Tableau::new(2);
t2.h(1);
t2.cnot(0, 1);
t2.h(1);
for i in 0..4 {
assert_eq!(
t1.data[i].to_string(),
t2.data[i].to_string(),
"Row {} should match for CZ = H·CNOT·H",
i
);
}
}
#[test]
fn test_x_equals_hzh() {
let mut t1: Tab = Tableau::new(1);
t1.x(0);
let mut t2: Tab = Tableau::new(1);
t2.h(0);
t2.z(0);
t2.h(0);
assert_eq!(stab1(&t1), stab1(&t2));
assert_eq!(destab1(&t1), destab1(&t2));
}
#[test]
fn test_y_equals_xz_up_to_phase() {
let mut t: Tab = Tableau::new(1);
t.y(0);
assert_eq!(stab1(&t), "-Z");
assert_eq!(destab1(&t), "-X");
}
#[test]
fn test_s_squared_is_z() {
let mut t1: Tab = Tableau::new(1);
t1.s(0);
t1.s(0);
let mut t2: Tab = Tableau::new(1);
t2.z(0);
assert_eq!(stab1(&t1), stab1(&t2));
assert_eq!(destab1(&t1), destab1(&t2));
}
#[test]
fn test_rx_zero_is_identity() {
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.rx(0, 0.0);
assert_eq!(g.coefficients.len(), 1);
assert!(!g.measure(0).unwrap());
}
#[test]
fn test_ry_zero_is_identity() {
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.ry(0, 0.0);
assert_eq!(g.coefficients.len(), 1);
assert!(!g.measure(0).unwrap());
}
#[test]
fn test_rz_zero_is_identity() {
let mut g: GTab = GeneralizedTableau::new(1, 1e-12);
g.rz(0, 0.0);
assert_eq!(g.coefficients.len(), 1);
assert!(!g.measure(0).unwrap());
}
#[test]
fn test_rxx_zero_is_identity() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxx(0, 1, 0.0);
assert_eq!(g.coefficients.len(), 1);
assert!(!g.measure(0).unwrap());
assert!(!g.measure(1).unwrap());
}
#[test]
fn test_rot2_2pi_is_identity_measurement() {
let mut g: GTab = GeneralizedTableau::new(2, 1e-12);
g.rxx(0, 1, 2.0 * PI);
assert!(!g.measure(0).unwrap());
assert!(!g.measure(1).unwrap());
}