Ask Your Question

How can I speed up symbolic function evaluation?

asked 2011-03-12 12:39:56 -0500

Ryan Hinton gravatar image

updated 2011-04-28 11:29:20 -0500

Kelvin Li gravatar image

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 (, 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]


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


edit retag flag offensive close merge delete

2 answers

Sort by » oldest newest most voted

answered 2011-03-12 12:57:05 -0500

kcrisman gravatar image

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!

edit flag offensive delete link more

answered 2011-03-29 23:05:10 -0500

Joaquim Puig gravatar image

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))
edit flag offensive delete link more


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

kcrisman gravatar imagekcrisman ( 2011-03-30 10:14:21 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools


Asked: 2011-03-12 12:39:56 -0500

Seen: 426 times

Last updated: Mar 29 '11