[Tutor] constructing semi-arbitrary functions

Peter Otten __peter__ at web.de
Tue Feb 18 18:59:53 CET 2014


Oscar Benjamin wrote:

> On 17 February 2014 20:13, Peter Otten <__peter__ at web.de> wrote:
>> André Walker-Loud <walksloud at gmail.com> wrote:
>>>
>>> The 3rd party minimizer utilizes the .func_code.co_varnames and
>>> .func_code.co_argcount to determine the name and number of variables to
>>> minimize.  eg.
>>>
>>> =========
>>> METHOD 2: use strings, exec and globals to construct function
>>> def minimize(pars,x,y,dy):
>>>     global g_x, g_y, g_dy
>>>     g_x = x; g_y = y; g_dy = dy
>>>     argnames = ['c_%i'%(i) for i in range(len(pars))]
>>>     funcargs = ", ".join(argnames)
>>>     funcdef = 'def chisq_mn(' + funcargs + '):\n'
>>>     funcdef += '    global g_x, g_y, g_dy\n'
>>>     funcdef += '    return chisq(['+funcargs+'],g_x,g_y,g_dy)\n' #chisq
>>>     is defined in same file
>>>     # evaluate string and build function
>>>     print "funcdef=", funcdef
>>>     exec funcdef in globals()
>>
>> I think you are looking for closures:
> 
> Closures would be a good fit for this if the third-party minimisation
> routine didn't assume that it always receives a function whose formal
> parameters are the variables to be minimised and have the names that
> are intended for display.

Thank you for reading the OP more thoroughly and for taking the time to 
explain to those who don't ;)

> This one would work (assuming that we want to minimise over x):
> 
>> def make_poly(coeff):
>>     def poly(x):
>>         return sum(c * x ** n for n, c in enumerate(coeff))
>>     return poly
> 
> This one won't work:
> 
>> def minimize(x, y, dy):
>>     def chisq_mn(*args):
>>         return chisq(args, x, y, dy)
>>     return chisq_mn
> 
>>>> def minimize(x, y, dy):
> ...     def chisq_mn(*args):
> ...         return chisq(args, x, y, dy)
> ...     return chisq_mn
> ...
>>>> f = minimize(2, 4, 0.1)
>>>> f.func_code.co_varnames
> ('args',)
>>>> f.func_code.co_argcount
> 0
> 
> The OP wants to pass this function to a routine that looks like:
> 
> def minimise(func):
>     num = func.func_code.co_argcount
>     names = func.func_code.co_varnames
>     # Actual minimisation code
>     return _minimise(func, num, names)


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:

"""
class iminuit.Minuit
Minuit(fcn, throw_nan=False, pedantic=True, frontend=None, 
forced_parameters=None, print_level=1, errordef=None, **kwds)

Construct minuit object from given fcn
Arguments:

[...]

forced_parameters: tell Minuit not to do function signature detection and 
use this argument instead. (Default None (automagically detect signature)
"""

http://iminuit.github.io/iminuit/api.html




More information about the Tutor mailing list