(1) A.B.Aeq.Beq和线性规划一样。C.Ceq则是独特的非线性约束,其中C代表非线性不等式约束,Ceq代表非线性等式约束。由于非线性规划的目标函数可能为非线性函数,所以要定义为函数,传入参数时只需传入:“函数名” 即可。
(2) 传入参数NONLCON为非线性约束的:“函数名”形式。函数返回值为[g,h],其中g为非线性不等式约束,如若有不等式函数fd(1) fd(2)…fd(n),则定义g(1)=fd(1) g(2)=fd(2) g(n)=fd(n)。其中h为等式约束,h(1) h(2)…h(n)与fd(i)同理。如若C(x)或者Ceq(x)右端有常数项,则移项到左边即可转换为标准形式。
(3) X0代表的是变量X的初始值,可以使用rand函数随机生成,fmincon函数默认从x0为中心开始搜索,直至找到函数的最小值,并返回距离x0最近的函数最小值对应的x值,在计算的时候就预先判定函数最小值的对应的x值的大概范围,以确保我们定的初值x0在所求的x附近,可减少计算量。
(4) 如若目标函数为非线性函数,但约束都为线性函数。线性约束可以在NONLCON中定义,但是要转换为此类约束形式,即右边常数项要移动到左边。除了定义在NONLCON中,也可也直接定义在线性约束A B Aeq Beq中,将参NONLCON传入[]即可。任何变量在使用之前都需要定义。所以如果返回z,不可以使用循z=z+x(i)来给z赋值。因为我们默认z为0,但其实它没有定义是不可以用的。需要在前面加上z=0;
(1) 二次规划定义如图所示。
(2) 需要注意的是形式中x’Hx部分可以结合出任意x(i)^2,也可也结合出任意x(i)*x(j),但是不可以凑出单项x(i),所以用f’x来表示单项的x(i)。f(i)为目标函数中x(i)的系数。而H矩阵中H(i,j)为x(i)*x(j)的系数(i!=j),H(i,i)的系数为x(i)*x(i)的系数的两倍。可参考文章内容:H矩阵求法。
(3) 二次规划使用H和f参数矩阵定义目标函数,所以不用额外写函数。需要注意的是f(i)表示x(i)的系数,不同f(i)之间用“;”分割。即f分割方式和b分割方式一样单一。
(1) 整数规划定义如下图所示。
(2) 特殊的0-1规划求解方法:
可能不精准的计算:设"0-1"变量为x1 x2…xn,则排列组合共有pow(2,n)种可能,即总共有pow(2,n)种待定解(不确定是否为可行解)。如果求可行解,只需要带入每一种可能看是否满足约束即可,但是我们要求的是最优解,如何求最优解?很简单,整数非线性规划就是比非线性规划多了整数要求,所以我们在非线性等式约束中定义整数条件即可。如x(1) x(2) … x(n) 为整数,则定义 h(1)=x(1)(x(1)-1) h(2)=x(2)(x(2)-1) h(n)=x(n)*(x(n)-1)。可通过循环多次提高可靠度,不过x0取值要更新必须非周期性才可以。
精准计算: 还有另一种方法就是如下的隐枚举法,即把每种排列组合的情况带入表达式,求出值作为约束条件,第二种方法已经排列组合出所有的情况,可以不使用现有函数,而自定义函数来检验约束条件,满足则比较最值而后据情况看是否更新,可得最终准确结果。
(3) 额外。当不适用系统函数时,就没有所谓的标准形式。可以以最大值为目标,当且仅当使用系统函数时有标准形式且需要注意转换。
.
%传入n,返回[2^n,n]的矩阵,矩阵每行为n为二进制数,二进制数皆不相同(即是排列组合的结果)
function [out]=bin_listg1(nsize)
n=2^nsize;
w=zeros(n,nsize);
for i=1:n
%bitget(x,a:b)返回十进制数x的二进制从右往左第a位到第b位的行向量。
w(i,:)=bitget(i-1,nsize:-1:1);
end
out=w;
end
% bin_listg1(2)
%
% ans =
%
% 0 0
% 0 1
% 1 0
% 1 1
function [g,h]=f2(x)
%常规线性或非线性约束
g(1)=x(1)+2*x(2)-x(3)-2;
g(2)=x(1)+4*x(2)+x(3)-4;
g(3)=x(1)+x(2)-3;
g(4)=4*x(2)+x(3)-6;
len=size(x,1);
n=2^len;
w=zeros(n,len);
%得到所有0-1变量枚举值
for i=1:n
w(i,:)=bitget(i-1,len:-1:1);
end
k=zeros(n,1);
for i=1:n
%计算枚举情况的值
k(i)=3*w(1)-2*w(2)+5*w(3);
%目标函数计算
g(i)=-3*x(1)+2*x(2)-5*x(3);
%枚举约束=目标函数-枚举情况的值
g(i)=g(i)-k(i);
end
%整形变量的设置
h(1)=x(1)*(x(1)-1);
h(2)=x(2)*(x(2)-1);
h(3)=x(3)*(x(3)-1);
end
(1) 随机取样定义如下图所示。
(2) 由于非0-1的整数规划,整数取值范围太大,如a<=x(i)<=b,设有n个变量,则排列组合有pow((b-a),n)种可能,当(b-1)超过10时就已经非常大了,所以常常不可取。那么如何求解呢?只能随机取样计算。即我们枚举不出所有的自变量组情况了,那只能大量枚举构建出部分的自变量组情况,所以求得的解往往不稳定(每次求得的解不同),也即往往求得的是局部解。
(3) 准确性判断:
根据pwo((b-a),n)可以判断出总可能情况,所以如果枚举k次,每次因取整枚举了两种情况,则共枚举2* k种情况。设枚举的重复率为j,则枚举了所有情况的 2k(1-j) / pow( (b-a),n )。
(4) 随机取样过程:
【1】编写函数传入变量矩阵x返回[f,g],f表示目标函数值,g(1) g(2) … g(n)表示右端为0的常数项不等式约束的计算值。
【2】使用rand生成随机取样的矩阵。要根据变量矩阵x的特点,如范围来随机生成构建矩阵x。然后对x矩阵进行向下取整和向上取整floor(x)和ceil(x)得到整数矩阵。
【3】对得到的两个矩阵依次进行:计算并保存函数值[f,g],判断g种约束是否都成立,sum(g<=0)==g约束数目。根据所求最大或者最小值,判断f是否更新p0,判断x1或者x2是否更新x0。
【4】循环结束后输出x0,p0。如下图所示
clc
rand('state',sum(clock));
p0=0;
tic
for i=1:10^6
x=99*rand(5,1);
x1=floor(x);
x2=ceil(x);
[f,g]=f2(x1);
if (sum(g<=0))==4
if f>p0
p0=f;
x0=x1;
end
end
[f,g]=f2(x2);
if (sum(g<=0))==4
if f>p0
p0=f;
x0=x2;
end
end
end
x0
p0
toc
function [z,g]=f2(x)
z=(x(1)^2+x(2)^2+3*x(3)^2+4*x(4)^2+2*x(5)^2-8*x(1)-2*x(2)-3*x(3)-x(4)-2*x(5));
g(1)=sum(x)-400;
g(2)=x(1)+2*x(2)+2*x(3)+x(4)+6*x(5)-800;
g(3)=2*x(1)+x(2)+6*x(3)-200;
g(4)=x(3)+x(4)+5*x(5)-200;
end
(5) 额外知识:
ceil函数的作用是朝正无穷方向取整,即将m/n的结果向正无穷方向取整,如m/n=3.12,则ceil(m/n)的结果为4。
matlab中的floor意思是“向下取整”,即取不大于x的最大整数,与“四舍五入”不同,下取整直接取按照数轴上最接近要求值的左边值,即不大于要求值的最大的那个整数值。
tic 是开始一个秒表计时器;toc是计算现在到tic所开始的计时器的时间间隔,单位是秒(S)。可以在MATLAB命令框中输入 start = tic过一会再输入toc(start),就可以得到这段时间间隔。如果有多个tic,就需要在tic刚开始时,在右侧定义不同的变量,并在toc()中明确指出计算那个时间间隔。
rand(‘state’,sum(100*clock))定义随时间变化的初值
eg:
start1 = tic;
start2 = tic;
toc(start1)
toc(start2)
%就可以分别得到tic到此时的时间间隔。