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.as_ref() == "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.as_ref() == "log" => {
81                self.simplify_log_function(args)
82            }
83
84            Expression::Function { name, args } if name.as_ref() == "ln" => {
85                self.simplify_ln_function(args)
86            }
87
88            Expression::Add(terms) => {
89                let simplified_terms: Vec<Expression> = terms
90                    .iter()
91                    .map(|term| term.simplify_logarithms())
92                    .collect();
93                Expression::add(simplified_terms)
94            }
95
96            Expression::Mul(factors) => {
97                let simplified_factors: Vec<Expression> = factors
98                    .iter()
99                    .map(|factor| factor.simplify_logarithms())
100                    .collect();
101                Expression::mul(simplified_factors)
102            }
103
104            _ => self.clone(),
105        }
106    }
107
108    /// Simplify trigonometric expressions
109    fn simplify_trigonometric(&self) -> Self {
110        match self {
111            Expression::Function { name, args } if self.is_trig_function(name) => {
112                self.simplify_trig_function(name, args)
113            }
114
115            Expression::Add(terms) => {
116                let simplified_terms: Vec<Expression> = terms
117                    .iter()
118                    .map(|term| term.simplify_trigonometric())
119                    .collect();
120                Expression::add(simplified_terms)
121            }
122
123            Expression::Mul(factors) => {
124                let simplified_factors: Vec<Expression> = factors
125                    .iter()
126                    .map(|factor| factor.simplify_trigonometric())
127                    .collect();
128                Expression::mul(simplified_factors)
129            }
130
131            _ => self.clone(),
132        }
133    }
134
135    /// Simplify other special functions
136    fn simplify_special_functions(&self) -> Self {
137        match self {
138            Expression::Function { name, args } => match name.as_ref() {
139                "sqrt" => self.simplify_sqrt(args),
140                "abs" => self.simplify_abs(args),
141                "exp" => self.simplify_exp(args),
142                "gamma" => self.simplify_gamma(args),
143                _ => self.clone(),
144            },
145            _ => self.clone(),
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153    use crate::symbol;
154
155    #[test]
156    fn test_factorial_computation() {
157        // Test 5! = 120
158        let expr = Expression::factorial(Expression::integer(5));
159        let result = expr.simplify_factorial();
160
161        assert_eq!(result, Expression::integer(120));
162
163        // Test 0! = 1
164        let expr = Expression::factorial(Expression::integer(0));
165        let result = expr.simplify_factorial();
166
167        assert_eq!(result, Expression::integer(1));
168
169        // Test 1! = 1
170        let expr = Expression::factorial(Expression::integer(1));
171        let result = expr.simplify_factorial();
172
173        assert_eq!(result, Expression::integer(1));
174    }
175
176    #[test]
177    fn test_logarithm_simplification() {
178        // Test ln(1) = 0
179        let expr = Expression::ln(Expression::integer(1));
180        let result = expr.simplify_logarithms();
181
182        assert_eq!(result, Expression::integer(0));
183
184        // Test ln(exp(x)) = x
185        let x = symbol!(x);
186        let expr = Expression::ln(Expression::function(
187            "exp",
188            vec![Expression::symbol(x.clone())],
189        ));
190        let result = expr.simplify_logarithms();
191
192        assert_eq!(result, Expression::symbol(x));
193    }
194
195    #[test]
196    fn test_trigonometric_simplification() {
197        // Test sin(0) = 0
198        let expr = Expression::function("sin", vec![Expression::integer(0)]);
199        let result = expr.simplify_trigonometric();
200
201        assert_eq!(result, Expression::integer(0));
202
203        // Test cos(0) = 1
204        let expr = Expression::function("cos", vec![Expression::integer(0)]);
205        let result = expr.simplify_trigonometric();
206
207        assert_eq!(result, Expression::integer(1));
208    }
209
210    #[test]
211    fn test_sqrt_simplification() {
212        // Test sqrt(4) = 2
213        let expr = Expression::sqrt(Expression::integer(4));
214        let result = expr.simplify_special_functions();
215
216        assert_eq!(result, Expression::integer(2));
217
218        // Test sqrt(0) = 0
219        let expr = Expression::sqrt(Expression::integer(0));
220        let result = expr.simplify_special_functions();
221
222        assert_eq!(result, Expression::integer(0));
223
224        // Test sqrt(1) = 1
225        let expr = Expression::sqrt(Expression::integer(1));
226        let result = expr.simplify_special_functions();
227
228        assert_eq!(result, Expression::integer(1));
229    }
230
231    #[test]
232    fn test_gamma_function() {
233        // Test Gamma(4) = 3! = 6
234        let expr = Expression::function("gamma", vec![Expression::integer(4)]);
235        let result = expr.simplify_special_functions();
236
237        assert_eq!(result, Expression::integer(6));
238
239        // Test Gamma(1) = 0! = 1
240        let expr = Expression::function("gamma", vec![Expression::integer(1)]);
241        let result = expr.simplify_special_functions();
242
243        assert_eq!(result, Expression::integer(1));
244    }
245
246    #[test]
247    fn test_advanced_zero_detection() {
248        // Test complex zero detection
249        let x = symbol!(x);
250        let expr = Expression::add(vec![
251            Expression::integer(4),
252            Expression::mul(vec![Expression::integer(4), Expression::symbol(x.clone())]),
253            Expression::mul(vec![
254                Expression::integer(-1),
255                Expression::mul(vec![
256                    Expression::integer(2),
257                    Expression::add(vec![
258                        Expression::integer(2),
259                        Expression::mul(vec![
260                            Expression::integer(2),
261                            Expression::symbol(x.clone()),
262                        ]),
263                    ]),
264                ]),
265            ]),
266        ]);
267
268        let result = expr.advanced_simplify();
269        // This is a complex case that might not simplify to zero immediately
270        // but should maintain the algebraic structure
271        assert!(!result.to_string().is_empty());
272    }
273}