Search code examples
pythonpython-3.xsympyevaluation

Sympy bug? Even with `evaluate=False` equations are automatically processed


Consider the following sympy code:

import sympy as sp
from sympy import Add
from sympy.abc import x

t1 = 2+2*x
t2 = x
myeq = sp.UnevaluatedExpr(Add(sp.UnevaluatedExpr(t1), sp.UnevaluatedExpr(t2), evaluate=False))

# BUG! Will print: x + 2*x + 2
# Yet it should print: 2+2*x+x
print(myeq)

This code snippet was adapted from this answer. There the terms are simpler, so Add preserved the order. But how can I make Add preserve the order in this case as well?

(Remark: If we change the terms to t1=x and t2=x**2 my approach with using the sp.UnevaluatedExpr works, but the original answer that did not have those terms does not. Alas, for my specific case, not even using sp.UnevaluatedExpr works.)


Solution

  • This is not a bug...

    ... but more a missing feature. All of it being documented.

    Here is what SymPy means by unevaluated.

    By unevaluated it is meant that the value inside of it will not interact with the expressions outside of it to give simplified outputs.

    In your example, the terms 2*x and x were not simplified, as is expected.

    Order of input

    What you are seeing is SymPy not preserving the order in which you input your terms. This is documented under the expression tree section.

    The arguments of the commutative operations Add and Mul are stored in an arbitrary (but consistent!) order, which is independent of the order inputted.

    This should not be a problem since Add and Mul are commutative.

    Although, if for some reason you want to preserve the order of input due to non-commutativity of multiplication, you can do so.

    In SymPy, you can create noncommutative Symbols using Symbol('A', commutative=False), and the order of multiplication for noncommutative Symbols is kept the same as the input)

    As for now, there does not seem to be non-commutative addition.