- 多目标规划的模型基础:
-
正负偏差变量
即d2+,d2-分别表示决策值超过和未达到目标值的部分。且di+,di-均大于0 -
刚性约束和目标约束(柔性目标约束具有偏差)
多目标规划中,刚性约束中保持>=/<=不变。约束需要变换为柔性约束时,需要把>=/<=改成=(因为已经有了d2+,d2-用来表示正负偏差),并且追加上(+di-di+)这里注意!是+di-,-di+,这是因为需要将目标还原回去,使其最接近原来的刚性约束 -
优先因子与权系数
对于若干个目标,分出主次和轻重缓急 -
目标规划的目标函数
是所有偏差变量的加权和。值得注意的是该加权和均取min值。且每个不同的等级需求中,并不一定di+、di-都出现。具体分析需要具体看题目
举例如下:
题目中说设备B既要求充分利用,又尽可能不加班,那么用时间衡量列出的表达式即为:min z=P3(d3- + d3+)之所以这里用+而不是-d3+的原因是:正负偏差不可能同时存在,必有di+di-=0(因为决策值不可能同时大于目标值又小于目标值),又前面是min,所以就取+,让di+和di-都是正值。故引出如下规则:
- 最后给出例题,并给出对应的解法:
问题:某企业生产甲、乙两种产品,需要用到 A, B,C 三种设备,关于产品的赢利与使用设备的工时及限制如下表所示。问该企业应如何安排生产,才能达到下列目标:
( 1)力求使利润指标不低于 1500 元;
( 2)考虑到市场需求,甲、乙两种产品的产量比应尽量保持 1:2;
( 3)设备 A 为贵重设备,严格禁止超时使用;
( 4)设备C 可以适当加班,但要控制;设备 B 既要求充分利用,又尽可能不加班。
在重要性上,设备 B 是设备C 的 3 倍。
建立相应的目标规划模型并求解。
解:设该企业生产甲乙两种产品的件数分别为 x1, x2 ,相应的目标规划模型为:
- 下面采用序贯解法,用lingo求解:
一级目标:
model:
sets:
variable/1..2/:x;!规定变量;
s_con_num/1..4/:g,dplus,dminus;!软约束条件个数(g的个数=dplus个数=dminus个数)以及需要的相关参数;
s_con(s_con_num,variable):c;!软约束系数;
endsets
data:
g=1500 0 16 15;
c=200 300 2 -1 4 0 0 5;
enddata
min=dminus(1);!第一个目标函数;!对应min=z中第一小部分;
2*x(1)+2*x(2)<12;!硬约束;
@for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); !利用设置完毕的数据构建软约束的表达式;
!软约束表达式;
@for(variable:@gin(x));!限制变量为整数;
end
此时,第一目标最优值为0,第一级偏差为0,下面进行第二步:
二级目标:
!求得dminus(1)=0,接着求解第二个目标;
model:
sets:
variable/1..2/:x;!规定变量;
s_con_num/1..4/:g,dplus,dminus;!软约束条件个数以及相关参数;
s_con(s_con_num,variable):c;!软约束系数;
endsets
data:
g=1500 0 16 15;
c=200 300 2 -1 4 0 0 5;
enddata
min=dminus(2)+dplus(2);!第二个目标函数;
2*x(1)+2*x(2)<12;!硬约束;
@for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i));
!软约束表达式;
dminus(1)=0;!第一目标结果;
@for(variable:@gin(x));
end
此时,第二目标最优值为0,偏差为0,下面进行第三步:
三级目标:
!求得dminus(2)=0,接着求解第三个目标;
model:
sets:
variable/1..2/:x;!规定变量;
s_con_num/1..4/:g,dplus,dminus;!软约束条件个数以及相关参数;
s_con(s_con_num,variable):c;!软约束系数;
endsets
data:
g=1500 0 16 15;
c=200 300 2 -1 4 0 0 5;
enddata
min=3*dminus(3)+3*dplus(3)+dminus(4);!第三个目标函数;
2*x(1)+2*x(2)<12;!硬约束;
@for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i));
!软约束表达式;
dminus(1)=0;!第一目标约束;
dminus(2)+dplus(2)=0;!二级目标约束;
@for(variable:@gin(x));
end
最终求得x1=2,x2=4,dplus(1)=100,最优利润为1600
由于上面的过程需要编写好几个程序,在使用时不方便,下面给出Lingo编写的一个通用程序,在程序中用到数据段未知数据的编程方法。
!序贯算法的核心就在于按照p的优先级依次视作单目标规划去求解 eg.p1表示优先级为1的,需要第一个计算;
model:
sets:
level/1..3/:p,z,goal;
variable/1..2/:x;
h_con_num/1..1/:b;
s_con_num/1..4/:g,dplus,dminus;
!以上为建立变量;
h_con(h_con_num,variable):a;!构建约束;
s_con(s_con_num,variable):c;!构建约束;
obj(level,s_con_num)/1 1,2 2,3 3,3 4/:wplus,wminus;!定义P(i)与dplus(i)、dminus(i)之间的系数.其中1 1代表P(1)和dplus(1)、dminus(1)的系数;
endsets
data:
ctr=?; !?表示需要输入;
goal=??0; !因为是一级一级去求偏差的,所以一共三级时,求解到最后一级时只需要输入前两级的最优偏差约束即可,所以goal是??0;
b=12;
g=1500 0 16 15;
a=2 2;
c=200 300 2 -1 4 0 0 5;
wplus=0 1 3 1;
wminus=1 1 3 0;
enddata
min=@ sum(level:p*z); !这个是按照一级一级来求的,因为从该行往下第二行可以发现在求该级目标的时候,其他级的系数均置为了0.;
p(ctr)=1; !p是序贯算法中的表示优先级的因子,不是一个系数。所以这里当作系数运算时令为1,详见下一行注释。序贯算法的核心就在于按照p的优先级依次视作单目标规划去求解 eg.p1表示优先级为1的,需要第一个计算;
@for(level(i)|i#ne#ctr:p(i)=0);!i不等于ctr时,p(i)为0;
@for(level(i):z(i)=@sum(obj(i,j):wplus(i,j)*dplus(j)+wminus(i,j)*dminus(j)));!构建z(i);
@for(h_con_num(i):@sum(variable(j):a(i,j)*x(j))<b(i));!第一个刚性约束;
@for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); !柔性约束;
@for(level(i)|i#lt#@ size(level):@ bnd(0,z(i),goal(i))); !这里是为了带上之前求出来的级别最优偏差的约束:0=<z(i)<=goal(i);
end
当程序运行时,会出现一个对话框。
在做第一级目标计算式,ctr输入1,goal(1),goal(2)输入两个较大的值(goal代表最优偏差),表明这两项约束不起作用。
求的第一级最优偏差为0,进行第二轮的计算。
在第二轮的目标运算中,ctr输入2,由于第一级偏差为0,因此goal(1)的输入值为0。
goal(2)输入一个较大的值,求得第二级的最优偏差仍为0,进行第三级计算。
在第三级计算中,ctr输入3,由于第一级,第二级偏差均为0,因此goal(1),goal(2)输入值均为0.