zell
zell

Reputation: 10204

A performance concern when using minimizing a two-parameter function with scipy

I have a 2-parameter python function

def foo(x,y):
          // a numeric operation that returns a double

I need to use scipy.optimize.minimize to locate a minimal point of f near a point, say (1.2, 3.4)

I have tried with

scipy.optimize.minimize(foo, (1.2, 3.4))

scipy.optimize.minimize(foo, [1.2, 3.4])

and

scipy.optimize.minimize(foo, *[1.2,3.4])

None of them works, yielding

TypeError: function takes exactly 2 arguments (1 given)

So my only solution seems to be wrapping the function, such as

scipy.optimize.minimize(lambda X:foo(*X), [1.2,3.4]),

The last one works, but I fear that the extra layer with the lambda term introduces unnecessary time overhead. Because my application is highly performance-sensitive, I am asking an efficient solution to let scipy.optimize.minimize accept a input pair for foo, without the potential time overhead. Any idea? Thanks.

Upvotes: 1

Views: 106

Answers (1)

lejlot
lejlot

Reputation: 66850

You should define your function in terms of a single (possibly multidimensional) argument. Thus you do not use

def foo(x,y):
      // a numeric operation that returns a double

but instead

def foo(x):
      // use x[0] in place of original x
      // and x[1] in place of original y

for example for f(x,y) = x + y^2 you use

def foo(x):
    return x[0] + x[1] ** 2

If you are not allowed to modify foo then you can always wrap it around with another function

def foowrap(x):
   return foo(x[0], x[1])

which should be slightly more efficient then unwraping list to positional arguments (* operator)

just to test

>>> timeit.timeit('foowrap([1,2])', setup='from __main__ import foowrap', number=10000000)
5.230706214904785    
>>> timeit.timeit('foo([1,2])', setup='from __main__ import foo', number=10000000) # this is your lambda term
5.379893779754639

so very small speedup, but it is.

Upvotes: 3

Related Questions