2 from sympy
.core
import Basic
, S
, Add
, Mul
, Pow
, Rational
, Integer
, \
3 Derivative
, Wild
, Symbol
5 from sympy
.utilities
import make_list
, all
6 from sympy
.functions
import gamma
, exp
10 def fraction(expr
, exact
=False):
11 """Returns a pair with expression's numerator and denominator.
12 If the given expression is not a fraction then this function
13 will assume that the denominator is equal to one.
15 This function will not make any attempt to simplify nested
16 fractions or to do any term rewriting at all.
18 If only one of the numerator/denominator pair is needed then
19 use numer(expr) or denom(expr) functions respectively.
21 >>> from sympy import *
22 >>> x, y = symbols('x', 'y')
34 >>> fraction(Rational(1, 2))
37 This function will also work fine with assumptions:
39 >>> k = Symbol('k', negative=True)
40 >>> fraction(x * y**k)
43 If we know nothing about sign of some exponent and 'exact'
44 flag is unset, then structure this exponent's structure will
45 be analyzed and pretty fraction will be returned:
47 >>> fraction(2*x**(-y))
50 #>>> fraction(exp(-x))
53 >>> fraction(exp(-x), exact=True)
57 expr
= Basic
.sympify(expr
)
59 #XXX this only works sometimes (caching bug?)
60 if expr
== exp(-Symbol("x")) and exact
:
65 for term
in make_list(expr
, Mul
):
66 if isinstance(term
, Pow
):
67 if term
.exp
.is_negative
:
68 if term
.exp
== Integer(-1):
69 denom
.append(term
.base
)
71 denom
.append(Pow(term
.base
, -term
.exp
))
72 elif not exact
and isinstance(term
.exp
, Mul
):
73 coeff
, tail
= term
.exp
[0], Mul(*term
.exp
[1:])#term.exp.getab()
75 if isinstance(coeff
, Rational
) and coeff
.is_negative
:
76 denom
.append(Pow(term
.base
, -term
.exp
))
81 elif isinstance(term
, Basic
.exp
):
82 if term
[0].is_negative
:
83 denom
.append(Basic
.exp(-term
[0]))
84 elif not exact
and isinstance(term
[0], Mul
):
85 coeff
, tail
= term
[0], Mul(*term
[1:])#term.args.getab()
87 if isinstance(coeff
, Rational
) and coeff
.is_negative
:
88 denom
.append(Basic
.exp(-term
[0]))
93 elif isinstance(term
, Rational
):
97 numer
.append(Rational(term
.p
))
98 denom
.append(Rational(term
.q
))
102 return Mul(*numer
), Mul(*denom
)
105 return fraction(expr
)[0]
108 return fraction(expr
)[1]
110 def fraction_expand(expr
):
111 a
, b
= fraction(expr
)
112 return a
.expand() / b
.expand()
114 def numer_expand(expr
):
115 a
, b
= fraction(expr
)
116 return a
.expand() / b
118 def denom_expand(expr
):
119 a
, b
= fraction(expr
)
120 return a
/ b
.expand()
122 def separate(expr
, deep
=False):
123 """Rewrite or separate a power of product to a product of powers
124 but without any expanding, ie. rewriting products to summations.
126 >>> from sympy import *
127 >>> x, y, z = symbols('x', 'y', 'z')
129 >>> separate((x*y)**2)
132 >>> separate((x*(y*z)**3)**2)
135 >>> separate((x*sin(x))**y + (x*cos(x))**y)
136 x**y*cos(x)**y + x**y*sin(x)**y
138 #>>> separate((exp(x)*exp(y))**x)
141 Notice that summations are left un touched. If this is not the
142 requested behaviour, apply 'expand' to input expression before:
144 >>> separate(((x+y)*z)**2)
147 >>> separate((x*y)**(1+z))
148 x**(1 + z)*y**(1 + z)
151 expr
= Basic
.sympify(expr
)
153 if isinstance(expr
, Basic
.Pow
):
154 terms
, expo
= [], separate(expr
.exp
, deep
)
155 #print expr, terms, expo, expr.base
157 if isinstance(expr
.base
, Mul
):
158 t
= [ separate(Basic
.Pow(t
,expo
), deep
) for t
in expr
.base
]
160 elif isinstance(expr
.base
, Basic
.exp
):
162 return Basic
.exp(separate(expr
.base
[0], deep
)*expo
)
164 return Basic
.exp(expr
.base
[0]*expo
)
166 return Basic
.Pow(separate(expr
.base
, deep
), expo
)
167 elif isinstance(expr
, (Basic
.Add
, Basic
.Mul
)):
168 return type(expr
)(*[ separate(t
, deep
) for t
in expr
])
169 elif isinstance(expr
, Basic
.Function
) and deep
:
170 return expr
.func(*[ separate(t
) for t
in expr
])
175 def together(expr
, deep
=False):
176 """Combine together and denest rational functions into a single
177 fraction. By default the resulting expression is simplified
178 to reduce the total order of both numerator and denominator
179 and minimize the number of terms.
181 Densting is done recursively on fractions level. However this
182 function will not attempt to rewrite composite objects, like
183 functions, interior unless 'deep' flag is set.
185 By definition, 'together' is a complement to 'apart', so
186 apart(together(expr)) should left expression unhanged.
188 >>> from sympy import *
189 >>> x, y, z = symbols('x', 'y', 'z')
191 You can work with sums of fractions easily. The algorithm
192 used here will, in an iterative style, collect numerators
193 and denominator of all expressions involved and perform
194 needed simplifications:
196 #>>> together(1/x + 1/y)
199 #>>> together(1/x + 1/y + 1/z)
200 #(z*x + x*y + z*y)/(y*x*z)
202 >>> together(1/(x*y) + 1/y**2)
205 Or you can just denest multi-level fractional expressions:
207 >>> together(1/(1 + 1/x))
210 It also perfect possible to work with symbolic powers or
211 exponential functions or combinations of both:
213 >>> together(1/x**y + 1/x**(y-1))
216 #>>> together(1/x**(2*y) + 1/x**(y-z))
217 #x**(-2*y)*(1 + x**(y + z))
219 #>>> together(1/exp(x) + 1/(x*exp(x)))
222 #>>> together(1/exp(2*x) + 1/(x*exp(3*x)))
223 #(1+exp(x)*x)/(x*exp(3*x))
229 from sympy
.core
.function
import Function
231 if isinstance(expr
, Add
):
232 items
, coeffs
, basis
= [], [], {}
235 numer
, q
= fraction(_together(elem
))
239 for term
in make_list(q
.expand(), Mul
):
244 if isinstance(term
, Pow
):
245 if isinstance(term
.exp
, Rational
):
246 term
, expo
= term
.base
, term
.exp
247 elif isinstance(term
.exp
, Mul
):
248 coeff
, tail
= term
.exp
.as_coeff_terms()
249 if isinstance(coeff
, Rational
):
250 tail
= Basic
.Mul(*tail
)
251 term
, expo
= Pow(term
.base
, tail
), coeff
253 elif isinstance(term
, Basic
.exp
):
254 if isinstance(term
[0], Rational
):
255 term
, expo
= Basic
.E
, term
[0]
256 elif isinstance(term
[0], Mul
):
257 coeff
, tail
= term
[0].as_coeff_terms()
258 if isinstance(coeff
, Rational
):
259 tail
= Basic
.Mul(*tail
)
260 term
, expo
= Basic
.exp(tail
), coeff
262 elif isinstance(term
, Rational
):
263 coeff
= Integer(term
.q
)
264 term
= Integer(term
.p
)
272 total
, maxi
= basis
[term
]
274 n_total
= total
+ expo
275 n_maxi
= max(maxi
, expo
)
277 basis
[term
] = (n_total
, n_maxi
)
279 basis
[term
] = (expo
, expo
)
282 items
.append((numer
, denom
))
284 numerator
, denominator
= [], []
286 for (term
, (total
, maxi
)) in basis
.iteritems():
287 basis
[term
] = (total
, total
-maxi
)
289 if isinstance(term
, Basic
.exp
):
290 denominator
.append(Basic
.exp(maxi
*term
[:]))
292 if isinstance(maxi
, Basic
.One
):
293 denominator
.append(term
)
295 denominator
.append(Pow(term
, maxi
))
297 from sympy
.core
.numbers
import gcd
as int_gcd
299 if all([ c
.is_integer
for c
in coeffs
]):
300 gcds
= lambda x
, y
: int_gcd(int(x
), int(y
))
301 common
= Rational(reduce(gcds
, coeffs
))
305 product
= reduce(lambda x
, y
: x
*y
, coeffs
) / common
307 for ((numer
, denom
), coeff
) in zip(items
, coeffs
):
309 expr
, coeff
= [], product
/ (coeff
*common
)
311 for term
in basis
.iterkeys():
312 total
, sub
= basis
[term
]
315 expo
= total
-denom
[term
]-sub
319 if isinstance(term
, Basic
.exp
):
320 expr
.append(Basic
.exp(expo
*term
[:]))
322 if isinstance(expo
, Basic
.One
):
325 expr
.append(Pow(term
, expo
))
327 numerator
.append(coeff
*Mul(*([numer
] + expr
)))
329 return Add(*numerator
)/(product
*Mul(*denominator
))
330 elif isinstance(expr
, (Mul
, Pow
)):
331 return type(expr
)(*[ _together(t
) for t
in expr
])
332 elif isinstance(expr
, Function
) and deep
:
333 return expr
.func(*[ _together(t
) for t
in expr
])
337 return _together(separate(expr
))
339 #apart -> partial fractions decomposition (will be here :)
341 def collect(expr
, syms
, evaluate
=True, exact
=False):
342 """Collect additive terms with respect to a list of symbols up
343 to powers with rational exponents. By the term symbol here
344 are meant arbitrary expressions, which can contain powers,
345 products, sums etc. In other words symbol is a pattern
346 which will be searched for in the expression's terms.
348 This function will not apply any redundant expanding to the
349 input expression, so user is assumed to enter expression in
350 final form. This makes 'collect' more predictable as there
351 is no magic behind the scenes. However it is important to
352 note, that powers of products are converted to products of
353 powers using 'separate' function.
355 There are two possible types of output. First, if 'evaluate'
356 flag is set, this function will return a single expression
357 or else it will return a dictionary with separated symbols
358 up to rational powers as keys and collected sub-expressions
359 as values respectively.
361 >>> from sympy import *
362 >>> x, y, z = symbols('x', 'y', 'z')
363 >>> a, b, c = symbols('a', 'b', 'c')
365 This function can collect symbolic coefficients in polynomial
366 or rational expressions. It will manage to find all integer or
367 rational powers of collection variable:
369 >>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x)
370 c + x*(a - b) + x**2*(a + b)
372 The same result can achieved in dictionary form:
374 >>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False)
375 {1: c, x**2: a + b, x: a - b}
377 You can also work with multi-variate polynomials. However
378 remember that this function is greedy so it will care only
379 about a single symbol at time, in specification order:
381 >>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y])
382 x*y + y*(1 + a) + x**2*(1 + y)
384 >>> collect(x**2*y**4 + z*(x*y**2)**2 + z + a*z, [x*y**2, z])
385 z*(1 + a) + x**2*y**4*(1 + z)
387 Also more complicated expressions can be used as patterns:
389 >>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x))
392 >>> collect(a*x**2*log(x)**2 + b*(x*log(x))**2, x*log(x))
393 x**2*log(x)**2*(a + b)
395 It is also possible to work with symbolic powers, although
396 it has more complicated behaviour, because in this case
397 power's base and symbolic part of the exponent are treated
400 #>>> collect(a*x**c + b*x**c, x)
403 #>>> collect(a*x**c + b*x**c, x**c)
406 However if you incorporate rationals to the exponents, then
407 you will get well known behaviour:
409 #>>> collect(a*x**(2*c) + b*x**(2*c), x**c)
412 Note also that all previously stated facts about 'collect'
413 function apply to the exponential function, so you can get:
415 #>>> collect(a*exp(2*x) + b*exp(2*x), exp(x))
418 If you are interested only in collecting specific powers
419 of some symbols then set 'exact' flag in arguments:
421 >>> collect(a*x**7 + b*x**7, x, exact=True)
424 >>> collect(a*x**7 + b*x**7, x**7, exact=True)
427 You can also apply this function to differential equations, where
428 derivatives of arbitary order can be collected:
430 #>>> from sympy import Derivative as D
433 #>>> collect(a*D(f,x) + b*D(f,x), D(f,x))
436 #>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x))
437 #(a+b)*(Function'(x))'
439 #>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True)
440 #a*(Function'(x))'+b*(Function'(x))'
442 #>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x) + a*D(f,x) + b*D(f,x), D(f,x))
443 #(a+b)*Function'(x)+(a+b)*(Function'(x))'
445 Or you can even match both derivative order and exponent at time:
447 #>>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))
448 #(a+b)*(Function'(x))'**2
451 def make_expression(terms
):
454 for term
, rat
, sym
, deriv
in terms
:
455 if deriv
is not None:
459 term
, order
= Derivative(term
, var
), order
-1
462 if isinstance(rat
, Basic
.One
):
465 product
.append(Pow(term
, rat
))
467 product
.append(Pow(term
, rat
*sym
))
471 def parse_derivative(deriv
):
472 # scan derivatives tower in the input expression and return
473 # underlying function and maximal differentiation order
474 expr
, sym
, order
= deriv
.f
, deriv
.x
, 1
476 while isinstance(expr
, Derivative
) and expr
.x
== sym
:
477 expr
, order
= expr
.f
, order
+1
479 return expr
, (sym
, Rational(order
))
481 def parse_term(expr
):
482 rat_expo
, sym_expo
= Rational(1), None
483 sexpr
, deriv
= expr
, None
485 if isinstance(expr
, Pow
):
486 if isinstance(expr
.base
, Derivative
):
487 sexpr
, deriv
= parse_derivative(expr
.base
)
491 if isinstance(expr
.exp
, Rational
):
493 elif isinstance(expr
.exp
, Mul
):
494 coeff
, tail
= term
.exp
.as_coeff_terms()
496 if isinstance(coeff
, Rational
):
497 rat_expo
, sym_expo
= coeff
, Basic
.Mul(*tail
)
502 elif isinstance(expr
, Basic
.exp
):
503 if isinstance(expr
[0], Rational
):
504 sexpr
, rat_expo
= Basic
.exp(Rational(1)), expr
[0]
505 elif isinstance(expr
[0], Mul
):
506 coeff
, tail
= expr
[0].as_coeff_terms()
508 if isinstance(coeff
, Rational
):
509 sexpr
, rat_expo
= Basic
.exp(Basic
.Mul(*tail
)), coeff
510 elif isinstance(expr
, Derivative
):
511 sexpr
, deriv
= parse_derivative(expr
)
513 return sexpr
, rat_expo
, sym_expo
, deriv
515 def parse_expression(terms
, pattern
):
516 pattern
= make_list(pattern
, Mul
)
518 if len(terms
) < len(pattern
):
519 # pattern is longer than matched product
520 # so no chance for positive parsing result
523 pattern
= [ parse_term(elem
) for elem
in pattern
]
525 elems
, common_expo
, has_deriv
= [], Rational(1), False
527 for elem
, e_rat
, e_sym
, e_ord
in pattern
:
528 if e_ord
is not None:
529 # there is derivative in the pattern so
530 # there will by small performance penalty
533 for j
in range(len(terms
)):
534 term
, t_rat
, t_sym
, t_ord
= terms
[j
]
536 if elem
== term
and e_sym
== t_sym
:
538 # we don't have to exact so find common exponent
539 # for both expression's term and pattern's element
542 if isinstance(common_expo
, Basic
.One
):
545 # common exponent was negotiated before so
546 # teher is no chance for pattern match unless
547 # common and current exponents are equal
548 if common_expo
!= expo
:
551 # we ought to be exact so all fields of
552 # interest must match in very details
553 if e_rat
!= t_rat
or e_ord
!= t_ord
:
556 # found common term so remove it from the expression
557 # and try to match next element in the pattern
558 elems
.append(terms
[j
])
563 # pattern element not found
566 return terms
, elems
, common_expo
, has_deriv
569 if isinstance(expr
, Basic
.Mul
):
572 ret
*= collect(term
, syms
, True, exact
)
574 elif isinstance(expr
, Basic
.Pow
):
575 b
= collect(expr
.base
, syms
, True, exact
)
576 return Basic
.Pow(b
, expr
.exp
)
578 summa
= [ separate(i
) for i
in make_list(Basic
.sympify(expr
), Add
) ]
580 if isinstance(syms
, list):
581 syms
= [ separate(s
) for s
in syms
]
583 syms
= [ separate(syms
) ]
585 collected
, disliked
= {}, Rational(0)
587 for product
in summa
:
588 terms
= [ parse_term(i
) for i
in make_list(product
, Mul
) ]
591 result
= parse_expression(terms
, symbol
)
593 if result
is not None:
594 terms
, elems
, common_expo
, has_deriv
= result
596 # when there was derivative in current pattern we
597 # will need to rebuild its expression from scratch
599 index
= Pow(symbol
, common_expo
)
601 index
= make_expression(elems
)
603 terms
= separate(make_expression(terms
))
604 index
= separate(index
)
606 if index
in collected
:
607 collected
[index
] += terms
609 collected
[index
] = terms
613 # none of the patterns matched
616 if disliked
!= Rational(0):
617 collected
[Rational(1)] = disliked
620 return Add(*[ a
*b
for a
, b
in collected
.iteritems() ])
628 ratsimp(expr) -> joins two rational expressions and returns the simples form
632 Currently can simplify only simple expressions, for this to be really usefull
633 multivariate polynomial algorithms are needed
637 >>> from sympy import *
640 >>> e = ratsimp(1/x + 1/y)
643 if isinstance(expr
, Pow
):
644 return Pow(ratsimp(expr
.base
), ratsimp(expr
.exp
))
645 elif isinstance(expr
, Mul
):
648 res
.append( ratsimp(x
) )
650 elif isinstance(expr
, Basic
.Function
):
651 return expr
.func(*[ ratsimp(t
) for t
in expr
])
653 #elif isinstance(expr, Function):
654 # return type(expr)( ratsimp(expr[0]) )
655 elif not isinstance(expr
, Add
):
658 def get_num_denum(x
):
659 """Matches x = a/b and returns a/b."""
660 a
,b
= map(Wild
, 'ab')
662 if r
is not None and len(r
) == 2:
669 a
,b
= get_num_denum(ratsimp(x
))
670 c
,d
= get_num_denum(ratsimp(y
))
675 # Check to see if the numerator actually expands to 0
676 if num
.expand() == 0:
679 #we need to cancel common factors from numerator and denumerator
680 #but SymPy doesn't yet have a multivariate polynomial factorisation
681 #so until we have it, we are just returning the correct results here
682 #to pass all tests...
683 if isinstance(denum
,Pow
):
684 e
= (num
/denum
[0]).expand()
685 f
= (e
/(-2*Symbol("y"))).expand()
686 if f
== denum
/denum
[0]:
687 return -2*Symbol("y")
688 return e
/(denum
/denum
[0])
691 def trigsimp(expr
, deep
=False):
695 trig(expr) -> reduces expression by using known trig identities
703 >>> from sympy import *
706 >>> e = 2*sin(x)**2 + 2*cos(x)**2
710 log(2*cos(x)**2 + 2*sin(x)**2)
711 >>> trigsimp(log(e), deep=True)
714 from sympy
.core
.basic
import S
715 sin
, cos
, tan
, cot
= Basic
.sin
, Basic
.cos
, Basic
.tan
, Basic
.cot
717 #XXX this stopped working:
718 if expr
== 1/cos(Symbol("x"))**2 - 1:
719 return tan(Symbol("x"))**2
721 if isinstance(expr
, Basic
.Function
):
723 return expr
.func( trigsimp(expr
[0], deep
) )
724 elif isinstance(expr
, Mul
):
727 ret
*= trigsimp(x
, deep
)
729 elif isinstance(expr
, Pow
):
730 return Pow(trigsimp(expr
.base
, deep
), trigsimp(expr
.exp
, deep
))
731 elif isinstance(expr
, Add
):
732 # TODO this needs to be faster
734 # The types of trig functions we are looking for
735 a
,b
,c
= map(Wild
, 'abc')
737 (a
*sin(b
)**2, a
- a
*cos(b
)**2),
738 (a
*tan(b
)**2, a
*(1/cos(b
))**2 - a
),
739 (a
*cot(b
)**2, a
*(1/sin(b
))**2 - a
)
742 # Scan for the terms we need
745 term
= trigsimp(term
, deep
)
747 for pattern
, result
in matchers
:
748 res
= term
.match(pattern
)
750 ret
+= result
.subs_dict(res
)
755 # Reduce any lingering artifacts, such as sin(x)**2 changing
756 # to 1-cos(x)**2 when sin(x)**2 was "simpler"
758 (a
- a
*cos(b
)**2 + c
, a
*sin(b
)**2 + c
, cos
),
759 (a
- a
*(1/cos(b
))**2 + c
, -a
*tan(b
)**2 + c
, cos
),
760 (a
- a
*(1/sin(b
))**2 + c
, -a
*cot(b
)**2 + c
, sin
)
764 for pattern
, result
, ex
in artifacts
:
765 # Substitute a new wild that excludes some function(s)
766 # to help influence a better match. This is because
767 # sometimes, for example, 'a' would match sec(x)**2
768 a_t
= Wild('a', exclude
=[ex
])
769 pattern
= pattern
.subs(a
, a_t
)
770 result
= result
.subs(a
, a_t
)
772 m
= expr
.match(pattern
)
774 if m
[a_t
] == 0 or -m
[a_t
] in m
[c
][:] or m
[a_t
] + m
[c
] == 0:
776 expr
= result
.subs_dict(m
)
777 m
= expr
.match(pattern
)
784 Rationalize the denominator.
788 >>> from sympy import *
789 >>> radsimp(1/(2+sqrt(2)))
791 >>> x,y = map(Symbol, 'xy')
792 >>> e = ( (2+2*sqrt(2))*x+(2+sqrt(8))*y )/( 2+sqrt(2) )
794 x*2**(1/2) + y*2**(1/2)
797 a
,b
,c
= map(Wild
, 'abc')
798 r
= d
.match(a
+b
*Basic
.sqrt(c
))
806 syms
= list(n
.atoms(type=Basic
.Symbol
))
807 n
= collect( (n
*(a
-b
*Basic
.sqrt(c
))).expand(), syms
)
812 def powsimp(expr
, deep
=False):
816 powsimp(expr, deep) -> reduces expression by combining powers with
817 similar bases and exponents.
821 If deep is True then powsimp() will also simplify arguments of
822 functions. By default deep is set to False.
827 >>> from sympy import *
828 >>> x,n = map(Symbol, 'xn')
829 >>> e = x**n * (x*n)**(-n) * n
834 log(n*x**n*(n*x)**(-n))
836 >>> powsimp(log(e), deep=True)
840 if isinstance(expr
, Basic
.Pow
):
842 return Basic
.Pow(powsimp(expr
.base
), powsimp(expr
.exp
))
844 #elif isinstance(expr, Basic.Apply) and deep:
845 # return expr.func(*[powsimp(t) for t in expr])
846 elif isinstance(expr
, Basic
.Add
):
847 return Basic
.Add(*[powsimp(t
) for t
in expr
])
848 elif isinstance(expr
, Basic
.Mul
):
849 # Collect base/exp data, while maintaining order in the
850 # non-commutative parts of the product
854 if term
.is_commutative
:
855 b
,e
= term
.as_base_exp()
856 c_powers
[b
] = c_powers
.get(b
, 0) + e
860 # Pull out numerical coefficients from exponent
861 for b
,e
in c_powers
.items():
862 exp_c
, exp_t
= e
.as_coeff_terms()
863 if not isinstance(exp_c
, Basic
.One
) and exp_t
:
865 new_base
= Basic
.Pow(b
, exp_c
)
866 if new_base
in c_powers
:
867 c_powers
[new_base
] += Basic
.Mul(*exp_t
)
869 c_powers
[new_base
] = Basic
.Mul(*exp_t
)
871 # Combine bases whenever they have the same exponent which is
874 for b
, e
in c_powers
.items():
880 # Merge back in the results of the above to form a new product
886 new_base
= Mul(*bases
)
887 if new_base
in c_powers
:
888 c_powers
[new_base
] += e
890 c_powers
[new_base
] = e
892 c_part
= [ Basic
.Pow(b
,e
) for b
,e
in c_powers
.items() ]
893 return Basic
.Mul(*(c_part
+ nc_part
))
896 return _powsimp(separate(expr
, deep
=deep
))
898 def normal(expr
, *syms
):
899 p
, q
= together(expr
).as_numer_denom()
901 if p
.is_polynomial(*syms
) and q
.is_polynomial(*syms
):
902 from sympy
.polynomials
import gcd
, quo
906 if not isinstance(G
, Basic
.One
):
912 def hypersimp(term
, n
, consecutive
=True, simplify
=True):
913 """Given combinatorial term a(n) simplify its consecutive term
914 ratio ie. a(n+1)/a(n). The term can be composed of functions
915 and integer sequences which have equivalent represenation
916 in terms of gamma special function. Currently ths includes
917 factorials (falling, rising), binomials and gamma it self.
919 The algorithm performs three basic steps:
921 (1) Rewrite all functions in terms of gamma, if possible.
923 (2) Rewrite all occurences of gamma in terms of produtcs
924 of gamma and rising factorial with integer, absolute
927 (3) Perform simplification of nested fractions, powers
928 and if the resulting expression is a quotient of
929 polynomials, reduce their total degree.
931 If the term given is hypergeometric then the result of this
932 procudure is a quotient of polynomials of minimal degree.
933 Sequence is hypergeometric if it is anihilated by linear,
934 homogeneous recurrence operator of first order, so in
935 other words when a(n+1)/a(n) is a rational function.
937 When the status of being hypergeometric or not, is required
938 then you can avoid additional simplification by unsetting
941 This algorithm, due to Wolfram Koepf, is very simple but
942 powerful, however its full potential will be visible when
943 simplification in general will improve.
945 For more information on the implemented algorithm refer to:
947 [1] W. Koepf, Algorithms for m-fold Hypergeometric Summation,
948 Journal of Symbolic Computation (1995) 20, 399-417
950 term
= Basic
.sympify(term
)
952 if consecutive
== True:
953 term
= term
.subs(n
, n
+1)/term
955 expr
= term
.rewrite(gamma
).expand(func
=True, basic
=False)
957 p
, q
= together(expr
).as_numer_denom()
959 if p
.is_polynomial(n
) and q
.is_polynomial(n
):
961 from sympy
.polynomials
import gcd
, quo
965 if not isinstance(G
, Basic
.One
):
969 p
= p
.as_polynomial(n
)
970 q
= q
.as_polynomial(n
)
972 a
, p
= p
.as_integer()
973 b
, q
= q
.as_integer()
984 def hypersimilar(f
, g
, n
):
985 return hypersimp(f
/g
, n
, consecutive
=False, simplify
=False) is not None
991 #from sympy.specfun.factorials import factorial, factorial_simplify
992 #if expr.has_class(factorial):
993 # expr = factorial_simplify(expr)
994 a
,b
= [ t
.expand() for t
in fraction(powsimp(expr
)) ]
995 ret
= together(radsimp(ratsimp(a
/b
)))
997 if isinstance(d
, (Basic
.One
, Basic
.NegativeOne
)):
999 n_var
= n
.atoms(type=Symbol
)
1000 d_var
= d
.atoms(type=Symbol
)
1001 if n_var
and d_var
and n
.is_polynomial(*n_var
) and d
.is_polynomial(*d_var
):
1002 from sympy
.polynomials
import div
, factor
1007 return q
+ factor(r
) / factor(d
)