飞道的博客

【数学建模】数学建模学习2---整数规划(例题+matlab代码实现)

434人阅读  评论(0)

1 概论

1.1 定义

规划中的变量(部分或全部)限制为整数时,称为整数规划。若在线性规划模型中,变量限制为整数,则称为整数线性规划。目前所流行的求解整数规划的方法,往往只适用于整数线性规划。目前还没有一种方法能有效地求解一切整数规划。

1.2 整数规划的分类

如不加特殊说明,一般指整数线性规划。对于整数线性规划模型大致可分为两类:

1.变量全限制为整数时,称纯(完全)整数规划。

2.变量部分限制为整数的,称混合整数规划。

1.3 整数规划特点

(i)原线性规划有最优解,当自变量限制为整数后,其整数规划解出现下述情况:

①原线性规划最优解全是整数,则整数规划最优解与线性规划最优解一致。

②整数规划无可行解。

③有可行解(当然就存在最优解),但最优解值变差。

(ii) 整数规划最优解不能按照实数最优解简单取整而获得。

1.4 求解方法分类

(i)分枝定界法—可求纯或混合整数线性规划。

(ii)割平面法—可求纯或混合整数线性规划。

(iii)隐枚举法—求解“0-1”整数规划:

①过滤隐枚举法;

②分枝隐枚举法。

(iv)匈牙利法—解决指派问题(“0-1”规划特殊情形)。

(v)蒙特卡洛法—求解各种类型规划。

下面将简要介绍常用的几种求解整数规划的方法。

2 分枝定界法

对有约束条件的最优化问题(其可行解为有限数)的所有可行解空间恰当地进行系统搜索,这就是分枝与定界内容。通常,把全部可行解空间反复地分割为越来越小的子集,称为分枝;并且对每个子集内的解集计算一个目标下界(对于最小值问题),这称为定界。在每次分枝后,凡是界限超出已知可行解集目标值的那些子集不再进一步分枝, 这样,许多子集可不予考虑,这称剪枝。这就是分枝定界法的主要思路。

分枝定界法可用于解纯整数或混合的整数规划问题。在本世纪六十年代初由 Land Doig 和 Dakin 等人提出的。由于这方法灵活且便于用计算机求解,所以现在它已是解整数规划的重要方法。目前已成功地应用于求解生产进度问题、旅行推销员问题、工厂选址问题、背包问题及分配问题等。

设有最大化的整数规划问题 A ,与它相应的线性规划为问题 B ,从解问题 B 开始,若其最优解不符合 A 的整数条件,那么 B 的最优目标函数必是 A 的最优目标函数 z* 的上界,记作 z ;而 A 的任意可行解的目标函数值将是 z* 的一个下界 z 。分枝定界法就是将 B 的可行域分成子区域的方法。逐步减小 z 和增大 z ,最终求到 z* 。现用下例来说明:

例 3 求解下述整数规划

解 (i)先不考虑整数限制,即解相应的线性规划 B ,得最优解为:

x1 = 4.8092, x2 = 1.8168,z = 355.8779

可见它不符合整数条件。这时 z 是问题 A 的最优目标函数值 z* 的上界,记作 z 。而x1 = 0, x2 = 0 显然是问题 A 的一个整数可行解,这时 z = 0 ,是 z* 的一个下界,记作 z , 即0 ≤ z* ≤ 356。

(ii)因为 x1, x2 当前均为非整数,故不满足整数要求,任选一个进行分枝。设选 x1

进行分枝,把可行集分成 2 个子集:

x1 ≤ [4.8092] = 4, x1 ≥ [4.8092] +1 = 5

因为 4 与 5 之间无整数,故这两个子集的整数解必与原可行集合整数解一致。这一步称为分枝。这两个子集的规划及求解如下:

(iii)对问题 B1 再进行分枝得问题 B11和 B12 ,它们的最优解为

(iv)对问题 B2 再进行分枝得问题 B21和 B22,它们的最优解为

从以上解题过程可得用分枝定界法求解整数规划(最大化)问题的步骤为:

开始,将要求解的整数规划问题称为问题 A ,将与它相应的线性规划问题称为问题 B 。

(i)解问题 B 可能得到以下情况之一:

(a) B 没有可行解,这时 A 也没有可行解,则停止.

(b) B 有最优解,并符合问题 A 的整数条件, B 的最优解即为 A 的最优解,则停止。

(c) B 有最优解,但不符合问题 A 的整数条件,记它的目标函数值为 z 。

(ii)用观察法找问题 A 的一个整数可行解,一般可取 xj = 0, j = 1,L,n ,试探,求得其目标函数值,并记作 z 。以 z* 表示问题 A 的最优目标函数值;这时有 z ≤ z* ≤ z进行迭代。

第一步:分枝,在 B 的最优解中任选一个不符合整数条件的变量 x j ,其值为bj , 以[bj] 表示小于bj 的最大整数。构造两个约束条件xj ≤ [bj] 和 xj ≥ [bj] +1将这两个约束条件,分别加入问题 B ,求两个后继规划问题 B1 和 B2 。不考虑整数条件求解这两个后继问题。

定界,以每个后继问题为一分枝标明求解的结果,与其它问题的解的结果中,找出最优目标函数值最大者作为新的上界 z 。从已符合整数条件的各分支中,找出目标函数值为最大者作为新的下界 z ,若无作用 z 不变。

第二步:比较与剪枝,各分枝的最优目标函数中若有小于 z 者,则剪掉这枝,即以后不再考虑了。若大于 z ,且不符合整数条件,则重复第一步骤。一直到最后得到z* = z 为止。得最优整数解

3 0 −1型整数规划

0 −1型整数规划是整数规划中的特殊情形,它的变量 x j 仅取值 0 或 1。这时 x j 称 为0 −1变量,或称二进制变量。 x j 仅取值 0 或 1 这个条件可由下述约束条件:0 ≤ xj ≤ 1,整数所代替,是和一般整数规划的约束条件形式一致的。在实际问题中,如果引入 0 −1变量,就可以把有各种情况需要分别讨论的线性规划问题统一在一个问题中讨论了。我们先介绍引入0 −1变量的实际问题,再研究解法。

3.1 引入0 −1变量的实际问题

3.1.1 投资场所的选定——相互排斥的计划

例 4 某公司拟在市东、西、南三区建立门市部。拟议中有 7 个位置(点)Ai(i = 1,2,L,7) 可供选择。规定

在东区。由 A1, A2 , A3 三个点中至多选两个;

在西区。由 A4 , A5 两个点中至少选一个;

在南区,由 A6 , A7 两个点中至少选一个。

如选用 Ai 点,设备投资估计为bi 元,每年可获利润估计为ci 元,但投资总额不能超过 B 元。问应选择哪几个点可使年利润为最大?

解题时先引入0 −1变量 xi(i =1,2,L,7)

于是问题可列写成:

3.1.2 相互排斥的约束条件

有两个相互排斥的约束条件

5x1 + 4x2 ≤ 24 或 7x1 + 3x2 ≤ 45。

为了统一在一个问题中,引入0 −1变量 y ,则上述约束条件可改写为:

其中 M 是充分大的数。

约束条件

可改写为

如果有 m 个互相排斥的约束条件:

为了保证这 m 个约束条件只有一个起作用,我们引入 m 个0 −1变量 yi(i = 1,2,L,m)和一个充分大的常数 M ,而下面这一组m +1个约束条件

3.1.3 关于固定费用的问题(Fixed Cost Problem)

在讨论线性规划时,有些问题是要求使成本为最小。那时总设固定成本为常数,并在线性规划的模型中不必明显列出。但有些固定费用(固定成本)的问题不能用一般线性规划来描述,但可改变为混合整数规划来解决,见下例。

例 5 某工厂为了生产某种产品,有几种不同的生产方式可供选择,如选定的生产方式投资高(选购自动化程度高的设备),由于产量大,因而分配到每件产品的变动成本就降低;反之,如选定的生产方式投资低,将来分配到每件产品的变动成本可能增加。

所以必须全面考虑。今设有三种方式可供选择,令x j 表示采用第 j 种方式时的产量;cj 表示采用第 j 种方式时每件产品的变动成本;k j 表示采用第 j 种方式时的固定成本。

为了说明成本的特点,暂不考虑其它约束条件。采用各种生产方式的总成本分别为

在构成目标函数时,为了统一在一个问题中讨论,现引入0 −1变量 y j ,令

(3)于是目标函数

(3)式这个规定可表为下述 3 个线性约束条件:

其中ε 是一个充分小的正常数,M 是个充分大的正常数。(4)式说明,当 x j > 0时 y j必须为 1;当 x j = 0时只有 y j 为 0 时才有意义,所以(4)式完全可以代替(3)式。

3.2 0 −1型整数规划解法之一(过滤隐枚举法)

解0 −1型整数规划最容易想到的方法,和一般整数规划的情形一样,就是穷举法,即检查变量取值为 0 或 1 的每一种组合,比较目标函数值以求得最优解,这就需要检查变量取值的 2n 个组合。对于变量个数 n 较大(例如 n >100 ),这几乎是不可能的。因此常设计一些方法,只检查变量取值的组合的一部分,就能求到问题的最优解。这样的方法称为隐枚举法(Implicit Enumeration),分枝定界法也是一种隐枚举法。当然,对 -21-有些问题隐枚举法并不适用,所以有时穷举法还是必要的。

下面举例说明一种解0 −1型整数规划的隐枚举法。

例 6

求解思路及改进措施:

(i) 先试探性求一个可行解,易看出(x1, x2 , x3 ) = (1,0,0) 满足约束条件,故为一个可行解,且 z = 3。

(ii) 因为是求极大值问题,故求最优解时,凡是目标值 z < 3的解不必检验是否满足约束条件即可删除,因它肯定不是最优解,于是应增加一个约束条件(目标值下界):

(iii) 改进过滤条件。

(iv)由于对每个组合首先计算目标值以验证过滤条件,故应优先计算目标值 z 大的组合,这样可提前抬高过滤门槛,以减少计算量。

4 蒙特卡洛法(随机取样法)

前面介绍的常用的整数规划求解方法,主要是针对线性整数规划而言,而对于非线性整数规划目前尚未有一种成熟而准确的求解方法,因为非线性规划本身的通用有效解法尚未找到,更何况是非线性整数规划。

然而,尽管整数规划由于限制变量为整数而增加了难度;然而又由于整数解是有限个,于是为枚举法提供了方便。当然,当自变量维数很大和取值范围很宽情况下,企图用显枚举法(即穷举法)计算出最优值是不现实的,但是应用概率理论可以证明,在一定的计算量的情况下,完全可以得出一个满意解。

例 7 已知非线性整数规划为:

如果用显枚举法试探,共需计算(100)5 = 1010 个点,其计算量非常之大。然而应用蒙特卡洛去随机计算106 个点,便可找到满意解,那么这种方法的可信度究竟怎样呢?

下面就分析随机取样采集106 个点计算时,应用概率理论来估计一下可信度。

不失一般性,假定一个整数规划的最优点不是孤立的奇点。

假设目标函数落在高值区的概率分别为 0.01,0.00001,则当计算106 个点后,有 任一个点能落在高值区的概率分别为1− 0.991000000 ≈ 0.99L99(100多位), 1− 0.999991000000 ≈ 0.999954602。

解 (i)首先编写 M 文件 mente.m 定义目标函数 f 和约束向量函数 g,程序如下:

function [f,g]=mengte(x);
f=x(1)^2+x(2)^2+3*x(3)^2+4*x(4)^2+2*x(5)-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];

(ii)编写M文件mainint.m如下求问题的解:

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 

end 

x0,p0 

toc 

本题可以使用LINGO软件求得精确的全局最有解,程序如下:

model: 

sets: 

row/1..4/:b; 
col/1..5/:c1,c2,x; 
link(row,col):a; 

endsets 

data: 

c1=1,1,3,4,2; 
c2=-8,-2,-3,-1,-2; 
a=1 1 1 1 1 
 1 2 2 1 6 
 2 1 6 0 0  
 0 0 1 1 5; 
b=400,800,200,200; 

enddata 

max=@sum(col:c1*x^2+c2*x); 
@for(row(i):@sum(col(j):a(i,j)*x(j))<b(i)); 
@for(col:@gin(x)); 
@for(col:@bnd(0,x,99)); 

end

5 指派问题的计算机求解

整数规划问题的求解可以使用 Lingo 等专用软件。对于一般的整数规划问题,无法直接利用 Matlab 的函数,必须利用 Matlab 编程实现分枝定界解法和割平面解法。但对于指派问题等0 −1整数规划问题,可以直接利用 Matlab 的函数 bintprog 进行求解。

例 8 求解下列指派问题,已知指派矩阵为

解:编写 Matlab 程序如下:

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: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 

求得最优指派方案为 x15 = x23 = x32 = x44 = x51 = 1,最优值为 21。

求解的 LINGO 程序如下:

model: 

sets: 

var/1..5/; 
link(var,var):c,x; 

endsets 

data: 

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;

enddata 

min=@sum(link:c*x); 
@for(var(i):@sum(var(j):x(i,j))=1); 
@for(var(j):@sum(var(i):x(i,j))=1); -24- 
@for(link:@bin(x)); 

end

6 生产与销售计划问题

6.1 问题实例

例 9 某公司用两种原油( A 和 B )混合加工成两种汽油(甲和乙)。甲、乙两种汽油含原油的最低比例分别为 50%和 60%,每吨售价分别为 4800 元和 5600 元。该公司现有原油 A 和 B 的库存量分别为 500 吨和 1000 吨,还可以从市场上买到不超过 1500吨的原油 A 。原油 A 的市场价为:购买量不超过 500 吨时的单价为 10000 元/吨;购买量超过 500 吨单不超过 1000 吨时,超过 500 吨的部分 8000 元/吨;购买量超过 1000 吨时,超过 1000 吨的部分 6000 元/吨。该公司应如何安排原油的采购和加工。

6.2 建立模型

(1)问题分析

安排原油采购、加工的目标是利润最大,题目中给出的是两种汽油的售价和原油 A的采购价,利润为销售汽油的收入与购买原油 A 的支出之差。这里的难点在于原油 A 的采购价与购买量的关系比较复杂,是分段函数关系,能否及如何用线性规划、整数规划模型加以处理是关键所在。

(2)模型建立

设原油 A 的购买量为 x(单位:吨)。根据题目所给数据,采购的支出c(x) 可表示为如下的分段线性函数(以下价格以千元/吨为单位):

设原油 A 用于生产甲、乙两种汽油的数量分别为 x11和 x12 ,原油 B 用于生产甲、乙两种汽油的数量分别为 x21 和 x22 ,则总的收入为 4.8(x11 + x21 ) + 5.6(x12 + x22 )(千元)。于是本例的目标函数(利润)为

约束条件包括加工两种汽油用的原油 A 、原油 B 库存量的限制,原油 A 购买量的限制,以及两种汽油含原油 A 的比例限制,它们表示为

6.3 求解模型

下面介绍 3 种解法

(1)解法一

一个自然的想法是将原油 A 的采购量 x 分解为三个量,即用 x1 , x2 , x3 分别表示以价 格 10 千元 / 吨 、 8 千 元 / 吨 、 6 千 元 / 吨采购的原油 A 的吨数,总支出为c(x) = 10x1 + 8x2 + 6x3,且x = x1 + x2 + x3 (13)

这时目标函数(6)变为线性函数:

max z = 4.8(x11 + x21 ) + 5.6(x12 + x22 ) − (10x1 + 8x2 + 6x3 ) (14)

应该注意到,只有当以 10 千元/吨的价格购买 x1 = 500(吨)时,才能以 8 千元/吨的价格购买 x2 (> 0) ,这个条件可以表示为(x1 − 500)x2 = 0 (15)

同理,只有当以 8 千元/吨的价格购买 x2 = 500(吨)时,才能以 6 千元/吨的价格购买x3 (> 0) ,于是

(x2 − 500)x3 = 0 (16)

此外, x1 , x2 , x3 的取值范围是0 ≤ x1 , x2 , x3 ≤ 500 (17)

由于有非线性约束(15)、(16),因而(7)~(17)构成非线性规划模型。将该模型输入 LINGO 软件如下:

model: 

sets: 

 var1/1..4/:y; !这里y(1)=x11,y(2)=x21,y(3)=x12,y(4)=x22; 
 var2/1..3/:x,c; 

endsets 

