I wanted to solve a constrained minimization problem using fmincon. But the constraints are defined in terms of a function like f(x_0)<a, where x_0 is a solution to the problem. Is it possible?
On the docs, the example only include this x_0<a form.
Code:
f_obj = #(x)var_zcors(x,t_cw);
opt_theta = fminbnd(f_obj,0,360);
Now, x should constrained such that f_constraint(x)< a.
Update(From answer by #Phil Goddard):
f_obj = #(x)var_zcors(x,t_cw);
f_nl = #(x)deal(f_constraint(x)-a,[]);
x0 = 180; % or whatever is appropriate
opt_theta = fmincon(f_obj,x0,[],[],[],[],0,360,f_nl);
Say in the above code f_constraint returns a vector [x_min y_max] instead of a scalar. And I want to specify the following constraints:
x_min>b
y_max<a
What is a possible way to achieve that?
You have a nonlinear constraint and hence need to use the nonlinear constraint input to fmincon. That is,
f_obj = #(x)var_zcors(x,t_cw);
f_nl = #(x)deal(f_constraint(x)-a,[]);
x0 = 180; % or whatever is appropriate
opt_theta = fmincon(f_obj,x0,[],[],[],[],0,360,f_nl);
If you have multiple (non-linear) constraints, then as per the examples in the doc, you write a function to return a vector of constraints. In your case you want to write a function in a separate file like the following:
function [c,ceq] = my_nonlinear_constraints(x,ab)
% define the non-linear inequality constraints
% (This assumes that ab is a 2 element vector containing your a and b
% variables.)
[x_min,y_max] = f_constraint(x);
c = nan(2,1);
c(1) = -x_min+ab(2); % this is x_min>b
c(2) = y_max-ab(1); % this is y_max<a
% There are no non-linear equality constraints, but this is required
ceq = [];
Then, to perform the optimization, you want
% Variables a and b must be defined prior to this.
f_obj = #(x)var_zcors(x,t_cw);
f_nl = #(x)my_nonlinear_constraints(x,[a b]);
x0 = 180; % or whatever is appropriate
opt_theta = fmincon(f_obj,x0,[],[],[],[],0,360,f_nl);
Related
When I implement such MATLAB codes to do convex optimization (the following example is similar to MATLAB official docs from here):
function [xsol,fval,history,searchdir] = runfmincon
clear;clc;
% Set up shared variables with outfun
history.x = [];
history.fval = [];
searchdir = [];
% Call optimization
x0 = [0.1 0.1];
options = optimoptions(#fmincon,'OutputFcn',#outfun,...
'Algorithm','interior-point','Display','iter');
[xsol,fval] = fmincon(#objfun,x0,[],[],[],[],[],[],#confun,options);
function stop = outfun(x,optimValues,state)
stop = false;
switch state
case 'init'
hold on
case 'iter'
% Concatenate current point and objective function
% value with history. x must be a row vector.
history.fval = [history.fval; optimValues.fval];
history.x = [history.x; x];
% Concatenate current search direction with
% searchdir.
searchdir = [searchdir;...
optimValues.searchdirection'];
plot(x(1),x(2),'o');
% Label points with iteration number and add title.
% Add .15 to x(1) to separate label from plotted 'o'.
text(x(1)+.15,x(2),...
num2str(optimValues.iteration));
title('Sequence of Points Computed by fmincon');
case 'done'
hold off
otherwise
end
end
function f = objfun(x)
f = -x(1)*x(2);
end
function [c, ceq] = confun(x)
% Nonlinear inequality constraints
c = [x(1)^2 + x(2)^2 -1];
% Nonlinear equality constraints
ceq = [];
end
end
When I run the code above, an error occurs:
出错 barrier
出错 fmincon (line 834)
[X,FVAL,EXITFLAG,OUTPUT,LAMBDA,GRAD,HESSIAN] = barrier(funfcn,X,A,B,Aeq,Beq,l,u,confcn,options.HessFcn, ...
出错 runfmincon (line 15)
[xsol,fval] = fmincon(#objfun,x0,[],[],[],[],[],[],#confun,options);
Plus, other methods, like sqp and active-set, work fine, ONLY interior-point leads to an error.
I have checked the initial point, I have NOT found any problems.
How to solve that? Please help me!!! Thanks!!!
Oh! I solved it!!! When implementing the interior-point method, just delete the parameter searchdir, and the codes corresponding to it—while for the sqp or active-set methods, keeping this parameter does not pose any problem.
I want to use MATLABs fmincon function to solve a non-linear problem of which I know that it can be solved in a different way very easily but I want to use fmincon (you might not need the following detailed information about the problem but I provided them in case you need):
Function f(x) is a quadratic function with its vertex at point (5|1).
f(x)=0.1(x-5)^2+1 for 0<=x<=5
Function g(x) is a polynom of order 4 with its vertex at Point (c|0).
g(x)=(x-c)^4 for 0<=x<=c
Function h is just a line on the x axis.
h=0 for c<=x<=5
I want to minimize the Area between the function f(x) and the two connected functions g(x) and h, in the interval [0,5]
minimize A=2*(int(f,[0,5])-int(g,[0,c]))=55/3 - (2*c^5)/5
Also I have the constraint that f(x) must always be 1 unit above the functions g(x) and h.
From the graph I know that the variable c must be between 0 and 2 (just a range for the fmincon function).
This is my .m file:
clc
clear
format long;
options = optimoptions(#fmincon, 'Display', 'iter', 'Algorithm', 'interior-point');
fun=#(x)55/3 - (2*(x(1))^5)/5;
lb = [0];
ub = [2];
[x,fval] = fmincon(fun,[0.1],[],[],[],[],lb,ub,#cons_Q6,options)
The constraints file looks like this (I inserted a lot of values for x with an increment of 0.1):
function [c,ceq]=cons_Q6(x)
c=[(0.0-x(1))^4-0.1*(0.0-5)^2
(0.1-x(1))^4-0.1*(0.1-5)^2
(0.2-x(1))^4-0.1*(0.2-5)^2
(0.3-x(1))^4-0.1*(0.3-5)^2
(0.4-x(1))^4-0.1*(0.4-5)^2
(0.5-x(1))^4-0.1*(0.5-5)^2
(0.6-x(1))^4-0.1*(0.6-5)^2
(0.7-x(1))^4-0.1*(0.7-5)^2
(0.8-x(1))^4-0.1*(0.8-5)^2
(0.9-x(1))^4-0.1*(0.9-5)^2
(1.0-x(1))^4-0.1*(1.0-5)^2
(1.1-x(1))^4-0.1*(1.1-5)^2
(1.2-x(1))^4-0.1*(1.2-5)^2
(1.3-x(1))^4-0.1*(1.3-5)^2
(1.4-x(1))^4-0.1*(1.4-5)^2
(1.5-x(1))^4-0.1*(1.5-5)^2
(1.6-x(1))^4-0.1*(1.6-5)^2
(1.7-x(1))^4-0.1*(1.7-5)^2
(1.8-x(1))^4-0.1*(1.8-5)^2
(1.9-x(1))^4-0.1*(1.9-5)^2
(2.0-x(1))^4-0.1*(2.0-5)^2
(2.1-x(1))^4-0.1*(2.1-5)^2
(2.2-x(1))^4-0.1*(2.2-5)^2
(2.3-x(1))^4-0.1*(2.3-5)^2
(2.4-x(1))^4-0.1*(2.4-5)^2
(2.5-x(1))^4-0.1*(2.5-5)^2
(2.6-x(1))^4-0.1*(2.6-5)^2
(2.7-x(1))^4-0.1*(2.7-5)^2
(2.8-x(1))^4-0.1*(2.8-5)^2
(2.9-x(1))^4-0.1*(2.9-5)^2
(3.0-x(1))^4-0.1*(3.0-5)^2
(3.1-x(1))^4-0.1*(3.1-5)^2
(3.2-x(1))^4-0.1*(3.2-5)^2
(3.3-x(1))^4-0.1*(3.3-5)^2
(3.4-x(1))^4-0.1*(3.4-5)^2
(3.5-x(1))^4-0.1*(3.5-5)^2
(3.6-x(1))^4-0.1*(3.6-5)^2
(3.7-x(1))^4-0.1*(3.7-5)^2
(3.8-x(1))^4-0.1*(3.8-5)^2
(3.9-x(1))^4-0.1*(3.9-5)^2
(4.0-x(1))^4-0.1*(4.0-5)^2
(4.1-x(1))^4-0.1*(4.1-5)^2
(4.2-x(1))^4-0.1*(4.2-5)^2
(4.3-x(1))^4-0.1*(4.3-5)^2
(4.4-x(1))^4-0.1*(4.4-5)^2
(4.5-x(1))^4-0.1*(4.5-5)^2
(4.6-x(1))^4-0.1*(4.6-5)^2
(4.7-x(1))^4-0.1*(4.7-5)^2
(4.8-x(1))^4-0.1*(4.8-5)^2
(4.9-x(1))^4-0.1*(4.9-5)^2
(5.0-x(1))^4-0.1*(5.0-5)^2
];
ceq=[];
As you can see, I've set the bounds for the unknown variable so that x(1)=[0,2] and I have set the constraints in the range [0,5] although I would only need them in the range of [0,2] because of the bounds for x(1).
Now, when I solve it like this I get a solution that doesn't fit all the constraints. But when I delete the unneccessary constraints in the range ]2;5]
function [c,ceq]=cons_Q6(x)
c=[(0.0-x(1))^4-0.1*(0.0-5)^2
(0.1-x(1))^4-0.1*(0.1-5)^2
(0.2-x(1))^4-0.1*(0.2-5)^2
(0.3-x(1))^4-0.1*(0.3-5)^2
(0.4-x(1))^4-0.1*(0.4-5)^2
(0.5-x(1))^4-0.1*(0.5-5)^2
(0.6-x(1))^4-0.1*(0.6-5)^2
(0.7-x(1))^4-0.1*(0.7-5)^2
(0.8-x(1))^4-0.1*(0.8-5)^2
(0.9-x(1))^4-0.1*(0.9-5)^2
(1.0-x(1))^4-0.1*(1.0-5)^2
(1.1-x(1))^4-0.1*(1.1-5)^2
(1.2-x(1))^4-0.1*(1.2-5)^2
(1.3-x(1))^4-0.1*(1.3-5)^2
(1.4-x(1))^4-0.1*(1.4-5)^2
(1.5-x(1))^4-0.1*(1.5-5)^2
(1.6-x(1))^4-0.1*(1.6-5)^2
(1.7-x(1))^4-0.1*(1.7-5)^2
(1.8-x(1))^4-0.1*(1.8-5)^2
(1.9-x(1))^4-0.1*(1.9-5)^2
(2.0-x(1))^4-0.1*(2.0-5)^2
];
ceq=[];
then I get the right result. Does anyone know why this happens and why MATLAB does not respect the constraints when I put them up for the whole range [0,5]?
-Your problem is more related to calculus than matlab tool
constraints like
function [c]=cons_Q6(x)
c=[x < 0; x > 0]; are just ignored by fmincon, because they are not logical
Technically you need to know the optimum c before solving
this optimization problem
- Another issue A = int(f,[0,5])-int(g,[0,c]) = 55/6 - c^5/5 instead of
A = 2*(int(f,[0,5])-int(g,[0,c])) = 55/3 - (2*c^5)/5
Factor 2 is used whether for even whether for odd function (like cosine or since).
Even for those kind of function the integration interval is reduced by half
I updated your optimization function and the solution c is as follow
x = [0, c], constraint is g(x)-f(x)-1<= 0--> (x-c)^4 -0.1(x-5)^2 <=0
x = [c, 5], constraint is h(x)-f(x)-1<= 0--> -0.1(x-5)^2 <=0
c must be predefined or guessed in advance, here I supposed c = 2
because your upper bound ub = 2
As a result
x = [0, 2], --> (x-c)^4 -0.1(x-5)^2 <=0
x = [2, 5], --> -0.1(x-5)^2 <=0
cons_Q6(x) is as follow
function [c,ceq]=cons_Q6(x)
c=[(0.0-x)^4-0.1*(0.0-5)^2;
(0.1-x)^4-0.1*(0.1-5)^2;
(0.2-x)^4-0.1*(0.2-5)^2;
(0.3-x)^4-0.1*(0.3-5)^2;
(0.4-x)^4-0.1*(0.4-5)^2;
(0.5-x)^4-0.1*(0.5-5)^2;
(0.6-x)^4-0.1*(0.6-5)^2;
(0.7-x)^4-0.1*(0.7-5)^2;
(0.8-x)^4-0.1*(0.8-5)^2;
(0.9-x)^4-0.1*(0.9-5)^2;
(1.0-x)^4-0.1*(1.0-5)^2;
(1.1-x)^4-0.1*(1.1-5)^2;
(1.2-x)^4-0.1*(1.2-5)^2;
(1.3-x)^4-0.1*(1.3-5)^2;
(1.4-x)^4-0.1*(1.4-5)^2;
(1.5-x)^4-0.1*(1.5-5)^2;
(1.6-x)^4-0.1*(1.6-5)^2;
(1.7-x)^4-0.1*(1.7-5)^2;
(1.8-x)^4-0.1*(1.8-5)^2;
(1.9-x)^4-0.1*(1.9-5)^2;
(2.0-x)^4-0.1*(2.0-5)^2;
-0.1*(2.1-5)^2;
-0.1*(2.2-5)^2;
-0.1*(2.3-5)^2;
-0.1*(2.4-5)^2;
-0.1*(2.5-5)^2;
-0.1*(2.6-5)^2;
-0.1*(2.7-5)^2;
-0.1*(2.8-5)^2;
-0.1*(2.9-5)^2;
-0.1*(3.0-5)^2;
-0.1*(3.1-5)^2;
-0.1*(3.2-5)^2;
-0.1*(3.3-5)^2;
-0.1*(3.4-5)^2;
-0.1*(3.5-5)^2;
-0.1*(3.6-5)^2;
-0.1*(3.7-5)^2;
-0.1*(3.8-5)^2;
-0.1*(3.9-5)^2;
-0.1*(4.0-5)^2;
-0.1*(4.1-5)^2;
-0.1*(4.2-5)^2;
-0.1*(4.3-5)^2;
-0.1*(4.4-5)^2;
-0.1*(4.5-5)^2;
-0.1*(4.6-5)^2;
-0.1*(4.7-5)^2;
-0.1*(4.8-5)^2;
-0.1*(4.9-5)^2;
-0.1*(5.0-5)^2;
];
ceq=[];
The constraints in the range ]2;5] are very necessary keep them
clc
clear
format long;
options = optimoptions(#fmincon, 'Display', 'iter', 'Algorithm',...
'interior-point');
fun=#(x)55/6 - (x^5)/5;
lb = [0];
ub = [2];
[c, A] = fmincon(fun,[0.1],[],[],[],[],lb,ub,#cons_Q6,options)
solution :
c = 1.257432726024430
A = 8.537951710969493
I need some help... I have got a model function which is :
function y = Surf(param,x);
global af1 af2 tData % A2 mER2
A1 = param(1); m1 = param(2); A2 = param(3); m2 = param(4);
m = param(5); n = param(6);
k1 = #(T) A1*exp(mER1/T);
k2 = #(T) A2*exp(mER2/T);
af = #(T) sech(af1*T+af2);
y = zeros(length(x),1);
for i = 1:length(x)
a = x(i,1); T = temperature(i,1);
y(i) = (k2(T)+k1(T)*(a.^m))*((af(T)-a).^n);
end
end
And I have got a set of Data giving Cure, Cure_rate, Temperature. Which are all in a single vertical column matrix.
Basically, I tried to use :
[output,R1] = lsqcurvefit(#Surf, initial_guess, Cure, Cure_rate)
[output2,R2] = nlinfit(Cure,Cure_rate,#Surf,initial_guess)
And they works pretty well, (my initial_guess are initial guess of parameters in the above model which is in : [1.1e+07 -7.8e+03 1.2e+06 -7.1e+03 2.2 0.72])
My main problem is, when I try to look into different methods which could do nonlinear regression such as fminsearch, fmincon, fsolve, fminunc, etc. They just dont work and I am quite confused about the input that I am considering. Mainly beacuse they dont work as same as nlinfit and lsqcurvefit (input of Cure, Cure_rate), most of them considered the model function and the initial guess only, The way I did the above:
output3 = fminsearch(#Surf,initial_guess)
output4 = fsolve(#Surf,initial_guess)
output5 = fmincon(#Surf,x0,A,b,Aeq,beq)
(Not sure what should I put for Linear Inequality Constraint:
A,b and Aeq,beq )
output6 = fminunc(#Surf,initial_guess)
The problem is Matlab keep saying either I have not enough input or too many input which I don't get it and how should I include my Dataset in the fitting function (Cure, Cure_rate) in the above functions, like in nlinfit and lsqcurvefit?
Is it possible to find the nearest solution to optimal for a mixed-integer problem? For example I would want the simplified problem below:
f = [1;1;1];
intcon = 1:3;
Aeq = [0.99,0.97,0.15];
beq = 0.16;
lb = zeros(3,1);
ub = [1;1;1];
x = intlinprog(f,intcon,[],[],Aeq,beq,lb,ub)
to return x=[0;0;1] as this is the nearest integer solution to the objective value of 0.16. Instead currently it returns
Intlinprog stopped because no point satisfies the constraints.
Does not necessarily have to run intlinprog. Would ideally need to also work if beq is low, for example 0.14.
You can introduce some slack variables to allow some constraint violation when needed as follows:
largeValue = 100; % choose some large value to penalise the constraint violation
f_ = [f; largeValue; largeValue]; % penalise both slack variables
Aeq_ = [Aeq, 1, -1]; % add a positive and negative slack variable to the constraint
beq_ = beq;
lb_ = [lb; 0; 0]; % limit the constraint to a positive number
ub_ = [ub; inf; inf];
x_ = intlinprog(f_,intcon,[],[],Aeq_,beq_,lb_,ub_); % solve the adapted problem
x = x_(1:3) % extract the solution of the original problem
Remarks
I added two (positive) slack variables, one for a positive constraint violation and another one for a negative constraint violation.
You should penalise the slack variables with a large value, otherwise it is beneficial to violate your constraints more than strictly necessary. A more general approach would be to determine a good penalisation value based on the values in f and Aeq, for example
largeValue = 2*max(abs(f))/min(abs(Aeq(Aeq ~= 0)))
For two variable function, say f(x,y)=x^2+y+b, where b is:
b=raylrnd(1*sqrt(2/pi),10^6,1) %% b is 1x1000000 vector
and subject to the constraint that: 2*x+1<=b.
I want to find the maximum of the function for a interval say x is between [-10,10], and y is between [-10,10] (Off course, my actual function is more complete than this, I will need help to set up the framework so I can apply it to my actual function).
Is there a way to implement this?
Attempt:
Step 1: Write a file objfun.m.
function f = objfun(x,b)
f = x(1)^2+(2)+b;
Step 2: Write a file confuneq.m for the nonlinear constraints.
function [c, ceq] = confuneq(x)
% Nonlinear inequality constraints
c = 2*x(1)+1-b;
Step 3: Invoke constrained optimization routine.
for i=1:1:length(b)
bi=b(i);
x0 = [-1,1]; % Make a starting guess at the solution
options = optimoptions(#fmincon,'Algorithm','sqp');
[x,fval] = fmincon(#objfun,x0,[],[],[],[],[],[],...
#confuneq,options);