【进阶六】Python实现SDVRPTW常见求解算法——遗传算法(GA)

基于python语言,采用经典蚁群算法(ACO)对 带硬时间窗的需求拆分车辆路径规划问题(SDVRPTW) 进行求解。

目录

  • 往期优质资源
  • 1. 适用场景
  • 2. 代码调整
    • 2.1 需求拆分
    • 2.2 需求拆分后的服务时长取值问题
  • 3. 求解结果
  • 4. 代码片段

往期优质资源


经过一年多的创作,目前已经成熟的代码列举如下,如有需求可私信联系,表明需要的 **问题与算法**,原创不宜,有偿获取。
VRP问题GAACOALNSDEDPSOQDPSOTSSA
CVRP
VRPTW
MDVRP
MDHVRP
MDHVRPTW
SDVRP
SDVRPTW

1. 适用场景

  • 求解SDVRPTW
  • 车辆类型单一
  • 车辆容量小于部分需求节点需求
  • 单一车辆基地
  • 带硬时间窗

2. 代码调整


2.1 需求拆分


与SDVRP问题相比,SDVRPTW问题不仅允许客户需求大于车辆载重,而且考虑了客户节点的时间窗约束。为了使得每个客户的需求得到满足,必须派遣一辆或多辆车辆在规定时间窗内对客户进行服务。对于需求节点的拆分,这里依然采取先验拆分策略,本文采用文献[1]提出的先验分割策略,表述如下:

(1)20/10/5/1拆分规则

  • m20 =max{ m ∈ Z + ∪ { 0 } ∣ 0.20 Q m < = D i m\in Z^+ \cup \{0\} | 0.20Qm <= D_i mZ+{0}∣0.20Qm<=Di }
  • m10 =max{ m ∈ Z + ∪ { 0 } ∣ 0.10 Q m < = D i − 0.20 Q m 20 m\in Z^+ \cup \{0\} | 0.10Qm <= D_i-0.20Qm_{20}~ mZ+{0}∣0.10Qm<=Di0.20Qm20  }
  • m5 =max{ m ∈ Z + ∪ { 0 } ∣ 0.05 Q m < = D i − 0.20 Q m 20 − 0.10 Q m 10 m\in Z^+ \cup \{0\} | 0.05Qm <= D_i-0.20Qm_{20}-0.10Qm_{10} mZ+{0}∣0.05Qm<=Di0.20Qm200.10Qm10 }
  • m1 =max{ m ∈ Z + ∪ { 0 } ∣ 0.01 Q m < = D i − 0.20 Q m 20 − 0.10 Q m 10 − 0.05 Q m 5 m\in Z^+ \cup \{0\} | 0.01Qm <= D_i-0.20Qm_{20}-0.10Qm_{10}-0.05Qm_{5} mZ+{0}∣0.01Qm<=Di0.20Qm200.10Qm100.05Qm5 }

(2)25/10/5/1拆分规则

  • m25 =max{ m ∈ Z + ∪ { 0 } ∣ 0.25 Q m < = D i m\in Z^+ \cup \{0\} | 0.25Qm <= D_i mZ+{0}∣0.25Qm<=Di }
  • m10 =max{ m ∈ Z + ∪ { 0 } ∣ 0.10 Q m < = D i − 0.25 Q m 25 m\in Z^+ \cup \{0\} | 0.10Qm <= D_i-0.25Qm_{25}~ mZ+{0}∣0.10Qm<=Di0.25Qm25  }
  • m5 =max{ m ∈ Z + ∪ { 0 } ∣ 0.05 Q m < = D i − 0.25 Q m 25 − 0.10 Q m 10 m\in Z^+ \cup \{0\} | 0.05Qm <= D_i-0.25Qm_{25}-0.10Qm_{10} mZ+{0}∣0.05Qm<=Di0.25Qm250.10Qm10 }
  • m1 =max{ m ∈ Z + ∪ { 0 } ∣ 0.01 Q m < = D i − 0.25 Q m 25 − 0.10 Q m 10 − 0.05 Q m 5 m\in Z^+ \cup \{0\} | 0.01Qm <= D_i-0.25Qm_{25}-0.10Qm_{10}-0.05Qm_{5} mZ+{0}∣0.01Qm<=Di0.25Qm250.10Qm100.05Qm5 }

