Skip to content
S.Y. Lee edited this page Mar 4, 2019 · 1 revision

Why does SymPy say that two equal expressions are unequal?

The equality operator (==) tests whether expressions have identical form, not whether they are mathematically equivalent.

To make equality testing useful in basic cases, SymPy tries to rewrite mathematically equivalent expressions to a canonical form when evaluating them. For example, SymPy evaluates both x+x and -(-2*x) to 2*x, and x*x to x**2.

The simplest example where the default transformations fail to generate a canonical form is for nonlinear polynomials, which can be represented in both factored and expanded form. Although clearly ( a(1+b) = a+ab ) mathematically, SymPy gives:

>>> from import a, b
>>> bool(a*(1+b) == a + a*b)

Likewise, SymPy fails to detect that the difference is zero:

>>> bool(a*(1+b) - (a+a*b) == 0)

If you want to determine the mathematical equivalence of nontrivial expressions, you should apply a more advanced simplification routine to both sides of the equation. In the case of polynomials, expressions can be rewritten in a canonical form by expanding them fully. This is done using the .expand() method in SymPy:

>>> A, B = a*(1+b), a + a*b
>>> bool(A.expand() == B.expand())
>>> (A - B).expand()

If .expand() does not help, try simplify(), trigsimp(), etc, which attempt more advanced transformations. For example,

>>> from sympy import sin, cos, trigsimp, Symbol
>>> x = Symbol("x")
>>> trigsimp(cos(x)**2 + sin(x)**2) == 1

I did the same calculation twice and got different results. What's going on?

This problem is probably due to erroneous caching of assumptions. Please report the bug to the mailing list or the issue tracker.

What is the best way to create symbols?

The most convenient way to create symbols when using SymPy interactively is via var. For example:

>>> from sympy import var
>>> var('x,y')
>>> x + y
x + y

The var function uses a hack to add the symbols to the current namespace, so you don't have to type each symbol name twice. In library code, it is better to create symbols explicitly:

x, y = symbols('x y')

This makes the code much clearer. Other ways of creating symbols are discussed in the article Creating Symbols.

How good is SymPy's performance?

SymPy is efficient enough for interactive use as an advanced calculator. SymPy is written entirely in Python, and the speed seems comparable to Maxima. Mathematica and Maple are faster, and if speed is important for your application, use our very fast C++ version: SymEngine, which is a subset of SymPy, can seamlessly convert expressions to and from SymPy and is roughly as fast as Mathematica or Maple. The goal of SymEngine is to be the fastest CAS (when used together with SymPy), it's a work in progress.

Where is SymPy going to? What are the nearest plans?

See our Roadmap

But the secret plan is to be the best CAS in Python. :)

What about Sage?

Sage will be the best opensource CAS (hopefully). More information here:

How do I clear the cache?

You can see/clear the cache content as follows:

    >>> from sympy.core.cache import *
    >>> print_cache()
        sort_key CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
        _subs CacheInfo(hits=0, misses=3, maxsize=1000, currsize=3)
        has CacheInfo(hits=3, misses=17, maxsize=1000, currsize=17)
        sort_key CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
        sort_key CacheInfo(hits=1, misses=3, maxsize=1000, currsize=3)
        as_leading_term CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
       expand CacheInfo(hits=0, misses=2, maxsize=1000, currsize=2)
       __new__ CacheInfo(hits=50, misses=41, maxsize=1000, currsize=41)
       args CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
       as_two_terms CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
       as_coeff_mul CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
       _eval_derivative CacheInfo(hits=0, misses=0, maxsize=1000, currsize=0)
       sort_key CacheInfo(hits=3, misses=2, maxsize=1000, currsize=2)

... lots of output follows ...

    >>> clear_cache()

How do I turn off caching?

Simply set the environment variable "SYMPY_USE_CACHE=no", for example:

$ SYMPY_USE_CACHE=no py.test sympy/core

Is there a method to get a list with all symbols in an expression?

Yes .atoms(Symbol), use it like this:

    >>> from import x, y, z
    >>> e = x + y*sin(z**2)
    >>> e.atoms()
    set([2, x, y, z])

    >>> e.atoms(Symbol)
    set([x, y, z])

