Simplify

simplify

sympy.simplify.simplify.simplify(expr, ratio=1.7, measure=<function count_ops>, rational=False, inverse=False, doit=True, **kwargs)[source]

Simplifies the given expression.

Explanation

Simplification is not a well defined term and the exact strategies this function tries can change in the future versions of SymPy. If your algorithm relies on “simplification” (whatever it is), try to determine what you need exactly - is it powsimp()?, radsimp()?, together()?, logcombine()?, or something else? And use this particular function directly, because those are well defined and thus your algorithm will be robust.

Nonetheless, especially for interactive use, or when you do not know anything about the structure of the expression, simplify() tries to apply intelligent heuristics to make the input expression “simpler”. For example:

>>> from sympy import simplify, cos, sin
>>> from sympy.abc import x, y
>>> a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2)
>>> a
(x**2 + x)/(x*sin(y)**2 + x*cos(y)**2)
>>> simplify(a)
x + 1

Note that we could have obtained the same result by using specific simplification functions:

>>> from sympy import trigsimp, cancel
>>> trigsimp(a)
(x**2 + x)/x
>>> cancel(_)
x + 1

In some cases, applying simplify() may actually result in some more complicated expression. The default ratio=1.7 prevents more extreme cases: if (result length)/(input length) > ratio, then input is returned unmodified. The measure parameter lets you specify the function used to determine how complex an expression is. The function should take a single argument as an expression and return a number such that if expression a is more complex than expression b, then measure(a) > measure(b). The default measure function is count_ops(), which returns the total number of operations in the expression.

For example, if ratio=1, simplify output cannot be longer than input.

>>> from sympy import sqrt, simplify, count_ops, oo
>>> root = 1/(sqrt(2)+3)

Since simplify(root) would result in a slightly longer expression, root is returned unchanged instead:

>>> simplify(root, ratio=1) == root
True

If ratio=oo, simplify will be applied anyway:

>>> count_ops(simplify(root, ratio=oo)) > count_ops(root)
True

Note that the shortest expression is not necessary the simplest, so setting ratio to 1 may not be a good idea. Heuristically, the default value ratio=1.7 seems like a reasonable choice.

You can easily define your own measure function based on what you feel should represent the “size” or “complexity” of the input expression. Note that some choices, such as lambda expr: len(str(expr)) may appear to be good metrics, but have other problems (in this case, the measure function may slow down simplify too much for very large expressions). If you do not know what a good metric would be, the default, count_ops, is a good one.

For example:

>>> from sympy import symbols, log
>>> a, b = symbols('a b', positive=True)
>>> g = log(a) + log(b) + log(a)*log(1/b)
>>> h = simplify(g)
>>> h
log(a*b**(1 - log(a)))
>>> count_ops(g)
8
>>> count_ops(h)
5

So you can see that h is simpler than g using the count_ops metric. However, we may not like how simplify (in this case, using logcombine) has created the b**(log(1/a) + 1) term. A simple way to reduce this would be to give more weight to powers as operations in count_ops. We can do this by using the visual=True option:

>>> print(count_ops(g, visual=True))
2*ADD + DIV + 4*LOG + MUL
>>> print(count_ops(h, visual=True))
2*LOG + MUL + POW + SUB
>>> from sympy import Symbol, S
>>> def my_measure(expr):
...     POW = Symbol('POW')
...     # Discourage powers by giving POW a weight of 10
...     count = count_ops(expr, visual=True).subs(POW, 10)
...     # Every other operation gets a weight of 1 (the default)
...     count = count.replace(Symbol, type(S.One))
...     return count
>>> my_measure(g)
8
>>> my_measure(h)
14
>>> 15./8 > 1.7 # 1.7 is the default ratio
True
>>> simplify(g, measure=my_measure)
-log(a)*log(b) + log(a) + log(b)

Note that because simplify() internally tries many different simplification strategies and then compares them using the measure function, we get a completely different result that is still different from the input expression by doing this.

If rational=True, Floats will be recast as Rationals before simplification. If rational=None, Floats will be recast as Rationals but the result will be recast as Floats. If rational=False(default) then nothing will be done to the Floats.

If inverse=True, it will be assumed that a composition of inverse functions, such as sin and asin, can be cancelled in any order. For example, asin(sin(x)) will yield x without checking whether x belongs to the set where this relation is true. The default is False.

Note that simplify() automatically calls doit() on the final expression. You can avoid this behavior by passing doit=False as an argument.

Also, it should be noted that simplifying the boolian expression is not well defined. If the expression prefers automatic evaluation (such as Eq() or Or()), simplification will return True or False if truth value can be determined. If the expression is not evaluated by default (such as Predicate()), simplification will not reduce it and you should use refine() or ask() function. This inconsistency will be resolved in future version.

See also

sympy.assumptions.refine.refine

Simplification using assumptions.

sympy.assumptions.ask.ask

Query for boolean expressions using assumptions.

separatevars

sympy.simplify.simplify.separatevars(expr, symbols=[], dict=False, force=False)[source]

Separates variables in an expression, if possible. By default, it separates with respect to all symbols in an expression and collects constant coefficients that are independent of symbols.

Explanation

If dict=True then the separated terms will be returned in a dictionary keyed to their corresponding symbols. By default, all symbols in the expression will appear as keys; if symbols are provided, then all those symbols will be used as keys, and any terms in the expression containing other symbols or non-symbols will be returned keyed to the string ‘coeff’. (Passing None for symbols will return the expression in a dictionary keyed to ‘coeff’.)

If force=True, then bases of powers will be separated regardless of assumptions on the symbols involved.

Notes

The order of the factors is determined by Mul, so that the separated expressions may not necessarily be grouped together.

Although factoring is necessary to separate variables in some expressions, it is not necessary in all cases, so one should not count on the returned factors being factored.

