一、线性目标规划介绍
线性规划在实践中得到了广泛的应用,但是存在两方面的不足:一是不能处理多目标优化的问题;二是其约束条件过于刚性化,不允许约束资源有丝毫差错。目标规划就是为了解决上述问题不足,而创建的一类数学模型。
在处理多目标问题分析各类目标的重要性时,引入了赋予个目标优先因子和加权系数等概念,进一步完善了数学模型,这里仅介绍有优先等级和加权系数的线性目标规划,下面所提到的目标规划均指线性目标规划。
二、目标规划的数学模型
在实际工厂决策时,需要考虑市场等一系列其他条件。
根据市场信息,产品Ⅰ的销售量有下降的趋势,故考虑产品Ⅰ的产量不大于产品Ⅱ。
超过计划供应的原材料时,需要高价采购,会使成本大幅度增加。
应尽可能充分利用设备台班,但不希望加班;
应尽可能达到并超过利润指标56元。
这样考虑产品决策,称为多目标决策问题。目标规划方法是解这类决策问题的方法之一。下面引入与建立目标规划数学模型有关的概念。正负偏差变量
,
:设
为决策变量,此外,引进正偏差变量
表示决策值超过目标值的部分;负偏差变量
表示决策值未达到目标值的部分。因为决策值不可能既要超过目标值同事又未达到目标值,即恒有
。
绝对约束和目标约束:绝对约束是指必须严格满足的等式约束和不等式约束;如线性规划问题的所有约束条件,不能满足这些约束条件的解称为非可行解,所以它们是硬约束。目标约束时目标规划特有的,可把约束右端项看做要追求的目标值。在达到此目标值时允许发生在偏差或负偏差,因此在这些约束中加入正负偏差变量,它们是软约束。线性规划问题的目标函数,在给定目标值和加入正负偏差变量后可变换为目标约束。也可以根据问题的需要将绝对约束变换为目标约束。
优先因子(优先等级)与权系数:一个规划问题常常有若干目标。但决策者在要求达到这些目标时,是由主次或轻重缓急的。要求第一位达到的目标赋予优先因子
,次位的目标赋予优先因子
,并规定
。表示
比
有更大的优先权。即首先保证
级目标的实现,这是可不考虑次级目标;而
级目标是在实现
级目标的基础上考虑的;以此类推。若要区别具有相同优先因子的两个目标的差别,这是可以分别赋予它们不同的权系数
,这些都由决策者按具体情况而定。
-
目标规划的目标函数:目标规划的目标函数(准则函数)是按照个目标约束的正、负偏差变量和赋予相应的优先因子及权系数而构造的。当每一目标值确定后,决策者的要求是尽可能缩小偏离目标值。因此目标规划的目标函数只能是。其基本形式有三种:
- 要求恰好达到目标值,即正负偏差变量都要尽可能地小,这时:
- 要求不超过目标值,即允许达不到目标值,就是正偏差变量要尽可能地小。这时
- 要求超过目标值,即超过量不限,但是必须是负偏差变量要尽可能地小,这时
- 要求恰好达到目标值,即正负偏差变量都要尽可能地小,这时:
对每一个具体目标规划问题,可根据决策者的要求和赋予个目标的优先因子来构造目标函数。而在建立目标规划的数学模型时,需要确定目标值、优先等级、权系数等,它都具有一定的主观性和模糊性,可以用专家评定法给以量化。
三、解目标规划的图解法
对只具有两个决策变量的目标规划的数学模型,可以使用图解法来分析求解。
先在平面直角坐标系的第一象限画出各约束条件。绝对约束条件的作图和线性规划相同。
四、解目标规划的单纯形法
目标规划的数学模型结构与线性规划的数学模型结构形式上并没有本质的区别,所以可用单纯形法求解。但是要考虑目标规划的数学模型一些特点,现做以下规定:
- 因目标规划问题的目标函数都是求最小化,所以以
为最优准则。
- 因非基变量的检验数中含有不同等级的优先因子,即
因
;从每个检验数的整体来看:检验数的正负首先决定于的
系数
的的正负。若
,这时此检验数的正负就决定于
的系数
的正负,下面可以类推。
解目标规划问题的单纯形法的计算步骤如下:
- 建立初始单纯形表,在表中将检验数行按优先因子个数分别列成K行,置k=1,即对应优先因子行中的第一行开始计数。
- 检查该行中是否存在负数,且对应列的前k-1行的系数是零。若有负数取其中最小者对应的变量为换入变量,转第三步。若无负数,转第五步;
- 按最小比值规则确定换出变量,当存在两个和两个以上相同的最小比值时,选取具有较高优先级别的变量为换出变量。
- 按单纯形法进行基变换运算,建立新的计算表,返回第二步。
- 当k=K时,计算结束。表中的解即为满意解。否则置k=k+1,返回第二步。
五、项目实战
5.1 案例一
某研究所领导在考虑本单位职工的升级调资方案时,依次遵循以下优先级顺序规定:
(1) 不超过年工资总额3000万元;
(2)提级时,每级的人数不超过定编规定的人数;
(3)Ⅱ,Ⅲ级的升级面尽可能达到现有人数的20%,且无越级提升。
此外,Ⅲ级不足编制的人数可录用新职工,又Ⅰ级的职工有10%要退休。
有关资料汇总于下表,问该领导应如何拟定一个满意的方案。
等级 | 工资额/(万元/年) | 现有人数/人 | 编制人数 |
---|---|---|---|
Ⅰ | 10.0 | 100 | 120 |
Ⅱ | 7.5 | 120 | 150 |
Ⅲ | 5.0 | 150 | 150 |
合计 | 370 | 420 |
解:使用线性目标规划来求解此问题,设分别表示提升到Ⅰ、Ⅱ级和录用到Ⅲ级的新职工人数。对各目标确定的优先因子为:
-
-- 不超过年工资总额3000万元;
-
-- 每级的人数不超过定编规定的人数;
-
-- Ⅱ、Ⅲ级的升级面尽可能达到现有人数的20%。
先分别建立各目标约束。
年工资总额不超过3000万元
每级的人数不超过定编规定的人数:
对Ⅰ级有:
对Ⅱ级有:
对Ⅲ级有:
Ⅱ、Ⅲ级的升级面不大于现有人数的20%:
对Ⅱ级有:
对Ⅲ级有:
目标函数:
经过整理后得到下列目标规划模型
该问题最终还是转换成了一个LP的问题,如何使用cplex来进行求解了,这里我们需要自定义优先因子,这里我们不妨分别取
来代表其优先级,权系数从这里看都是1,这里的正负偏差,我们可以当作决策变量来考虑,即目标规划模型转化为以下线性规划模型:
package com.opreation.research;
import ilog.concert.*;
import ilog.cplex.IloCplex;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.util.HashSet;
import java.util.Random;
import static ilog.cplex.IloCplex.IntParam.SolnPoolIntensity;
/**
* @Description: 线性目标规划求解
* @Author
* @Date 2022/7/28 14:18
*/
public class LPTest {
public static void main(String[] args) throws IloException {
try{
// 1. 创建模型
IloCplex cplex = new IloCplex();
// 2. 定义优化参数
// 定义基本参数
IloNumVar[] x = cplex.numVarArray(3, 0, Double.MAX_VALUE);
// 定义约束参数
IloNumVar[] d = cplex.numVarArray(12, 0, Double.MAX_VALUE);
double[] c = {10, 0, 5, 0, 5, 0, 5, 0, 0, 1, 0, 1};
IloNumExpr cs1 = cplex.numExpr();
for(int i=0;i<12;i++){
cs1 = cplex.sum(cs1,cplex.prod(c[i], d[i]));
}
// 3. 设置目标函数
cplex.addMinimize(cs1);
// 4. 设置约束
cplex.addEq(cplex.sum(cplex.prod(2.5,x[0]), cplex.prod(2.5,x[1]), cplex.prod(5,x[2]), d[1], cplex.prod(-1, d[0])), 450);
cplex.addEq(cplex.sum(x[0], d[3], cplex.prod(-1, d[2])), 30);
cplex.addEq(cplex.sum(cplex.prod(-1,x[0]), x[1], d[5], cplex.prod(-1, d[4])), 30);
cplex.addEq(cplex.sum(cplex.prod(-1, x[1]), x[2], d[7], cplex.prod(-1, d[6])), 0);
cplex.addEq(cplex.sum(x[0], d[9], cplex.prod(-1, d[8])), 24);
cplex.addEq(cplex.sum(x[1], d[11], cplex.prod(-1, d[10])), 30);
// // 5. 模型求解及输出
if(cplex.solve()){
cplex.output().println("Solution status = " + cplex.getStatus());
cplex.output().println("Solution Value = " + cplex.getObjValue());
double[] val = cplex.getValues(x);
double[] vald = cplex.getValues(d);
for(int j=0;j<3;j++){
System.out.println("x" + (j+1) + " = " + val[j]);
}
for(int j=0;j<12;j++){
System.out.println("d" + (j+1) + " = " + vald[j]);
}
}
cplex.end();
} catch (IloException e){
System.err.println("Concert exception caught: " + e);
}
}
}
运行结果:
Tried aggregator 1 time.
LP Presolve eliminated 1 rows and 8 columns.
Reduced LP has 5 rows, 7 columns, and 12 nonzeros.
Presolve time = 0.00 sec. (0.00 ticks)
Iteration log . . .
Iteration: 1 Dual objective = 0.000000
Solution status = Optimal
Solution Value = 0.0
x1 = 24.0
x2 = 30.0
x3 = 0.0
d1 = 0.0
d2 = 315.0
d3 = 0.0
d4 = 6.0
d5 = 0.0
d6 = 24.0
d7 = 0.0
d8 = 30.0
d9 = 0.0
d10 = 0.0
d11 = 0.0
d12 = 0.0
结果分析:
在课本习题上给出的满意解是取值为0,此时变量(晋升到Ⅰ级的人数/人)、
(晋升到Ⅱ级的人数/人)、
(新招收Ⅲ级的人数/人)、
(工资总额的结余额/万元)、
(Ⅰ级缺编人数/人)、
(Ⅱ级缺编人数/人)、
(Ⅲ级缺编人数/人)分别为24、30、30、16.5、6、24、0。
在cplex的给出的满意解取值为0,此时变量(晋升到Ⅰ级的人数/人)、
(晋升到Ⅱ级的人数/人)、
(新招收Ⅲ级的人数/人)、
(工资总额的结余额/万元)、
(Ⅰ级缺编人数/人)、
(Ⅱ级缺编人数/人)、
(Ⅲ级缺编人数/人)分别为24、30、0、315、6、24、30。
这里cplex求出的满意解和书本上的满意解不一样,这边将cplex求出来的满意解代入计算一下:
从上述计算结果可知,该问题有多个满意解,cplex求解出来的解和书本上的解都是满意解。
5.2 案例二
已知有三个产地给四个销地供应某种产品,产销地之间的供需量和单位运价表见下表。有关部门在研究调运方案时依次考虑以下七项目标,并规定其相应的优先等级:
---
是重点保证单位,必须全部满足其需要;
---
向
提供的产量不少于100;
--- 每个销地的供应量不小于其需要量的80%;
--- 所定调运方案的总费用不超过最小运费调用方案的10%;
--- 因路段的问题,尽量避免安排将
的产品往
;
--- 给
和
的供应率要相同;
--- 力求总运费最省;
试求满意的调运方案。
产地 | 销地 | 产量 | |||
---|---|---|---|---|---|
5 | 2 | 6 | 7 | 300 | |
3 | 5 | 4 | 6 | 200 | |
4 | 5 | 2 | 3 | 400 | |
销量 | 200 | 100 | 450 | 250 | 900/1000 |
解:目标函数为:
供应约束
需求约束
向
提供的产品了不少于100:
每个销地的供应量不小于其需要量的80%:
调运方案的总费用不超过最小运费调运方案的10%:
力求总运费最省
最终得到总运费为3360元。