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')
40 >>> fraction(Rational(1, 2))
43 This function will also work fine with assumptions:
45 >>> k = Symbol('k', negative=True)
46 >>> fraction(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))
56 #>>> fraction(exp(-x))
59 >>> fraction(exp(-x), exact=True)
65 #XXX this only works sometimes (caching bug?)
66 if expr
== exp(-Symbol("x")) and exact
:
71 for term
in make_list(expr
, Mul
):
73 if term
.exp
.is_negative
:
74 if term
.exp
is S
.NegativeOne
:
75 denom
.append(term
.base
)
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
))
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]))
99 elif term
.is_Rational
:
103 numer
.append(Rational(term
.p
))
104 denom
.append(Rational(term
.q
))
108 return Mul(*numer
), Mul(*denom
)
111 return fraction(expr
)[0]
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)
138 >>> separate((x*(y*z)**3)**2)
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)
148 >>> separate((sin(x)*cos(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)
157 >>> separate((x*y)**(1+z))
158 x**(1 + z)*y**(1 + z)
164 terms
, expo
= [], separate(expr
.exp
, deep
)
165 #print expr, terms, expo, expr.base
168 t
= [ separate(C
.Pow(t
,expo
), deep
) for t
in expr
.base
.args
]
170 elif expr
.base
.func
is C
.exp
:
172 return C
.exp(separate(expr
.base
[0], deep
)*expo
)
174 return C
.exp(expr
.base
[0]*expo
)
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
])
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)
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)
215 Or you can just denest multi-level fractional expressions:
217 >>> together(1/(1 + 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))
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)))
232 #>>> together(1/exp(2*x) + 1/(x*exp(3*x)))
233 #(1+exp(x)*x)/(x*exp(3*x))
239 from sympy
.core
.function
import Function
242 items
, coeffs
, basis
= [], [], {}
244 for elem
in expr
.args
:
245 numer
, q
= fraction(_together(elem
))
249 for term
in make_list(q
.expand(), Mul
):
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
:
261 term
, expo
= Pow(term
.base
, tail
), coeff
263 elif term
.func
is C
.exp
:
264 if term
[0].is_Rational
:
265 term
, expo
= C
.E
, term
[0]
267 coeff
, tail
= term
[0].as_coeff_terms()
268 if coeff
.is_Rational
:
270 term
, expo
= C
.exp(tail
), coeff
272 elif term
.is_Rational
:
273 coeff
= Integer(term
.q
)
274 term
= Integer(term
.p
)
282 total
, maxi
= basis
[term
]
284 n_total
= total
+ expo
285 n_maxi
= max(maxi
, expo
)
287 basis
[term
] = (n_total
, n_maxi
)
289 basis
[term
] = (expo
, expo
)
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
[:]))
303 denominator
.append(term
)
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
))
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
]
323 expo
= total
-denom
[term
]-sub
327 if term
.func
is C
.exp
:
328 expr
.append(C
.exp(expo
*term
[:]))
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
])
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)
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))
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
413 >>> collect(a*x**c + b*x**c, x)
416 >>> collect(a*x**c + b*x**c, x**c)
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)
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))
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)
437 >>> collect(a*x**7 + b*x**7, x**7, exact=True)
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))
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
):
467 for term
, rat
, sym
, deriv
in terms
:
468 if deriv
is not None:
472 term
, order
= Derivative(term
, var
), order
-1
478 product
.append(Pow(term
, rat
))
480 product
.append(Pow(term
, rat
*sym
))
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
500 return expr
, (sym
, Rational(order
))
502 def parse_term(expr
):
503 rat_expo
, sym_expo
= S
.One
, None
504 sexpr
, deriv
= expr
, None
507 if isinstance(expr
.base
, Derivative
):
508 sexpr
, deriv
= parse_derivative(expr
.base
)
512 if expr
.exp
.is_Rational
:
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
)
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
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
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
:
559 # we don't have to exact so find common exponent
560 # for both expression's term and pattern's element
563 if common_expo
is S
.One
:
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
:
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
:
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
])
584 # pattern element not found
587 return terms
, elems
, common_expo
, has_deriv
592 for term
in expr
.args
:
593 ret
*= collect(term
, syms
, True, exact
)
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
]
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
) ]
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
620 index
= Pow(symbol
, common_expo
)
622 index
= make_expression(elems
)
624 terms
= separate(make_expression(terms
))
625 index
= separate(index
)
627 if index
in collected
:
628 collected
[index
] += terms
630 collected
[index
] = terms
634 # none of the patterns matched
637 if disliked
is not S
.Zero
:
638 collected
[S
.One
] = disliked
641 return Add(*[ a
*b
for a
, b
in collected
.iteritems() ])
649 ratsimp(expr) -> joins two rational expressions and returns the simples form
653 Currently can simplify only simple expressions, for this to be really usefull
654 multivariate polynomial algorithms are needed
658 >>> from sympy import *
661 >>> e = ratsimp(1/x + 1/y)
665 return Pow(ratsimp(expr
.base
), ratsimp(expr
.exp
))
669 res
.append( ratsimp(x
) )
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
:
679 def get_num_denum(x
):
680 """Matches x = a/b and returns a/b."""
681 a
,b
= map(Wild
, 'ab')
683 if r
is not None and len(r
) == 2:
688 y
= Add(*expr
.args
[1:])
690 a
,b
= get_num_denum(ratsimp(x
))
691 c
,d
= get_num_denum(ratsimp(y
))
696 # Check to see if the numerator actually expands to 0
697 if num
.expand() == 0:
702 def trigsimp(expr
, deep
=False):
706 trig(expr) -> reduces expression by using known trig identities
714 >>> from sympy import *
717 >>> e = 2*sin(x)**2 + 2*cos(x)**2
721 log(2*cos(x)**2 + 2*sin(x)**2)
722 >>> trigsimp(log(e), deep=True)
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
734 return expr
.func( trigsimp(expr
.args
[0], deep
) )
738 ret
*= trigsimp(x
, deep
)
741 return Pow(trigsimp(expr
.base
, deep
), trigsimp(expr
.exp
, deep
))
743 # TODO this needs to be faster
745 # The types of trig functions we are looking for
746 a
,b
,c
= map(Wild
, 'abc')
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
755 for term
in expr
.args
:
756 term
= trigsimp(term
, deep
)
758 for pattern
, result
in matchers
:
759 res
= term
.match(pattern
)
761 ret
+= result
.subs(res
)
766 # Reduce any lingering artifacts, such as sin(x)**2 changing
767 # to 1-cos(x)**2 when sin(x)**2 was "simpler"
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
)
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
)
785 if m
[a_t
] == 0 or -m
[a_t
] in m
[c
].args
or m
[a_t
] + m
[c
] == 0:
787 expr
= result
.subs(m
)
788 m
= expr
.match(pattern
)
795 Rationalize the denominator.
799 >>> from sympy import *
800 >>> radsimp(1/(2+sqrt(2)))
802 >>> x,y = map(Symbol, 'xy')
803 >>> e = ( (2+2*sqrt(2))*x+(2+sqrt(8))*y )/( 2+sqrt(2) )
805 x*2**(1/2) + y*2**(1/2)
808 a
,b
,c
= map(Wild
, 'abc')
809 r
= d
.match(a
+b
*sqrt(c
))
817 syms
= list(n
.atoms(Symbol
))
818 n
= collect( (n
*(a
-b
*sqrt(c
))).expand(), syms
)
823 def powsimp(expr
, deep
=False):
827 powsimp(expr, deep) -> reduces expression by combining powers with
828 similar bases and exponents.
832 If deep is True then powsimp() will also simplify arguments of
833 functions. By default deep is set to False.
838 >>> from sympy import *
839 >>> x,n = map(Symbol, 'xn')
840 >>> e = x**n * (x*n)**(-n) * n
845 log(n*x**n*(n*x)**(-n))
847 >>> powsimp(log(e), deep=True)
853 return C
.Pow(powsimp(expr
.base
), powsimp(expr
.exp
))
855 elif expr
.is_Function
and deep
:
856 return expr
.func(*[powsimp(t
) for t
in expr
.args
])
858 return C
.Add(*[powsimp(t
) for t
in expr
.args
])
860 # Collect base/exp data, while maintaining order in the
861 # non-commutative parts of the product
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
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
:
876 new_base
= C
.Pow(b
, exp_c
)
877 if new_base
in c_powers
:
878 c_powers
[new_base
] += C
.Mul(*exp_t
)
880 c_powers
[new_base
] = C
.Mul(*exp_t
)
882 # Combine bases whenever they have the same exponent which is
885 for b
, e
in c_powers
.items():
891 # Merge back in the results of the above to form a new product
897 new_base
= Mul(*bases
)
898 if new_base
in c_powers
:
899 c_powers
[new_base
] += e
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
))
907 return _powsimp(separate(expr
, deep
=deep
))
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
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
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
938 g
= f
.subs(k
, k
+1) / f
941 g
= g
.expand(func
=True, basic
=False)
944 return Poly
.cancel(g
, k
)
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
)
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
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
1000 >>> from sympy import *
1001 >>> nsimplify(4/(1+sqrt(5)), [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])
1007 >>> nsimplify(pi, tolerance=0.01)
1011 expr
= sympify(expr
)
1014 bprec
= int(prec
*3.33)
1017 for constant
in constants
:
1018 constant
= sympify(constant
)
1019 v
= constant
.evalf(prec
)
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()
1028 if not ((re
.is_Real
or re
.is_Integer
) and (im
.is_Real
or im
.is_Integer
)):
1031 def nsimplify_real(x
):
1032 orig
= mpmath
.mp
.dps
1033 xv
= x
._to
_mpmath
(bprec
)
1035 # We'll be happy with low precision if a simple fraction
1036 if not (tolerance
or full
):
1038 rat
= mpmath
.findpoly(xv
, 1)
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
)
1049 newexpr
= newexpr
[0]
1050 return sympify(newexpr
)
1052 mpmath
.mp
.dps
= orig
1054 if re
: re
= nsimplify_real(re
)
1055 if im
: im
= nsimplify_real(im
)
1059 return re
+ im
*S
.ImaginaryUnit