Billy Matlock
Billy Matlock

Reputation: 350

How to simplify lengthy symbolic expressons in SymPy

I have been working on some integrations and even though the system is working, it takes much more time to work than it should.

The problem is that the expressions are many pages, and even though they are 3 variables only, sy.simplify just crashes the Kernel after 4 hours or so.

Is there a way to make such lengthy expressions more compact?

EDIT:

Trying to recreate a test expression, using cse. I can't really substitute the symbols to make a final expression, equal to the 1st one

sy.var('a:c x')
testexp = sp.log(x)+a*(0.5*x)**2+(b*(0.5*x)**2+b+sp.log(x))/c
r, e = sy.cse(testexp)
FinalFunction = sy.lambdify(r[0:][0]+(a,b,c,x),e[0])
Points = sy.lambdify((a,b,c,x),r[0:][1])
FinalFunction(Points(1,1,1,1),1,1,1,1)

>>>NameError: name 'x1' is not defined

Upvotes: 0

Views: 455

Answers (1)

smichr
smichr

Reputation: 18964

cse(expr) is sometimes a way to get a more compact representation since repeated subexpressions can be replaced with a single symbol. cse returns a list of repeated expressions and a list of expressions (a singleton if you only passed a single expression):

>>> from sympy import solve
>>> var('a:c x');solve(a*x**2+b*x+c, x)
(a, b, c, x)
[(-b + sqrt(-4*a*c + b**2))/(2*a), -(b + sqrt(-4*a*c + b**2))/(2*a)]
>>> r, e = cse(_)
>>> for i in r: pprint(Eq(*i))
...
        _____________
       ╱           2
x₀ = ╲╱  -4⋅a⋅c + b
      1
x₁ = ───
     2⋅a
>>> for i in e: pprint(i)
...
x₁⋅(-b + x₀)
-x₁⋅(b + x₀)

You are still going to have long expressions but they will be represented more compactly (and more efficiently for computatation) if cse is able to identify repeated subexpressions.

To use this in SymPy you can create two Lambdas: one to translate the variables into the replacement values and the other to use those values:

>>> v = (a,b,c,x)
>>> Pts = Lambda(v, tuple([i[1] for i in r]+list(v)))
>>> Pts(1,2,3,4)
(2*sqrt(2)*I, 1/2, 1, 2, 3, 4)
>>> Func = Lambda(tuple([i[0] for i in r]+list(v)), tuple(e))
>>> Func(*Pts(1,2,3,4))
(-1 + sqrt(2)*I, -1 - sqrt(2)*I)

Upvotes: 2

Related Questions