建模算法(二)——整数规划
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
建模算法(⼆)——整数规划
⼀、概述
1、定义:规划中变量部分或全部定义成整数是,称为整数规划。
2、分类:纯整数规划和混合整数规划。
3、特点:
(1)原线性规划有最优解,当⾃变量限制为整数后:
a、原最优解全是整数,那最优解仍成⽴
b、整数规划没有可⾏解
c、有可⾏解,但是不是原最优解
4、求解⽅法分类
(1)分⽀定界法
(2)割平⾯法
(3)隐枚举法
(4)匈⽛利法
(5)蒙特卡洛法
⼆、分⽀定界法
1、算法如下(求解整数规划最⼤化问题)
MATLAB实现
function r=checkint(x)
%判断x(i)是不是整数了。
是的话r(i)返回1,不是的话,返回0
%输⼊参数:x X向量
%输出参数:r R向量
for i=1:length(x)
if(min(abs(x(i)-floor(x(i))),abs(x(i)-ceil(x(i))))<1e-3)
r(i)=1;
else
r(i)=0;
end
end
function val=isrowinmat(arow,mat)
%⽤来判断mat中是否包含与arow⼀样的向量
%输⼊变量:arow 向量
% mat 矩阵
%输出变量:val 1表⽰有,0表⽰没有
val=0;
rows=size(mat,1);
for i=1:rows
temp=(mat(i,:)==arow);
if length(find(temp==0))==0
val=1;
return;
else
val=0;
end;
end
% [x,fval,exitflag,output,lambda]=lpint(ifint.f,A,b,Aeq,beq)
% [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb)
% [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub)
% [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub,x0)
% [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub,x0,options)
if nargin<10, options=[]; end
if nargin<9, x0=[]; end
if nargin<8, ub=inf*ones(size(f)); end
if nargin<7, lb=zeros(size(f)); end
[x,fval,exitflag,output,lambda]=linprog(f,A,b,Aeq,beq,lb,ub,x0,options);
if exitflag<=0 %表⽰线性规划没有最优解
return
end
v1=find(ifint==1); %找到需要整数规划的变量的下标
temp=x(v1);%如果不是要求整数规划的就可以返回了。
if isempty(temp)
return
end
v2=find(checkint(temp)==0);
if isempty(v2) %都是整数,得到最众解
return
end
k=v1(v2(1));
temp1=zeros(1,length(f));
temp1(k)=1;
low=floor(x(k));
if isrowinmat([temp1,low],[A,b])==1
thisA=A;
thisb=b;
else
thisA=[A;temp1];
thisb=b;
thisb(end+1)=low;
end
[x1,fval1,exitflag1,output1,lambda1]=linprogdis(ifint,f,thisA,thisb,Aeq,beq,lb,ub,x0,options);
temp2=zeros(1,length(f));
temp2(k)=-1;
high=-ceil(x(k));
if isrowinmat([temp2,high],[A,b])==1
thisA=A;
thisb=b;
else
thisA=[A;temp2];
thisb=b;
thisb(end+1)=high;
end
[x2,fval2,exitflag2,output2,lambda2]=linprogdis(ifint,f,thisA,thisb,Aeq,beq,lb,ub,x0,options);
if (isempty(v2) && ((exitflag1>0 && exitflag2<=0 && fval<=fval)||(exitflag2>0 && exitflag1<=0 && fval<=fval2)||(exitflag1>0 && exitflag2>0 && fval<=fval1 && fval<=fval2))) disp('error call');
return ; %表⽰都是整数
end
if exitflag1>0&&exitflag2<=0
x=x1;
fval=fval1;
exitflag=exitflag1;
output=output1;
lambda=lambda1;
elseif exitflag1<=0&&exitflag2>0
x=x2;
fval=fval2;
exitflag=exitflag2;
output=output2;
lambda=lambda2;
elseif exitflag1>0 && exitflag2>0
if fval1<fval2
x=x1;
fval=fval1;
exitflag=exitflag1;
output=output1;
lambda=lambda1;
fval=fval2;
exitflag=exitflag2;
output=output2;
lambda=lambda2;
end
end
三、0-1型整数规划
1、定义:就是变量的取值只能是0-1,这样的话,其实我们可以将不同的整数规划转化成0-1规划。
2、实际问题:
这⾥我们就可以直接列出⼀个是0-1规划的⽅程,设的变量xi,“1”表⽰被选中,“0”表⽰没被选中
3、相互排斥的约束条件可以转化成同类型的。
四、求解整数规划的3种⽅法
(1)穷举法,这种⽐较⼟= =,但是最有效,⽽且某些情况只能穷举。
(2)过渡隐枚举法
a、先试探性求⼀个可⾏解X(随便带⼊求值)
b、然后根据是求极⼤值还是极⼩值,如果是求极⼤值,那么凡是⽬标值<X的解不必检验是否满⾜约束条件即可删除,如果是求极⼩值,那么凡是⽬标值>X不必检验是否满⾜约束条件就可满⾜。
c、改进新的过滤条件
d、然后验证⽬标值,最终求得。
PS:怎么说呢,这个⽅法就是⼀种变相的穷举,如果运⽓不好,就会变成全部都穷举,但是因为是先⽐较⽬标值,所以可以减少计算量,因⽽还是有效的(但是要注意不要犯反复测验的错误)、
(3)蒙特卡洛法(随机抽样法)
就是选择不穷举全部点,⽽是采⽤随机的⽅式来抽取样本估计整体,如果样本⾜够⼤,可信度是很⼤的。
例如求解此题:
MATLAB编程求解:
function [ f,g ] = mengte( x )
%MENGTE 键⼊整数线性规划的⽬标函数和约束条件
% f:指的是⽬标函数向量
% g:指的是约束条件向量
f=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=[sum(x)-400
x(1)+2*x(2)+2*x(3)+x(4)+6*x(5)-800
2*x(1)+x(2)+6*x(3)-200
x(3)+x(4)+5*x(5)-200];
end
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]=mengte(x1);
if sum(g<=0)==4
if p0<=f
x0=x1;p0=f;
end
end
[f,g]=mengte(x2);
if sum(g<=0)==4
if p0<=f
x0=x2;p0=f;
end
end
五、0-1整数规划的求解
例如求解这个指派问题。
由于MATLAB⾥⾯有封装好的函数- -,我就不⽤C++再写了。
不过这个问题还是很容易写出来的,⼀些⽐赛题⽬也会出现的。
c=[3,8,2,10,3;
8,7,2,9,7;
6,4,2,7,5;
8,4,2,3,5;
9,10,6,9,10]
c=c(:);%就是变成列向量(提取矩阵的⽅法)
a=zeros(10,25);
for i=1:5
a(i,(i-1)*5+1:1:5*i)=1;
a(5+i,i:5:25)=1;
end
b=ones(10,1);
[x,y]=bintprog(c,[],[],a,b);
x=reshape(x,[5,5]),y。