mathhook_core/algebra/
advanced_simplify.rs1mod helpers;
12
13use crate::core::Expression;
14
15pub 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 fn advanced_simplify(&self) -> Self {
27 let mut result = self.clone();
28
29 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 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 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 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 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 let expr = Expression::factorial(Expression::integer(5));
159 let result = expr.simplify_factorial();
160
161 assert_eq!(result, Expression::integer(120));
162
163 let expr = Expression::factorial(Expression::integer(0));
165 let result = expr.simplify_factorial();
166
167 assert_eq!(result, Expression::integer(1));
168
169 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 let expr = Expression::ln(Expression::integer(1));
180 let result = expr.simplify_logarithms();
181
182 assert_eq!(result, Expression::integer(0));
183
184 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 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 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 let expr = Expression::sqrt(Expression::integer(4));
214 let result = expr.simplify_special_functions();
215
216 assert_eq!(result, Expression::integer(2));
217
218 let expr = Expression::sqrt(Expression::integer(0));
220 let result = expr.simplify_special_functions();
221
222 assert_eq!(result, Expression::integer(0));
223
224 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 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 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 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 assert!(!result.to_string().is_empty());
272 }
273}