6

I have a function which takes several arguments (one array and two floats) and returns a scalar (float). Now I want to minimize this function by varying two of the arguments: the two floats. The array is "unpacked" inside the function at its contents (arrays and floats) are then used.

How can this be done using SciPy's fmin function? I am having a very hard time figuring out the right syntax for this..

The function is something like:

def func(x, y, data)
    data1=data[0]
    data2=data[...]
    ...
    ...
    result = ...x...y...data1...data2... #result is a scalar (float)
    return result

What should scipy.optimize.fmin look like in this case?

optimize.fmin(func, ???)

Many thanks in advance!

All the best, p.p.

user1987501
  • 91
  • 1
  • 4

2 Answers2

5

scipy assumes that the arguments are in an array. You can define a helper function:

def helper(xy):
    return func(xy[0], xy[1], data)

and minimize it with optimize.fmin:

optimize.fmin(helper, np.array([x0, y0]), ...)
Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
  • Thank you! I managed to sort it out and tried to answer my own question, but "Users with less than 10 reputation can't answer their own question for 8 hours after asking". I'll post the answer tomorrow. – user1987501 Jan 17 '13 at 17:54
3

I found the answer in SciPy's documentation! I am just not used to the programming "lingo" of the documentation... (although the documentation has been VERY useful for a newbie as myself).

So, the way to do it is the following:

  • Instead of defining the function (to be minimized) as in my question, it should be defined as

    def func(x, *args) #it is literally "*args"!
        y=x[0]
        z=x[1]
        data1=data[0]
        data2=data[...]
        ...
        result = ...y...z...data1...data2... #result is a scalar (float)
        return result
    
  • Now, the optimize.fmin function should be

    optimize.fmin(func, x0=[y_estimate, z_estimate], args=(data))
    

Apparently (maybe I'm wrong) when you provide the array x0 (initial guess) to the optimize.fmin function, it then knows that the it will have to optimize an array with the "size" of x0. All other data you need in your function has to be given in the tuple args (in this example there is only one array in the tuple args, but it could be args=(data1, data2, ...), in which case you wouldn't need to unpack it inside the function).

Summary: the initial guess x0 is just an array; the extra arguments args is just a tuple; the function should be (literally!) defined as def func(x, *args); the array x and the tuple args can then be 'unpacked' inside the function (with y=x[0], z=x[1], ... and data1=args[0], data2=args[1], ...).

user1987501
  • 91
  • 1
  • 4
  • 1
    Minor point but I think you mean data1=args[0], data2=args[...] in your definition of func above. – pjc42 Jul 09 '15 at 00:29