一个整数线性规划的例子(分枝定界法)[有代码]
本帖最后由 messenger 于 2010-9-6 16:14 编辑整数现行规划用lingo等很多软件都可以解,Matlab没有现成的函数(有0-1规划的函数bintprog),一般的整数规划是用分支定界法来解,有个好处就是可以求出所有解,而lingo只能求出一个解,下面是程序,其中分支定界的程序源于网络(具体的地址忘了)
这是原问题的模型,matlab代码如下:clear;clc;close all
N=7;
pos0=;
p=ones(1,N);
p(pos0)=0;
c=hankel(1:N,0:N-1);
a=fliplr(p(c));
b=-;
t=0.4;
h = text;
h1 = text;
set(h,'Interpreter','latex');
set(h,'string','$$\overbrace{}$$','Rotation',90,'position',,'fontsize',90);
set(h1,'Interpreter','latex','string','min=$$\sum_{i=1}^{7} x_{i}$$','position',,'fontsize',20,'Rotation',0);
for i=1:N
ii=find(a(i,:));
S=sprintf('\\fontsize{20}x_{%d}+x_{%d}+x_{%d}+x_{%d}+x_{%d}>=%d',ii(1),ii(2),ii(3),ii(4),ii(5),-b(i));
text(0.5,t,S);
t=t-0.1;
end
S='\fontsize{20}x_{i}>=0';
text(0.5,t,S);
axis()
axis off以下是求解的程序代码 clear;clc;close all
N = 7;
f = ones(N,1);
N=7;
M=;
a=diag(-ones(1,N-M(1)+1),M(1)-1)+diag(-ones(1,N-M(2)+1),M(2)-1)+...
diag(-ones(1,M(3)),M(3)-N)+diag(-ones(1,M(4)),M(4)-N)+ones(N);
A=-a;
b=-;
lb = zeros(N,1);
% = linprog(f,A,b,[],[],lb);
Aeq=[];beq=[];
LB=lb;UB=[];
=ILp(f,A,b,Aeq,beq,LB,UB,[],1,[]) ;
xn=round(xn);
function =ILp(f,G,h,Geq,heq,lb,ub,x,id,options)
%整数线性规划分支定界法,可求解纯整数规划和混合整数规划。
%y=minf’*x s.t. G*x<=h Geq*x=heq x为全整数或混合整数列向量
%用法
%=ILp(f,G,h,Geq,heq,lb,ub,x,id,options)
%参数说明
%lb:解的下界列向量(Default:-int)
%ub:解的上界列向量(Default:int)
%x:迭代初值列向量
%id:整数变量指标列向量,1-整数,0-实数(Default:1)
global upper opt c x0 A b Aeq beq ID options;
warning off all;
if nargin<10
options=optimset({});
options.Display='off';
options.LargeScale='off';
end
if nargin<9,id=ones(size(f));end
if nargin<8,x=[];end
if nargin<7 ||isempty(ub),ub=inf*ones(size(f));end
if nargin<6 ||isempty(lb),lb=zeros(size(f));end
if nargin<5,heq=[];end
if nargin<4,Geq=[];end
upper=inf;c=f;x0=x;A=G;b=h;Aeq=Geq;beq=heq;ID=id;
ftemp=ILP(lb(:),ub(:));
x=opt;y=upper;
%下面是子函数
function ftemp=ILP(vlb,vub)
warning off all;
global upper opt c x0 A b Aeq beq ID options;
=linprog(c,A,b,Aeq,beq,vlb,vub,x0,options);
if how <=0
return;
end;
if ftemp-upper>0.00005 %in order to avoid error
return;
end;
if max(abs(x.*ID-round(x.*ID)))<0.00005
if upper-ftemp>0.00005 %in order to avoid error
opt=x';upper=ftemp;
return;
else
opt=;
return;
end;
end;
notintx=find(abs(x-round(x))>=0.00005); %in order to avoid error
intx=fix(x);tempvlb=vlb;tempvub=vub;
if vub(notintx(1,1),1)>=intx(notintx(1,1),1)+1;
tempvlb(notintx(1,1),1)=intx(notintx(1,1),1)+1;
ftemp=ILP(tempvlb,vub);
end;
if vlb(notintx(1,1),1)<=intx(notintx(1,1),1)
tempvub(notintx(1,1),1)=intx(notintx(1,1),1);
ftemp=ILP(vlb,tempvub);
end
和1stOpt对比下:
代码:
MultiRun = 15;
IntParameter x(7);
Constant c=;
MaxFunction Sum(i=1:7,x)(x);
For(i=1:7)(Sum(j=i:i+4)(x)<=c);
用线性算法只有一个结果,用全局算法,自动运行15次得14组结果:
1: 1,4,12,0,7,5,2; 目标函数 = 31
2: 1,4,12,0,9,3,2; 目标函数 = 31
3: 1,8,8,0,10,2,2; 目标函数 = 31
4: 3,4,12,0,10,2,0; 目标函数 = 31
5: 1,4,12,0,8,4,2; 目标函数 = 31
6: 1,8,8,0,6,6,2; 目标函数 = 31
7: 2,6,10,0,6,6,1; 目标函数 = 31
8: 2,8,8,0,6,6,1; 目标函数 = 31
9: 2,3,13,0,6,6,1; 目标函数 = 31
10: 2,7,9,0,11,1,1; 目标函数 = 31
11: 1,8,8,0,7,5,2; 目标函数 = 31
12: 1,6,10,0,8,4,2; 目标函数 = 31
13: 2,8,8,0,10,2,1; 目标函数 = 31
14: 3,8,8,0,11,1,0; 目标函数 = 31 本帖最后由 qibbxxt 于 2010-8-31 20:00 编辑
2# shamohu
不好意思,那会太着急,把模型写错了,现在修改了一下,我计算的结果如下:
xn =
8 0 12 0 11 5 0
7 1 12 0 11 5 0
7 1 12 0 11 4 1
6 2 12 0 11 5 0
6 2 12 0 11 4 1
6 2 12 0 11 3 2
5 3 12 0 11 5 0
5 3 12 0 11 4 1
5 3 12 0 11 3 2
5 3 12 0 11 2 3
4 4 12 0 11 5 0
4 4 12 0 11 4 1
4 4 12 0 11 3 2
4 4 12 0 11 2 3
4 4 12 0 11 1 4
3 5 12 0 11 5 0
3 5 12 0 11 4 1
3 5 12 0 11 3 2
3 5 12 0 11 2 3
3 5 12 0 11 1 4
3 5 12 0 11 0 5
2 6 12 0 11 5 0
2 6 12 0 11 4 1
2 6 12 0 11 3 2
2 6 12 0 11 2 3
2 6 12 0 11 1 4
2 6 12 0 11 0 5
1 7 12 0 11 5 0
1 7 12 0 11 4 1
1 7 12 0 11 3 2
1 7 12 0 11 2 3
1 7 12 0 11 1 4
1 7 12 0 11 0 5
0 8 12 0 11 5 0
0 8 12 0 11 4 1
0 8 12 0 11 3 2
0 8 12 0 11 2 3
0 8 12 0 11 1 4
0 8 12 0 11 0 5
最小值均为36
另外有空我也学学1stOpt,看来挺好用的 3# qibbxxt
2#给出的最小值为31,而不是36。
另外,用1stopt 求解,可能会遗漏正确的解。 一楼好像把模型改动了,原先目标函数是求最大,约束都是小于等于。因此2楼求的是最大,而3楼是最小,约束也不同。现修改与目前的一楼一样:
MultiRun = 100;
IntParameter x(7);
Constant c=;
MinFunction Sum(i=1:7,x)(x);
For(i=1:7)(Sum(j=i:i+4)(x)>=c);
自动运行100次,得到37组不同结果:
1: 5,3,12,0,11,4,1; 目标函数 = 36
2: 1,7,12,0,11,0,5; 目标函数 = 36
3: 1,7,12,0,11,2,3; 目标函数 = 36
4: 3,5,12,0,11,0,5; 目标函数 = 36
5: 0,8,12,0,11,4,1; 目标函数 = 36
6: 5,3,12,0,11,3,2; 目标函数 = 36
7: 2,6,12,0,11,1,4; 目标函数 = 36
8: 6,2,12,0,11,4,1; 目标函数 = 36
9: 6,2,12,0,11,5,0; 目标函数 = 36
10: 5,3,12,0,11,5,0; 目标函数 = 36
11: 1,7,12,0,11,1,4; 目标函数 = 36
12: 7,1,12,0,11,4,1; 目标函数 = 36
13: 4,4,12,0,11,5,0; 目标函数 = 36
14: 1,7,12,0,11,3,2; 目标函数 = 36
15: 2,6,12,0,11,4,1; 目标函数 = 36
16: 4,4,12,0,11,4,1; 目标函数 = 36
17: 3,5,12,0,11,5,0; 目标函数 = 36
18: 3,5,12,0,11,1,4; 目标函数 = 36
19: 2,6,12,0,11,0,5; 目标函数 = 36
20: 6,2,12,0,11,3,2; 目标函数 = 36
21: 3,5,12,0,11,4,1; 目标函数 = 36
22: 0,8,12,0,11,2,3; 目标函数 = 36
23: 4,4,12,0,11,1,4; 目标函数 = 36
24: 2,6,12,0,11,5,0; 目标函数 = 36
25: 1,7,12,0,11,5,0; 目标函数 = 36
26: 3,5,12,0,11,2,3; 目标函数 = 36
27: 4,4,12,0,11,2,3; 目标函数 = 36
28: 7,1,12,0,11,5,0; 目标函数 = 36
29: 8,0,12,0,11,5,0; 目标函数 = 36
30: 0,8,12,0,11,0,5; 目标函数 = 36
31: 1,7,12,0,11,4,1; 目标函数 = 36
32: 0,8,12,0,11,3,2; 目标函数 = 36
33: 2,6,12,0,11,2,3; 目标函数 = 36
34: 0,8,12,0,11,1,4; 目标函数 = 36
35: 0,8,12,0,11,5,0; 目标函数 = 36
36: 3,5,12,0,11,3,2; 目标函数 = 36
37: 2,6,12,0,11,3,2; 目标函数 = 36 4# lin2009
对比了一下,1stOpt比matlab少两组解
5 3 12 0 11 2 3
4 4 12 0 11 3 2
对比的代码如下:
clear;clc;close all
stOpt_re=[5,3,12,0,11,4,1
1,7,12,0,11,0,5
1,7,12,0,11,2,3
3,5,12,0,11,0,5
0,8,12,0,11,4,1
5,3,12,0,11,3,2
2,6,12,0,11,1,4
6,2,12,0,11,4,1
6,2,12,0,11,5,0
5,3,12,0,11,5,0
1,7,12,0,11,1,4
7,1,12,0,11,4,1
4,4,12,0,11,5,0
1,7,12,0,11,3,2
2,6,12,0,11,4,1
4,4,12,0,11,4,1
3,5,12,0,11,5,0
3,5,12,0,11,1,4
2,6,12,0,11,0,5
6,2,12,0,11,3,2
3,5,12,0,11,4,1
0,8,12,0,11,2,3
4,4,12,0,11,1,4
2,6,12,0,11,5,0
1,7,12,0,11,5,0
3,5,12,0,11,2,3
4,4,12,0,11,2,3
7,1,12,0,11,5,0
8,0,12,0,11,5,0
0,8,12,0,11,0,5
1,7,12,0,11,4,1
0,8,12,0,11,3,2
2,6,12,0,11,2,3
0,8,12,0,11,1,4
0,8,12,0,11,5,0
3,5,12,0,11,3,2
2,6,12,0,11,3,2];
matlab_re=[8 0 12 0 11 5 0
7 1 12 0 11 5 0
7 1 12 0 11 4 1
6 2 12 0 11 5 0
6 2 12 0 11 4 1
6 2 12 0 11 3 2
5 3 12 0 11 5 0
5 3 12 0 11 4 1
5 3 12 0 11 3 2
5 3 12 0 11 2 3
4 4 12 0 11 5 0
4 4 12 0 11 4 1
4 4 12 0 11 3 2
4 4 12 0 11 2 3
4 4 12 0 11 1 4
3 5 12 0 11 5 0
3 5 12 0 11 4 1
3 5 12 0 11 3 2
3 5 12 0 11 2 3
3 5 12 0 11 1 4
3 5 12 0 11 0 5
2 6 12 0 11 5 0
2 6 12 0 11 4 1
2 6 12 0 11 3 2
2 6 12 0 11 2 3
2 6 12 0 11 1 4
2 6 12 0 11 0 5
1 7 12 0 11 5 0
1 7 12 0 11 4 1
1 7 12 0 11 3 2
1 7 12 0 11 2 3
1 7 12 0 11 1 4
1 7 12 0 11 0 5
0 8 12 0 11 5 0
0 8 12 0 11 4 1
0 8 12 0 11 3 2
0 8 12 0 11 2 3
0 8 12 0 11 1 4
0 8 12 0 11 0 5];
matlabIsIn1stOPt=ismember(matlab_re,stOpt_re,'rows');
stOPtIsInmatlab=ismember(stOpt_re,matlab_re,'rows');
re=matlab_re(not(matlabIsIn1stOPt),:);
6# qibbxxt
"对比的代码"可以直接用集合差运算:
setdiff(matlab_re,stOpt_re,'rows')
ans =
4 4 12 0 11 3 2
5 3 12 0 11 2 3 1stOpt的确不能保证给出全部最优解。估计它用的全局最优算法,初值都是随机赋的。
1stOpt的代码是很精短且易懂的。 7# lin2009
恩,互相作差,这样就全面一些 8# shamohu
恩,matlab由于基于矩阵操作,所以用起来稍麻烦一些
1stOpt在做规划问题时代码简洁易懂,就和lingo一样,但是就是很难保证找到所有解 本帖最后由 upc1984 于 2010-9-1 10:59 编辑
1# qibbxxt
我新学的也编了一个
function y=myfun0901(x)
y=x(1)+x(2)+x(3)+x(4)+x(5)+x(6)+x(7);
A=[1 0 0 1 1 1 1;...
1 1 0 0 1 1 1;...
1 1 1 0 0 1 1;...
1 1 1 1 0 0 1;...
1 1 1 1 1 0 0;...
0 1 1 1 1 1 1;...
0 0 1 1 1 1 1];
A=-A;
b=;
b=-b';
lb=;
lu=;
x0=;
x=fmincon(@myfun0901,x0,A,b,[],[],lb,lu)
计算结果
Active inequalities (to within options.TolCon = 1e-006):
lower upper ineqlin ineqnonlin
4 2
3
5
7
x =
4.0022 3.9978 12.0000 0 11.0000 2.8835 2.1165
y =
36.0000
不过有小数,不好办~ 11# upc1984
1.这个问题是整数线性规划,你用的是非线性规划
2.matlab没有自带的求解整数规划的函数(0-1规划除外),所以整数线性规划用分支定界法
3.建议你好好看下运筹学关于规划部分 本帖最后由 bainhome 于 2010-9-4 01:37 编辑
嗯,整数线规用非线性方法做是个糟糕的误区,以前初学时我也犯过这种错误,这是应该去避免的。
这个分枝定界法的程序看起很不错的样子,以前找过整数线规的程序都不是很好用,意外看到这个,谢谢qibbxxt。同时建议加技术分:整数线规的MATLAB程序在版内好像没有出现过,加上应用的讨论则肯定没有,尤其在特殊的个案中和1stopt比较时能不落下风,难能可贵。 13# bainhome
谢谢bainhome兄,这个程序是不好找,我以前也找过很多,都用不了
页:
[1]