use mathhook_core::algebra::equation_analyzer::{
EquationAnalyzer, EquationType, SmartEquationSolver,
};
use mathhook_core::algebra::solvers::{SolverResult, SystemEquationSolver, SystemSolver};
use mathhook_core::{symbol, Expression};
#[test]
fn test_system_detection_multiple_variables() {
let x = symbol!(x);
let y = symbol!(y);
let equation = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::symbol(y.clone()),
Expression::integer(-3),
]);
let equation_type = EquationAnalyzer::analyze(&equation, &x);
assert!(
matches!(equation_type, EquationType::Linear | EquationType::System),
"Should detect equation with multiple variables as Linear or System"
);
}
#[test]
#[ignore = "FIXME: Lets find out why"]
fn test_polynomial_system_detection() {
let x = symbol!(x);
let y = symbol!(y);
let equation = Expression::add(vec![
Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
Expression::symbol(y.clone()),
Expression::integer(-1),
]);
let equation_type = EquationAnalyzer::analyze(&equation, &x);
assert!(
matches!(
equation_type,
EquationType::Quadratic | EquationType::Cubic | EquationType::Quartic
),
"Should detect x² + y as polynomial equation, got {:?}",
equation_type
);
}
#[test]
fn test_smart_solver_system_routing() {
let x = symbol!(x);
let y = symbol!(y);
let eq1 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::symbol(y.clone()),
Expression::integer(-3),
]);
let eq2 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(y.clone())]),
Expression::integer(-1),
]);
let solver = SmartEquationSolver::new();
let result = solver.solve_system(&[eq1, eq2], &[x, y]);
match result {
SolverResult::Multiple(sols) => {
assert_eq!(sols.len(), 2, "Should have 2 solutions (x and y)");
assert_eq!(sols[0], Expression::integer(2), "x should be 2");
assert_eq!(sols[1], Expression::integer(1), "y should be 1");
}
_ => panic!(
"Expected unique solution for simple 2x2 linear system, got {:?}",
result
),
}
}
#[test]
fn test_system_solver_linear_2x2() {
let x = symbol!(x);
let y = symbol!(y);
let solver = SystemSolver::new();
let eq1 = Expression::add(vec![
Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
Expression::symbol(y.clone()),
Expression::integer(-5),
]);
let eq2 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(y.clone())]),
Expression::integer(-1),
]);
let result = solver.solve_system(&[eq1, eq2], &[x, y]);
match result {
SolverResult::Multiple(sols) => {
assert_eq!(sols.len(), 2);
assert_eq!(sols[0], Expression::integer(2));
assert_eq!(sols[1], Expression::integer(1));
}
_ => panic!("Expected unique solution, got {:?}", result),
}
}
#[test]
fn test_polynomial_system_routes_to_groebner() {
let x = symbol!(x);
let y = symbol!(y);
let solver = SystemSolver::new();
let eq1 = Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(-1)]);
let eq2 = Expression::add(vec![Expression::symbol(y.clone()), Expression::integer(-2)]);
let result = solver.solve_system(&[eq1, eq2], &[x, y]);
match result {
SolverResult::Multiple(sols) => {
assert_eq!(sols.len(), 2);
}
SolverResult::Partial(_) => {
}
_ => panic!(
"Expected Multiple or Partial for simple polynomial system, got {:?}",
result
),
}
}
#[test]
#[ignore = "FIXME: Lets find out why"]
fn test_groebner_stub_mathematical_honesty() {
let x = symbol!(x);
let y = symbol!(y);
let solver = SystemSolver::new();
let eq1 = Expression::add(vec![
Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
Expression::pow(Expression::symbol(y.clone()), Expression::integer(2)),
Expression::integer(-1),
]);
let eq2 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(y.clone())]),
]);
let result = solver.solve_system(&[eq1, eq2], &[x, y]);
assert!(
!matches!(result, SolverResult::NoSolution),
"Should NOT return NoSolution for solvable system - this is mathematically incorrect. \
Expected Multiple or Partial. Got: {:?}",
result
);
assert!(
matches!(result, SolverResult::Partial(_) | SolverResult::Multiple(_)),
"Expected Partial or Multiple, got {:?}",
result
);
}
#[test]
fn test_no_regression_linear_systems() {
let x = symbol!(x);
let y = symbol!(y);
let z = symbol!(z);
let solver = SystemSolver::new();
let eq1 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::symbol(y.clone()),
Expression::symbol(z.clone()),
Expression::integer(-6),
]);
let eq2 = Expression::add(vec![
Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
Expression::symbol(y.clone()),
Expression::integer(-3),
]);
let eq3 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(y.clone())]),
Expression::mul(vec![Expression::integer(2), Expression::symbol(z.clone())]),
Expression::integer(-1),
]);
let result = solver.solve_system(&[eq1, eq2, eq3], &[x, y, z]);
match result {
SolverResult::Multiple(sols) => {
assert_eq!(sols.len(), 3, "Should have 3 solutions");
}
_ => panic!(
"Expected unique solution for 3x3 linear system, got {:?}",
result
),
}
}
#[test]
fn test_architecture_no_hardcoded_routing() {
let x = symbol!(x);
let y = symbol!(y);
let smart_solver = SmartEquationSolver::new();
let eq1 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::symbol(y.clone()),
Expression::integer(-3),
]);
let eq2 = Expression::add(vec![
Expression::symbol(x.clone()),
Expression::mul(vec![Expression::integer(-1), Expression::symbol(y.clone())]),
Expression::integer(-1),
]);
let result = smart_solver.solve_system(&[eq1, eq2], &[x, y]);
assert!(
matches!(result, SolverResult::Multiple(_)),
"SmartEquationSolver should route to SystemSolver via traits, not hardcoded"
);
}