draft implementation of arbitrary PDF
[sympy.git] / sympy / simplify / simplify.py
blob0acd8373d7b6df9f6170a3f30f23977afc7cf011
2 from sympy.core import Basic, S, C, Add, Mul, Pow, Rational, Integer, \
3 Derivative, Wild, Symbol, sympify
5 from sympy.core.numbers import igcd
7 from sympy.utilities import make_list, all
8 from sympy.functions import gamma, exp, sqrt
10 from sympy.polys import Poly
12 from sys import maxint
14 import sympy.mpmath as mpmath
16 def fraction(expr, exact=False):
17 """Returns a pair with expression's numerator and denominator.
18 If the given expression is not a fraction then this function
19 will assume that the denominator is equal to one.
21 This function will not make any attempt to simplify nested
22 fractions or to do any term rewriting at all.
24 If only one of the numerator/denominator pair is needed then
25 use numer(expr) or denom(expr) functions respectively.
27 >>> from sympy import *
28 >>> x, y = symbols('x', 'y')
30 >>> fraction(x/y)
31 (x, y)
32 >>> fraction(x)
33 (x, 1)
35 >>> fraction(1/y**2)
36 (1, y**2)
38 >>> fraction(x*y/2)
39 (x*y, 2)
40 >>> fraction(Rational(1, 2))
41 (1, 2)
43 This function will also work fine with assumptions:
45 >>> k = Symbol('k', negative=True)
46 >>> fraction(x * y**k)
47 (x, y**(-k))
49 If we know nothing about sign of some exponent and 'exact'
50 flag is unset, then structure this exponent's structure will
51 be analyzed and pretty fraction will be returned:
53 >>> fraction(2*x**(-y))
54 (2, x**y)
56 #>>> fraction(exp(-x))
57 #(1, exp(x))
59 >>> fraction(exp(-x), exact=True)
60 (exp(-x), 1)
62 """
63 expr = sympify(expr)
65 #XXX this only works sometimes (caching bug?)
66 if expr == exp(-Symbol("x")) and exact:
67 return (expr, 1)
69 numer, denom = [], []
71 for term in make_list(expr, Mul):
72 if term.is_Pow:
73 if term.exp.is_negative:
74 if term.exp is S.NegativeOne:
75 denom.append(term.base)
76 else:
77 denom.append(Pow(term.base, -term.exp))
78 elif not exact and term.exp.is_Mul:
79 coeff, tail = term.exp.args[0], Mul(*term.exp.args[1:])#term.exp.getab()
81 if coeff.is_Rational and coeff.is_negative:
82 denom.append(Pow(term.base, -term.exp))
83 else:
84 numer.append(term)
85 else:
86 numer.append(term)
87 elif term.func is C.exp:
88 if term.args[0].is_negative:
89 denom.append(C.exp(-term.args[0]))
90 elif not exact and term.args[0].is_Mul:
91 coeff, tail = term.args[0], Mul(*term.args[1:])#term.args.getab()
93 if coeff.is_Rational and coeff.is_negative:
94 denom.append(C.exp(-term.args[0]))
95 else:
96 numer.append(term)
97 else:
98 numer.append(term)
99 elif term.is_Rational:
100 if term.is_integer:
101 numer.append(term)
102 else:
103 numer.append(Rational(term.p))
104 denom.append(Rational(term.q))
105 else:
106 numer.append(term)
108 return Mul(*numer), Mul(*denom)
110 def numer(expr):
111 return fraction(expr)[0]
113 def denom(expr):
114 return fraction(expr)[1]
116 def fraction_expand(expr):
117 a, b = fraction(expr)
118 return a.expand() / b.expand()
120 def numer_expand(expr):
121 a, b = fraction(expr)
122 return a.expand() / b
124 def denom_expand(expr):
125 a, b = fraction(expr)
126 return a / b.expand()
128 def separate(expr, deep=False):
129 """Rewrite or separate a power of product to a product of powers
130 but without any expanding, ie. rewriting products to summations.
132 >>> from sympy import *
133 >>> x, y, z = symbols('x', 'y', 'z')
135 >>> separate((x*y)**2)
136 x**2*y**2
138 >>> separate((x*(y*z)**3)**2)
139 x**2*y**6*z**6
141 >>> separate((x*sin(x))**y + (x*cos(x))**y)
142 x**y*cos(x)**y + x**y*sin(x)**y
144 #this does not work because of exp combining
145 #>>> separate((exp(x)*exp(y))**x)
146 #exp(x*y)*exp(x**2)
148 >>> separate((sin(x)*cos(x))**y)
149 cos(x)**y*sin(x)**y
151 Notice that summations are left un touched. If this is not the
152 requested behaviour, apply 'expand' to input expression before:
154 >>> separate(((x+y)*z)**2)
155 z**2*(x + y)**2
157 >>> separate((x*y)**(1+z))
158 x**(1 + z)*y**(1 + z)
161 expr = sympify(expr)
163 if expr.is_Pow:
164 terms, expo = [], separate(expr.exp, deep)
165 #print expr, terms, expo, expr.base
167 if expr.base.is_Mul:
168 t = [ separate(C.Pow(t,expo), deep) for t in expr.base.args ]
169 return C.Mul(*t)
170 elif expr.base.func is C.exp:
171 if deep == True:
172 return C.exp(separate(expr.base[0], deep)*expo)
173 else:
174 return C.exp(expr.base[0]*expo)
175 else:
176 return C.Pow(separate(expr.base, deep), expo)
177 elif expr.is_Add or expr.is_Mul:
178 return type(expr)(*[ separate(t, deep) for t in expr.args ])
179 elif expr.is_Function and deep:
180 return expr.func(*[ separate(t) for t in expr.args])
181 else:
182 return expr
185 def together(expr, deep=False):
186 """Combine together and denest rational functions into a single
187 fraction. By default the resulting expression is simplified
188 to reduce the total order of both numerator and denominator
189 and minimize the number of terms.
191 Densting is done recursively on fractions level. However this
192 function will not attempt to rewrite composite objects, like
193 functions, interior unless 'deep' flag is set.
195 By definition, 'together' is a complement to 'apart', so
196 apart(together(expr)) should left expression unhanged.
198 >>> from sympy import *
199 >>> x, y, z = symbols('x', 'y', 'z')
201 You can work with sums of fractions easily. The algorithm
202 used here will, in an iterative style, collect numerators
203 and denominator of all expressions involved and perform
204 needed simplifications:
206 #>>> together(1/x + 1/y)
207 #(x + y)/(y*x)
209 #>>> together(1/x + 1/y + 1/z)
210 #(z*x + x*y + z*y)/(y*x*z)
212 >>> together(1/(x*y) + 1/y**2)
213 (x + y)/(x*y**2)
215 Or you can just denest multi-level fractional expressions:
217 >>> together(1/(1 + 1/x))
218 x/(1 + x)
220 It also perfect possible to work with symbolic powers or
221 exponential functions or combinations of both:
223 >>> together(1/x**y + 1/x**(y-1))
224 x**(-y)*(1 + x)
226 #>>> together(1/x**(2*y) + 1/x**(y-z))
227 #x**(-2*y)*(1 + x**(y + z))
229 #>>> together(1/exp(x) + 1/(x*exp(x)))
230 #(1+x)/(x*exp(x))
232 #>>> together(1/exp(2*x) + 1/(x*exp(3*x)))
233 #(1+exp(x)*x)/(x*exp(3*x))
237 def _together(expr):
239 from sympy.core.function import Function
241 if expr.is_Add:
242 items, coeffs, basis = [], [], {}
244 for elem in expr.args:
245 numer, q = fraction(_together(elem))
247 denom = {}
249 for term in make_list(q.expand(), Mul):
250 expo = S.One
251 coeff = S.One
254 if term.is_Pow:
255 if term.exp.is_Rational:
256 term, expo = term.base, term.exp
257 elif term.exp.is_Mul:
258 coeff, tail = term.exp.as_coeff_terms()
259 if coeff.is_Rational:
260 tail = C.Mul(*tail)
261 term, expo = Pow(term.base, tail), coeff
262 coeff = S.One
263 elif term.func is C.exp:
264 if term[0].is_Rational:
265 term, expo = C.E, term[0]
266 elif term[0].is_Mul:
267 coeff, tail = term[0].as_coeff_terms()
268 if coeff.is_Rational:
269 tail = C.Mul(*tail)
270 term, expo = C.exp(tail), coeff
271 coeff = S.One
272 elif term.is_Rational:
273 coeff = Integer(term.q)
274 term = Integer(term.p)
276 if term in denom:
277 denom[term] += expo
278 else:
279 denom[term] = expo
281 if term in basis:
282 total, maxi = basis[term]
284 n_total = total + expo
285 n_maxi = max(maxi, expo)
287 basis[term] = (n_total, n_maxi)
288 else:
289 basis[term] = (expo, expo)
291 coeffs.append(coeff)
292 items.append((numer, denom))
294 numerator, denominator = [], []
296 for (term, (total, maxi)) in basis.iteritems():
297 basis[term] = (total, total-maxi)
299 if term.func is C.exp:
300 denominator.append(C.exp(maxi*term[:]))
301 else:
302 if maxi is S.One:
303 denominator.append(term)
304 else:
305 denominator.append(Pow(term, maxi))
307 if all([ c.is_integer for c in coeffs ]):
308 gcds = lambda x, y: igcd(int(x), int(y))
309 common = Rational(reduce(gcds, coeffs))
310 else:
311 common = S.One
313 product = reduce(lambda x, y: x*y, coeffs) / common
315 for ((numer, denom), coeff) in zip(items, coeffs):
317 expr, coeff = [], product / (coeff*common)
319 for term in basis.iterkeys():
320 total, sub = basis[term]
322 if term in denom:
323 expo = total-denom[term]-sub
324 else:
325 expo = total-sub
327 if term.func is C.exp:
328 expr.append(C.exp(expo*term[:]))
329 else:
330 if expo is S.One:
331 expr.append(term)
332 else:
333 expr.append(Pow(term, expo))
335 numerator.append(coeff*Mul(*([numer] + expr)))
337 return Add(*numerator)/(product*Mul(*denominator))
338 elif expr.is_Mul or expr.is_Pow:
339 return type(expr)(*[ _together(t) for t in expr.args ])
340 elif expr.is_Function and deep:
341 return expr.func(*[ _together(t) for t in expr.args ])
342 else:
343 return expr
345 return _together(separate(expr))
347 #apart -> partial fractions decomposition (will be here :)
349 def collect(expr, syms, evaluate=True, exact=False):
350 """Collect additive terms with respect to a list of symbols up
351 to powers with rational exponents. By the term symbol here
352 are meant arbitrary expressions, which can contain powers,
353 products, sums etc. In other words symbol is a pattern
354 which will be searched for in the expression's terms.
356 This function will not apply any redundant expanding to the
357 input expression, so user is assumed to enter expression in
358 final form. This makes 'collect' more predictable as there
359 is no magic behind the scenes. However it is important to
360 note, that powers of products are converted to products of
361 powers using 'separate' function.
363 There are two possible types of output. First, if 'evaluate'
364 flag is set, this function will return a single expression
365 or else it will return a dictionary with separated symbols
366 up to rational powers as keys and collected sub-expressions
367 as values respectively.
369 >>> from sympy import *
370 >>> x, y, z = symbols('x', 'y', 'z')
371 >>> a, b, c = symbols('a', 'b', 'c')
373 This function can collect symbolic coefficients in polynomial
374 or rational expressions. It will manage to find all integer or
375 rational powers of collection variable:
377 >>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x)
378 c + x*(a - b) + x**2*(a + b)
380 The same result can achieved in dictionary form:
382 >>> d = collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False)
383 >>> d[x**2]
384 a + b
385 >>> d[x]
386 a - b
387 >>> d[sympify(1)]
390 You can also work with multi-variate polynomials. However
391 remember that this function is greedy so it will care only
392 about a single symbol at time, in specification order:
394 >>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y])
395 x*y + y*(1 + a) + x**2*(1 + y)
397 >>> collect(x**2*y**4 + z*(x*y**2)**2 + z + a*z, [x*y**2, z])
398 z*(1 + a) + x**2*y**4*(1 + z)
400 Also more complicated expressions can be used as patterns:
402 >>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x))
403 (a + b)*sin(2*x)
405 >>> collect(a*x**2*log(x)**2 + b*(x*log(x))**2, x*log(x))
406 x**2*log(x)**2*(a + b)
408 It is also possible to work with symbolic powers, although
409 it has more complicated behaviour, because in this case
410 power's base and symbolic part of the exponent are treated
411 as a single symbol:
413 >>> collect(a*x**c + b*x**c, x)
414 a*x**c + b*x**c
416 >>> collect(a*x**c + b*x**c, x**c)
417 x**c*(a + b)
419 However if you incorporate rationals to the exponents, then
420 you will get well known behaviour:
422 #>>> collect(a*x**(2*c) + b*x**(2*c), x**c)
423 #x**(2*c)*(a + b)
425 Note also that all previously stated facts about 'collect'
426 function apply to the exponential function, so you can get:
428 >>> collect(a*exp(2*x) + b*exp(2*x), exp(x))
429 (a + b)*exp(2*x)
431 If you are interested only in collecting specific powers
432 of some symbols then set 'exact' flag in arguments:
434 >>> collect(a*x**7 + b*x**7, x, exact=True)
435 a*x**7 + b*x**7
437 >>> collect(a*x**7 + b*x**7, x**7, exact=True)
438 x**7*(a + b)
440 You can also apply this function to differential equations, where
441 derivatives of arbitary order can be collected:
443 >>> from sympy import Derivative as D
444 >>> f = Function('f') (x)
446 >>> collect(a*D(f,x) + b*D(f,x), D(f,x))
447 (a + b)*D(f(x), x)
449 >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x))
450 (a + b)*D(D(f(x), x), x)
452 >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True)
453 a*D(D(f(x), x), x) + b*D(D(f(x), x), x)
455 >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x) + a*D(f,x) + b*D(f,x), D(f,x))
456 (a + b)*D(D(f(x), x), x) + (a + b)*D(f(x), x)
458 Or you can even match both derivative order and exponent at time:
460 >>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))
461 (a + b)*D(D(f(x), x), x)**2
464 def make_expression(terms):
465 product = []
467 for term, rat, sym, deriv in terms:
468 if deriv is not None:
469 var, order = deriv
471 while order > 0:
472 term, order = Derivative(term, var), order-1
474 if sym is None:
475 if rat is S.One:
476 product.append(term)
477 else:
478 product.append(Pow(term, rat))
479 else:
480 product.append(Pow(term, rat*sym))
482 return Mul(*product)
484 def parse_derivative(deriv):
485 # scan derivatives tower in the input expression and return
486 # underlying function and maximal differentiation order
487 if len(deriv.symbols) != 1:
488 raise NotImplementedError('Improve Derivative support in collect')
489 expr, sym, order = deriv.expr, deriv.symbols[0], 1
491 while isinstance(expr, Derivative):
492 if len(expr.symbols) != 1:
493 raise NotImplementedError('Improve Derivative support in collect')
495 if expr.symbols[0] == sym:
496 expr, order = expr.expr, order+1
497 else:
498 break
500 return expr, (sym, Rational(order))
502 def parse_term(expr):
503 rat_expo, sym_expo = S.One, None
504 sexpr, deriv = expr, None
506 if expr.is_Pow:
507 if isinstance(expr.base, Derivative):
508 sexpr, deriv = parse_derivative(expr.base)
509 else:
510 sexpr = expr.base
512 if expr.exp.is_Rational:
513 rat_expo = expr.exp
514 elif expr.exp.is_Mul:
515 coeff, tail = term.exp.as_coeff_terms()
517 if coeff.is_Rational:
518 rat_expo, sym_expo = coeff, C.Mul(*tail)
519 else:
520 sym_expo = expr.exp
521 else:
522 sym_expo = expr.exp
523 elif expr.func is C.exp:
524 if expr.args[0].is_Rational:
525 sexpr, rat_expo = S.Exp1, expr.args[0]
526 elif expr.args[0].is_Mul:
527 coeff, tail = expr.args[0].as_coeff_terms()
529 if coeff.is_Rational:
530 sexpr, rat_expo = C.exp(C.Mul(*tail)), coeff
531 elif isinstance(expr, Derivative):
532 sexpr, deriv = parse_derivative(expr)
534 return sexpr, rat_expo, sym_expo, deriv
536 def parse_expression(terms, pattern):
537 pattern = make_list(pattern, Mul)
539 if len(terms) < len(pattern):
540 # pattern is longer than matched product
541 # so no chance for positive parsing result
542 return None
543 else:
544 pattern = [ parse_term(elem) for elem in pattern ]
546 elems, common_expo, has_deriv = [], S.One, False
548 for elem, e_rat, e_sym, e_ord in pattern:
549 if e_ord is not None:
550 # there is derivative in the pattern so
551 # there will by small performance penalty
552 has_deriv = True
554 for j in range(len(terms)):
555 term, t_rat, t_sym, t_ord = terms[j]
557 if elem == term and e_sym == t_sym:
558 if exact == False:
559 # we don't have to exact so find common exponent
560 # for both expression's term and pattern's element
561 expo = t_rat / e_rat
563 if common_expo is S.One:
564 common_expo = expo
565 else:
566 # common exponent was negotiated before so
567 # teher is no chance for pattern match unless
568 # common and current exponents are equal
569 if common_expo != expo:
570 return None
571 else:
572 # we ought to be exact so all fields of
573 # interest must match in very details
574 if e_rat != t_rat or e_ord != t_ord:
575 continue
577 # found common term so remove it from the expression
578 # and try to match next element in the pattern
579 elems.append(terms[j])
580 del terms[j]
582 break
583 else:
584 # pattern element not found
585 return None
587 return terms, elems, common_expo, has_deriv
589 if evaluate:
590 if expr.is_Mul:
591 ret = 1
592 for term in expr.args:
593 ret *= collect(term, syms, True, exact)
594 return ret
595 elif expr.is_Pow:
596 b = collect(expr.base, syms, True, exact)
597 return C.Pow(b, expr.exp)
599 summa = [ separate(i) for i in make_list(sympify(expr), Add) ]
601 if isinstance(syms, list):
602 syms = [ separate(s) for s in syms ]
603 else:
604 syms = [ separate(syms) ]
606 collected, disliked = {}, S.Zero
608 for product in summa:
609 terms = [ parse_term(i) for i in make_list(product, Mul) ]
611 for symbol in syms:
612 result = parse_expression(terms, symbol)
614 if result is not None:
615 terms, elems, common_expo, has_deriv = result
617 # when there was derivative in current pattern we
618 # will need to rebuild its expression from scratch
619 if not has_deriv:
620 index = Pow(symbol, common_expo)
621 else:
622 index = make_expression(elems)
624 terms = separate(make_expression(terms))
625 index = separate(index)
627 if index in collected:
628 collected[index] += terms
629 else:
630 collected[index] = terms
632 break
633 else:
634 # none of the patterns matched
635 disliked += product
637 if disliked is not S.Zero:
638 collected[S.One] = disliked
640 if evaluate:
641 return Add(*[ a*b for a, b in collected.iteritems() ])
642 else:
643 return collected
645 def ratsimp(expr):
647 Usage
648 =====
649 ratsimp(expr) -> joins two rational expressions and returns the simples form
651 Notes
652 =====
653 Currently can simplify only simple expressions, for this to be really usefull
654 multivariate polynomial algorithms are needed
656 Examples
657 ========
658 >>> from sympy import *
659 >>> x = Symbol('x')
660 >>> y = Symbol('y')
661 >>> e = ratsimp(1/x + 1/y)
663 expr = sympify(expr)
664 if expr.is_Pow:
665 return Pow(ratsimp(expr.base), ratsimp(expr.exp))
666 elif expr.is_Mul:
667 res = []
668 for x in expr.args:
669 res.append( ratsimp(x) )
670 return Mul(*res)
671 elif expr.is_Function:
672 return expr.func(*[ ratsimp(t) for t in expr.args ])
674 #elif expr.is_Function:
675 # return type(expr)( ratsimp(expr[0]) )
676 elif not expr.is_Add:
677 return expr
679 def get_num_denum(x):
680 """Matches x = a/b and returns a/b."""
681 a,b = map(Wild, 'ab')
682 r = x.match(a/b)
683 if r is not None and len(r) == 2:
684 return r[a],r[b]
685 return x, S.One
687 x = expr.args[0]
688 y = Add(*expr.args[1:])
690 a,b = get_num_denum(ratsimp(x))
691 c,d = get_num_denum(ratsimp(y))
693 num = a*d+b*c
694 denum = b*d
696 # Check to see if the numerator actually expands to 0
697 if num.expand() == 0:
698 return 0
700 return num/denum
702 def trigsimp(expr, deep=False):
704 Usage
705 =====
706 trig(expr) -> reduces expression by using known trig identities
708 Notes
709 =====
712 Examples
713 ========
714 >>> from sympy import *
715 >>> x = Symbol('x')
716 >>> y = Symbol('y')
717 >>> e = 2*sin(x)**2 + 2*cos(x)**2
718 >>> trigsimp(e)
720 >>> trigsimp(log(e))
721 log(2*cos(x)**2 + 2*sin(x)**2)
722 >>> trigsimp(log(e), deep=True)
723 log(2)
725 from sympy.core.basic import S
726 sin, cos, tan, cot = C.sin, C.cos, C.tan, C.cot
728 #XXX this stopped working:
729 if expr == 1/cos(Symbol("x"))**2 - 1:
730 return tan(Symbol("x"))**2
732 if expr.is_Function:
733 if deep:
734 return expr.func( trigsimp(expr.args[0], deep) )
735 elif expr.is_Mul:
736 ret = S.One
737 for x in expr.args:
738 ret *= trigsimp(x, deep)
739 return ret
740 elif expr.is_Pow:
741 return Pow(trigsimp(expr.base, deep), trigsimp(expr.exp, deep))
742 elif expr.is_Add:
743 # TODO this needs to be faster
745 # The types of trig functions we are looking for
746 a,b,c = map(Wild, 'abc')
747 matchers = (
748 (a*sin(b)**2, a - a*cos(b)**2),
749 (a*tan(b)**2, a*(1/cos(b))**2 - a),
750 (a*cot(b)**2, a*(1/sin(b))**2 - a)
753 # Scan for the terms we need
754 ret = S.Zero
755 for term in expr.args:
756 term = trigsimp(term, deep)
757 res = None
758 for pattern, result in matchers:
759 res = term.match(pattern)
760 if res is not None:
761 ret += result.subs(res)
762 break
763 if res is None:
764 ret += term
766 # Reduce any lingering artifacts, such as sin(x)**2 changing
767 # to 1-cos(x)**2 when sin(x)**2 was "simpler"
768 artifacts = (
769 (a - a*cos(b)**2 + c, a*sin(b)**2 + c, cos),
770 (a - a*(1/cos(b))**2 + c, -a*tan(b)**2 + c, cos),
771 (a - a*(1/sin(b))**2 + c, -a*cot(b)**2 + c, sin)
774 expr = ret
775 for pattern, result, ex in artifacts:
776 # Substitute a new wild that excludes some function(s)
777 # to help influence a better match. This is because
778 # sometimes, for example, 'a' would match sec(x)**2
779 a_t = Wild('a', exclude=[ex])
780 pattern = pattern.subs(a, a_t)
781 result = result.subs(a, a_t)
783 m = expr.match(pattern)
784 while m is not None:
785 if m[a_t] == 0 or -m[a_t] in m[c].args or m[a_t] + m[c] == 0:
786 break
787 expr = result.subs(m)
788 m = expr.match(pattern)
790 return expr
791 return expr
793 def radsimp(expr):
795 Rationalize the denominator.
797 Examples:
798 =========
799 >>> from sympy import *
800 >>> radsimp(1/(2+sqrt(2)))
801 1 - 1/2*2**(1/2)
802 >>> x,y = map(Symbol, 'xy')
803 >>> e = ( (2+2*sqrt(2))*x+(2+sqrt(8))*y )/( 2+sqrt(2) )
804 >>> radsimp(e)
805 x*2**(1/2) + y*2**(1/2)
807 n,d = fraction(expr)
808 a,b,c = map(Wild, 'abc')
809 r = d.match(a+b*sqrt(c))
810 if r is not None:
811 a = r[a]
812 if r[b] == 0:
813 b,c = 0,0
814 else:
815 b,c = r[b],r[c]
817 syms = list(n.atoms(Symbol))
818 n = collect( (n*(a-b*sqrt(c))).expand(), syms )
819 d = a**2 - c*b**2
821 return n/d
823 def powsimp(expr, deep=False):
825 Usage
826 =====
827 powsimp(expr, deep) -> reduces expression by combining powers with
828 similar bases and exponents.
830 Notes
831 =====
832 If deep is True then powsimp() will also simplify arguments of
833 functions. By default deep is set to False.
836 Examples
837 ========
838 >>> from sympy import *
839 >>> x,n = map(Symbol, 'xn')
840 >>> e = x**n * (x*n)**(-n) * n
841 >>> powsimp(e)
842 n**(1 - n)
844 >>> powsimp(log(e))
845 log(n*x**n*(n*x)**(-n))
847 >>> powsimp(log(e), deep=True)
848 log(n**(1 - n))
850 def _powsimp(expr):
851 if expr.is_Pow:
852 if deep:
853 return C.Pow(powsimp(expr.base), powsimp(expr.exp))
854 return expr
855 elif expr.is_Function and deep:
856 return expr.func(*[powsimp(t) for t in expr.args])
857 elif expr.is_Add:
858 return C.Add(*[powsimp(t) for t in expr.args])
859 elif expr.is_Mul:
860 # Collect base/exp data, while maintaining order in the
861 # non-commutative parts of the product
862 c_powers = {}
863 nc_part = []
864 for term in expr.args:
865 if term.is_commutative:
866 b,e = term.as_base_exp()
867 c_powers[b] = c_powers.get(b, 0) + e
868 else:
869 nc_part.append(term)
871 # Pull out numerical coefficients from exponent
872 for b,e in c_powers.items():
873 exp_c, exp_t = e.as_coeff_terms()
874 if not (exp_c is S.One) and exp_t:
875 del c_powers[b]
876 new_base = C.Pow(b, exp_c)
877 if new_base in c_powers:
878 c_powers[new_base] += C.Mul(*exp_t)
879 else:
880 c_powers[new_base] = C.Mul(*exp_t)
882 # Combine bases whenever they have the same exponent which is
883 # not numeric
884 c_exp = {}
885 for b, e in c_powers.items():
886 if e in c_exp:
887 c_exp[e].append(b)
888 else:
889 c_exp[e] = [b]
891 # Merge back in the results of the above to form a new product
892 for e in c_exp:
893 bases = c_exp[e]
894 if len(bases) > 1:
895 for b in bases:
896 del c_powers[b]
897 new_base = Mul(*bases)
898 if new_base in c_powers:
899 c_powers[new_base] += e
900 else:
901 c_powers[new_base] = e
903 c_part = [ C.Pow(b,e) for b,e in c_powers.items() ]
904 return C.Mul(*(c_part + nc_part))
905 return expr
907 return _powsimp(separate(expr, deep=deep))
909 def hypersimp(f, k):
910 """Given combinatorial term f(k) simplify its consecutive term ratio
911 ie. f(k+1)/f(k). The input term can be composed of functions and
912 integer sequences which have equivalent representation in terms
913 of gamma special function.
915 The algorithm performs three basic steps:
917 (1) Rewrite all functions in terms of gamma, if possible.
919 (2) Rewrite all occurrences of gamma in terms of products
920 of gamma and rising factorial with integer, absolute
921 constant exponent.
923 (3) Perform simplification of nested fractions, powers
924 and if the resulting expression is a quotient of
925 polynomials, reduce their total degree.
927 If f(k) is hypergeometric then as result we arrive with a
928 quotient of polynomials of minimal degree. Otherwise None
929 is returned.
931 For more information on the implemented algorithm refer to:
933 [1] W. Koepf, Algorithms for m-fold Hypergeometric Summation,
934 Journal of Symbolic Computation (1995) 20, 399-417
936 f = sympify(f)
938 g = f.subs(k, k+1) / f
940 g = g.rewrite(gamma)
941 g = g.expand(func=True, basic=False)
943 if g.is_fraction(k):
944 return Poly.cancel(g, k)
945 else:
946 return None
948 def hypersimilar(f, g, k):
949 """Returns True if 'f' and 'g' are hyper-similar.
951 Similarity in hypergeometric sens means that a quotient of
952 f(k) and g(k) is a rational function in k. This procedure
953 is useful in solving recurrence relations.
955 For more information see hypersimp().
958 f, g = map(sympify, (f, g))
960 h = (f/g).rewrite(gamma)
961 h = h.expand(func=True, basic=False)
963 return h.is_fraction(k)
965 def combsimp(expr):
966 return expr
968 def simplify(expr):
969 """Naively simplifies the given expression.
971 Simplification is not a well defined term and the exact strategies
972 this function tries can change in the future versions of SymPy. If
973 your algorithm relies on "simplification" (whatever it is), try to
974 determine what you need exactly - is it powsimp(), or radsimp(),
975 or together(), or something else? And use this particular function
976 directly, because those are well defined and thus your algorithm
977 will be robust.
980 expr = Poly.cancel(powsimp(expr))
981 return together(expr.expand())
983 def nsimplify(expr, constants=[], tolerance=None, full=False):
985 Numerical simplification -- tries to find a simple formula
986 that numerically matches the given expression. The input should
987 be possible to evalf to a precision of at least 30 digits.
989 Optionally, a list of (rationally independent) constants to
990 include in the formula may be given.
992 A lower tolerance may be set to find less exact matches.
994 With full=True, a more extensive search is performed
995 (this is useful to find simpler numbers when the tolerance
996 is set low).
998 Examples:
1000 >>> from sympy import *
1001 >>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
1002 -2 + 2*GoldenRatio
1003 >>> nsimplify((1/(exp(3*pi*I/5)+1)))
1004 1/2 - I*(1/4 + 1/10*5**(1/2))**(1/2)
1005 >>> nsimplify(I**I, [pi])
1006 exp(-pi/2)
1007 >>> nsimplify(pi, tolerance=0.01)
1008 22/7
1011 expr = sympify(expr)
1013 prec = 30
1014 bprec = int(prec*3.33)
1016 constants_dict = {}
1017 for constant in constants:
1018 constant = sympify(constant)
1019 v = constant.evalf(prec)
1020 if not v.is_Real:
1021 raise ValueError("constants must be real-valued")
1022 constants_dict[str(constant)] = v._to_mpmath(bprec)
1024 exprval = expr.evalf(prec, chop=True)
1025 re, im = exprval.as_real_imag()
1027 # Must be numerical
1028 if not ((re.is_Real or re.is_Integer) and (im.is_Real or im.is_Integer)):
1029 return expr
1031 def nsimplify_real(x):
1032 orig = mpmath.mp.dps
1033 xv = x._to_mpmath(bprec)
1034 try:
1035 # We'll be happy with low precision if a simple fraction
1036 if not (tolerance or full):
1037 mpmath.mp.dps = 15
1038 rat = mpmath.findpoly(xv, 1)
1039 if rat is not None:
1040 # XXX: will need to reverse rat coefficients when
1041 # updating mpmath in sympy
1042 return Rational(-int(rat[0]), int(rat[1]))
1043 mpmath.mp.dps = prec
1044 newexpr = mpmath.identify(xv, constants=constants_dict,
1045 tolerance=tolerance, full=full)
1046 if not newexpr:
1047 raise ValueError
1048 if full:
1049 newexpr = newexpr[0]
1050 return sympify(newexpr)
1051 finally:
1052 mpmath.mp.dps = orig
1053 try:
1054 if re: re = nsimplify_real(re)
1055 if im: im = nsimplify_real(im)
1056 except ValueError:
1057 return expr
1059 return re + im*S.ImaginaryUnit