Question

I do a lot of ODE simulations and I work with a few python parameter optimization tools (e.g. scipy.optimize.minimize, emcee) that require parameters to be passed in as a list. This makes them very cumbersome, as I have to refer to the parameters as params[0], params[1], etc. as opposed to more intuitive names that actually describe their role in the simulation. My solution to this so far has been something along the lines of this:

k1 = 1.0 
k2 = 0.5
N = 0.01

params = [k1,k2,N]

def sim(params,timerange):
    k1 = params[0]
    k2 = params[1]
    N = params[2]

    # run the simulation

This is really kludgey and is unsatisfactory for a number of reasons. Whenever I need to add new parameters to the simulation I have to modify the params list and change how I'm manually unpacking the list inside the simulate function; wastes some time making new references each round of simulating, etc.

I'm wondering if there's a sane, non-kludgey solution for defining the parameters with names, passing them to a function as a list, and then referring to them by those same names inside the list.

Was it helpful?

Solution

def sim(params,timerange):
    k1,k2,N = params

Is what you want I think ..,.. if you added an extra param you would just add it after N ... but it would not be an optional argument

or maybe better

def sim(*params,**kwargs):
    timerange = kwargs.get('timerange',default_timerange)
    K1,K2,N = params #assuming you know you have exactly 3

#then call it like so
sim(k1,k2,N,timerange=(-100,100))

OTHER TIPS

I usually do what Joran suggests in his answer:

def sim(params, timerange):
    k1, k2, N = params
    ...

but you can also do this:

def sim((k1, k2, N), timerange):
    ...

(At least, that works in Python 2.7. I haven't tried it with other Python versions.) I tested the idea with scipy.integrate.odeint, scipy.integrate.ode and scipy.optimize.minimize, and it worked fine. For example, in the following code, you can use either cost or cost2 as the first argument to minimize:

from scipy.optimize import minimize

def cost(z, a, b):
    x, y = z
    c = (x - a)**2 + (y - b)**2
    return c

def cost2((x, y), a, b):
    c = (x - a)**2 + (y - b)**2
    return c

if __name__ == "__main__":
    a = 5.0
    b = 1.5
    x0 = 4.2
    y0 = 1.5
    sol = minimize(cost2, (x0, y0), args=(a,b))
    print sol['x']
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top