运输问题和指派问题—R实现
随着社会和经济的不断进步,现代物流业蓬勃发展,如何充分利用时间、信息、仓储、配送和联运体系创造更多的价值,是物流运作必须解决的问题。日益复杂的运输活动使得运输问题变得越来越庞杂,但是其核心思想仍然是实现现有资源的最优化配置。运输问题经常出现在计划货物配送和从某些供给地区到达需求地区之间的服务中,特别是每个供给地区(起点)的货物可获得量是有限的,每个需求地区(目的地)的货物需求量是已知的,运输问题中最常用的目标是要使货物从起点到目的地的运输成本最低。指派问题是运输问题的一种特殊情况,通常涉及到多个任务和多个执行者之间的任务分配,如将工作分配给机器,对代理分配任务,将销售人员分配给销售区域,将合同分配给投标人,等等。
一、运输问题
运输问题(transportation problem) 属于线性规划问题,可以根据模型按照线性规划的方式求解,但由于其特殊性,用常规的线性规划来求解并不是最有效的方法。lpSolve包提供了函数lp.transport() 来求解运输问题。
1.1运输问题的数学模型
一般地,产销平衡的运输问题可以表述为:设有个地点(称为产地或发地),,...,的某种物资调至个地点(称为销地或收地),,...,,各个产地需要调出的物资量分别为单位,各个销地需要调进的物资量分别为 单位,且各个发点的供应量之和等于各个收点的需求量之和。已知每个发点 到每个收点 的物资单位调运价格为,现问如何安排调运,才能使总运费最小。
于是得产销平衡运输问题的数学模型:
=
=
=
不平衡运输问题只要简单地调整约束的松紧关系即得。
1.2 R计算程序
例1: 有三个造纸厂A1、A2 和A3,造纸量分别为16 个单位、10 个单位和22 个单位,四个客户B1、B2、B3 和B4 的需求量分别为8 个单位、14 个单位、12 个单位和14 个单位。造纸厂到客户之间的单位运价如表所示,确定总运费最少的调运方案。单位运价表如下所示:
[,1] [,2] [,3] [,4]
[1,] 4 12 4 11
[2,] 2 10 3 9
[3,] 8 5 11 6
总产量等于总销量,都为48 个单位,这是一个产销平衡的运输问题。
R代码及运行结果如下:
library(lpSolve)
costs <-matrix(c(4,2,8,12,10,5,4,3,11,11,9,6),nrow=3) #运费矩阵
row.signs <- rep("=", 3) #各家造纸厂的产量恰好可以售完,故都取等号
row.rhs <- c(16,10,22) #销量约束值
col.signs <- rep("=", 4) #各家客户需求量恰好可以满足,故都取等号
col.rhs <- c(8,14,12,14) #需求约束值
res <-lp.transport(costs,"min",row.signs,row.rhs,col.signs,col.rhs)
1.3 计算结果
lp.transport(costs,"min",row.signs,row.rhs,col.signs,col.rhs)
Success: the objective function is 244
res <-lp.transport(costs,"min",row.signs,row.rhs,col.signs,col.rhs)
res #输出最小运费
res$solution #输出运输方案
[,1] [,2] [,3] [,4]
[1,] 4 0 12 0
[2,] 4 0 0 6
[3,] 0 14 0 8
输出结果表示问题成功解决,最少运费为244。运送方案为: A1→B1 : 4 个单位,A1→B3 : 12 个单位,A2→B1 :4 个单位,A2→B4 : 6 个单位,A3→B2 : 14 个单位,A3→B4 : 8个单位。
二、运输问题实例
例2:某制药公司在全国设有六个生产基地,这些生产基地每天将这些药分别运往八个地区的经销部门,已知从每个生产基地到各销售部门每箱药品的运价如下表所示,问该制药公司应如何调运(运输方案),使在满足各销售部门需要的情况下,总的运输费用最少?
B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | 产量 | |
---|---|---|---|---|---|---|---|---|---|
A1 | 6 | 2 | 6 | 7 | 4 | 2 | 5 | 9 | 60 |
A2 | 4 | 9 | 5 | 3 | 8 | 5 | 8 | 2 | 55 |
A3 | 5 | 2 | 1 | 9 | 7 | 4 | 3 | 3 | 51 |
A4 | 7 | 6 | 7 | 3 | 9 | 2 | 9 | 1 | 43 |
A5 | 2 | 3 | 9 | 5 | 7 | 2 | 6 | 5 | 41 |
A6 | 5 | 5 | 2 | 2 | 8 | 1 | 4 | 3 | 52 |
销量 | 35 | 37 | 22 | 32 | 41 | 32 | 43 | 38 |
该问题是供大于求的不平衡运输问题。
2.1 R计算程序
#运输问题加载包
library(lpSolve)
#运价矩阵
costs<-matrix(c(6,4,5,7,2,5,2,9,2,6,3,
5,6,5,1,7,9,2,7,3,9,3,5,2,4,8,7,
9,7,8,2,5,4,2,2,1,5,8,3,7,6,4,9,2,3,1,5,3),nrow=6)
row.signs<-rep("<=",6) #产量约束符号
row.rhs<-c(60,55,51,43,41,52) #产量约束向量
col.signs<-rep("=",8) #销量约束符号
col.rhs<-c(35,37,22,32,41,32,43,38) #销量约束向量
#最优解和最优值
res<-lp.transport(costs,"min",row.signs,row.rhs,col.signs,col.rhs)
res
res$solution
2.2 R计算结果
最优值
Success: the objective function is 664
最优解
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 0 19 0 0 41 0 0 0
[2,] 0 0 0 32 0 0 0 1
[3,] 0 12 0 0 0 0 39 0
[4,] 0 0 0 0 0 6 0 37
[5,] 35 6 0 0 0 0 0 0
[6,] 0 0 22 0 0 26 4 0
由R输出结果可知6个生产点8个销售点的最小运费为664,相应的运送方案为A1→B2:19个单位,A1→B5:41个单位,A2→B4:32个单位,A2→B8:1个单位,A3→B2:12个单位,A3→B7:39个单位,A4→B8:37个单位,A5→B1:35个单位,A5→B2:6个单位,A6→B3:22单位,A6→B6:26个单位,A6→B7:4个单位。
三、指派问题
指派问题(assignment problem) 属于0-1 整数规划,是一种特殊的整数规划问题。指派问题的标准形式(以人和事为例) 是:有n个人和n个事,已知第i个人做第j件事的费用为Cij (i; j = 1, 2,…n),要求确定人和事之间的一一对应的指派方案,使完成n件事的总费用最少。指派问题是运输问题中的一种特殊情况,"派合适的人去做合适的事"是对该问题的最贴切描述。工人相当于产地,工作相当于销地,那么劳动就是产品,工资就是运费。所以,运输问题所拥有的特点指派问题都有,而特殊之处就是在指派问题中,各个产地和销地的产量和需求量都是"1"。这个全新的特点使得其解法在运输问题解法的基础上得到了简化。
3.1 指派问题数学模型
最优指派问题也称为最优匹配问题,它是运输问题的特殊情况。问题描述如下:
设有个人,计划做项工作,其中 表示第个人做第项工作的收益,现求一种指派方式,使得每个人完成一项工作,总收益最大。设决策变量为当第个人做第项工作时,决策变量=1;否则,决策变量=0,因此最优指派问题可以写成0-1规划模型:
=
=1
=1
=1 or 0
如果表示第i个人做第j项工作所用的花费,则目标函数为求最小。
例3: 某工厂有6名工人 ,分别操作6台车床。已知每个工人Ai(i = 1, 2,…,6)对每台机床Bj(j = 1,2,…,6) 的每小时单产量为(i; j = 1,2,…,6)。每小时单产量如下表(这里-99表示不会操作),求产值最大的分配方案。
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 20 15 16 5 4 7
[2,] 17 15 33 12 8 6
[3,] 9 12 18 16 30 13
[4,] 12 8 11 27 19 14
[5,] -99 7 10 21 10 32
[6,] -99 -99 -99 6 11 13
3.2 R处理包和函数
#R中lpSolve包提供了函数lp.assign() 来求解标准指派问题,其用法如下:
library(lpsolve)
lp.assign(cost.mat,direction = "min", presolve = 0, compute.sens = 0)
#其中,cost.mat为指派问题的系数矩阵,其元素的意义根据实际情况而定,可以是费用、时间、成本等。direction 为逻辑变量,来决定求总费用的最大值还是最小值,默认求总费用的最小值;compute.sens决定是否进行灵敏度分析。
3.3 R处理程序
library(lpSolve)
z<-c( 20, 15 , 16 , 5, 4, 7, 17, 15, 33, 12 , 8 , 6, 9, 12, 18, 16, 30, 13, 12, 8, 11, 27, 19, 14 ,-99, 7, 10, 21, 10, 32, -99, -99, -99, 6, 11, 13)
cost<-matrix(z,nrow=6,byrow=T)
assign.sol<-lp.assign(cost.mat=cost,direction="max")
assign.sol
#Success: the objective function is 135
assign.sol$solution
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 0 0 0
[2,] 0 0 1 0 0 0
[3,] 0 1 0 0 0 0
[4,] 0 0 0 1 0 0
[5,] 0 0 0 0 0 1
[6,] 0 0 0 0 1 0
最优分配:第1个人做第1项工作;第2个人做第3项工作;第3个人做第2项工作;第4个人做第4项工作;第5个人做第6项工作;第6个人做第5项工作。
四、指派问题实例
例4: 某商业公司计划开办5家新商店。为了尽早建成营业,商业公司决定由6家建筑公司分别承建。已知建筑公司Ai(i = 1, 2,…,5) 对新商店Bj(j = 1,2,…,5) 的建造费用的报价(万元) 为(i; j = 1,2,…,5)。该公司应对5家建筑公司怎样分配建筑任务,才能使总的建筑费用最少?
4.1 费用矩阵
[,1] [,2] [,3] [,4] [,5]
[1,] 4 8 7 18 12
[2,] 7 9 17 14 10
[3,] 6 9 12 8 7
[4,] 6 7 14 6 10
[5,] 6 9 12 10 6
4.2 R计算求解
library(lpSolve)
x=matrix(c(4,7,6,6,6,8,9,9,7,9,7,17,12,14,12,18,14,8,6,10,12,10,7,10,6),ncol=5) ##指派问题的系数矩阵
lp.assign(x)
lp.assign(x)
Success: the objective function is 34
assign.sol<-lp.assign(x,direction="min")
assign.sol$solution
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 1 0 0
[2,] 0 1 0 0 0
[3,] 1 0 0 0 0
[4,] 0 0 0 1 0
[5,] 0 0 0 0 1
从运行结果可以看出,最优解已经成功找到。最优指派方案是:A1 承建B3,A2 承建B2,A3 承建B1,A4 承建B4,A5 承建B5。这样安排能使总费用最少,为7 + 9 + 6 + 6 + 6 = 34 万元。
五、总结
运用运筹学的知识和方法对运输问题进行资源的优化配置和人员的合理分配,不仅可以为企业节省成本,提高效益和利润还可以节约运输的时间,为科学管理带来决策支持,为广大的消费者带来优惠和便利。指派问题是特殊的运输问题,是运输问题的离散化表达。在实际应用中,常会遇到各种非标准形式的指派问题,有时不能直接调用函数,处理方法是将它们化为标准形式(胡运权, 2007),然后再通过标准方法求解。同运输问题一样,有许多软件可以求解这一类问题,比如LINGO 在解决指派问题时,也必须通过各种命令建立数据集、模型、目标函数、约束函数等,比较繁琐,相比之下,R两三句代码就可以快速解决问题,较之LINGO 软件,的确方便快捷了许多。
参考文献
1.运筹学笔记 运输问题
2.【R语言在最优化中的应用】lpSolve包解决 指派问题和指派问题
3.运筹说 第39期 | 运输问题经典例题讲解
4.R语言与优化模型:线性规划、整数规划和运输问题
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)