use cheq::{Atom, QEqSolver, get_default_parameters};
pub struct TestCase<'a> {
pub name: &'a str,
pub atoms: Vec<Atom>,
pub expected: Vec<(usize, f64)>,
}
pub fn run_group_test(
group_name: &str,
cases: Vec<TestCase>,
group_avg_limit: f64,
group_max_limit: f64,
) {
let params = get_default_parameters();
let solver = QEqSolver::new(params);
let mut group_total_error = 0.0;
let mut group_max_error = 0.0;
let mut total_data_points = 0;
println!("\nRunning Group Test: {}", group_name);
println!("{:-<80}", "");
println!(
"{:<25} | {:<10} | {:<10} | {:<10}",
"Molecule", "Atom Idx", "Expected", "Calculated"
);
for case in cases {
let result = match solver.solve(&case.atoms, 0.0) {
Ok(res) => res,
Err(e) => {
println!(
"{:<25} | {:<10} | {:<10} | ERROR: {:?}",
case.name, "-", "-", e
);
group_total_error += 100.0;
group_max_error = 100.0;
total_data_points += 1;
continue;
}
};
for (index, expected_q) in &case.expected {
let calculated_q = result.charges[*index];
let error = (calculated_q - expected_q).abs();
println!(
"{:<25} | {:<10} | {:<10.4} | {:<10.4} (Err: {:.4})",
case.name, index, expected_q, calculated_q, error
);
group_total_error += error;
if error > group_max_error {
group_max_error = error;
}
total_data_points += 1;
}
}
let group_avg_error = if total_data_points > 0 {
group_total_error / total_data_points as f64
} else {
0.0
};
println!("{:-<80}", "");
println!("Group Statistics for '{}':", group_name);
println!(" Total Data Points: {}", total_data_points);
println!(
" Group Avg Error: {:.4} (Limit: {:.4})",
group_avg_error, group_avg_limit
);
println!(
" Group Max Error: {:.4} (Limit: {:.4})",
group_max_error, group_max_limit
);
println!("{:-<80}\n", "");
assert!(
group_avg_error <= group_avg_limit,
"Group average error {:.4} exceeds limit {:.4}",
group_avg_error,
group_avg_limit
);
assert!(
group_max_error <= group_max_limit,
"Group maximum error {:.4} exceeds limit {:.4}",
group_max_error,
group_max_limit
);
}