Examples

>>> from sympy.abc import x, y, z, alpha
>>> from sympy import separatevars, sin
>>> separatevars((x*y)**y)
(x*y)**y
>>> separatevars((x*y)**y, force=True)
x**y*y**y
>>> e = 2*x**2*z*sin(y)+2*z*x**2
>>> separatevars(e)
2*x**2*z*(sin(y) + 1)
>>> separatevars(e, symbols=(x, y), dict=True)
{'coeff': 2*z, x: x**2, y: sin(y) + 1}
>>> separatevars(e, [x, y, alpha], dict=True)
{'coeff': 2*z, alpha: 1, x: x**2, y: sin(y) + 1}

If the expression is not really separable, or is only partially separable, separatevars will do the best it can to separate it by using factoring.

>>> separatevars(x + x*y - 3*x**2)
-x*(3*x - y - 1)

If the expression is not separable then expr is returned unchanged or (if dict=True) then None is returned.

>>> eq = 2*x + y*sin(x)
>>> separatevars(eq) == eq
True
>>> separatevars(2*x + y*sin(x), symbols=(x, y), dict=True) is None
True

nthroot

sympy.simplify.simplify.nthroot(expr, n, max_len=4, prec=15)[source]

Compute a real nth-root of a sum of surds.

Parameters

expr : sum of surds

n : integer

max_len : maximum number of surds passed as constants to nsimplify

Algorithm

First nsimplify is used to get a candidate root; if it is not a root the minimal polynomial is computed; the answer is one of its roots.

Examples

>>> from sympy.simplify.simplify import nthroot
>>> from sympy import sqrt
>>> nthroot(90 + 34*sqrt(7), 3)
sqrt(7) + 3

kroneckersimp

sympy.simplify.simplify.kroneckersimp(expr)[source]

Simplify expressions with KroneckerDelta.

The only simplification currently attempted is to identify multiplicative cancellation:

Examples

>>> from sympy import KroneckerDelta, kroneckersimp
>>> from sympy.abc import i
>>> kroneckersimp(1 + KroneckerDelta(0, i) * KroneckerDelta(1, i))
1

besselsimp

sympy.simplify.simplify.besselsimp(expr)[source]

Simplify bessel-type functions.

Explanation

This routine tries to simplify bessel-type functions. Currently it only works on the Bessel J and I functions, however. It works by looking at all such functions in turn, and eliminating factors of “I” and “-1” (actually their polar equivalents) in front of the argument. Then, functions of half-integer order are rewritten using strigonometric functions and functions of integer order (> 1) are rewritten using functions of low order. Finally, if the expression was changed, compute factorization of the result with factor().

>>> from sympy import besselj, besseli, besselsimp, polar_lift, I, S
>>> from sympy.abc import z, nu
>>> besselsimp(besselj(nu, z*polar_lift(-1)))
exp(I*pi*nu)*besselj(nu, z)
>>> besselsimp(besseli(nu, z*polar_lift(-I)))
exp(-I*pi*nu/2)*besselj(nu, z)
>>> besselsimp(besseli(S(-1)/2, z))
sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z))
>>> besselsimp(z*besseli(0, z) + z*(besseli(2, z))/2 + besseli(1, z))
3*z*besseli(0, z)/2

hypersimp

sympy.simplify.simplify.hypersimp(f, k)[source]

Given combinatorial term f(k) simplify its consecutive term ratio i.e. f(k+1)/f(k). The input term can be composed of functions and integer sequences which have equivalent representation in terms of gamma special function.

Explanation

The algorithm performs three basic steps:

  1. Rewrite all functions in terms of gamma, if possible.

  2. Rewrite all occurrences of gamma in terms of products of gamma and rising factorial with integer, absolute constant exponent.

  3. Perform simplification of nested fractions, powers and if the resulting expression is a quotient of polynomials, reduce their total degree.

If f(k) is hypergeometric then as result we arrive with a quotient of polynomials of minimal degree. Otherwise None is returned.

For more information on the implemented algorithm refer to:

  1. W. Koepf, Algorithms for m-fold Hypergeometric Summation, Journal of Symbolic Computation (1995) 20, 399-417

hypersimilar

sympy.simplify.simplify.hypersimilar(f, g, k)[source]

Returns True if f and g are hyper-similar.

Explanation

Similarity in hypergeometric sense means that a quotient of f(k) and g(k) is a rational function in k. This procedure is useful in solving recurrence relations.

For more information see hypersimp().

nsimplify

sympy.simplify.simplify.nsimplify(expr, constants=(), tolerance=None, full=False, rational=None, rational_conversion='base10')[source]

Find a simple representation for a number or, if there are free symbols or if rational=True, then replace Floats with their Rational equivalents. If no change is made and rational is not False then Floats will at least be converted to Rationals.

Explanation

For numerical expressions, a simple formula that numerically matches the given numerical expression is sought (and the input should be possible to evalf to a precision of at least 30 digits).

Optionally, a list of (rationally independent) constants to include in the formula may be given.

A lower tolerance may be set to find less exact matches. If no tolerance is given then the least precise value will set the tolerance (e.g. Floats default to 15 digits of precision, so would be tolerance=10**-15).

With full=True, a more extensive search is performed (this is useful to find simpler numbers when the tolerance is set low).

When converting to rational, if rational_conversion=’base10’ (the default), then convert floats to rationals using their base-10 (string) representation. When rational_conversion=’exact’ it uses the exact, base-2 representation.

Examples

>>> from sympy import nsimplify, sqrt, GoldenRatio, exp, I, pi
>>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
-2 + 2*GoldenRatio
>>> nsimplify((1/(exp(3*pi*I/5)+1)))
1/2 - I*sqrt(sqrt(5)/10 + 1/4)
>>> nsimplify(I**I, [pi])
exp(-pi/2)
>>> nsimplify(pi, tolerance=0.01)
22/7
>>> nsimplify(0.333333333333333, rational=True, rational_conversion='exact')
6004799503160655/18014398509481984
>>> nsimplify(0.333333333333333, rational=True)
1/3

