# How can I speed up symbolic function evaluation?

I have a few hundred lines of code that calculate a system of ODEs. The resulting system of several hundred to several thousand equations take a long time to integrate. (I'm using SciPy's integrate interface; testing on a small case suggested it's several times faster than GSL's ode_solver for my problem.)

Of course, most of the time is spent in evaluating my equations. I'm already using fast_callable to speed up the calculations. It made a wonderful difference. But it's still taking hours or even days for the larger systems. I want to put this integration inside an optimizer, so any speed gain is great.

Stealing the example from the reference manual (http://www.sagemath.org/doc/numerical...), I'm currently doing something like the following.

import scipy
from scipy import integrate
var('x, y')
mu = 10.0
dy = (y, -x + mu*y*(1-x**2))
dy_fc = tuple(fast_callable(expr, domain=float, vars=(x,y)) for expr in dy)
def f_1(y,t):
return [f(*y) for f in dy_fc]

xx=scipy.arange(0,100,.1)
yy=integrate.odeint(f_1,[1,0],xx)


I don't think I can speed up the integrate routine. Can I do anything to speed up f_1?

Thanks!

edit retag close merge delete

Sort by » oldest newest most voted

In my opinion, the funcion desolve_odeint (in versions >=4.6) provides what you want. Basically it takes a symbolic expression as the vector field, it compiles it to a fast float expression and then integrates it using the scipy.odeint solver. I have never used with hundreds of variables, but let us know your experiences...

In your case I would do the following:

sage: var('x, y')
sage: mu = 10.0
sage: dy = (y, -x + mu*y*(1-x**2))
sage: dy_fc = [expr for expr in dy]
sage: xx=srange(0,50.05,0.001) # I would plot more points
sage: ics=[1.0,0.0]
sage: sol=desolve_odeint(dy_fc,ics,xx,[x,y])


and if you want a nice plot

sage: line(sol)+plot_vector_field(dy_fc,(x,-2,2),(y,-15,15))

more

But didn't the original poster already use scipy.odeint and fast_callable/fast_float? Let's hope it works, though!

( 2011-03-30 17:14:21 +0200 )edit

You may be able to use Cython to speed up such things. In order to do so most efficiently, you'd want to cdef certain data types (for instance, the outputs of dy_fc?) and the function you are using.

I'm not at all a Cython expert, though; I know it really depends on the specifics of your use case, and of course fast_callable is already pretty nice. Here are random links which could conceivably help (or not):

Good luck!

more