max=4.8*(y(1)+y(2))+5.6*(y(3)+y(4))-@sum(var2:c*x); 
y(1)+y(3)<@sum(var2:x)+500; 
y(2)+y(4)<1000; 
0.5*(y(1)-y(2))>0; 
0.4*y(3)-0.6*y(4)>0; 
(x(1)-500)*x(2)=0; 
(x(2)-500)*x(3)=0; 
@for(var2:@bnd(0,x,500)); 

data: 

c=10 8 6; 

enddata 

end

可以用菜单命令“LINGO|Options”在“Global Solver”选项卡上启动全局优化选型,并运行上述程序求得全局最有解:购买 1000 吨原油 A ,与库存的 500 吨原油 A 和1000 吨原油 B 一起,共生产 2500 吨汽油乙,利润为 5000(千元)。

(2)解法二

引入 0-1 变量将(15)和(16)转化为线性约束。

令 z1 = 1, z2 = 1, z3 = 1分别表示以 10 千元/吨、8 千元/吨、6 千元/吨的价格采

购原油 A ,则约束(15)和(16)可以替换为

式(7)~(14),式(17)~(21)构成混合整数线性规划模型,将它输入 LINGO 软件如下:

model: 

sets: 

 var1/1..4/:y; !这里y(1)=x11,y(2)=x21,y(3)=x12,y(4)=x22; 
 var2/1..3/:x,z,c; 

endsets 

max=4.8*(y(1)+y(2))+5.6*(y(3)+y(4))-@sum(var2:c*x); 
y(1)+y(3)<@sum(var2:x)+500; 
y(2)+y(4)<1000; 
0.5*(y(1)-y(2))>0; 
0.4*y(3)-0.6*y(4)>0; 

@for(var1(i)|i #lt# 3:500*z(i+1)<x(i);x(i)<500*z(i)); 
x(3)<500*z(3); 
@for(var2:@bin(z)); 
@for(var2:@bnd(0,x,500)); 

data: 

c=10 8 6; 

enddata 

end

(3)解法三

直接处理分段线性函数c(x) 。式(5)表示的函数c(x) 如图 1 所示。记 x 轴上的分点为b1 = 0 ,b2 = 500 ,b3 = 1000 。当 x 属于第 1 个小区间[b1,b2 ]时,记 x = w1b1 + w2b2 , w1 + w2 = 1, w1,w2 ≥ 0,因为c(x) 在[b1,b2 ]上是线性的,

所 以 c(x) = w1c(b1) + w2c(b2 ) 。同样,当 x 属于第 2 个小区间 [b2 ,b3 ] 时 ,x = w2b2 + w3b3 ,w2 + w3 =1,w2 ,w3 ≥ 0,c(x) = w2c(b2 ) + w3c(b3 ) 。当 x 属于第3 个小区间 [b3 ,b4 ] 时 , x = w3b3 + w4b4 , w3 + w4 = 1 , w3 ,w4 ≥ 0 , c(x) = w3c(b3 ) + w4c(b4 ) 。为了表示 x 在哪个小区间,引入 0-1 变量 zk (k = 1,2,3) , 当 x 在第 k 个小区间时, zk = 1,否则, zk = 0 。这样, w1,w2 ,w3 ,w4 ,z1,z2 ,z3 应满足

此时 x 和c(x) 可以统一地表示为

式(6)~(13),式(22)~(26)也构成一个混合整数线性规划模型,可以用LINGO 求解。输入的 LINGO 模型如下:

model: 

sets: 

 var/1..4/:b,c,y,z,w; 
!这里y(1)=x11,y(2)=x21,y(3)=x12,y(4)=x22 
端点数为4,即分段数为3; 

endsets 

data: 

b=0,500,1000,1500; 
c=0,5000,9000,12000; 
z=,,,0; !增加的虚拟变量z(4)=0; 

enddata 

max=4.8*(y(1)+y(2))+5.6*(y(3)+y(4))-@sum(var:c*w); 
y(1)+y(3)<@sum(var:b*w)+500; 
y(2)+y(4)<1000; 
0.5*(y(1)-y(2))>0; 
0.4*y(3)-0.6*y(4)>0; 
w(1)<z(1); 

@for(var(i)|i #ne# 1:w(i)<z(i-1)+z(i)); 
@sum(var:z)=1; 
@sum(var:w)=1; 
@for(var:@bin(z)); 

End 

转载:https://blog.csdn.net/qq_44528283/article/details/117390794
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场