[Tutor] constructing semi-arbitrary functions

Oscar Benjamin oscar.j.benjamin at gmail.com
Wed Feb 19 13:33:21 CET 2014


On 18 February 2014 17:59, Peter Otten <__peter__ at web.de> wrote:
>
> I don't know if the OP may use it, but there seems to be a version of minuit
> that allows to override the function signature:
>
> """
> forced_parameters: tell Minuit not to do function signature detection and
> use this argument instead. (Default None (automagically detect signature)
> """

Interesting. I don't really understand why it works that way though.
Looking here

   http://iminuit.github.io/iminuit/api.html#function-sig-label

I find the suggestion to do instead:

"""
f = lambda x,m,c: m*x+c
#the beauty here is that all you need to build
#a Chi^2 is just your function and data
class GenericChi2:
    def __init__(self, f, x, y):
        self.f = f
        args = describe(f)#extract function signature
        self.func_code = Struct(
                co_varnames = args[1:],#dock off independent param
                co_argcount = len(args)-1
            )
    def __call__(self, *arg):
        return sum((self.f(x,*arg)-y)**2 for x,y in zip(self.x, self.y))

m = Minuit(GenericChi2(f,x,y))
"""

But that just seems a bit ridiculous to me.

If it were my library I would probably be aiming to handle complex
cases with a closure-based solution like this:

def make_chisq(f, xdata, ydata):
    def chisq(m, c):
        return sum((self.f(x,m, c)-y)**2 for x,y in zip(xdata, ydata))
    return chisq

f = lambda x,m,c: m*x+c
m = Minuit(make_chisq(xdata, ydata), names=['m', 'c'])

At the least I don't understand why it needs both the argument names
and the number of arguments as independent quantities. Surely
len(names) would be the number of arguments... Or am I missing
something?

BTW to the OP the functions in scipy.optimize don't do any of this.
You just pass in the function and an initial guess at the parameter
values. It doesn't care about the names and infers the number of
parameters from the initial guess. Also numpy has a polyfit function
that you can just call with polyfit(xdata, ydata, deg) where deg is
the degree of the polynomial you want to fit. Under the hood it solves
the scaled Vandermonde matrix as I described earlier:
https://github.com/numpy/numpy/blob/master/numpy/polynomial/polynomial.py#L1351


Oscar


More information about the Tutor mailing list