Your main problem is that you put binary tests returning 1
on success in your non-linear constraint function, which expects <= 0
on success.
Your second problem is putting linear constraints in the nonlinear constraint function. This 'works', but fmincon can do some tricks with known-linear constraints, and you're not getting the benefit.
Below is the runnable example showing the results of
- The broken nonlinear-only constraints
- The fixed nonlinear-only constraints
- The combination linear/nonlinear constraints
code:
function example()
% initial conditions
x0=[1;1;1];
% linear constraint system (Ax <= b)
A = [0 -1 0;
0 1 0;
-1 0 0;
0 0 -1];
b = [-1 3 0 0]';
display('Run with broken nonlinear-only constraints');
[x,fval]=fmincon(@obj,x0,[],[],[],[],[],[],@conBroken)
display('Run with fixed nonlinear-only constraints');
[x,fval]=fmincon(@obj,x0,[],[],[],[],[],[],@conFixed)
display('Run with linear/nonlinear constraints');
[x,fval]=fmincon(@obj,x0,A,b,[],[],[],[],@conNonlin)
% oops, x(...)>0 is 1 upon success
function [c,ceq]=conBroken(x)
c=[(20*((16+x(2)^2)^.5))-100000*(x(2)*x(3)); (80*1+x(2)^2)^.5-100000*x(2)*x(3); -x(2)+3; -x(2)+1; x(3)>0; x(1)>0];
ceq=[];
% good, -x(...) <= 0 when x>0
function [c,ceq]=conFixed(x)
c=[(20*((16+x(2)^2)^.5))-100000*(x(2)*x(3)); (80*1+x(2)^2)^.5-100000*x(2)*x(3); -x(2)+3; -x(2)+1; -x(3); -x(1)];
ceq=[];
% moved linear constraints to where they should be
function [c,ceq]=conNonlin(x)
c=[(20*((16+x(2)^2)^.5))-100000*(x(2)*x(3)); (80*1+x(2)^2)^.5-100000*x(2)*x(3);];
ceq=[];
% objective function
function f=obj(x)
f=x(1)*((16+x(2)^2)^.5)+x(3)*((1+x(2)^2)^.5);
Which gives the following results:
Run with broken nonlinear-only constraints -- violates the x>0 constraint
Solver stopped prematurely.
fmincon stopped because it exceeded the function evaluation limit,
options.MaxFunEvals = 3000 (the default value).
x =
-23.3480
6.3806
0.0470
fval =
-175.5250
Run with fixed nonlinear-only constraints -- moving slowly in the right direction
Solver stopped prematurely.
fmincon stopped because it exceeded the function evaluation limit,
options.MaxFunEvals = 3000 (the default value).
x =
0.1893
1.8200
0.5598
fval =
1.9947
Run with linear/nonlinear constraints -- works!
Local minimum found that satisfies the constraints.
Optimization completed because the objective function is non-decreasing in
feasible directions, to within the default value of the function tolerance, and
constraints are satisfied to within the default value of the constraint tolerance.
x =
0.0000
1.9993
0.0004
fval =
0.0010
The lesson is: always provide your linear constraints separately, so the magic can happen.
20*sqrt((...
– Matthew Gunn