运筹学中的节约里程法及其python实现
节约里程法简介
节约里程法,又称C-W算法 、节约算法或节约法,是由Clarke和Wright于1964年首次提出的,用来解决VRP问题,是重要的物流算法,是用来解决运输车辆数目不确定的问题的最有名的启发式算法。
节约里程法核心思想是依次将运输问题中的两个回路合并为一个回路,每次使合并后的总运输距离减小的幅度最大,直到达到一辆车的装载限制时,再进行下一辆车的优化。优化过程分为并行方式和串行方式两种。
利用节约法确定配送路线的主要出发点是,根据配送中心的运输能力和配送中心到各个用户以及各个用户之间的距离来制定使总的车辆运输的吨公里数最小的配送方案。另还需满足以下条件;(1)所有用户的要求;(2)不使任何一辆车超载;(3)每辆车每天的总运行时间或行驶里程不超过规定的上限;(4)用户到货时间要求。
基本原理
基本思想为为达到高效率的配送,使配送的时间最小距离最短成本最低,而寻找的最佳配送路线。
假定有n个访问地,把每个访问地看成一个点,并取其中的一个点为基点(起点),例如以1点为基点。首先将每个点与该基点相连接,构成线路1→j→1(j=2,3,…,n),这样就得到了一个具有n-1条线路的图(当然,这时尚未形成Hamilton回路)。旅行者按此线路访问这n个点所走的路程总和为
z=∑j=2nC1jz=\sum_{j=2}^n{C_{1j}}z=j=2∑nC1j
其中C1jC_{1j}C1j为由点1到点j的路段长度,注意此处假定C1j=Cj1C_{1j}=C_{j1}C1j=Cj1(对所有j)。
若连接点i和点j,即使旅行者走弧(i,j)时(当然这时就不再经过弧(i,1)和弧(1,j),所引起的路程节约值s(i,j)可计算如下
s(i,j)=2c1i+2c1j−c1i+c1j+cij)=c1i+c1j−cijs(i,j)=2c_{1i}+2c_{1j}-c_{1i}+c_{1j}+c_{ij})=c_{1i}+c_{1j}-c_{ij}s(i,j)=2c1i+2c1j−c1i+c1j+cij)=c1i+c1j−cij
对不同的点对(i,j),s(i,j)越大,旅行者通过弧(i,j)时所节约的路程越多,因而应优先将其安排到旅行线路中去,使旅行者旅行时通过这一条弧。
迭代步骤
在具体应用该方法时,可按以下步骤进行。
(1)选取基点,例如以1点为基点。将每个点与该基点相连接,得到n-1条线路1→j→1(j=2,3,…,n)。
(2)对不违背限制条件的所有可连接点对(i,j),如下计算其节约值(i,j不为基点)
s(i,j)==c1i+c1j−cijs(i,j)==c_{1i}+c_{1j}-c_{ij}s(i,j)==c1i+c1j−cij
(3)将所有s(i,j)s(i,j)s(i,j)按其值的大小由大到小排列。
(4)按s(i,j)s(i,j)s(i,j)的上述顺序,逐个考察其端点i和j,若满足以下条件,就将弧(i,j)插入到线路中。其条件是:
a. 点i和点j不在一条线路上;
b. 点i和点j均与基点相邻。
(5)返回步骤(4),直至考察完所有可插入弧(i,j)为止。
通过以上各迭代步骤,使问题的解逐步得到改善,最后达到满意解(也有可能达到最优解)。
例题
已知配送中心P0向5个用户Pj配送货物,其配送路线网络、配送中心与用户的距离以及用户之间的距离如下图所示,配送中心有3台2t卡车和2台4t两种车辆可供使用。利用节约里程法制定最优的配送方案。
第一步,作运输里程表,列出配送中心到用户及用户间的最短距离。
第二步,按节约里程公式求得相应的节约里程数。
第三步,将节约里程按从大到小顺序排列。
第四步,根据载重量约束与节约里程大小,顺序连接各客户结点,形成两个配送线。
P2P3-P3P4-P2P4-P4P5-P1P2-P1P5-P1P3-P2P5-P3P5-P1P4
得出结果:
配送线路一:
运量=1.7+0.9+1.4=4t
运行距离=8+4+5+7=24km
用一辆4t车运送,节约距离为18km
配送线路二:
运量=2.4+1.5=3.9t<4t
运行距离=8+10+16=34km
用一辆4t车运送,节约距离为2km
初始方案:配送线路5条,需要车5辆,配送距离=39*2=78km
优化后的方案:2条配送路线,2辆4t车,配送距离=24+34=58km
python程序
import csv
from operator import itemgetterclass Vrp():# -----------初始数据定义---------------------def __init__(self):self.mans = 9 # 客户数量self.tons = 3 # 车辆载重self.distanceLimit = 1000 # 车辆一次行驶的最大距离self.distance = [] # 各个客户及配送中心距离self.q = [0, 1, 1.1, 0.9, 0.8, 1.1, 0.4, 0.7, 0.8, 0.9] # 10个客户分布需要的货物的需求量,第0位为配送中心自己self.savings = [] # 节约度self.Routes = [] # 路线self.Cost = 0 # 总路程# -----------导入距离数据---------------------def datainput(self):with open("data.csv", "r") as csvfile:reader = csv.reader(csvfile)for line in reader:line = [float(x) for x in line]self.distance.append(line)# -----------节约算法主程序---------------------def savingsAlgorithms(self):saving = 0for i in range(1, len(self.q)):self.Routes.append([i])for i in range(1, len(self.Routes) + 1): # 使用Sij = Ci0 + C0j - Cij计算节约度for j in range(1, len(self.Routes) + 1):if i == j:passelse:saving = (self.distance[i][0] + self.distance[0][j]) - self.distance[i][j]self.savings.append([i, j, saving]) # 将结果以元组形式存放在列表中self.savings = sorted(self.savings, key=itemgetter(2), reverse=True) # 按照节约度从大到小进行排序for i in range(len(self.savings)):print(self.savings[i][0],'--',self.savings[i][1], " ",self.savings[i][2]) # 打印节约度for i in range(len(self.savings)):startRoute = []endRoute = []routeDemand = 0for j in range(len(self.Routes)):if (self.savings[i][0] == self.Routes[j][-1]):endRoute = self.Routes[j]elif (self.savings[i][1] == self.Routes[j][0]):startRoute = self.Routes[j]if ((len(startRoute) != 0) and (len(endRoute) != 0)):for k in range(len(startRoute)):routeDemand += self.q[startRoute[k]]for k in range(len(endRoute)):routeDemand += self.q[endRoute[k]]routeDistance = 0routestore = [0]+endRoute+startRoute+[0]for i in range(len(routestore)-1):# print(routestore[i],routestore[i+1])# print(self.distance[routestore[i]][routestore[i+1]])routeDistance += self.distance[routestore[i]][routestore[i+1]]#print(routestore,"== ==:",routeDistance)if (routeDemand <= self.tons) and (routeDistance <= self.distanceLimit): # 按照限制规则对路线进行更改self.Routes.remove(startRoute)self.Routes.remove(endRoute)self.Routes.append(endRoute + startRoute)breakfor i in range(len(self.Routes)):self.Routes[i].insert(0, 0)self.Routes[i].insert(len(self.Routes[i]), 0)# -----------输出最终结果---------------------def printRoutes(self):for i in self.Routes:costs = 0for j in range(len(i)-1):costs += self.distance[i[j]][i[j+1]]print("路线: ",i," 路程: ",costs)def calcCosts(self):for i in range(len(self.Routes)):for j in range(len(self.Routes[i]) - 1):self.Cost += self.distance[self.Routes[i][j]][self.Routes[i][j + 1]]print("\nTotal Distance: ", round(self.Cost, 3))# -----------Master函数---------------------def start(self): # Master函数,调用所有其他函数print("== == == == == == == == == == == == == == == 导入数据 == == == == == == == = == == == == == == == =")self.datainput()print("== == == 距离表 == == ==")for i in self.distance:print(i)print("== == == 需求表 == == ==")print(self.q)print("== == == 限制条件 == == ==")print("车辆最大载重:",self.tons)print("车辆最长运输距离:", self.distanceLimit)print("== == == == == == == == == == == == == == == 节约度 == == == == == == == = == == == == == == == =")self.savingsAlgorithms() # 函数调用计算节省量并生成路线print("== == == == == == == == == == == == == == == 结果 == == == == == == == = == == == == == == == =")self.printRoutes()self.calcCosts()self.datainput()if __name__ == '__main__':vrp = Vrp()vrp.start()
参考网址:
节约里程法-百度百科
节约里程算法的python实现(含github地址)
C# 节约里程法实现(原理很详细,还有例题)
运筹学中的节约里程法及其python实现相关推荐
- 节约里程法java代码_患者,男,70岁,有多年排尿困难,呈淋漓状,近2年来双侧腹股沟区出现半年圆形肿块,站立时明显,平卧后消失,体检时压迫内环肿块仍出现,诊断为...
In cross-cultural training process, language can have a important impact on social adaptation. 关于环己烷 ...
- 求解VRP问题的节约里程法、sweep扫描算法和λ互换法
第05章 求解容量约束车辆路径问题的启发式算法 Edited by Jiannywang@163.com 目 录 5.1 节约里程法. 1 5.1.1 C-W节约算法简介. 1 5.1.2 C-W ...
- matlab节约里程法_芳烃产业链里程碑:唐山旭阳30万吨/年苯乙烯项目一次性开车成功...
近日,中国旭阳集团(1907.HK)旗下唐山旭阳30万吨/年苯乙烯项目分析化验合格后的苯乙烯从退料管线切至产品采出管线,标志着年产30万吨苯乙烯装置各流程全部打通,产品合格采出,装置一次性开车成功,使 ...
- python中一个对象只能被一个变量引用吗_Python中for循环里的变量无法被引用的解决方法...
在之前的编程语言里,学到for循环里面是可以重置变量i的值的,然后让整个for循环从头开始,但是在python里面却行不通这是为什么呢? 在python中,for循环相当于一个迭代器(Iterator ...
- 【Python——类】 同一个类中一个函数里调用另一个函数的方法
[Python-类] 同一个类中一个函数里调用另一个函数的方法 class Solution:def a(self):self.b() # 注意这种写法:self.类名def b(self):prin ...
- idea python-IDEA里如何安装Python插件打造开发环境(图文详解)
前言 python是一种功能强大和适用面很广的开发语言,在大数据应用和机器学习日益流行的年代,python凭借其简洁.易用和可扩展性获得很多用户的支持,近年来使用率高速增长.python环境下,集成了 ...
- python在审计中的应用-【干货】Python自动化审计及实现
在这个语法树构造中,body里包含着if构造中的语句return HttpResponse("2"),type为Compare表示该构造体为断定语句,left表示左值即源码中的ty ...
- python中的字典推导式_17.python 字典推导式(经典代码)
在昨天的文章中,我们介绍了关于** python列表推导式** 的使用,字典推导式使用方法其实也类似,也是通过循环和条件判断表达式配合使用,不同的是字典推导式返回值是一个字典,所以整个表达式需要写在{ ...
- python中的命名空间_深入理解Python中的命名空间和范围
Python中的命名空间和范围 在Python中,每个包.模块.类.函数和方法函数都拥有一个"名称空间",其中解析了变量名称.下面本篇文章就来带大家认识一下Python中的命名空间 ...
- 如何用Python读取Excel中图片?又如何用Python往Excel中写入图片?
大家好,在使用Python进行办公自动化操作时,一定少不了与Excel表格的交互,我们通常是用pandas处理表格数据,但大多数情况下,都是读取表格中的数值进行分析. 那么你知道如何使用Python读 ...
最新文章
- 羊皮卷的故事-第十章-羊皮卷之三
- php-css外边距
- 计算机分php,计算机按照处理数据的形态分类,可以分为什么?
- [20170927]关于hugepages.txt
- GitHub Actions使用学习最全文档
- 启动tomcat的startup.bat闪退问题
- 2011年工作简单总结
- Farkas 定理的几何证明
- python群发邮件 不进垃圾箱_邮件群发如何不进垃圾箱
- 百度地图api调用时json.loads()报错ValueError: No JSON object could be decoded解决
- 大数据相关职位的知识储备与系统学习路线规划以及所需时间
- KVM基于Web部署虚拟主机
- (MC维嘉)JAVA 面向对象(3)
- 向量数据库入坑:使用 Docker 和 Milvus 快速构建本地轻量图片搜索引擎
- Epub 阅读器 - iOS
- PHP用户注册页面测试用例,用户注册界面测试用例
- 程序员免费学习编程的5个网站,你知道几个?
- 图片宽度尺寸输出为500px的PX
- iOS 7 Sprite Kit游戏——探险
- 视觉slam14讲ch5 opencv安装 ubuntu20.04
热门文章
- Eclipse / Spring Tool Suite 配置
- 21、2010年中兴面试题
- 多元统计分析基于r课后答案_智慧树多元统计分析及R语言建模课后答案
- 图论及其应用 2012年 期末考试答案总结
- 电力安全工作规程发电厂和变电站电气部分_电气主接线知识精讲!
- 如何判断绩效管理系统实施是否有效
- 惠普z800工作站bios设置_HP工作站 BIOS说明 适用Z228 Z440 Z230 Z640 Z840 Z800 Z620 Z420 Z820主板设置 -...
- RapidXML的读写
- PPT镂空字体、填充文字、图片字、拆分字制作
- canon l11121e驱动_佳能打印机l11121e驱动下载