3

I'm trying to minimize a non-linear objective function (my actual function is much more complicated than that, but I found that even this simple function illustrates the point), where I know that minimum is obtained at the initial point x0:

fun = @(x) x(1)^2+x(2)^2;
x0 = [0 0];
lb1 = [0 0];
lb2 = [-1 -1];

[xc1 fvalc1] = fmincon(fun, x0, [],[],[],[], lb1, [Inf Inf])

Which outputs:

>> xc1 = 1.0e-03 * [0.6457    0.6457]
>> fvalc1 = 8.3378e-07

However, both using a different lower bound or using fminsearch instead work correctly:

[xc2 fvalc2] = fmincon(fun, x0, [],[],[],[], lb2, [Inf Inf])
>> xc2 = [0     0]
>> fvalc2 =  0

[xs fvals] = fminsearch(fun, x0)
>> xs =  [0     0]
>> fvals =   0

What goes wrong in the first fmincon call?

MMG
  • 2,962
  • 5
  • 8
  • 35
bonifaz
  • 578
  • 3
  • 14

1 Answers1

5

We can diagnose this using the output output argument as specified in the docs

[xc1, fvalc1, ~, output] = fmincon(fun, x0, [],[],[],[], lb1, [Inf Inf])

The value output.stepsize is the final step size taken in the iterative solving process. In this case:

output.stepsize
>> ans = 6.586e-4

The estimated minima was at x = [6.457e-4, 6.457e-4] and the lower bounds you've permitted are [0 0], so the solver is not permitted to take another step! Another step would give x = [-1.29e-5, -1.29e-5] which is outside of the boundaries.

When you allow the lower bounds to be [-1, -1] the solver can over-shoot the minimum and approach it from all directions.


Moreover, we can use the options input to get even better insight!

options.Display = 'iter';
[xc1, fvalc1, ~, output] = fmincon(fun, x0, [],[],[],[], lb1, [Inf Inf], [], options);

Printed to the command window we see this:

Your initial point x0 is not between bounds lb and ub; FMINCON
shifted x0 to strictly satisfy the bounds.

                                            First-order      Norm of
 Iter F-count            f(x)  Feasibility   optimality         step
    0       3    1.960200e+00    0.000e+00    9.900e-01
    1       6    1.220345e-02    0.000e+00    8.437e-01    1.290e+00
    2       9    4.489374e-02    0.000e+00    4.489e-02    1.014e-01
    3      12    1.172900e-02    0.000e+00    1.173e-02    1.036e-01
    4      15    3.453565e-03    0.000e+00    3.454e-03    4.953e-02
    5      18    1.435780e-03    0.000e+00    1.436e-03    2.088e-02
    6      21    4.659097e-04    0.000e+00    4.659e-04    1.631e-02
    7      24    2.379407e-04    0.000e+00    2.379e-04    6.160e-03
    8      27    6.048934e-05    0.000e+00    6.049e-05    7.648e-03
    9      30    1.613884e-05    0.000e+00    1.614e-05    3.760e-03
   10      33    5.096660e-06    0.000e+00    5.097e-06    1.760e-03
   11      36    2.470360e-06    0.000e+00    2.470e-06    6.858e-04
   12      39    8.337765e-07    0.000e+00    8.338e-07    6.586e-04

So your x0 is invalid! This is why the solver doesn't return the result with 1 iteration and lower bounds of [0 0].

fminsearch also works for the same reason - you've not imposed a lower bound on which the solution sits.

Wolfie
  • 21,886
  • 7
  • 23
  • 50
  • Why is `x0=[0 0]` not within the lower bound `lb=[0 0]`? No matter the floating point representation, it should be within. – bonifaz Mar 05 '18 at 12:20
  • 1
    It is not *between* the bounds, i.e. `lb < x0 < ub`. You can have a solution which sits on the boundary (although as you've seen above, the step size will dictate how close you get), but the intial guess has to be between them for the solver to work as I assume it's based on 3 *unique* points. Notably, the default method is `'interior-point'`, the clue is in the name. – Wolfie Mar 05 '18 at 12:25