use crate::algebra::equation_analyzer::SmartEquationSolver;
use crate::core::{Expression, Symbol};
use crate::simplify::Simplify;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SolverResult {
Single(Expression),
Multiple(Vec<Expression>),
NoSolution,
InfiniteSolutions,
}
#[derive(Debug, Clone)]
pub struct SolverConfig {
pub max_iterations: u32,
pub tolerance: f64,
pub use_numeric: bool,
pub simplify_results: bool,
}
impl Default for SolverConfig {
fn default() -> Self {
Self {
max_iterations: 1000,
tolerance: 1e-10,
use_numeric: false,
simplify_results: true,
}
}
}
pub struct MathSolver {
config: SolverConfig,
smart_solver: SmartEquationSolver,
}
impl MathSolver {
pub fn new() -> Self {
Self {
config: SolverConfig::default(),
smart_solver: SmartEquationSolver::new(),
}
}
pub fn with_config(config: SolverConfig) -> Self {
Self {
config,
smart_solver: SmartEquationSolver::new(),
}
}
pub fn solve(&self, equation: &Expression, variable: &Symbol) -> SolverResult {
match equation {
Expression::Relation(relation_data) => {
let left = &relation_data.left;
let right = &relation_data.right;
let standard_form = Expression::add(vec![
left.clone(),
Expression::mul(vec![Expression::integer(-1), right.clone()]),
]);
let (algebra_result, _explanation) = self
.smart_solver
.solve_with_equation(&standard_form, variable);
let result = self.convert_solver_result(algebra_result);
if self.config.simplify_results {
match result {
SolverResult::Single(expr) => SolverResult::Single(expr.simplify()),
SolverResult::Multiple(exprs) => {
SolverResult::Multiple(exprs.iter().map(|e| e.simplify()).collect())
}
other => other,
}
} else {
result
}
}
_ => {
let (algebra_result, _explanation) =
self.smart_solver.solve_with_equation(equation, variable);
let result = self.convert_solver_result(algebra_result);
if self.config.simplify_results {
match result {
SolverResult::Single(expr) => SolverResult::Single(expr.simplify()),
SolverResult::Multiple(exprs) => {
SolverResult::Multiple(exprs.iter().map(|e| e.simplify()).collect())
}
other => other,
}
} else {
result
}
}
}
}
pub fn solve_system(
&self,
equations: &[Expression],
variables: &[Symbol],
) -> Vec<SolverResult> {
equations
.iter()
.map(|eq| self.solve(eq, &variables[0]))
.collect()
}
pub fn configure(&mut self, config: SolverConfig) {
self.config = config;
}
fn convert_solver_result(
&self,
algebra_result: crate::algebra::solvers::SolverResult,
) -> SolverResult {
match algebra_result {
crate::algebra::solvers::SolverResult::Single(expr) => SolverResult::Single(expr),
crate::algebra::solvers::SolverResult::Multiple(exprs) => SolverResult::Multiple(exprs),
crate::algebra::solvers::SolverResult::NoSolution => SolverResult::NoSolution,
crate::algebra::solvers::SolverResult::InfiniteSolutions => {
SolverResult::InfiniteSolutions
}
crate::algebra::solvers::SolverResult::Parametric(exprs) => {
SolverResult::Multiple(exprs)
}
crate::algebra::solvers::SolverResult::Partial(exprs) => SolverResult::Multiple(exprs),
}
}
}
impl Default for MathSolver {
fn default() -> Self {
Self::new()
}
}