How to pass max iterations to fmin in scipy brute optimization

Viewed 1053

I am trying to do a brute force optimization in SciPy.

(imported scipy.optimize as spo)

res_brute = spo.brute(self.minimize_this, rranges, full_output=True, finish=spo.fmin)

My question is: How do I make sure spo.fmin stops after N iterations? I can't seem to pass it any arguments.

1 Answers

brute doesn't have an option to pass additional arguments to the minimization function, so to override the default behavior, you'll have to create a wrapper of fmin and in the wrapper, set the maxiter argument. The wrapper is then passed to brute as the finish argument.

For example, suppose we want the minimum of

def func(x):
    return np.cos(3*x) + 0.25*(x-5)**2

on the interval [0, 10], and we want to limit the maximum number of iterations of fmin to 4. Here's how that can be done (in an ipython session).

First, the imports:

In [102]: import numpy as np

In [103]: from scipy.optimize import brute, fmin

Define the objective function:

In [104]: def func(x):
     ...:     return np.cos(3*x) + 0.25*(x-5)**2
     ...: 

Call brute, using a lambda expression for the finish argument. The lambda expression just passes its arguments on to fmin, along with full_output=True and maxiter=4. (Instead of a lambda expression, you could define a separate function that does the same thing.)

In [110]: brute(func, [slice(0, 10, 0.1)], finish=lambda func, x0, args=(): fmin(func, x0, args, full_output=True, maxiter=4))
Warning: Maximum number of iterations has been exceeded.
Out[110]: array([ 5.2325])

For comparison, here's the result when maxiter=100:

In [111]: brute(func, [slice(0, 10, 0.1)], finish=lambda func, x0, args=(): fmin(func, x0, args, full_output=True, maxiter=100))
Optimization terminated successfully.
         Current function value: -0.986810
         Iterations: 13
         Function evaluations: 26
Out[111]: array([ 5.2235498])

And when we don't use maxiter in the call to fmin in the lambda expression:

In [112]: brute(func, [slice(0, 10, 0.1)], finish=lambda func, x0, args=(): fmin(func, x0, args, full_output=True))
Optimization terminated successfully.
         Current function value: -0.986810
         Iterations: 13
         Function evaluations: 26
Out[112]: array([ 5.2235498])

As expected, that result is the same as not overriding finish:

In [113]: brute(func, [slice(0, 10, 0.1)])
Out[113]: array([ 5.2235498])
Related