posify

sympy.simplify.simplify.posify(eq)[source]

Return eq (with generic symbols made positive) and a dictionary containing the mapping between the old and new symbols.

Explanation

Any symbol that has positive=None will be replaced with a positive dummy symbol having the same name. This replacement will allow more symbolic processing of expressions, especially those involving powers and logarithms.

A dictionary that can be sent to subs to restore eq to its original symbols is also returned.

>>> from sympy import posify, Symbol, log, solve
>>> from sympy.abc import x
>>> posify(x + Symbol('p', positive=True) + Symbol('n', negative=True))
(_x + n + p, {_x: x})
>>> eq = 1/x
>>> log(eq).expand()
log(1/x)
>>> log(posify(eq)[0]).expand()
-log(_x)
>>> p, rep = posify(eq)
>>> log(p).expand().subs(rep)
-log(x)

It is possible to apply the same transformations to an iterable of expressions:

>>> eq = x**2 - 4
>>> solve(eq, x)
[-2, 2]
>>> eq_x, reps = posify([eq, x]); eq_x
[_x**2 - 4, _x]
>>> solve(*eq_x)
[2]

logcombine

sympy.simplify.simplify.logcombine(expr, force=False)[source]

Takes logarithms and combines them using the following rules:

  • log(x) + log(y) == log(x*y) if both are positive

  • a*log(x) == log(x**a) if x is positive and a is real

If force is True then the assumptions above will be assumed to hold if there is no assumption already in place on a quantity. For example, if a is imaginary or the argument negative, force will not perform a combination but if a is a symbol with no assumptions the change will take place.

Examples

>>> from sympy import Symbol, symbols, log, logcombine, I
>>> from sympy.abc import a, x, y, z
>>> logcombine(a*log(x) + log(y) - log(z))
a*log(x) + log(y) - log(z)
>>> logcombine(a*log(x) + log(y) - log(z), force=True)
log(x**a*y/z)
>>> x,y,z = symbols('x,y,z', positive=True)
>>> a = Symbol('a', real=True)
>>> logcombine(a*log(x) + log(y) - log(z))
log(x**a*y/z)

The transformation is limited to factors and/or terms that contain logs, so the result depends on the initial state of expansion:

>>> eq = (2 + 3*I)*log(x)
>>> logcombine(eq, force=True) == eq
True
>>> logcombine(eq.expand(), force=True)
log(x**2) + I*log(x**3)

See also

posify

replace all symbols with symbols having positive assumptions

sympy.core.function.expand_log

expand the logarithms of products and powers; the opposite of logcombine

Radsimp

radsimp

sympy.simplify.radsimp.radsimp(expr, symbolic=True, max_terms=4)[source]

Rationalize the denominator by removing square roots.

Explanation

The expression returned from radsimp must be used with caution since if the denominator contains symbols, it will be possible to make substitutions that violate the assumptions of the simplification process: that for a denominator matching a + b*sqrt(c), a != +/-b*sqrt(c). (If there are no symbols, this assumptions is made valid by collecting terms of sqrt(c) so the match variable a does not contain sqrt(c).) If you do not want the simplification to occur for symbolic denominators, set symbolic to False.

If there are more than max_terms radical terms then the expression is returned unchanged.

Examples

>>> from sympy import radsimp, sqrt, Symbol, pprint
>>> from sympy import factor_terms, fraction, signsimp
>>> from sympy.simplify.radsimp import collect_sqrt
>>> from sympy.abc import a, b, c
>>> radsimp(1/(2 + sqrt(2)))
(2 - sqrt(2))/2
>>> x,y = map(Symbol, 'xy')
>>> e = ((2 + 2*sqrt(2))*x + (2 + sqrt(8))*y)/(2 + sqrt(2))
>>> radsimp(e)
sqrt(2)*(x + y)

No simplification beyond removal of the gcd is done. One might want to polish the result a little, however, by collecting square root terms:

>>> r2 = sqrt(2)
>>> r5 = sqrt(5)
>>> ans = radsimp(1/(y*r2 + x*r2 + a*r5 + b*r5)); pprint(ans)
    ___       ___       ___       ___
  \/ 5 *a + \/ 5 *b - \/ 2 *x - \/ 2 *y
------------------------------------------
   2               2      2              2
5*a  + 10*a*b + 5*b  - 2*x  - 4*x*y - 2*y
>>> n, d = fraction(ans)
>>> pprint(factor_terms(signsimp(collect_sqrt(n))/d, radical=True))
        ___             ___
      \/ 5 *(a + b) - \/ 2 *(x + y)
------------------------------------------
   2               2      2              2
5*a  + 10*a*b + 5*b  - 2*x  - 4*x*y - 2*y

If radicals in the denominator cannot be removed or there is no denominator, the original expression will be returned.

>>> radsimp(sqrt(2)*x + sqrt(2))
sqrt(2)*x + sqrt(2)

Results with symbols will not always be valid for all substitutions:

>>> eq = 1/(a + b*sqrt(c))
>>> eq.subs(a, b*sqrt(c))
1/(2*b*sqrt(c))
>>> radsimp(eq).subs(a, b*sqrt(c))
nan

If symbolic=False, symbolic denominators will not be transformed (but numeric denominators will still be processed):

>>> radsimp(eq, symbolic=False)
1/(a + b*sqrt(c))

rad_rationalize

sympy.simplify.radsimp.rad_rationalize(num, den)[source]

Rationalize num/den by removing square roots in the denominator; num and den are sum of terms whose squares are positive rationals.