How can I make my editor highlight trailing whitespace red?

This depends on your editor.

  • For Vim/Gvim, add the following to your .vimrc:
if has('gui_running')
    hi WhiteSpaceEOL guibg=#FF0000
    hi WhiteSpaceEOL ctermbg=Red endif
match WhitespaceEOL /\s\+\%#\@<!$/
  • For emacs, add the following to your .emacs file:
(setq-default highlight-trailing-whitespace)

Alternately, use M-x customize-variable show-trailing-whitespace.

How to connect to our Gitter channel?

Our Gitter channel is at, just click on the link and connect using GitHub.

For reference, we used to use IRC, at #sympy at FreeNode (irc://, but we do not anymore.

Why doesn't changing one variable change another that depends it?

The short answer is "because it doesn't depend on it." :-) Even though you are working with equations, you are still working with Python objects. The equations you are typing use the values present at the time of creation to "fill in" values, just like regular Python definitions. They are not altered by changes made afterwards. Consider the following:

    >>> a = Symbol('a') # create an object with name 'a' for variable a to point to
    >>> b = a + 1; b    # create another object that refers to what 'a' refers to
    a + 1
    >>> a = 4; a        # a now points to the literal integer 4, not Symbol('a')
    >>> b               # but b is still pointing at Symbol('a')
    a + 1

Changing quantity a does not change b; you are not working with a set of simultaneous equations. To evaluate b with a particular value of a, use subs method instead of assigning to a:

    >>> b.subs(a, 4)

It might be helpful to remember that the string that gets printed when you print a variable referring to a SymPy object is the string that was give to it when it was created; that string does not have to be the same as the variable that you assign it to:

    >>> r, t, d = symbols('rate time short_life')
    >>> d = r*t; d
    >>> r=80; t=2; d    # we haven't changed d, only r and t
    >>> d=r*t; d        # now d is using the current values of r and t

When I copy and paste an expression during interactive work, why do I get a different answer?

Even though you are working with SymPy objects, not everything you type is a SymPy object. If you are working with a Python version earlier than 3 and have not issued a from __future__ import division command then dividing an integer by a larger integer will give 0

    >>> a=4; 1/a
    >>> from __future__ import division
    >>> 1/a

    >>> del division

This could be the source of the difference that you see when you copy and paste a result. The work-around for this is to use sympify() on that copied expression which changes integers to a SymPy object or just use a index to access the piece of the output that you are interested in:

    >>> from sympy import solve, sympify
    >>> a,b = symbols('a b')

    >>> solve((2*a-b)*a-3, a)               #doctest: +RELEASE_ONLY
    [b/4 - (b**2 + 24)**(1/2)/4, b/4 + (b**2 + 24)**(1/2)/4]
    >>> solve((2*a-b)*a-3, a)               #doctest: +FUTURE_ONLY
        [b/4 - sqrt(b**2 + 24)/4, b/4 + sqrt(b**2 + 24)/4]
    >>> root1 = b/4 - (24 + b**2)**(1/2)/4; root1               # the 1/2 went to 0
    b/4 - 1/4
    >>> root1 = sympify('b/4 - (24 + b**2)**(1/2)/4'); root1  # SymPy preserves the integers #doctest: +RELEASE_ONLY
    b/4 - (b**2 + 24)**(1/2)/4

    >>> solve((2*a-b)*a-3,a)
    [b/4 - (b**2 + 24)**(1/2)/4, b/4 + (b**2 + 24)**(1/2)/4]
    >>> root1=_[0]; root1
    b/4 - (b**2 + 24)**(1/2)/4

How can I get SymPy to not change what I enter?

Sometimes you might want a fraction in an unsimplified form (e.g. 2/4 instead of 1/2) or you might want terms raised to a power to not have the power distributed to each term (e.g. (x*y)**2 instead of x**2*y**2). Presently, the way to get the raw form is by building the expression with the evaluate=False option, e.g.

    >>> from sympy import Mul, Pow, Rational
    >>> Mul(2, Rational(1,4), evaluate=False)
    >>> Pow(x*y, 2, evaluate=False)
Clone this wiki locally
You can’t perform that action at this time.