2

I would like to find a local maximum of a function f(x) where x can range between two fixed values since f(x) would tend to +inf if x tends to +inf. I've been trying to use such algorithms as scipy.optimize.fmin_l_bfgs_band scipy.optimize.fmin_tnc (from scipy.ref guide) but I can't figure out how to correctly set the bounds. (I know, it must be something stupid but I'm quite a noob with Python). Let's give an easy example:

>>>import scipy.optimize as opt  
>>>import scipy  
>>>from numpy import *  

>>>def f (x): return x**(1/2.0)  
>>>max_x = opt.fmin_l_bfgs_b(lambda x: -f(x), [0,0], bounds=([0,0],[9,0])) #I want x to range between 0 and 9 and fmax be 3

The output is pretty strange, though: I get nothing at all! Not even an error! What am I missing?

9
  • 1
    What does >>> max_x <enter> say? Commented May 27, 2013 at 22:23
  • Note that max_x will be a 3-tuple as per the docs... The 3rd element will also give some information as to progress Commented May 27, 2013 at 22:25
  • Try Newton's method on the function's derivative several times to find critical points on the function. One of those critical points should be the maximum. This assumes that the function is sufficiently well-behaved. Commented May 27, 2013 at 22:26
  • Surely the function -sqrt(x) has no local maxima? Commented May 27, 2013 at 22:34
  • Your function is 1-dimensional, but you're trying to use 2-d initial guess and bounds. That's suspicious. Commented May 27, 2013 at 22:50

2 Answers 2

4

The bounds argument goes [(lower1,upper1),(lower2,upper2)], not [(lower1,lower2),(upper1,upper2)]. If you look at your result (max_x) you will see "ERROR: NO FEASIBLE SOLUTION", which I am guessing is because your bounds specify an empty set.

Here is a correct way to call the function. I assume the square root is just an example. I used -x**2 instead.

import scipy.optimize as opt
import scipy
from numpy import *
def f(x):
    print x
    return -x**(2)

max_x = opt.fmin_l_bfgs_b(lambda x: -f(x), 1.0, bounds=[(-9,9)],approx_grad=True)

Because you are not specifying a gradient function, you need to set approx_grad=True. The 1.0 is my initial guess for the maximum (although it is obviously zero for this example). I added a print statement so I can see each time the function is called, but that's normally not necessary. For more details on different ways to call fmin_l_bfgs_b, see here.

The above code results in:

[ 1.]
[ 1.]
[ 1.00000001]
[-0.99999999]
[-0.99999999]
[-0.99999998]
[ 0.001]
[ 0.001]
[ 0.00100001]
[ -5.01108742e-09]
[ -5.01108742e-09]
[  4.98891258e-09]

And max_x looks like this:

(array([ -5.01108742e-09]),
 array([  2.51109971e-17]),
 {'funcalls': 4,
  'grad': array([ -2.21748344e-11]),
  'task': 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL',
  'warnflag': 0})
Sign up to request clarification or add additional context in comments.

2 Comments

Well, it's great! Your code is working perfectly! Actually, I was a bit doubtful about the bounds argument, I thought I had tried all the combinations between those values but it looks as if I hadn't! Just one last question: how can I use separately the fmin value I get among the max_x results? I mean, I would like to use fmin for other calculations: let's say, multiply it by two (in your example still zero, though). Can I do that?
The returned value is a standard Python data structure called a tuple, which is similar to a list except that it's immutable. If you look at the link in my answer, under "returns" you'll see three labelled objects, x, f, and d. These correspond to the three items in the returned tuple. You can access the first one, labelled "x" in the linked doc, as max_x[0]. Note that it is a numpy array and not a simple float. You can get at the elements of a numpy array in the same way. For example, max_x[0][0] is the first element in your (potentially multivariate) optimal point.
4

Why are you using multivariate minimizers? Try scipy.optimize.fminbound.

max_x = opt.fminbound(lambda x: -f(x), 0, 9)

1 Comment

To be honest, I didn't know this particular function! (scipy.optimize.fminbound) However, it works as well: I'll keep that in mind for quick evaluations of min/max, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.