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 == "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 == "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 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 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 let expr = Expression::factorial(Expression::integer(5));
157 let result = expr.simplify_factorial();
158
159 assert_eq!(result, Expression::integer(120));
160
161 let expr = Expression::factorial(Expression::integer(0));
163 let result = expr.simplify_factorial();
164
165 assert_eq!(result, Expression::integer(1));
166
167 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 let expr = Expression::ln(Expression::integer(1));
178 let result = expr.simplify_logarithms();
179
180 assert_eq!(result, Expression::integer(0));
181
182 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 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 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 let expr = Expression::sqrt(Expression::integer(4));
212 let result = expr.simplify_special_functions();
213
214 assert_eq!(result, Expression::integer(2));
215
216 let expr = Expression::sqrt(Expression::integer(0));
218 let result = expr.simplify_special_functions();
219
220 assert_eq!(result, Expression::integer(0));
221
222 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 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 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 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 assert!(!result.to_string().is_empty());
270 }
271}