【数学建模算法】(5)整数规划应用实例:生产与销售计划问题
之前的几篇番外,我们介绍了运筹学软件Lingo的用法,之后对于规划问题的处理,如无特殊说明,均视为采用Lingo求解。
例1 生产与销售问题
某公司用两种原油( A 和 B )混合加工成两种汽油(甲和乙)。甲、乙两种汽油含原油的最低比例分别为 50%和 60%,每吨售价分别为 4800 元和 5600 元。该公司现有原油 A 和 B 的库存量分别为 500 吨和 1000 吨,还可以从市场上买到不超过 1500吨的原油 A 。原油 A 的市场价为:购买量不超过 500 吨时的单价为 10000 元/吨;购买量超过 500 吨单不超过 1000 吨时,超过 500 吨的部分 8000 元/吨;购买量超过 1000 吨时,超过 1000 吨的部分 6000 元/吨。该公司应如何安排原油的采购和加工。
1.问题分析
安排原油采购、加工的目标是利润最大,题目中给出的是两种汽油的售价和原油 A的采购价,利润为销售汽油的收入与购买原油 A 的支出之差。这里的难点在于原油 A 的采购价与购买量的关系比较复杂,是分段函数关系,能否及如何用线性规划、整数规划模型加以处理是关键所在。
2.模型建立
设原油的购买量为
(单位:吨)。根据题目所给数据,采购的支出
可表示为如下的分段线性函数(以下价格以千元/吨为单位)
设原油用于生产甲,乙两种汽油的数量分别为
和
,原油
用来生产两种汽油的数量分别是
和
,则总的输入为
(千元)。于是本例的目标函数(利润)为:
(此处代表一个非线性分段函数)
约束条件包括两种汽油用的原油,
的库存限制,原油
购买量的限制,原油
的比例限制。
现在问题在于,目标函数中的c(x)是一个非线性函数
3.模型求解
下面介绍三种解法:
(1)解法一:
一个自然的想法是将原油A采购量的x分为三个量,用,
,
分别表示10千元每吨,8千元每吨,6千元每吨采购的原油A的吨数,总支出为
且:
此时目标函数变为线性函数:
如何把分段的限制条件加入呢?
注意到,只有当以10千元每吨的价格购买吨时,才能以8千元/吨的价格购买
,这个条件可以表示为:
同理,用同样的条件来限制和
:
此外,还有本身的取值范围:
综合以上所有条件,得到最终的程序:
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
运行得到全局最优解:购买1000吨原油,与库存的500吨原油A与1000吨原油B一起,共产生2500吨汽油乙,利润为5000(千元)。
(2)解法二
引入0-1变量
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)解法三
直接处理分段线性函数。
记分断点
当处于第一个小区间
,记
,
因为
在
上是线性的。

同理,当处于第二个小区间时,
,,
当处于第三个小区间
时
,
为了表示在哪个区间内,引入0-1变量
,当
在第
个小区间时,
,否则,
,这样
应满足:
此时可将和x统一表示。
此时又是一个线性规划模型。
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