在实现过程中,对于需求超过车辆容量的客户必须进行需求拆分,而对于未超过车辆容量的客户可以拆分也可以不拆分,这里设置了参数比例进行限制。

2.2 需求拆分后的服务时长取值问题


节点的服务时长会影响车辆的行进时间,进而会影响与节点时间窗的匹配问题。一般来说,节点的服务时长与需求量成正比关系,在进行节点需求拆分后,新节点的需求量降低,其服务时长理应也降低。但从标准数据集来看,各需求节点的服务时长均采用同一数值。因此本文在代码实现过程中也采用固定值,不考虑新节点服务时长的变化。当然,如有需要,也可以设置单位货物的服务时长,根据拆分后节点的具体需求量设置相应的服务时长。


3. 求解结果


(1)收敛曲线
在这里插入图片描述

(2)车辆路径
在这里插入图片描述

(3)输出内容

在这里插入图片描述


4. 代码片段


(1)数据结构

# 数据结构:解
class Sol():def __init__(self):self.obj=None # 目标函数值self.node_no_seq=[] # 解的编码self.route_list=[] # 解的解码self.timetable_list=[] # 车辆访问各点的时间self.route_distance_list = None
# 数据结构:需求节点
class Node():def __init__(self):self.id=0 # 节点idself.x_coord=0 # 节点平面横坐标self.y_coord=0  # 节点平面纵坐标self.demand=0 # 节点需求self.start_time=0 # 节点开始服务时间self.end_time=1440 # 节点结束服务时间self.service_time=0 # 单次服务时长self.vehicle_speed = 0 # 行驶速度
# 数据结构:车场节点
class Depot():def __init__(self):self.id=0 # 节点idself.x_coord=0 # 节点平面横坐标self.y_coord=0  # 节点平面纵坐标self.start_time=0 # 节点开始服务时间self.end_time=1440 # 节点结束服务时间self.v_speed = 0 # 行驶速度self.v_cap = 80 # 车辆容量
# 数据结构:全局参数
class Model():def __init__(self):self.best_sol=None # 全局最优解self.sol_list=[] # 解的集合self.demand_dict = {}  # 需求节点集合self.depot = None  # 车场节点集合self.demand_id_list = [] # 需求节点id集合self.distance_matrix = {}  # 距离矩阵self.time_matrix = {}  # 时间矩阵self.number_of_demands = 0 # 需求点数量self.demand_id_list_ = []  # 经先验需求分割后的节点集合self.demand_dict_ = {}  # 需求分割后的节点需求集合self.distance_matrix_ = {}  # 原始节点id间的距离矩阵self.time_matrix_ = {}  # 原始节点id间的时间矩阵self.mapping = {}  # 需求分割前后的节点对应关系self.split_rate = 0.5 # 控制需求分割的比例(需求超出车辆容量的除外)self.popsize = 100 # 种群规模self.alpha = 2 # 信息启发式因子self.beta = 3 # 期望启发式因子self.Q = 100 # 信息素总量self.rho = 0.5 # 信息素挥发因子self.tau = {} # 弧信息素集合self.tau0 = 100 # 路径初始信息素

(2)距离矩阵

# 初始化参数:计算距离矩阵时间矩阵
def calDistanceTimeMatrix(model):for i in range(len(model.demand_id_list)):from_node_id = model.demand_id_list[i]for j in range(len(model.demand_id_list)):to_node_id = model.demand_id_list[j]dist = math.sqrt((model.demand_dict[from_node_id].x_coord - model.demand_dict[to_node_id].x_coord) ** 2+ (model.demand_dict[from_node_id].y_coord - model.demand_dict[to_node_id].y_coord) ** 2)model.distance_matrix[from_node_id, to_node_id] = distmodel.time_matrix[from_node_id,to_node_id] = math.ceil(dist/model.depot.v_speed)dist = math.sqrt((model.demand_dict[from_node_id].x_coord - model.depot.x_coord) ** 2 +(model.demand_dict[from_node_id].y_coord - model.depot.y_coord) ** 2)model.distance_matrix[from_node_id, model.depot.id] = distmodel.distance_matrix[model.depot.id, from_node_id] = distmodel.time_matrix[from_node_id,model.depot.id] = math.ceil(dist/model.depot.v_speed)model.time_matrix[model.depot.id,from_node_id] = math.ceil(dist/model.depot.v_speed)

(3)邻域搜索

