关于使用 fmincon 最小化具有复杂非线性约束的函数的一般问题

问题描述

让乐趣 = X(1)*X(2)*X(3) - X(4)*X(5) + X(1)^(2)

参数向量 X = [X(1),X(2),X(3),X(4),X(5)]

约束:

  1. X(1) > 0;
  2. X(1)-(X(4)*X(3))
  3. X(4)X(3)(X(2)-((1-X(3))/2))

当约束更简单时,我可以根据情况制作适当的 A,b,Aeq,beq,lb,ub,nonlcon 向量或矩阵。但是当约束很复杂时如何处理。

解决方法

您可以使用惩罚法作为解决任何约束问题的一般方法。网络上有很多关于 this 等惩罚方法的信息。

,

您可以修改您的函数,以便在每次违反约束时添加一个大值。这并不优雅,但会很容易。每个约束都被反转,如果约束的逆为真,则将 10^6 添加到函数返回值。我试过这个方法。它不能很好地工作,可能是因为函数中的不连续性导致内置例程 fmincon() 出现问题。以下是不该做的事情:

function Z = frbeginner2(x)
%FRBEGINNER2 Function to minimize
%   x(1:5) = model parameters
%   Function frbeginner2() is to be minimized subject to constraints
Z=x(1)*x(2)*x(3)-x(4)*x(5)+x(1)^2 ...
    +1e6*(x(1)<=0) ...
    +1e6*(x(1)-(x(4)*x(3))>x(2)) ...
    +1e6*(x(2)>(2-x(3))/3) ...
    +1e6*(x(4)*x(3)*(x(2)-((1-x(3))/2))>x(1)*(x(2)-x(1)+(x(4)*x(3))));
end

一个更好的解决方案是阅读关于 fmincon() 的 Matlab 帮助。它有一个可选参数 nonlcon,它是一个函数的名称,该函数返回 2 个数组,cceq:不等式约束(如果有),以及等式约束的方程值(如果有)。第一个约束 x(1)>0 是通过将 x(1) 的下限设置为 0 来实现的,函数 frbeginCon() 负责处理其他约束。没有等式约束,所以 ceq 返回 0 的值。我尝试使用下面的函数为 nonlcon 调用 fmincon(),并且对于许多随机起点都取得了不错的结果。

function [c,ceq] = frbeginCon(x)
%FRBEGINCON Constraints specified by rbeginner on stack overflow,2021-01-15
%   x1..x5 = model parameters
%   These are the constarints on function frbegin0().
%   Constraints: 
%   1. X(1) > 0;     %handle this constraint by set lb(1)=0
%   2. X(1)-(X(4)*X(3)) <= X(2) <= (2-X(3))/3;
%   3. X(4)X(3)(X(2)-((1-X(3))/2)) <= X(1)(X(2)-X(1)+(X(4)*X(3)));
%   Convert each constraint to equation that is <=0 when constraint is met.
%   2a. X(1)-X(4)*X(3)- X(2) <= 0
%   2b. X(2) - (2-X(3))/3 <=0
%   3.  X(4)*X(3)*(X(2)-((1-X(3))/2)) - X(1)*(X(2)-X(1)+X(4)*X(3)) <= 0
    x1=x(1); x2=x(2); x3=x(3); x4=x(4); x5=x(5);
    c=[x1-x2-x4*x3,x2-(2-x3)/3,x4*x3*(x2-((1-x3)/2))-x1*(x2-x1+x4*x3)];
    ceq=0;

end 

最小化函数就是

function z = frbegin(x)
%FRBEGIN Function specified by rbeginner on stack overflow,2021-01-15
%   x1..x5 = model parameters
%   Minimize function frbegin() subject to constraints.
    z=x(1)*x(2)*x(3)-x(4)*x(5)+x(1)^2;
end
,

谢谢大家的帮助。我走上了@Erwin Kalvelagen 建议的道路。对于其他人来说,这也是一个非常好的方法。我就是这样做的

创建一个空问题

prob1 = optimproblem

定义有边界的优化变量

    x1 = optimvar("x1","LowerBound",0);
x2        = optimvar("x2","UpperBound",1);
x3     = optimvar("x3",0);
x4      = optimvar("x4",1);
x5     = optimvar("x5",1);

创建目标函数

edit function

创建优化表达式

obj = fcn2optimexpr(@function,x1,x2,x3,x4,x5)

分配目标函数

prob1.Objective = obj

设置约束

constr1 = x1 - (x4*x3) - x2 <=0;
prob1.Constraints.optim1 = constr1;
constr2 = x2 - ((2-x3)/3) <=0;
prob1.Constraints.optim2 = constr2;
constr3 = (x4*(x3))*(x2-((1-x3)/2))-(x1*(x2-x1+(x4*x3)))<=0;
prob1.Constraints.optim3 = constr3;

再看问题检查

showproblem(prob1)

设置初始条件

x0.x1 = 0.01;
x0.x2 = 0.15;
x0.x3 = 0.20;
x0.x4 = 0.20;
x0.x5 = 0.5;

解决问题

[sol,fval,exitflag] = solve(prob1,x0)

希望这会有所帮助。谢谢@Mansour Torabi,尤其是@rosewc 的帮助。