指派问题——航班安排问题的R实现
在生活中经常遇到这样的问题,某单位需完成n项任务,恰好有n个人可承担这些任务。由于每人的专长不同,各人完成任务不同(或所费时间),效率也不同。于是产生应指派哪个人去完成哪项任务,使完成n项任务的总效率最高(或所需总时间最小),这类问题称为指派问题或分派问题。
一、指派问题的数学模型
最优指派问题也称为最优匹配问题,它是运输问题的特殊情况。
例:有一份中文说明书,需译成英、日、德、俄、法5种文字,分别记作A、B、C、D、E。现有甲、乙、丙、丁、戊5人,他们将中文说明书翻译成不同语种的说明书所需时间如下表所示。问应指派何人去完成何工作,使所需总时间最少?
A | B | C | D | E | |
---|---|---|---|---|---|
甲 | 3 | 5 | 2 | 1 | 6 |
乙 | 2 | 1 | 4 | 3 | 5 |
丙 | 4 | 3 | 1 | 2 | 5 |
丁 | 6 | 1 | 2 | 3 | 5 |
戊 | 5 | 3 | 4 | 6 | 1 |
对应每个指派问题,需有类似上表那样的数表,称为效率矩阵或系数矩阵,其元素\(c_{ij}>0(i,j = 1,2,…,𝑛)\)表示指 派第\(i\)人去完成第\(j\)项任务时的效率(或时间、成本等)。
一般指派问题描述如下:
设有\(n\)个人,计划做\(n\)项工作,其中$ c_{ij}$ 表示第\(i\) 个人做第\(j\)项工作的收益,现求一种指派方式,使得每个人完成一项工作,总收益最大。
设决策变量为\(x_{ij}\), 当第\(i\)个人做第\(j\)项工作时,决策变量\(x_{ij}=1\);否则,决策变量\(x_{ij}=0\),因此最优指派问题可以写成0-1规划模型:
如果\(c_{ij}\)表示第\(i\)个人做第\(j\)项工作所用的花费,则目标函数为求最小。
二、航班安排问题
某航空公司经营 A、B、C 三个城市的航线,这些航线每天班次起飞与到达时间如下表。 设飞机在机场停留的损失费用大致与停留时间的平方成正比。又每架飞机从降落 到下班起飞至少需2小时准备时间,航班安排信息见下表,试决定一个使停留 费用损失为最小的分配飞行方案。
航班号 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
起飞城市 | A | A | A | A | A | B | B | B | C | C | B | B | C | C |
起飞时间 | 9:00 | 10:00 | 15:00 | 20:00 | 22:00 | 4:00 | 11:00 | 15:00 | 7:00 | 15:00 | 13:00 | 18:00 | 15:00 | 7:00 |
到达城市 | B | B | B | C | C | A | A | A | A | A | C | C | B | B |
到达时间 | 12:00 | 13:00 | 18:00 | 24:00:00 | 2:00 (次日) | 7:00 | 14:00 | 18:00 | 11:00 | 19:00 | 18:00 | 23:00 | 20:00 | 12:00 |
【解析】该问题目标就是要减少机场停留时间,做好航班之间的衔接,下面分A、B、C三个城市考虑其损失费用。由表中数据可知,飞到A城市的航班有106、107、108、109和110,从A机场起飞的航班有101、102、103、104和105,下面计算他们续飞各种可能的费用,考虑109航班续接102航班的机场停留时间,109航班11.00到达A机场,102航班计划起飞时间为10.00,所以当天不能续飞,只能等到第二天起飞,要等待时间为23小时,费用为529K,其他情况同理计算,就得在A城市损失费用矩阵如下:
A城市损失费用:
起飞\到达 | 101 | 102 | 103 | 104 | 105 |
---|---|---|---|---|---|
106 | 4k | 9k | 64k | 169k | 225k |
107 | 361k | 400k | 625k | 36k | 64k |
108 | 225k | 256k | 441k | 4k | 16k |
109 | 484k | 529k | 16k | 81k | 121k |
110 | 196k | 225k | 400k | 625k | 9k |
因而可用指派问题进行求解,获得在A城市停留的最小费用。由于损失费用矩阵乘上同一个正数不影响其最优解,所以不用考虑损失费用的计量单位。
同理,B城市损失费用:
起飞\到达 | 106 | 107 | 108 | 111 | 112 |
---|---|---|---|---|---|
101 | 256k | 256k | 256k | 256k | 256k |
101 | 256k | 256k | 256k | 256k | 256k |
102 | 225k | 225k | 225k | 225k | 225k |
103 | 100k | 100k | 100k | 100k | 100k |
113 | 64k | 64k | 64k | 64k | 64k |
同理,C城市损失费用:
起飞\到达 | 109 | 110 | 113 | 114 |
---|---|---|---|---|
104 | 49k | 225k | 225k | 49k |
105 | 25k | 169k | 169k | 25k |
111 | 169k | 441k | 441k | 169k |
112 | 64k | 256k | 256k | 64k |
三、航班安排的R实现
调用R语言程序包“lpsolve”,求解上面三个指派问题的最优解,得出航班安排方案。
3.1 A城市费用
library(lpSolve)
a1 = c(4, 9, 64, 169,225)
a2 = c(361, 400, 625, 36, 64)
a3 = c(225, 256, 441, 4, 16)
a4=c(484, 529, 16, 81, 121)
a5=c(196, 225, 400, 625, 9)
cost = rbind(a1,a2,a3,a4,a5)
colnames(cost)=c("101","102","103","104","105")
rownames(cost)=c("106","107","108","109","110")
assign.sol<-lp.assign(cost.mat=cost,direction="min")
assign.sol$solution
colnames(assign.sol$solution)=c("101","102","103","104","105")
rownames(assign.sol$solution)=c("106","107","108","109","110")
assign.sol$solution
assign.sol$objval
assign.sol$solution #最优指派方案
101 102 103 104 105
106 0 1 0 0 0
107 0 0 0 1 0
108 0 0 0 0 1
109 0 0 1 0 0
110 1 0 0 0 0
assign.sol$objval #最优值
273
起飞\到达 | 101 | 102 | 103 | 104 | 105 |
---|---|---|---|---|---|
106 | 0 | 1 | 0 | 0 | 0 |
107 | 0 | 0 | 0 | 1 | 0 |
108 | 0 | 0 | 0 | 0 | 1 |
109 | 0 | 0 | 1 | 0 | 0 |
110 | 1 | 0 | 0 | 0 | 0 |
3.2 B城市费用
library(lpSolve)
a1 = c(256, 529, 9, 625, 36)
a2 = c(225, 484, 4, 576, 25)
a3 = c(100, 289, 441, 361, 576)
a4=c(64, 225, 361, 289, 484)
a5=c(256, 529, 9, 625, 36)
cost = rbind(a1,a2,a3,a4,a5)
colnames(cost)=c("106","107","108","111","112")
rownames(cost)=c("101","102","103","113","114")
assign.sol<-lp.assign(cost.mat=cost,direction="min")
colnames(assign.sol$solution)=c("106","107","108","111","112")
rownames(assign.sol$solution)=c("101","102","103","113","114")
assign.sol$solution
assign.sol$objval
assign.sol$solution
106 107 108 111 112
101 0 0 0 0 1
102 1 0 0 0 0
103 0 1 0 0 0
113 0 0 0 1 0
114 0 0 1 0 0
assign.sol$objval
848
起飞\到达 | 106 | 107 | 108 | 111 | 112 |
---|---|---|---|---|---|
101 | 0 | 0 | 0 | 0 | 1 |
102 | 1 | 0 | 0 | 0 | 0 |
103 | 0 | 1 | 0 | 0 | 0 |
113 | 0 | 0 | 0 | 1 | 0 |
114 | 0 | 0 | 1 | 0 | 0 |
3.3 C城市费用
library(lpSolve)
a1 = c(49, 225, 225, 49)
a2 = c(25, 169, 169, 25)
a3 = c(169, 441, 441, 169)
a4=c(64, 256, 256, 64)
cost = rbind(a1,a2,a3,a4)
colnames(cost)=c("109","110","113","114")
rownames(cost)=c("104","105","111","112")
assign.sol<-lp.assign(cost.mat=cost,direction="min")
colnames(assign.sol$solution)=c("109","110","113","114")
rownames(assign.sol$solution)=c("104","105","111","112")
assign.sol$solution
assign.sol$objval
assign.sol$solution
109 110 113 114
104 0 1 0 0
105 0 0 1 0
111 1 0 0 0
112 0 0 0 1
assign.sol$objval
627
起飞\到达 | 109 | 110 | 113 | 114 |
---|---|---|---|---|
104 | 0 | 1 | 0 | 0 |
105 | 0 | 0 | 1 | 1 |
111 | 0 | 0 | 0 | 0 |
112 | 1 | 0 | 0 | 0 |
所以使停留费用损失最小的方案为:
101(A)→110(C) →104(A) →107(B) →103(A) →109(C) →112(B) →101(A)
102(A) →106(B) →102(A)
105(A) →108(B) →114(C) →111(B) →113(C) →105(A)
损失费:273K+848K+627K=1748K