# 蚂蚁移动
def movePosition(model):sol_list=[]local_sol=Sol()local_sol.obj=float('inf')for _ in range(model.popsize):#随机初始化蚂蚁为止node_no_seq=[random.randint(0,len(model.demand_id_list_)-1)]all_node_no_seq=copy.deepcopy(model.demand_id_list_)all_node_no_seq.remove(node_no_seq[-1])#确定下一个访问节点while len(all_node_no_seq)>0:next_node_no=searchNextNode(model,node_no_seq[-1],all_node_no_seq)node_no_seq.append(next_node_no)all_node_no_seq.remove(next_node_no)sol=Sol()sol.node_no_seq=node_no_seqsol.timetable_list,sol.obj, sol.route_distance,sol.route_list = calObj(node_no_seq,model)sol_list.append(sol)if sol.obj < local_sol.obj:local_sol = copy.deepcopy(sol)model.sol_list=copy.deepcopy(sol_list)if local_sol.obj<model.best_sol.obj:model.best_sol=copy.deepcopy(local_sol)
# 搜索下一移动节点
def searchNextNode(model,current_node_no,SE_List):prob=np.zeros(len(SE_List))for i,node_no in enumerate(SE_List):eta=1/model.distance_matrix_[current_node_no,node_no] if model.distance_matrix_[current_node_no,node_no] else 0.0001tau=model.tau[current_node_no,node_no]prob[i]=((eta**model.alpha)*(tau**model.beta))#采用轮盘法选择下一个访问节点cumsumprob=(prob/sum(prob)).cumsum()cumsumprob -= np.random.rand()return SE_List[list(cumsumprob >= 0).index(True)]

# 参考

【1】 A novel approach to solve the split delivery vehicle routing problem

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/302539.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧水库解决方案(打造水库智慧监测体系)

​作为一名水利自动化系统集成商,最近我司接手了一个智慧水库建设项目。这个项目位于一座山区的大型水库,目的是对其进行现代化、智能化改造,提升供水、防洪等管理水平。&#xff08;key-iot.com.cn&#xff09; 在方案设计之初,我们组织了现场勘测,全面了解水库的实际情况。这…

创建型模式--2.简单工厂模式【人造恶魔果实工厂1】

1. 工厂模式的特点 在海贼王中&#xff0c;作为原王下七武海之一的多弗朗明哥&#xff0c;可以说是新世界最大的流氓头子&#xff0c;拥有无上的权利和无尽的财富。他既是德雷斯罗萨国王又是地下世界的中介&#xff0c;控制着世界各地的诸多产业&#xff0c;人造恶魔果实工厂就…

基于springboot实现校园资料分享平台系统项目【项目源码+论文说明】

基于springboot实现校园资料分享平台系统演示 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了校园资料分享平台的开发全过程。通过分析企业对于校园资料分享平台的需求&#xff…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.1-4.4

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.1 深层神经网络&#xff08;Deep L-layer neural network&#xff09;4.2 前向传播和反向传播&#xff08;Forward and backward pro…

“逃离”OpenAI!36人出走,已拿600亿融资

“逃离”OpenAI&#xff01;36人出走&#xff0c;已拿600亿融资© 由 智东西 提供 智东西 作者 | 程茜 编辑 | 心缘 最近OpenAI频繁高薪挖人&#xff0c;把马斯克惹毛了。 马斯克在社交平台X上公开爆料&#xff1a;OpenAI一直在高薪挖特斯拉工程师&#xff0c;甚至还想…

四、书城开发-2、热门搜索/推荐页面的开发

热门搜索的开发 热门搜索页面的交互主要有4个交互点 第一个交互是点击搜索框时&#xff0c;热门搜索会渐影显示&#xff1b;第二个交互是点击返回图标时热门搜索会渐影消失&#xff1b;第三个交互是热门搜索滑动页面的时候搜索栏下面会出现阴影&#xff0c;回到顶部时阴影会消…

深入浅出 -- 系统架构之微服务标准组件及职责

我们来认识一下微服务架构在Java体系中依托哪些组件实现的。 相对于单体架构的简单粗暴&#xff0c;微服务的核心是将应用打散&#xff0c;形成多个独立提供的微服务&#xff0c;虽然从管理与逻辑上更符合业务需要。但微服务架构也带来了很多急需解决的核心问题&#xff1a; 1…

PDF锐化

