简体   繁体   中英

Sympy simplify logic

I've recently start use Sympy, and from very beginning it behaves strange from my viewpoint.

Consider two polynomials, fx and tn_shifted of one variable. I subtract one from another to get polynom p2. Then I perform simplify of it, and get a completely different expression, as shown below.

import sympy as spy
from sympy import Symbol

x = Symbol('x')
a, b = 1, 3
n = 3
tn = lambda x: x**3 - 3*x
fx = spy.simplify(x**3 - 2*x**2 + x + 1)

tn_shifted = (b - a)**n / (2**(2*n - 1)) * tn((2*x - (b + a)) / (b - a))
tn_shifted = spy.simplify(tn_shifted)

p2_ethalon = fx - tn_shifted
print(fx - p2_ethalon - tn_shifted)

p2_simplified = spy.simplify(fx - tn_shifted)
print(fx - p2_simplified - tn_shifted)

p2_expanded = spy.expand(fx - tn_shifted)
print(fx - p2_expanded - tn_shifted)

print(p2_ethalon - p2_simplified)

Here is an output:

0
0.25*x**3 - 1.5*x**2 + 3.0*x - 0.25*(x - 2)**3 - 2.0
0.25*x**3 - 1.5*x**2 + 3.0*x - 0.25*(x - 2)**3 - 2.0
0.25*x**3 - 1.5*x**2 + 3.0*x - 0.25*(x - 2)**3 - 2.0

Sympy comes with anaconda for python 3.5 under OS X Yosemite Here is pip show sympy info

Name: sympy
Version: 0.7.6.1
Summary: Computer algebra system (CAS) in Python
Home-page: http://sympy.org
Author: SymPy development team
Author-email: sympy@googlegroups.com
License: BSD
Location: /Users/cnst/anaconda/lib/python3.5/site-packages

So, is there a bug or Sympy has some nontrivial logic when it simplifies expression?

There is no bug. If you simplify the last three expressions, you'll see they all cancel out.

>>> print(fx - p2_simplified - tn_shifted)
0.25*x**3 - 1.5*x**2 + 3.0*x - 0.25*(x - 2)**3 - 2.0
>>> print((fx - p2_simplified - tn_shifted).simplify())
0

Once you force that (x - 2)**3 term to expand, it all works out. Why does this happen though? Initially, you have

>>> fx
x**3 - 2*x**2 + x + 1
>>> tn_shifted
-0.75*x + 0.25*(x - 2)**3 + 1.5
>>> p2_ethalon
x**3 - 2*x**2 + 1.75*x - 0.25*(x - 2)**3 - 0.5

So, naturally,

>>> p2_ethalon + tn_shifted
x**3 - 2*x**2 + 1.0*x + 1.0

When you subtract that from fx , it causes everything to cancel out nicely. However, for p2_simplified , you ask it to simplify p2_ethalon in isolation, which returns

>>> p2_simplified
0.75*x**3 - 0.5*x**2 - 1.25*x + 1.5

The problem here is that when you add this to tn_shifted , sympy doesn't realise that by expanding the cubic from tn_shifted it would allow everything to simplify even more, so they stay in limbo as a more complex expression.

>>> p2_simplified + tn_shifted
0.75*x**3 - 0.5*x**2 - 2.0*x + 0.25*(x - 2)**3 + 3.0

However, if you were to expand the cubic from tn_shifted , the above would simplify to fx .

>>> tn_expanded = tn_shifted.expand()
>>> p2_simplified + tn_expanded
1.0*x**3 - 2.0*x**2 + 1.0*x + 1.0

Bottom line, sympy doesn't aggressively simplify an expression every time a new term is added, multiplied, subtracted, etc. And simplifying a part of an expression in isolation may prevent sympy later on to see a bigger pattern which would lead to a more global simplification.

I've had a similar experience with Maple a few of times, where, in order to bring a formula to the exact form I wanted, I had to nest functions like simplify(collect(expand(expr))).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM