simplify, expand, factor and friends

SymPy · Essentials · 12 min

There is no single 'simplest' form; knowing the targeted functions gives you control over the result.

simplify() tries many strategies and returns whatever looks shortest. It is great for exploration, but it is slow and its output form is unpredictable. When you know the shape you want, use a targeted function:

  • expand(e) multiplies out products and powers: (x + 1)**2 becomes x**2 + 2*x + 1.
  • factor(e) does the reverse for polynomials, factoring over the rationals.
  • collect(e, x) groups terms by powers of x.
  • cancel(e) puts a rational function into the canonical form p/q with common factors removed.
  • apart(e) does partial fraction decomposition.
  • together(e) combines terms over a common denominator.
  • trigsimp, expand_trig, powsimp, logcombine handle trig, power and log identities.

To test whether two expressions are equal mathematically, check simplify(a - b) == 0. Plain a == b compares tree structure, so (x + 1)**2 == x**2 + 2*x + 1 is False.

Some identities only hold under assumptions. simplify(sqrt(x**2)) stays sqrt(x**2) because for negative or complex x it is not x; declaring the symbol positive changes that.

Example

from sympy import symbols, simplify, expand, factor, collect, cancel, apart, sin, cos

x, y = symbols("x y")
print(expand((x + 1)**2))                 # x**2 + 2*x + 1
print(factor(x**3 - x**2 + x - 1))        # (x - 1)*(x**2 + 1)
print(collect(x*y + x - 3 + 2*x**2 - x**2*y, x))  # x**2*(2 - y) + x*(y + 1) - 3
print(cancel((x**2 + 2*x + 1) / (x**2 + x)))      # (x + 1)/x
print(apart(1 / (x**2 - 1)))              # -1/(2*(x + 1)) + 1/(2*(x - 1))
print(simplify(sin(x)**2 + cos(x)**2))    # 1

a, b = (x + 1)**2, x**2 + 2*x + 1
print(a == b, simplify(a - b) == 0)       # False True

Remember

  • simplify is a heuristic; prefer expand, factor, collect, cancel, apart when you know the target
  • == is structural equality; use simplify(a - b) == 0 for math equality

Watch out for

  • Calling simplify inside loops over large expressions: it can be very slow.

Check yourself

  1. What does (x + 1)**2 == x**2 + 2*x + 1 return?
  2. You want 1/(x**2 - 1) written as a sum of simpler fractions. Which function?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html