Examples

>>> from sympy import sqrt
>>> from sympy.simplify.radsimp import rad_rationalize
>>> rad_rationalize(sqrt(3), 1 + sqrt(2)/3)
(-sqrt(3) + sqrt(6)/3, -7/9)

collect

sympy.simplify.radsimp.collect(expr, syms, func=None, evaluate=None, exact=False, distribute_order_term=True)[source]

Collect additive terms of an expression.

Explanation

This function collects additive terms of an expression with respect to a list of expression up to powers with rational exponents. By the term symbol here are meant arbitrary expressions, which can contain powers, products, sums etc. In other words symbol is a pattern which will be searched for in the expression’s terms.

The input expression is not expanded by collect(), so user is expected to provide an expression in an appropriate form. This makes collect() more predictable as there is no magic happening behind the scenes. However, it is important to note, that powers of products are converted to products of powers using the expand_power_base() function.

There are two possible types of output. First, if evaluate flag is set, this function will return an expression with collected terms or else it will return a dictionary with expressions up to rational powers as keys and collected coefficients as values.

Examples

>>> from sympy import S, collect, expand, factor, Wild
>>> from sympy.abc import a, b, c, x, y

This function can collect symbolic coefficients in polynomials or rational expressions. It will manage to find all integer or rational powers of collection variable:

>>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x)
c + x**2*(a + b) + x*(a - b)

The same result can be achieved in dictionary form:

>>> d = collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False)
>>> d[x**2]
a + b
>>> d[x]
a - b
>>> d[S.One]
c

You can also work with multivariate polynomials. However, remember that this function is greedy so it will care only about a single symbol at time, in specification order:

>>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y])
x**2*(y + 1) + x*y + y*(a + 1)

Also more complicated expressions can be used as patterns:

>>> from sympy import sin, log
>>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x))
(a + b)*sin(2*x)

>>> collect(a*x*log(x) + b*(x*log(x)), x*log(x))
x*(a + b)*log(x)

You can use wildcards in the pattern:

>>> w = Wild('w1')
>>> collect(a*x**y - b*x**y, w**y)
x**y*(a - b)

It is also possible to work with symbolic powers, although it has more complicated behavior, because in this case power’s base and symbolic part of the exponent are treated as a single symbol:

>>> collect(a*x**c + b*x**c, x)
a*x**c + b*x**c
>>> collect(a*x**c + b*x**c, x**c)
x**c*(a + b)

However if you incorporate rationals to the exponents, then you will get well known behavior:

>>> collect(a*x**(2*c) + b*x**(2*c), x**c)
x**(2*c)*(a + b)

Note also that all previously stated facts about collect() function apply to the exponential function, so you can get:

>>> from sympy import exp
>>> collect(a*exp(2*x) + b*exp(2*x), exp(x))
(a + b)*exp(2*x)

If you are interested only in collecting specific powers of some symbols then set exact flag in arguments:

>>> collect(a*x**7 + b*x**7, x, exact=True)
a*x**7 + b*x**7
>>> collect(a*x**7 + b*x**7, x**7, exact=True)
x**7*(a + b)

You can also apply this function to differential equations, where derivatives of arbitrary order can be collected. Note that if you collect with respect to a function or a derivative of a function, all derivatives of that function will also be collected. Use exact=True to prevent this from happening:

>>> from sympy import Derivative as D, collect, Function
>>> f = Function('f') (x)

>>> collect(a*D(f,x) + b*D(f,x), D(f,x))
(a + b)*Derivative(f(x), x)

>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), f)
(a + b)*Derivative(f(x), (x, 2))

>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True)
a*Derivative(f(x), (x, 2)) + b*Derivative(f(x), (x, 2))

>>> collect(a*D(f,x) + b*D(f,x) + a*f + b*f, f)
(a + b)*f(x) + (a + b)*Derivative(f(x), x)

Or you can even match both derivative order and exponent at the same time:

>>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))
(a + b)*Derivative(f(x), (x, 2))**2

Finally, you can apply a function to each of the collected coefficients. For example you can factorize symbolic coefficients of polynomial:

>>> f = expand((x + a + 1)**3)

>>> collect(f, x, factor)
x**3 + 3*x**2*(a + 1) + 3*x*(a + 1)**2 + (a + 1)**3

Note

Arguments are expected to be in expanded form, so you might have to call expand() prior to calling this function.

sympy.simplify.radsimp.rcollect(expr, *vars)[source]

Recursively collect sums in an expression.

Examples

>>> from sympy.simplify import rcollect
>>> from sympy.abc import x, y
>>> expr = (x**2*y + x*y + x + y)/(x + y)
>>> rcollect(expr, y)
(x + y*(x**2 + x + 1))/(x + y)

collect_sqrt

sympy.simplify.radsimp.collect_sqrt(expr, evaluate=None)[source]

Return expr with terms having common square roots collected together. If evaluate is False a count indicating the number of sqrt-containing terms will be returned and, if non-zero, the terms of the Add will be returned, else the expression itself will be returned as a single term. If evaluate is True, the expression with any collected terms will be returned.

Note: since I = sqrt(-1), it is collected, too.

Examples

>>> from sympy import sqrt
>>> from sympy.simplify.radsimp import collect_sqrt
>>> from sympy.abc import a, b
>>> r2, r3, r5 = [sqrt(i) for i in [2, 3, 5]]
>>> collect_sqrt(a*r2 + b*r2)
sqrt(2)*(a + b)
>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r3)
sqrt(2)*(a + b) + sqrt(3)*(a + b)
>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r5)
sqrt(3)*a + sqrt(5)*b + sqrt(2)*(a + b)

If evaluate is False then the arguments will be sorted and returned as a list and a count of the number of sqrt-containing terms will be returned:

>>> collect_sqrt(a*r2 + b*r2 + a*r3 + b*r5, evaluate=False)
((sqrt(3)*a, sqrt(5)*b, sqrt(2)*(a + b)), 3)
>>> collect_sqrt(a*sqrt(2) + b, evaluate=False)
((b, sqrt(2)*a), 1)
>>> collect_sqrt(a + b, evaluate=False)
((a + b,), 0)

collect_const

sympy.simplify.radsimp.collect_const(expr, *vars, Numbers=True)[source]

A non-greedy collection of terms with similar number coefficients in an Add expr. If vars is given then only those constants will be targeted. Although any Number can also be targeted, if this is not desired set Numbers=False and no Float or Rational will be collected.

Parameters

expr : SymPy expression

This parameter defines the expression the expression from which terms with similar coefficients are to be collected. A non-Add expression is returned as it is.

vars : variable length collection of Numbers, optional

Specifies the constants to target for collection. Can be multiple in number.

Numbers : bool

Specifies to target all instance of sympy.core.numbers.Number class. If Numbers=False, then no Float or Rational will be collected.

Returns

expr : Expr

Returns an expression with similar coefficient terms collected.

Examples

>>> from sympy import sqrt
>>> from sympy.abc import s, x, y, z
>>> from sympy.simplify.radsimp import collect_const
>>> collect_const(sqrt(3) + sqrt(3)*(1 + sqrt(2)))
sqrt(3)*(sqrt(2) + 2)
>>> collect_const(sqrt(3)*s + sqrt(7)*s + sqrt(3) + sqrt(7))
(sqrt(3) + sqrt(7))*(s + 1)
>>> s = sqrt(2) + 2
>>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7))
(sqrt(2) + 3)*(sqrt(3) + sqrt(7))
>>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7), sqrt(3))
sqrt(7) + sqrt(3)*(sqrt(2) + 3) + sqrt(7)*(sqrt(2) + 2)

The collection is sign-sensitive, giving higher precedence to the unsigned values:

>>> collect_const(x - y - z)
x - (y + z)
>>> collect_const(-y - z)
-(y + z)
>>> collect_const(2*x - 2*y - 2*z, 2)
2*(x - y - z)
>>> collect_const(2*x - 2*y - 2*z, -2)
2*x - 2*(y + z)

fraction

sympy.simplify.radsimp.fraction(expr, exact=False)[source]

Returns a pair with expression’s numerator and denominator. If the given expression is not a fraction then this function will return the tuple (expr, 1).

This function will not make any attempt to simplify nested fractions or to do any term rewriting at all.

If only one of the numerator/denominator pair is needed then use numer(expr) or denom(expr) functions respectively.

>>> from sympy import fraction, Rational, Symbol
>>> from sympy.abc import x, y
>>> fraction(x/y)
(x, y)
>>> fraction(x)
(x, 1)
>>> fraction(1/y**2)
(1, y**2)
>>> fraction(x*y/2)
(x*y, 2)
>>> fraction(Rational(1, 2))
(1, 2)

This function will also work fine with assumptions:

>>> k = Symbol('k', negative=True)
>>> fraction(x * y**k)
(x, y**(-k))

If we know nothing about sign of some exponent and exact flag is unset, then structure this exponent’s structure will be analyzed and pretty fraction will be returned:

>>> from sympy import exp, Mul
>>> fraction(2*x**(-y))
(2, x**y)
>>> fraction(exp(-x))
(1, exp(x))
>>> fraction(exp(-x), exact=True)
(exp(-x), 1)

The exact flag will also keep any unevaluated Muls from being evaluated:

>>> u = Mul(2, x + 1, evaluate=False)
>>> fraction(u)
(2*x + 2, 1)
>>> fraction(u, exact=True)
(2*(x  + 1), 1)

Ratsimp

ratsimp

sympy.simplify.ratsimp.ratsimp(expr)[source]

Put an expression over a common denominator, cancel and reduce.

Examples

>>> from sympy import ratsimp
>>> from sympy.abc import x, y
>>> ratsimp(1/x + 1/y)
(x + y)/(x*y)

ratsimpmodprime

sympy.simplify.ratsimp.ratsimpmodprime(expr, G, *gens, quick=True, polynomial=False, **args)[source]

Simplifies a rational expression expr modulo the prime ideal generated by G. G should be a Groebner basis of the ideal.

Examples

>>> from sympy.simplify.ratsimp import ratsimpmodprime
>>> from sympy.abc import x, y
>>> eq = (x + y**5 + y)/(x - y)
>>> ratsimpmodprime(eq, [x*y**5 - x - y], x, y, order='lex')
(-x**2 - x*y - x - y)/(-x**2 + x*y)

If polynomial is False, the algorithm computes a rational simplification which minimizes the sum of the total degrees of the numerator and the denominator.

If polynomial is True, this function just brings numerator and denominator into a canonical form. This is much faster, but has potentially worse results.

References

R663

M. Monagan, R. Pearce, Rational Simplification Modulo a Polynomial Ideal, http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.163.6984 (specifically, the second algorithm)

Trigonometric simplification

trigsimp

sympy.simplify.trigsimp.trigsimp(expr, **opts)[source]

reduces expression by using known trig identities

Explanation

method: - Determine the method to use. Valid choices are ‘matching’ (default), ‘groebner’, ‘combined’, and ‘fu’. If ‘matching’, simplify the expression recursively by targeting common patterns. If ‘groebner’, apply an experimental groebner basis algorithm. In this case further options are forwarded to trigsimp_groebner, please refer to its docstring. If ‘combined’, first run the groebner basis algorithm with small default parameters, then run the ‘matching’ algorithm. ‘fu’ runs the collection of trigonometric transformations described by Fu, et al. (see the \(fu\) docstring).

Examples

