use opt_einsum_path::contract::contract_path;
use opt_einsum_path::parser::get_symbol;
use rstest::rstest;
#[rstest]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("dp", 15)]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("dp", 50)]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("optimal", 5)]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("branch-1", 100)]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("greedy", 200)]
#[ignore = "This test is computationally expensive and should be run separately."]
#[case("random-greedy-128", 200)]
fn test_large(#[case] optimizer: &str, #[case] n: u32) {
println!("Testing large path optimization with n = {n} and opt = {optimizer}");
let mut einsum_str = "ab,ac,".to_string();
einsum_str += &(1..n - 1)
.map(|i| {
let j = 3 * i;
format!(
"{}{}{},{}{}{},",
get_symbol(j),
get_symbol(j - 1),
get_symbol(j + 2),
get_symbol(j),
get_symbol(j - 2),
get_symbol(j + 1),
)
})
.collect::<String>();
einsum_str += &format!(
"{}{},{}{}",
get_symbol(3 * (n - 1)),
get_symbol(3 * (n - 1) - 1),
get_symbol(3 * (n - 1)),
get_symbol(3 * (n - 1) - 2)
);
println!("Einsum string: {einsum_str}");
let len_ops = einsum_str.split(',').count();
let shapes = vec![vec![3, 10], vec![3, 10]]
.into_iter()
.chain(std::iter::repeat_n(vec![3, 10, 10], len_ops - 4))
.chain(vec![vec![3, 10], vec![3, 10]])
.collect::<Vec<_>>();
let time = std::time::Instant::now();
let (path, info) = contract_path(&einsum_str, &shapes, optimizer, None).unwrap();
let elapsed = time.elapsed();
println!("Optimal path: {path:?}");
println!("Optimal cost: {:?}", info.opt_cost);
println!("Elapsed time: {elapsed:?}");
}