PDF Shaper Ultimate(pdf转图片) 编辑->添加文件->选中一个要处理的pdf 操作->转换->PDF转为图片 ComicEnhancerPro设置(把图片锐化) PDF Shaper Ultimate(图片转pdf) 编辑-添加图片->选中所有锐化处理后的图片 转换->图片转为pdf&#xff08;会把所有图…

最新AI工具系统ChatGPT网站运营源码SparkAi系统V6.0版本,GPTs应用、AI绘画、AI换脸、垫图混图、Suno-v3-AI音乐生成大模型全支持

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

《深入Linux内核架构》第4章 进程虚拟内存(2)

目录 4.3 内存映射原理 4.4 数据结构 4.4.1 树和链表 4.4.2 虚拟内存区域VMA的表示 4.4.3 相关数据结构 本节讲VMA结构体struct vm_area_struct和struct address_space。 4.3 内存映射原理 所有进程的虚拟空间总和比物理内存大得多&#xff0c;因此只有最常用的虚拟空间…

生活日常韩语成人外语培训中为什么韩国人说话喜欢用“~도록”?

많이 받는 질문 중 하나가 ‘~도록’을 자신에게 쓸 수 있는가 하는 것이다. 즉 “제가 하도록 하겠습니다” “조심하도록 하겠습니다” “말씀드리도록 하겠습니다” 등과 같은 표현이다. 我经常被问到的问题之一就是能否将“~도록”用于自己。比如“我来做吧”、“我会小心…

深度学习500问——Chapter06: 循环神经网络(RNN)(2)

文章目录 6.4 CNN和RNN的区别 6.5 RNNs与FNNs有什么区别 6.6 RNNs训练和传统ANN训练异同点 6.7 为什么RNN训练的时候Loss波动很大 6.8 标准RNN前向输出流程 6.9 BPTT算法推导 6.9 RNN中为什么会出现梯度消失 6.10 如何解决RNN中的梯度消失问题 6.4 CNN和RNN的区别 类别特点描述…

sfml sdl2 windows vscode 调试和coderunner插件运行

链接库写在编译链接命令里&#xff0c;如果没有使用到不会加入到生成的可执行文件里。所以tasks.json可以这样写&#xff0c; {"version": "2.0.0","tasks": [{"type": "cppbuild","label": "C/C: g.exe 生…

Apache Pulsar源码解析之Lookup机制

文章目录 引言Lookup是什么客户端实现原理服务端实现原理总结 引言 在学习Pulsar一段时间后&#xff0c;相信大家也或多或少听说Lookup这个词&#xff0c;今天就一起来深入剖析下Pulsar是怎么设计的它吧 Lookup是什么 在客户端跟服务端建立TCP连接前有些信息需要提前获取&am…

arm-linux-gnueabihf-gcc默认目录

默认编译的头文件目录&#xff1a; /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib 默认编译的库文件目录&#xff1a; /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/ …

vscode 重命名很慢或失败 vscode renames are slow

网上问题&#xff0c; 插件问题&#xff08;我遇见的排除&#xff0c;不是&#xff09;被其他程序占用问题&#xff0c;&#xff08;我这边是这个&#xff09; 解决方案&#xff1a; 打开【资源管理器】&#xff0c;使用火绒 或其他软件&#xff0c;查看文件夹 or 文件 被哪个…

2024.4.9-day12-CSS 常用样式属性和字体图标

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业 作业 <!DOCTYPE html> <html lang"zh-CN"><he…

go之web框架gin

介绍 Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API&#xff0c;性能要好得多&#xff0c;多亏了 httprouter&#xff0c;速度提高了 40 倍。 如果您需要性能和良好的生产力&#xff0c;您一定会喜欢 Gin。 安装 go get -u github.com/gin-gonic/g…

【C++】unordered 系列关联式容器

文章目录 1. unordered 系列关联式容器2. unordered_map2.1 unordered_map 的文档介绍2.2 unordered_map 的接口说明 3. unordered_set4. 在线 OJ 1. unordered 系列关联式容器 在 C 98 中&#xff0c;STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可…

STM32中C编程引入C++程序

C具备类的创建思想很实用于实际场景多相似性的框架搭建&#xff1b;同种类型或相似类型的C的优势明显因此进行相互嵌套使用 需要在C中使用C类的话&#xff0c;你可以通过C的“extern "C"”语法来实现。这允许你在C代码中使用C的链接方式&#xff0c;而在C代码中使用…