>>> from sympy import trigsimp, sin, cos, log
>>> from sympy.abc import x
>>> e = 2*sin(x)**2 + 2*cos(x)**2
>>> trigsimp(e)
2

Simplification occurs wherever trigonometric functions are located.

>>> trigsimp(log(e))
log(2)

Using \(method="groebner"\) (or \("combined"\)) might lead to greater simplification.

The old trigsimp routine can be accessed as with method ‘old’.

>>> from sympy import coth, tanh
>>> t = 3*tanh(x)**7 - 2/coth(x)**7
>>> trigsimp(t, method='old') == t
True
>>> trigsimp(t)
tanh(x)**7

Power simplification

powsimp

sympy.simplify.powsimp.powsimp(expr, deep=False, combine='all', force=False, measure=<function count_ops>)[source]

reduces expression by combining powers with similar bases and exponents.

Explanation

If deep is True then powsimp() will also simplify arguments of functions. By default deep is set to False.

If force is True then bases will be combined without checking for assumptions, e.g. sqrt(x)*sqrt(y) -> sqrt(x*y) which is not true if x and y are both negative.

You can make powsimp() only combine bases or only combine exponents by changing combine=’base’ or combine=’exp’. By default, combine=’all’, which does both. combine=’base’ will only combine:

 a   a          a                          2x      x
x * y  =>  (x*y)   as well as things like 2   =>  4

and combine=’exp’ will only combine

 a   b      (a + b)
x * x  =>  x

combine=’exp’ will strictly only combine exponents in the way that used to be automatic. Also use deep=True if you need the old behavior.

When combine=’all’, ‘exp’ is evaluated first. Consider the first example below for when there could be an ambiguity relating to this. This is done so things like the second example can be completely combined. If you want ‘base’ combined first, do something like powsimp(powsimp(expr, combine=’base’), combine=’exp’).

Examples

>>> from sympy import powsimp, exp, log, symbols
>>> from sympy.abc import x, y, z, n
>>> powsimp(x**y*x**z*y**z, combine='all')
x**(y + z)*y**z
>>> powsimp(x**y*x**z*y**z, combine='exp')
x**(y + z)*y**z
>>> powsimp(x**y*x**z*y**z, combine='base', force=True)
x**y*(x*y)**z
>>> powsimp(x**z*x**y*n**z*n**y, combine='all', force=True)
(n*x)**(y + z)
>>> powsimp(x**z*x**y*n**z*n**y, combine='exp')
n**(y + z)*x**(y + z)
>>> powsimp(x**z*x**y*n**z*n**y, combine='base', force=True)
(n*x)**y*(n*x)**z
>>> x, y = symbols('x y', positive=True)
>>> powsimp(log(exp(x)*exp(y)))
log(exp(x)*exp(y))
>>> powsimp(log(exp(x)*exp(y)), deep=True)
x + y

Radicals with Mul bases will be combined if combine=’exp’

>>> from sympy import sqrt
>>> x, y = symbols('x y')

Two radicals are automatically joined through Mul:

>>> a=sqrt(x*sqrt(y))
>>> a*a**3 == a**4
True

But if an integer power of that radical has been autoexpanded then Mul does not join the resulting factors:

>>> a**4 # auto expands to a Mul, no longer a Pow
x**2*y
>>> _*a # so Mul doesn't combine them
x**2*y*sqrt(x*sqrt(y))
>>> powsimp(_) # but powsimp will
(x*sqrt(y))**(5/2)
>>> powsimp(x*y*a) # but won't when doing so would violate assumptions
x*y*sqrt(x*sqrt(y))

powdenest

sympy.simplify.powsimp.powdenest(eq, force=False, polar=False)[source]

Collect exponents on powers as assumptions allow.

Explanation

Given (bb**be)**e, this can be simplified as follows:
  • if bb is positive, or

  • e is an integer, or

  • |be| < 1 then this simplifies to bb**(be*e)

Given a product of powers raised to a power, (bb1**be1 * bb2**be2...)**e, simplification can be done as follows:

  • if e is positive, the gcd of all bei can be joined with e;

  • all non-negative bb can be separated from those that are negative and their gcd can be joined with e; autosimplification already handles this separation.

  • integer factors from powers that have integers in the denominator of the exponent can be removed from any term and the gcd of such integers can be joined with e

Setting force to True will make symbols that are not explicitly negative behave as though they are positive, resulting in more denesting.

Setting polar to True will do simplifications on the Riemann surface of the logarithm, also resulting in more denestings.

When there are sums of logs in exp() then a product of powers may be obtained e.g. exp(3*(log(a) + 2*log(b))) - > a**3*b**6.

Examples

>>> from sympy.abc import a, b, x, y, z
>>> from sympy import Symbol, exp, log, sqrt, symbols, powdenest
>>> powdenest((x**(2*a/3))**(3*x))
(x**(2*a/3))**(3*x)
>>> powdenest(exp(3*x*log(2)))
2**(3*x)

Assumptions may prevent expansion:

>>> powdenest(sqrt(x**2))
sqrt(x**2)
>>> p = symbols('p', positive=True)
>>> powdenest(sqrt(p**2))
p

No other expansion is done.

>>> i, j = symbols('i,j', integer=True)
>>> powdenest((x**x)**(i + j)) # -X-> (x**x)**i*(x**x)**j
x**(x*(i + j))

But exp() will be denested by moving all non-log terms outside of the function; this may result in the collapsing of the exp to a power with a different base:

>>> powdenest(exp(3*y*log(x)))
x**(3*y)
>>> powdenest(exp(y*(log(a) + log(b))))
(a*b)**y
>>> powdenest(exp(3*(log(a) + log(b))))
a**3*b**3

If assumptions allow, symbols can also be moved to the outermost exponent:

>>> i = Symbol('i', integer=True)
>>> powdenest(((x**(2*i))**(3*y))**x)
((x**(2*i))**(3*y))**x
>>> powdenest(((x**(2*i))**(3*y))**x, force=True)
x**(6*i*x*y)
>>> powdenest(((x**(2*a/3))**(3*y/i))**x)
((x**(2*a/3))**(3*y/i))**x
>>> powdenest((x**(2*i)*y**(4*i))**z, force=True)
(x*y**2)**(2*i*z)
>>> n = Symbol('n', negative=True)
>>> powdenest((x**i)**y, force=True)
x**(i*y)
>>> powdenest((n**i)**x, force=True)
(n**i)**x

Combinatorial simplification

combsimp

sympy.simplify.combsimp.combsimp(expr)[source]

Simplify combinatorial expressions.

Explanation

This function takes as input an expression containing factorials, binomials, Pochhammer symbol and other “combinatorial” functions, and tries to minimize the number of those functions and reduce the size of their arguments.

The algorithm works by rewriting all combinatorial functions as gamma functions and applying gammasimp() except simplification steps that may make an integer argument non-integer. See docstring of gammasimp for more information.

Then it rewrites expression in terms of factorials and binomials by rewriting gammas as factorials and converting (a+b)!/a!b! into binomials.

If expression has gamma functions or combinatorial functions with non-integer argument, it is automatically passed to gammasimp.

Examples

>>> from sympy.simplify import combsimp
>>> from sympy import factorial, binomial, symbols
>>> n, k = symbols('n k', integer = True)
>>> combsimp(factorial(n)/factorial(n - 3))
n*(n - 2)*(n - 1)
>>> combsimp(binomial(n+1, k+1)/binomial(n, k))
(n + 1)/(k + 1)

Square Root Denesting

sqrtdenest

sympy.simplify.sqrtdenest.sqrtdenest(expr, max_iter=3)[source]

Denests sqrts in an expression that contain other square roots if possible, otherwise returns the expr unchanged. This is based on the algorithms of [1].

Examples

>>> from sympy.simplify.sqrtdenest import sqrtdenest
>>> from sympy import sqrt
>>> sqrtdenest(sqrt(5 + 2 * sqrt(6)))
sqrt(2) + sqrt(3)

References

R664

http://researcher.watson.ibm.com/researcher/files/us-fagin/symb85.pdf

R665

