1use crate::core::{Expression, Number};
13use num_bigint::BigInt;
14use num_rational::BigRational;
15use num_traits::{One, Zero};
16
17pub trait RationalSimplify {
19 fn simplify_rational(&self) -> Self;
20 fn rationalize(&self) -> Self;
21 fn to_rational_form(&self) -> (Expression, Expression); }
23
24impl RationalSimplify for Expression {
25 fn simplify_rational(&self) -> Self {
27 match self {
28 Expression::Mul(factors) => self.simplify_rational_multiplication(factors),
30
31 Expression::Pow(base, exp) => {
33 if let Expression::Number(Number::Integer(n)) = exp.as_ref() {
35 if *n < 0 {
36 let positive_exp = Expression::integer(-n);
38 let denominator = Expression::pow(base.as_ref().clone(), positive_exp);
39 return self
40 .create_rational_division(&Expression::integer(1), &denominator);
41 }
42 }
43 self.clone()
44 }
45
46 _ => self.clone(),
47 }
48 }
49
50 fn to_rational_form(&self) -> (Expression, Expression) {
52 match self {
53 Expression::Number(Number::Rational(r)) => (
54 Expression::big_integer(r.numer().clone()),
55 Expression::big_integer(r.denom().clone()),
56 ),
57
58 Expression::Mul(factors) => {
59 let (num_factors, den_factors) = self.separate_rational_factors(factors);
60
61 let numerator = if num_factors.is_empty() {
62 Expression::integer(1)
63 } else {
64 Expression::mul(num_factors)
65 };
66
67 let denominator = if den_factors.is_empty() {
68 Expression::integer(1)
69 } else {
70 Expression::mul(den_factors)
71 };
72
73 (numerator, denominator)
74 }
75
76 Expression::Pow(base, exp) => {
77 if let Expression::Number(Number::Integer(n)) = exp.as_ref() {
78 if *n < 0 {
79 let positive_exp = Expression::integer(-n);
81 let denominator = Expression::pow(base.as_ref().clone(), positive_exp);
82 return (Expression::integer(1), denominator);
83 }
84 }
85 (self.clone(), Expression::integer(1))
86 }
87
88 _ => (self.clone(), Expression::integer(1)),
89 }
90 }
91
92 fn rationalize(&self) -> Self {
94 self.clone()
96 }
97}
98
99impl Expression {
100 fn simplify_rational_multiplication(&self, factors: &[Expression]) -> Expression {
102 let (numerator_factors, denominator_factors) = self.separate_rational_factors(factors);
103
104 self.cancel_common_factors(&numerator_factors, &denominator_factors)
107 }
108
109 fn separate_rational_factors(
111 &self,
112 factors: &[Expression],
113 ) -> (Vec<Expression>, Vec<Expression>) {
114 let mut numerator_factors = Vec::new();
115 let mut denominator_factors = Vec::new();
116
117 for factor in factors {
118 match factor {
119 Expression::Pow(base, exp) => {
121 if let Expression::Number(Number::Integer(n)) = exp.as_ref() {
122 if *n < 0 {
123 let positive_exp = Expression::integer(-n);
124 denominator_factors
125 .push(Expression::pow(base.as_ref().clone(), positive_exp));
126 } else {
127 numerator_factors.push(factor.clone());
128 }
129 } else {
130 numerator_factors.push(factor.clone());
131 }
132 }
133
134 _ => {
136 numerator_factors.push(factor.clone());
137 }
138 }
139 }
140
141 (numerator_factors, denominator_factors)
142 }
143
144 fn cancel_common_factors(
146 &self,
147 num_factors: &[Expression],
148 den_factors: &[Expression],
149 ) -> Expression {
150 if den_factors.is_empty() {
151 if num_factors.is_empty() {
153 return Expression::integer(1);
154 } else if num_factors.len() == 1 {
155 return num_factors[0].clone();
156 } else {
157 return Expression::mul(num_factors.to_vec());
158 }
159 }
160
161 let numerator = if num_factors.is_empty() {
162 Expression::integer(1)
163 } else {
164 Expression::mul(num_factors.to_vec())
165 };
166
167 let denominator = Expression::mul(den_factors.to_vec());
168
169 let gcd = numerator.gcd(&denominator);
171
172 if !gcd.is_one() {
173 let simplified_num = self.divide_expressions(&numerator, &gcd);
175 let simplified_den = self.divide_expressions(&denominator, &gcd);
176
177 self.create_rational_division(&simplified_num, &simplified_den)
178 } else {
179 self.create_rational_division(&numerator, &denominator)
180 }
181 }
182
183 fn create_rational_division(
185 &self,
186 numerator: &Expression,
187 denominator: &Expression,
188 ) -> Expression {
189 if denominator.is_one() {
190 numerator.clone()
191 } else if numerator.is_zero() {
192 Expression::integer(0)
193 } else {
194 Expression::mul(vec![
196 numerator.clone(),
197 Expression::pow(denominator.clone(), Expression::integer(-1)),
198 ])
199 }
200 }
201
202 fn divide_expressions(&self, dividend: &Expression, divisor: &Expression) -> Expression {
204 match (dividend, divisor) {
205 (Expression::Number(Number::Integer(a)), Expression::Number(Number::Integer(b))) => {
207 if !b.is_zero() {
208 let rational = BigRational::new(BigInt::from(*a), BigInt::from(*b));
209 if rational.denom().is_one() {
210 Expression::big_integer(rational.numer().clone())
211 } else {
212 Expression::number(Number::rational(rational))
213 }
214 } else {
215 dividend.clone() }
217 }
218
219 _ if dividend == divisor => Expression::integer(1),
221
222 (Expression::Mul(factors), _) => {
224 let mut remaining_factors = factors.as_ref().clone();
225 if let Some(pos) = remaining_factors.iter().position(|f| f == divisor) {
226 remaining_factors.remove(pos);
227 if remaining_factors.is_empty() {
228 Expression::integer(1)
229 } else if remaining_factors.len() == 1 {
230 remaining_factors[0].clone()
231 } else {
232 Expression::mul(remaining_factors)
233 }
234 } else {
235 dividend.clone()
236 }
237 }
238
239 _ => dividend.clone(),
241 }
242 }
243
244 pub fn add_rationals(&self, other: &Expression) -> Expression {
246 let (num1, den1) = self.to_rational_form();
247 let (num2, den2) = other.to_rational_form();
248
249 if den1 == den2 {
250 let new_num = Expression::add(vec![num1, num2]);
252 self.create_rational_division(&new_num, &den1)
253 } else {
254 let new_num = Expression::add(vec![
256 Expression::mul(vec![num1, den2.clone()]),
257 Expression::mul(vec![num2, den1.clone()]),
258 ]);
259 let new_den = Expression::mul(vec![den1, den2]);
260
261 self.create_rational_division(&new_num, &new_den)
262 }
263 }
264
265 pub fn multiply_rationals(&self, other: &Expression) -> Expression {
267 let (num1, den1) = self.to_rational_form();
268 let (num2, den2) = other.to_rational_form();
269
270 let new_num = Expression::mul(vec![num1, num2]);
271 let new_den = Expression::mul(vec![den1, den2]);
272
273 self.create_rational_division(&new_num, &new_den)
274 }
275
276 pub fn simplify_complex_rational(&self) -> Expression {
278 match self {
280 Expression::Mul(factors) => {
281 let mut rational_parts = Vec::new();
283 let mut other_parts = Vec::new();
284
285 for factor in factors.iter() {
286 if self.is_rational_expression(factor) {
287 rational_parts.push(factor.clone());
288 } else {
289 other_parts.push(factor.clone());
290 }
291 }
292
293 if rational_parts.len() > 1 {
294 let mut result = rational_parts[0].clone();
296 for rational in &rational_parts[1..] {
297 result = result.multiply_rationals(rational);
298 }
299
300 if !other_parts.is_empty() {
302 other_parts.push(result);
303 Expression::mul(other_parts)
304 } else {
305 result
306 }
307 } else {
308 self.clone()
309 }
310 }
311 _ => self.clone(),
312 }
313 }
314
315 fn is_rational_expression(&self, expr: &Expression) -> bool {
317 match expr {
318 Expression::Number(Number::Rational(_)) => true,
319 Expression::Pow(_, exp) => {
320 if let Expression::Number(Number::Integer(n)) = exp.as_ref() {
322 *n < 0
323 } else {
324 false
325 }
326 }
327 _ => false,
328 }
329 }
330
331 pub fn extract_rational_coefficient(&self) -> (BigRational, Expression) {
333 match self {
334 Expression::Number(Number::Rational(r)) => ((**r).clone(), Expression::integer(1)),
335 Expression::Number(Number::Integer(n)) => {
336 (BigRational::from(BigInt::from(*n)), Expression::integer(1))
337 }
338 Expression::Mul(factors) => {
339 let mut coefficient = BigRational::one();
340 let mut non_rational_factors = Vec::new();
341
342 for factor in factors.iter() {
343 match factor {
344 Expression::Number(Number::Rational(r)) => {
345 coefficient *= r.as_ref();
346 }
347 Expression::Number(Number::Integer(n)) => {
348 coefficient *= BigRational::from(BigInt::from(*n));
349 }
350 _ => {
351 non_rational_factors.push(factor.clone());
352 }
353 }
354 }
355
356 let remaining = if non_rational_factors.is_empty() {
357 Expression::integer(1)
358 } else if non_rational_factors.len() == 1 {
359 non_rational_factors[0].clone()
360 } else {
361 Expression::mul(non_rational_factors)
362 };
363
364 (coefficient, remaining)
365 }
366 _ => (BigRational::one(), self.clone()),
367 }
368 }
369
370 pub fn extract_rational_parts(&self) -> (String, String, Expression) {
375 let (rational, remainder) = self.extract_rational_coefficient();
376 (
377 rational.numer().to_string(),
378 rational.denom().to_string(),
379 remainder,
380 )
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387 use crate::symbol;
388
389 #[test]
390 fn test_rational_detection() {
391 let rational = Expression::number(Number::rational(BigRational::new(
393 BigInt::from(3),
394 BigInt::from(4),
395 )));
396
397 let (num, den) = rational.to_rational_form();
398
399 assert_eq!(num, Expression::integer(3));
400 assert_eq!(den, Expression::integer(4));
401 }
402
403 #[test]
404 fn test_simple_rational_combination() {
405 let half = Expression::number(Number::rational(BigRational::new(
407 BigInt::from(1),
408 BigInt::from(2),
409 )));
410 let third = Expression::number(Number::rational(BigRational::new(
411 BigInt::from(1),
412 BigInt::from(3),
413 )));
414
415 let result = half.add_rationals(&third);
416 println!("1/2 + 1/3 = {}", result);
417
418 assert!(!result.is_zero());
420 }
421
422 #[test]
423 fn test_rational_simplification() {
424 let x = symbol!(x);
425
426 let expr = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-1));
428 let result = expr.simplify_rational();
429
430 println!("x^(-1) simplified = {}", result);
431 assert!(!result.is_zero());
432 }
433
434 #[test]
435 fn test_rational_multiplication() {
436 let frac1 = Expression::number(Number::rational(BigRational::new(
438 BigInt::from(2),
439 BigInt::from(3),
440 )));
441 let frac2 = Expression::number(Number::rational(BigRational::new(
442 BigInt::from(3),
443 BigInt::from(4),
444 )));
445
446 let result = frac1.multiply_rationals(&frac2);
447 println!("(2/3) * (3/4) = {}", result);
448
449 assert!(!result.is_zero());
450 }
451
452 #[test]
453 fn test_common_factor_cancellation() {
454 let x = symbol!(x);
455
456 let numerator =
458 Expression::mul(vec![Expression::integer(6), Expression::symbol(x.clone())]);
459 let denominator =
460 Expression::mul(vec![Expression::integer(9), Expression::symbol(x.clone())]);
461
462 let expr = Expression::integer(1).create_rational_division(&numerator, &denominator);
463 let result = expr.simplify_rational();
464
465 println!("(6x)/(9x) simplified = {}", result);
466 assert!(!result.is_zero());
467 }
468
469 #[test]
470 fn test_extract_rational_coefficient() {
471 let x = symbol!(x);
472
473 let expr = Expression::mul(vec![
474 Expression::number(Number::rational(BigRational::new(
475 BigInt::from(3),
476 BigInt::from(4),
477 ))),
478 Expression::symbol(x.clone()),
479 ]);
480
481 let (coeff, remaining) = expr.extract_rational_coefficient();
482
483 println!(
484 "Coefficient: {}, Remaining: {}",
485 Expression::number(Number::rational(coeff)),
486 remaining
487 );
488
489 assert_eq!(remaining, Expression::symbol(x));
490 }
491}