MGrd
MGrd

Reputation: 1

Multiple arguments in python

I'm using the built-in Levenberg-Marquardt algorithm to fit some data. It calls some function which needs to have the syntax foo(x,a1,a2,...,an), where an are parameters and the number of input arguments specifies the number of dimensions the L-M algorithm minimizes. Currently this foo function calls some other function I have defined as :

foo(x, a1, a2, ..., an):
    ai = [a1,a2,...,an]
    result = somefun(x,ai)
    return result

Is there a way to use a compact syntax in this case? I would like to be able to define some parameter L = n, which specifies the number of input arguments somewhere before the function definition.

Note: Please also read that using foo(x,*ai), will generate ValueError: Unable to determine number of fit parameters before marking as duplicate.

Upvotes: 0

Views: 506

Answers (3)

user2357112
user2357112

Reputation: 281948

The function you're using, scipy.optimize.curve_fit, only needs to introspect f to find the number of arguments if you don't pass an initial guess as a p0 argument. If you can provide a good guess, do so; otherwise, you can pass in a guess of all ones:

scipy.optimize.curve_fit(f, xdata, ydata, p0=[1]*n)

Then you can use def f(x, *args) syntax.

If for some reason you really need f to have independently specified positional arguments, I would use exec. That's rarely a good idea, but in this case, it may be warranted.

template = '''
def f(x, {args}):
    return somefun(x, [{args}])
'''

definition = template.format(args=', '.join('a'+str(i) for i in xrange(n)))
namespace = {'somefun': somefun}
exec definition in namespace
f = namespace['f']

Upvotes: 0

eewallace
eewallace

Reputation: 99

You should probably specify in your question that the function you're using is from scipy, which is not part of the standard library.

From the docstring for scipy.optimize.curve_fit:

optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False, check_finite=True, **kw)
...
Parameters
----------

f : callable
The model function, f(x, ...).  It must take the independent
variable as the first argument and the parameters to fit as
separate remaining arguments.

xdata : An M-length sequence or an (k,M)-shaped array
for functions with k predictors.
The independent variable where the data is measured.

ydata : M-length sequence
The dependent data --- nominally f(xdata, ...)

p0 : None, scalar, or N-length sequence
Initial guess for the parameters.  If None, then the initial
values will all be 1 (**if the number of parameters for the function
can be determined using introspection, otherwise a ValueError
is raised**).
...

With the foo(x,*args) construction, the number of parameters can't be determined from introspection, so you get your ValueError, but you can still pass a sequence of initial values via the p0 argument, which will let the algorithm know that the number of parameters is the length of that sequence. So for example,

n=5
foo(x,*args):
    return somefun(x,args)
curve_fit(foo,x0,y0,p0=[1]*n)

Upvotes: 1

TheBlackCat
TheBlackCat

Reputation: 10328

Use the *args syntax:

foo(x, *args):
    result = somefun(x, args)
    return result

This grabs all arguments besides x and stores them in the tuple args.

Upvotes: 2

Related Questions