use rsgridsynth::clear_caches;
use rsgridsynth::config::config_from_theta_epsilon;
use rsgridsynth::gridsynth::gridsynth_gates;
use serial_test::serial;
#[test]
#[serial]
fn simple_test() {
let pi = std::f64::consts::PI;
let theta = pi / 8.0; let epsilon = 1e-10;
let gates_1234 = "HTHTSHTSHTHTSHTHTSHTHTHTSHTSHTHTHTHTHTHTSHTSHTHTSHTSHTSHTSHTHTSHTSHTSHTHTHTHTHTHTSHTSHTHTSHTSHTSHTHTHTSHTSHTSHTSHTSHTSHTSHTHTHTHTHTSHTSHTSHTSHTSHTSHTHTHTHTHTSHTHTSHTHTHTSHTSHTSHTHTSHTSHTHTSHTHTSHTSHTHTSHTHTHTSHTSHTSHTSHTHTHTHTSHTHTHTSHTHTSHTHTHTSHTHTSHTHTSHTXSSWWW";
let gates_101 = "HTSHTSHTSHTHTHTSHTHTHTSHTSHTHTHTHTHTHTSHTHTHTHTSHTSHTHTSHTHTHTHTHTHTHTHTSHTHTHTHTSHTHTSHTSHTSHTSHTHTSHTSHTHTSHTSHTHTSHTHTHTSHTSHTHTHTHTSHTHTSHTHTSHTHTHTSHTSHTHTHTHTHTSHTHTSHTSHTHTHTHTSHTHTHTSHTHTHTHTSHTHTSHTSHTHTSHTHTSHTHTHTHTHTHTHTHTSHTHTHTSHTSSSWW";
let gates_1 = "HTSHTHTHTSHTHTHTHTHTHTHTHTSHTHTSHTHTSHTSHTHTSHTHTHTHTSHTHTHTSHTHTHTHTSHTSHTHTSHTHTHTHTHTSHTSHTHTHTSHTHTSHTHTSHTHTHTHTSHTSHTHTHTSHTHTSHTSHTHTSHTSHTHTSHTSHTSHTSHTHTSHTHTHTHTSHTHTHTHTHTHTHTHTSHTHTSHTSHTHTHTHTSHTHTHTHTHTHTSHTSHTHTHTSHTHTHTSHTSHTSHTSSSWW";
let test_inputs = vec![(1234, gates_1234), (101, gates_101), (1, gates_1)];
let verbose = false;
let up_to_phase = false;
for (seed, expected_gates) in test_inputs {
clear_caches();
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase);
let gates = gridsynth_gates(&mut gridsynth_config).gates;
assert_eq!(gates, expected_gates, "Test failed for seed: {}", seed);
}
}
#[test]
#[serial]
fn pi_over_two_test() {
let pi = std::f64::consts::PI;
let theta = pi / 2.0;
let epsilons = vec![1e-2, 1e-3, 1e-10];
let verbose = false;
let up_to_phase = false;
for epsilon in epsilons {
let seeds = 10..50;
for seed in seeds {
clear_caches();
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase);
let gates = gridsynth_gates(&mut gridsynth_config).gates;
let expected_gates = "SWWWWWWW";
assert_eq!(gates, expected_gates);
}
}
}
#[test]
#[serial]
fn pi_over_4_exact_test() {
let pi = std::f64::consts::PI;
let theta = pi / 4.0;
let epsilon = 1e-10;
let seed = 1234;
let up_to_phase = false;
let verbose = false;
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase);
let gates = gridsynth_gates(&mut gridsynth_config).gates;
let expected_gates = "SHTSHTHTSHTSHTHTSHTHTHTSHTSHTSHTHTSHTSHTHTHTSHTSHTSHTHTHTSHTHTSHTSHTSHTSHTSHTSHTSHTHTHTHTSHTHTHTHTHTHTSHTSHTHTHTSHTSHTHTHTHTSHTSHTHTSHTSHTSHTHTSHTHTHTSHTSHTHTSHTSHTSHTHTSHTHTHTSHTHTHTSHTSHTSHTSHTHTHTHTHTSHTSHTSHTHTSHTSHTHTSHTHTSHTHTHTHTSHTSHTHTSHTSHTSHTHTSHTSHTSHTHTSHTHTHTSHTHTHTSHTSHTHTSHTSHTHTSHTSHTSHTHTHTSHTSHTSHTSHTHTHTHTSHTHTHTHTHTSHTSHTHTSHSWW";
assert_eq!(gates, expected_gates);
}
#[test]
#[serial]
fn pi_over_4_with_phase_test() {
let pi = std::f64::consts::PI;
let theta = pi / 4.0;
let epsilon = 1e-10;
let seed = 1234;
let up_to_phase = true;
let verbose = false;
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase);
let gates = gridsynth_gates(&mut gridsynth_config).gates;
let expected_gates = "TWWWWWWW";
assert_eq!(gates, expected_gates);
}
#[test]
#[serial]
fn test_correct_decomposition_exact() {
let epsilon = 1e-10;
let verbose = false;
let seed = 0u64;
let up_to_phase = false;
let thetas = (0..64).map(|k| k as f64 * std::f64::consts::PI / 32.0);
for theta in thetas {
clear_caches();
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase)
.with_compute_error(true);
let res = gridsynth_gates(&mut gridsynth_config);
match res.error {
Some(error) => {
println!(
"theta = {theta}, gates = {}, error = {:.6e}, correct = {:?}",
res.gates, error, res.is_correct,
)
}
None => panic!("Expected computed error"),
}
assert!(res.is_correct.is_some_and(|v| v));
}
}
#[test]
#[serial]
fn test_correct_decomposition_up_to_phase() {
let epsilon = 1e-10;
let verbose = false;
let seed = 0u64;
let up_to_phase = true;
let thetas = (0..64).map(|k| k as f64 * std::f64::consts::PI / 32.0);
for theta in thetas {
clear_caches();
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase)
.with_compute_error(true);
let res = gridsynth_gates(&mut gridsynth_config);
match res.error {
Some(error) => {
println!(
"theta = {theta}, gates = {}, error = {:.6e}, correct = {:?}",
res.gates, error, res.is_correct,
)
}
None => panic!("Expected computed error"),
}
assert!(res.is_correct.is_some_and(|v| v));
}
}
#[test]
#[serial]
fn test_low_precision_bug() {
let pi = std::f64::consts::PI;
let theta = pi / 2.0;
let epsilon = 1e-1;
let verbose = false;
let mut gridsynth_config = config_from_theta_epsilon(theta, epsilon, 1234, verbose, false);
gridsynth_gates(&mut gridsynth_config);
}
#[test]
#[serial]
fn test_shared_cache_across_denomexp_no_panic() {
let epsilon = 1e-3;
let verbose = false;
let seed = 0u64;
let up_to_phase = true;
let mut panic_thetas = Vec::new();
let mut incorrect_thetas = Vec::new();
let mut max_error = 0.0_f64;
clear_caches();
for i in 1..=320 {
let theta = i as f64 * 0.01;
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let mut gridsynth_config =
config_from_theta_epsilon(theta, epsilon, seed, verbose, up_to_phase)
.with_compute_error(true);
gridsynth_gates(&mut gridsynth_config)
}));
match result {
Ok(res) => {
if let Some(error) = res.error {
max_error = max_error.max(error);
}
if !res.is_correct.is_some_and(|v| v) {
incorrect_thetas.push(theta);
}
}
Err(_) => panic_thetas.push(theta),
}
}
println!(
"shared-cache scan: n=320 epsilon={epsilon} panics={} incorrect={} max_error={max_error:.6e}",
panic_thetas.len(),
incorrect_thetas.len()
);
assert!(panic_thetas.is_empty(), "panic_thetas={panic_thetas:?}");
assert!(
incorrect_thetas.is_empty(),
"incorrect_thetas={incorrect_thetas:?}"
);
}
#[test]
#[serial]
fn test_timeouts_preserved_after_synthesis() {
let mut gridsynth_config =
config_from_theta_epsilon(std::f64::consts::PI / 8.0, 1e-10, 1234, false, true);
gridsynth_config.diophantine_data.diophantine_timeout = 237;
gridsynth_config.diophantine_data.factoring_timeout = 61;
clear_caches();
let result = gridsynth_gates(&mut gridsynth_config);
assert!(!result.gates.is_empty());
assert_eq!(gridsynth_config.diophantine_data.diophantine_timeout, 237);
assert_eq!(gridsynth_config.diophantine_data.factoring_timeout, 61);
}