D. J. Jeffrey and A. D. Rich, ‘Symplifying Square Roots of Square Roots by Denesting’ (available at http://www.cybertester.com/data/denest.pdf)

Common Subexpression Elimination

cse

sympy.simplify.cse_main.cse(exprs, symbols=None, optimizations=None, postprocess=None, order='canonical', ignore=(), list=True)[source]

Perform common subexpression elimination on an expression.

Parameters

exprs : list of SymPy expressions, or a single SymPy expression

The expressions to reduce.

symbols : infinite iterator yielding unique Symbols

The symbols used to label the common subexpressions which are pulled out. The numbered_symbols generator is useful. The default is a stream of symbols of the form “x0”, “x1”, etc. This must be an infinite iterator.

optimizations : list of (callable, callable) pairs

The (preprocessor, postprocessor) pairs of external optimization functions. Optionally ‘basic’ can be passed for a set of predefined basic optimizations. Such ‘basic’ optimizations were used by default in old implementation, however they can be really slow on larger expressions. Now, no pre or post optimizations are made by default.

postprocess : a function which accepts the two return values of cse and

returns the desired form of output from cse, e.g. if you want the replacements reversed the function might be the following lambda: lambda r, e: return reversed(r), e

order : string, ‘none’ or ‘canonical’

The order by which Mul and Add arguments are processed. If set to ‘canonical’, arguments will be canonically ordered. If set to ‘none’, ordering will be faster but dependent on expressions hashes, thus machine dependent and variable. For large expressions where speed is a concern, use the setting order=’none’.

ignore : iterable of Symbols

Substitutions containing any Symbol from ignore will be ignored.

list : bool, (default True)

Returns expression in list or else with same type as input (when False).

Returns

replacements : list of (Symbol, expression) pairs

All of the common subexpressions that were replaced. Subexpressions earlier in this list might show up in subexpressions later in this list.

reduced_exprs : list of SymPy expressions

The reduced expressions with all of the replacements above.

Examples

>>> from sympy import cse, SparseMatrix
>>> from sympy.abc import x, y, z, w
>>> cse(((w + x + y + z)*(w + y + z))/(w + x)**3)
([(x0, y + z), (x1, w + x)], [(w + x0)*(x0 + x1)/x1**3])

List of expressions with recursive substitutions:

>>> m = SparseMatrix([x + y, x + y + z])
>>> cse([(x+y)**2, x + y + z, y + z, x + z + y, m])
([(x0, x + y), (x1, x0 + z)], [x0**2, x1, y + z, x1, Matrix([
[x0],
[x1]])])

Note: the type and mutability of input matrices is retained.

>>> isinstance(_[1][-1], SparseMatrix)
True

The user may disallow substitutions containing certain symbols:

>>> cse([y**2*(x + 1), 3*y**2*(x + 1)], ignore=(y,))
([(x0, x + 1)], [x0*y**2, 3*x0*y**2])

The default return value for the reduced expression(s) is a list, even if there is only one expression. The \(list\) flag preserves the type of the input in the output:

>>> cse(x)
([], [x])
>>> cse(x, list=False)
([], x)

opt_cse

sympy.simplify.cse_main.opt_cse(exprs, order='canonical')[source]

Find optimization opportunities in Adds, Muls, Pows and negative coefficient Muls.

Parameters

exprs : list of SymPy expressions

The expressions to optimize.

order : string, ‘none’ or ‘canonical’

The order by which Mul and Add arguments are processed. For large expressions where speed is a concern, use the setting order=’none’.

Returns

opt_subs : dictionary of expression substitutions

The expression substitutions which can be useful to optimize CSE.

Examples

>>> from sympy.simplify.cse_main import opt_cse
>>> from sympy.abc import x
>>> opt_subs = opt_cse([x**-2])
>>> k, v = list(opt_subs.keys())[0], list(opt_subs.values())[0]
>>> print((k, v.as_unevaluated_basic()))
(x**(-2), 1/(x**2))

tree_cse

sympy.simplify.cse_main.tree_cse(exprs, symbols, opt_subs=None, order='canonical', ignore=())[source]

Perform raw CSE on expression tree, taking opt_subs into account.

Parameters

exprs : list of SymPy expressions

The expressions to reduce.

symbols : infinite iterator yielding unique Symbols

The symbols used to label the common subexpressions which are pulled out.

opt_subs : dictionary of expression substitutions

The expressions to be substituted before any CSE action is performed.

order : string, ‘none’ or ‘canonical’

The order by which Mul and Add arguments are processed. For large expressions where speed is a concern, use the setting order=’none’.

ignore : iterable of Symbols

Substitutions containing any Symbol from ignore will be ignored.

Hypergeometric Function Expansion

hyperexpand

sympy.simplify.hyperexpand.hyperexpand(f, allow_hyper=False, rewrite='default', place=None)[source]

Expand hypergeometric functions. If allow_hyper is True, allow partial simplification (that is a result different from input, but still containing hypergeometric functions).

If a G-function has expansions both at zero and at infinity, place can be set to 0 or zoo to indicate the preferred choice.

Examples

>>> from sympy.simplify.hyperexpand import hyperexpand
>>> from sympy.functions import hyper
>>> from sympy.abc import z
>>> hyperexpand(hyper([], [], z))
exp(z)

Non-hyperegeometric parts of the expression and hypergeometric expressions that are not recognised are left unchanged:

>>> hyperexpand(1 + hyper([1, 1, 1], [], z))
hyper((1, 1, 1), (), z) + 1

EPath Tools

EPath class

class sympy.simplify.epathtools.EPath(path)[source]

Manipulate expressions using paths.

EPath grammar in EBNF notation:

literal   ::= /[A-Za-z_][A-Za-z_0-9]*/
number    ::= /-?\d+/
type      ::= literal
attribute ::= literal "?"
all       ::= "*"
slice     ::= "[" number? (":" number? (":" number?)?)? "]"
range     ::= all | slice
query     ::= (type | attribute) ("|" (type | attribute))*
selector  ::= range | query range?
path      ::= "/" selector ("/" selector)*

See the docstring of the epath() function.

apply(expr, func, args=None, kwargs=None)[source]

Modify parts of an expression selected by a path.

Examples

>>> from sympy.simplify.epathtools import EPath
>>> from sympy import sin, cos, E
>>> from sympy.abc import x, y, z, t
>>> path = EPath("/*/[0]/Symbol")
>>> expr = [((x, 1), 2), ((3, y), z)]
>>> path.apply(expr, lambda expr: expr**2)
[((x**2, 1), 2), ((3, y**2), z)]
>>> path = EPath("/*/*/Symbol")
>>> expr = t + sin(x + 1) + cos(x + y + E)
>>> path.apply(expr, lambda expr: 2*expr)
t + sin(2*x + 1) + cos(2*x + 2*y + E)
select(expr)[source]

Retrieve parts of an expression selected by a path.

Examples

>>> from sympy.simplify.epathtools import EPath
>>> from sympy import sin, cos, E
>>> from sympy.abc import x, y, z, t
>>> path = EPath("/*/[0]/Symbol")
>>> expr = [((x, 1), 2), ((3, y), z)]
>>> path.select(expr)
[x, y]
>>> path = EPath("/*/*/Symbol")
>>> expr = t + sin(x + 1) + cos(x + y + E)
>>> path.select(expr)
[x, x, y]

epath

sympy.simplify.epathtools.epath(path, expr=None, func=None, args=None, kwargs=None)[source]

Manipulate parts of an expression selected by a path.

Parameters

path : str | EPath

A path as a string or a compiled EPath.

expr : Basic | iterable

An expression or a container of expressions.

func : callable (optional)

A callable that will be applied to matching parts.

args : tuple (optional)

Additional positional arguments to func.

kwargs : dict (optional)

Additional keyword arguments to func.

Explanation

This function allows to manipulate large nested expressions in single line of code, utilizing techniques to those applied in XML processing standards (e.g. XPath).

If func is None, epath() retrieves elements selected by the path. Otherwise it applies func to each matching element.

Note that it is more efficient to create an EPath object and use the select and apply methods of that object, since this will compile the path string only once. This function should only be used as a convenient shortcut for interactive use.

This is the supported syntax:

  • select all: /*

    Equivalent of for arg in args:.

  • select slice: /[0] or /[1:5] or /[1:5:2]

    Supports standard Python’s slice syntax.

  • select by type: /list or /list|tuple

    Emulates isinstance().

  • select by attribute: /__iter__?

    Emulates hasattr().

Examples

>>> from sympy.simplify.epathtools import epath
>>> from sympy import sin, cos, E
>>> from sympy.abc import x, y, z, t
>>> path = "/*/[0]/Symbol"
>>> expr = [((x, 1), 2), ((3, y), z)]
>>> epath(path, expr)
[x, y]
>>> epath(path, expr, lambda expr: expr**2)
[((x**2, 1), 2), ((3, y**2), z)]
>>> path = "/*/*/Symbol"
>>> expr = t + sin(x + 1) + cos(x + y + E)
>>> epath(path, expr)
[x, x, y]
>>> epath(path, expr, lambda expr: 2*expr)
t + sin(2*x + 1) + cos(2*x + 2*y + E)