mathhook_core/algebra/
advanced_simplify.rs

1//! Advanced simplification operations including special functions
2//! Handles factorial, trigonometric functions, logarithms, and complex simplifications
3//!
4//! # Noncommutative Simplification Rules
5//!
6//! All simplification rules respect noncommutativity:
7//! - log(AB) = log(A) + log(B) is ONLY valid when A and B commute
8//! - For matrices: log(AB) ≠ log(A) + log(B) in general
9//! - This implementation checks commutativity before applying simplification rules
10
11mod helpers;
12
13use crate::core::Expression;
14
15/// Trait for advanced simplification operations
16pub trait AdvancedSimplify {
17    fn advanced_simplify(&self) -> Self;
18    fn simplify_factorial(&self) -> Self;
19    fn simplify_logarithms(&self) -> Self;
20    fn simplify_trigonometric(&self) -> Self;
21    fn simplify_special_functions(&self) -> Self;
22}
23
24impl AdvancedSimplify for Expression {
25    /// Perform advanced simplification including special functions
26    fn advanced_simplify(&self) -> Self {
27        let mut result = self.clone();
28
29        // Apply various advanced simplification techniques
30        result = result.simplify_factorial();
31        result = result.simplify_logarithms();
32        result = result.simplify_trigonometric();
33        result = result.simplify_special_functions();
34
35        result
36    }
37
38    /// Simplify factorial expressions
39    fn simplify_factorial(&self) -> Self {
40        match self {
41            Expression::Function { name, args } if name == "factorial" => {
42                if args.len() == 1 {
43                    self.compute_factorial(&args[0])
44                } else {
45                    self.clone()
46                }
47            }
48
49            Expression::Add(terms) => {
50                let simplified_terms: Vec<Expression> =
51                    terms.iter().map(|term| term.simplify_factorial()).collect();
52                Expression::add(simplified_terms)
53            }
54
55            Expression::Mul(factors) => {
56                let simplified_factors: Vec<Expression> = factors
57                    .iter()
58                    .map(|factor| factor.simplify_factorial())
59                    .collect();
60                Expression::mul(simplified_factors)
61            }
62
63            Expression::Pow(base, exp) => {
64                Expression::pow(base.simplify_factorial(), exp.simplify_factorial())
65            }
66
67            Expression::Function { name, args } => {
68                let simplified_args: Vec<Expression> =
69                    args.iter().map(|arg| arg.simplify_factorial()).collect();
70                Expression::function(name.clone(), simplified_args)
71            }
72
73            _ => self.clone(),
74        }
75    }
76
77    /// Simplify logarithmic expressions
78    fn simplify_logarithms(&self) -> Self {
79        match self {
80            Expression::Function { name, args } if name == "log" => {
81                self.simplify_log_function(args)
82            }
83
84            Expression::Function { name, args } if name == "ln" => self.simplify_ln_function(args),
85
86            Expression::Add(terms) => {
87                let simplified_terms: Vec<Expression> = terms
88                    .iter()
89                    .map(|term| term.simplify_logarithms())
90                    .collect();
91                Expression::add(simplified_terms)
92            }
93
94            Expression::Mul(factors) => {
95                let simplified_factors: Vec<Expression> = factors
96                    .iter()
97                    .map(|factor| factor.simplify_logarithms())
98                    .collect();
99                Expression::mul(simplified_factors)
100            }
101
102            _ => self.clone(),
103        }
104    }
105
106    /// Simplify trigonometric expressions
107    fn simplify_trigonometric(&self) -> Self {
108        match self {
109            Expression::Function { name, args } if self.is_trig_function(name) => {
110                self.simplify_trig_function(name, args)
111            }
112
113            Expression::Add(terms) => {
114                let simplified_terms: Vec<Expression> = terms
115                    .iter()
116                    .map(|term| term.simplify_trigonometric())
117                    .collect();
118                Expression::add(simplified_terms)
119            }
120
121            Expression::Mul(factors) => {
122                let simplified_factors: Vec<Expression> = factors
123                    .iter()
124                    .map(|factor| factor.simplify_trigonometric())
125                    .collect();
126                Expression::mul(simplified_factors)
127            }
128
129            _ => self.clone(),
130        }
131    }
132
133    /// Simplify other special functions
134    fn simplify_special_functions(&self) -> Self {
135        match self {
136            Expression::Function { name, args } => match name.as_str() {
137                "sqrt" => self.simplify_sqrt(args),
138                "abs" => self.simplify_abs(args),
139                "exp" => self.simplify_exp(args),
140                "gamma" => self.simplify_gamma(args),
141                _ => self.clone(),
142            },
143            _ => self.clone(),
144        }
145    }
146}
147
148#[cfg(test)]
149mod tests {
150    use super::*;
151    use crate::symbol;
152
153    #[test]
154    fn test_factorial_computation() {
155        // Test 5! = 120
156        let expr = Expression::factorial(Expression::integer(5));
157        let result = expr.simplify_factorial();
158
159        assert_eq!(result, Expression::integer(120));
160
161        // Test 0! = 1
162        let expr = Expression::factorial(Expression::integer(0));
163        let result = expr.simplify_factorial();
164
165        assert_eq!(result, Expression::integer(1));
166
167        // Test 1! = 1
168        let expr = Expression::factorial(Expression::integer(1));
169        let result = expr.simplify_factorial();
170
171        assert_eq!(result, Expression::integer(1));
172    }
173
174    #[test]
175    fn test_logarithm_simplification() {
176        // Test ln(1) = 0
177        let expr = Expression::ln(Expression::integer(1));
178        let result = expr.simplify_logarithms();
179
180        assert_eq!(result, Expression::integer(0));
181
182        // Test ln(exp(x)) = x
183        let x = symbol!(x);
184        let expr = Expression::ln(Expression::function(
185            "exp",
186            vec![Expression::symbol(x.clone())],
187        ));
188        let result = expr.simplify_logarithms();
189
190        assert_eq!(result, Expression::symbol(x));
191    }
192
193    #[test]
194    fn test_trigonometric_simplification() {
195        // Test sin(0) = 0
196        let expr = Expression::function("sin", vec![Expression::integer(0)]);
197        let result = expr.simplify_trigonometric();
198
199        assert_eq!(result, Expression::integer(0));
200
201        // Test cos(0) = 1
202        let expr = Expression::function("cos", vec![Expression::integer(0)]);
203        let result = expr.simplify_trigonometric();
204
205        assert_eq!(result, Expression::integer(1));
206    }
207
208    #[test]
209    fn test_sqrt_simplification() {
210        // Test sqrt(4) = 2
211        let expr = Expression::sqrt(Expression::integer(4));
212        let result = expr.simplify_special_functions();
213
214        assert_eq!(result, Expression::integer(2));
215
216        // Test sqrt(0) = 0
217        let expr = Expression::sqrt(Expression::integer(0));
218        let result = expr.simplify_special_functions();
219
220        assert_eq!(result, Expression::integer(0));
221
222        // Test sqrt(1) = 1
223        let expr = Expression::sqrt(Expression::integer(1));
224        let result = expr.simplify_special_functions();
225
226        assert_eq!(result, Expression::integer(1));
227    }
228
229    #[test]
230    fn test_gamma_function() {
231        // Test Gamma(4) = 3! = 6
232        let expr = Expression::function("gamma", vec![Expression::integer(4)]);
233        let result = expr.simplify_special_functions();
234
235        assert_eq!(result, Expression::integer(6));
236
237        // Test Gamma(1) = 0! = 1
238        let expr = Expression::function("gamma", vec![Expression::integer(1)]);
239        let result = expr.simplify_special_functions();
240
241        assert_eq!(result, Expression::integer(1));
242    }
243
244    #[test]
245    fn test_advanced_zero_detection() {
246        // Test complex zero detection
247        let x = symbol!(x);
248        let expr = Expression::add(vec![
249            Expression::integer(4),
250            Expression::mul(vec![Expression::integer(4), Expression::symbol(x.clone())]),
251            Expression::mul(vec![
252                Expression::integer(-1),
253                Expression::mul(vec![
254                    Expression::integer(2),
255                    Expression::add(vec![
256                        Expression::integer(2),
257                        Expression::mul(vec![
258                            Expression::integer(2),
259                            Expression::symbol(x.clone()),
260                        ]),
261                    ]),
262                ]),
263            ]),
264        ]);
265
266        let result = expr.advanced_simplify();
267        // This is a complex case that might not simplify to zero immediately
268        // but should maintain the algebraic structure
269        assert!(!result.to_string().is_empty());
270    }
271}