如何写代码实现VRP问题中车辆容量限制及时间窗要求(python)

问题研究背景

使用遗传模拟退火算法求解如下10个卸货点的VRPTW问题。为了使研究的问题更加有意义,本人将时间限理解为服务点一天的具体可以允许配送的时间。 如果不要求车辆从配送中心出发的时间是统一的并且为0时刻,那么就默认第一个配送节点是一定能赶到的。采取从配送中心出发的时间不为0时刻的策略,默认一定能达到第一个配送点,所以采用最早到达时间推算车辆出发的时间。
假设配送中心营业时间是早上七点至晚上七点,即配送中心也有最早和最晚时间窗要求,车辆配送货物应该满足这个发车即回到配送中心的最晚时间限制。卸货点1-10的时间限制理解如下:卸货点1要求在下午1点至下午4点配送,卸货点1要求的服务时间是半个小时;卸货点2要求在下午4点至下午6点配送,卸货点2要求的服务时间是1个小时,以此类推其他的卸货点的配送及服务时间限制。算法中用到配送及服务时间是下午的情况,例如卸货点1可转成数字表示是[13,16]。

在这里插入图片描述

配送点的需求货物量如下:

在这里插入图片描述

配送点的达到时间窗及服务时间如下:

在这里插入图片描述

代码编码思路

取染色体,依次判断染色体的基因是否满足车辆载重量及时间窗限制条件,染色体基因片段如果不满足两者,则默认为一条路线,在中间插入配送中心节点0.

考虑是否可以写两个独立的函数,先判断车辆的载重量限制,再前面生成的解再次寻优判断是否满足时间窗限制。

编写代码过程中遇到的错误

从配送中心出发立即回到配送中心

chrom [10  1  5  2  3  6  4  9  7  8]
*******000******
*******000******
routes [[0, 0, 0]]

当首次配送的需求点为卸货点10时,最早到达时间要求是下午5点,配送中心开门是上午七点,关门是下午七点,两点之间的路径长度是160公里,车辆每小时的车速是40公里/小时,所以最佳的方案是不考虑先去卸货点10完成配送任务,因为车辆返回时赶不上配送中心的关门时间。

在这里插入图片描述

一些其他的错误

opulation [[ 7  6  1  2  9  3  4  5  8 10][ 3  2  5 10  7  4  6  8  1  9][ 4  6  8  7  1  9  5  3  2 10][10  5  7  2  6  4  3  9  8  1][ 9  7 10  8  2  1  4  5  3  6][ 5 10  9  3  6  1  2  4  8  7][ 5  6  2  7  3 10  9  4  8  1][ 2  9  1  3 10  8  6  4  5  7][ 7  3  1  6  2 10  9  8  4  5][10  4  5  9  6  7  3  2  1  8][ 2  4  3  5  8  6  7  1 10  9][ 9  2  6  8  3  1  5  4 10  7][10  2  9  5  1  4  6  3  8  7][ 4  9  5  2  6  1 10  3  8  7][ 7  4  6  8  9 10  3  2  1  5][10  1  4  9  6  2  3  5  7  8][10  9  5  4  3  2  8  1  7  6][ 7  3  8  1 10  5  4  2  9  6][ 3  9 10  4  6  7  5  2  1  8][ 5 10  3  6  4  7  9  1  2  8][ 5  7  3  6  1  2  4  9 10  8][ 3  9  1 10  5  4  2  7  6  8][10  7  1  2  5  8  6  9  4  3][10  6  8  2  9  7  4  5  1  3][ 4  2  7  1  9  3 10  5  8  6][ 7  4  5  8  1  3  9  6 10  2][ 4  1  7  5  9  2  3 10  8  6][ 5  3  1 10  8  9  7  6  4  2][ 7  3  4  5  9  6  8  1 10  2][ 4  2  5 10  1  9  6  7  8  3][ 1  6  4  2 10  7  3  8  9  5][ 9  4  3  6  8 10  2  1  7  5][ 4  7  2  3  9 10  1  5  6  8][ 5  6 10  8  9  7  2  1  3  4][ 8  3  9  1  6  5  4 10  7  2][ 5  7  4  9  3  8 10  1  2  6][ 7  2  9  1  6  5  4 10  3  8][ 6 10  4  5  8  7  1  3  9  2][ 9  5 10  8  3  6  7  2  1  4][ 5  6  3 10  4  9  8  7  1  2][ 7  1  8  6  2  3  9  5 10  4][ 9  1  8  7  4  3  2  6 10  5][ 7  3  2 10  1  6  4  9  8  5][ 5  9  6  3  7  2  8  4  1 10][ 1  2  4  7  8  5  3  6  9 10][ 3  7  2  1  6 10  5  9  4  8][ 7  5  9  3  8  4 10  2  1  6][ 5  6  8 10  9  3  7  4  1  2][ 3  9  7  6  5  2 10  1  4  8][ 3  4  2  7  1  9  8  5 10  6]]
chrom [ 7  6  1  2  9  3  4  5  8 10]
*******000******
total_path_list [[0, 7, 6, 0], [0, 1, 2, 9, 0], [0, 3, 0], [0, 4, 5, 8, 0], [0, 10, 0]]
node 2
node 3
new_chrom [2, 3, 0, 9, 0, 0]
*******000******
total_path_list [[0, 0, 9, 0]]
new_chrom [9]
*******000******
total_path_list [[0, 9, 0]]
node 9
new_chrom [9]
routes [9]
cannotbe_firstnode_served [4, 5, 7, 10]
*******000******
total_path_list [[0, 5, 1, 2, 0], [0, 10, 0], [0, 4, 6, 0], [0, 3, 0], [0, 7, 8, 0], [0, 9, 0]]
path_list [0, 5, 1, 2, 0]
path_list [0, 10, 0]
path_list [0, 4, 6, 0]
path_list [0, 3, 0]
path_list [0, 7, 8, 0]
path_list [0, 9, 0]
new_chrom [3, 9, 5, 10, 4, 7]
*******000******
total_path_list [[0, 10, 0], [0, 4, 0], [0, 5, 0], [0, 7, 0]]
total_path_list [[0, 2, 3, 0], [0, 4, 5, 0], [0, 6, 7, 0], [0, 8, 9, 0], [0, 10, 0], [0, 1, 0]]
path_list [0, 2, 3, 0]
path_list [0, 4, 5, 0]
path_list [0, 6, 7, 0]
path_list [0, 8, 9, 0]
path_list [0, 10, 0]
path_list [0, 1, 0]
feasible_node_list [2, 3, 6, 8, 9, 1]
not_feasible_node_list [4, 5, 7, 10]
new_chrom [2, 3, 6, 8, 9, 1, 4, 5, 7, 10]Process finished with exit code 0

函数代码

修改卸货点的时间窗,增加求得时间窗+车辆载重量约束限制的可行解概率。
在这里插入图片描述

车辆容量限制的代码见本博主的博文《【纠错】遗传算法求解VRP计算车辆容量限制的代码有bug》,时间窗要求的函数如下:

def time_window_restraint(total_path_list):# 先求解车辆容量限制,再计算时间窗限制,硬时间窗限制# 如果不要求车辆从配送中心出发的时间是统一的并且为0时刻,那么就默认第一个配送节点是一定能赶到的# 采取从配送中心出发的时间不为0时刻的策略,默认一定能达到第一个配送点,所以采用最早到达时间推算车辆出发的时间# 假设配送中心营业时间是早上七点至晚上七点# 先排除算例无解的场景,即配送中心开门时间都不能实现派车辆运输的场景print("total_path_list", total_path_list)not_feasible_node_list = []feasible_node_list = []feasible_path_list = []for i in range(len(total_path_list)):path_list = total_path_list[i]arrive_time = demand_time_window[0, path_list[1]]leave_time = arrive_time + demand_service_time[path_list[1]]if path_list[1] in cannotbe_firstnode_served:not_feasible_node_list.extend(path_list[1:-1])else:# 默认第一个服务点的时间窗一定是满足要求的if len(path_list) == 3:# 返回配送中心的时间back_center_time = leave_time + travel_time_graph[path_list[-2]][0]if back_center_time > dis_center_open_time[1]:not_feasible_node_list.append(path_list[-2])else:# 只有一个配送节点的场景feasible_node_list.append(path_list[-2])else:feasible_node_list.append(path_list[1])if len(path_list) == 4:before_node = path_list[1]cur_node = path_list[2]arrive_time = leave_time + travel_time_graph[before_node][cur_node]if (arrive_time < demand_time_window[0, cur_node]) or (arrive_time > demand_time_window[1, cur_node]):# 不可行解# 判断是否加入不可行解集合if before_node in feasible_node_list:feasible_node_list.remove(before_node)not_feasible_node_list.append(before_node)not_feasible_node_list.append(cur_node)else:not_feasible_node_list.append(cur_node)else:leave_time = arrive_time + demand_service_time[cur_node]# 返回配送中心的时间back_center_time = leave_time + travel_time_graph[cur_node][0]if back_center_time > dis_center_open_time[1]:# 判断是否加入不可行解集合if before_node in feasible_node_list:feasible_node_list.remove(before_node)not_feasible_node_list.append(before_node)not_feasible_node_list.append(cur_node)else:not_feasible_node_list.append(cur_node)else:# 判断是否加入可行解集合if before_node in not_feasible_node_list:not_feasible_node_list.append(cur_node)else:feasible_node_list.append(cur_node)else:remain_node_list = path_list[2:-1]for index in range(len(remain_node_list)):cur_node = remain_node_list[index]if len(remain_node_list) == 1:before_node = remain_node_list[0]else:before_node = remain_node_list[index-1]arrive_time = leave_time + travel_time_graph[before_node][cur_node]if (arrive_time < demand_time_window[0, cur_node]) or (arrive_time > demand_time_window[1, cur_node]):# 不可行解# 判断是否加入不可行解集合if before_node in feasible_node_list:feasible_node_list.remove(before_node)not_feasible_node_list.append(before_node)not_feasible_node_list.append(cur_node)else:not_feasible_node_list.append(cur_node)else:leave_time = arrive_time + demand_service_time[cur_node]if cur_node == path_list[-2]:# 返回配送中心的时间back_center_time = leave_time + travel_time_graph[path_list[-2]][0]if back_center_time > dis_center_open_time[1]:# 判断是否加入不可行解集合if before_node in feasible_node_list:feasible_node_list.remove(before_node)not_feasible_node_list.append(before_node)not_feasible_node_list.append(cur_node)else:# 判断是否加入可行解集合not_feasible_node_list.append(cur_node)else:# 判断是否加入可行解集合if before_node in not_feasible_node_list:not_feasible_node_list.append(cur_node)else:feasible_node_list.append(cur_node)else:# 判断是否加入可行解集合if before_node in not_feasible_node_list:not_feasible_node_list.append(cur_node)else:feasible_node_list.append(cur_node)new_chrom = []if len(feasible_node_list) > 0:for node in feasible_node_list:new_chrom.append(node)if len(not_feasible_node_list) > 0:for node in not_feasible_node_list:new_chrom.append(node)not_feasible_node_flag = Trueelse:not_feasible_node_flag = Falseprint("new_chrom", new_chrom)return not_feasible_node_flag, feasible_node_list, new_chrom
def get_feasible_route(chrom):# 先判断是否满足车辆最大载重量限制cur_chrom = copy.deepcopy(chrom)not_feasible_node_flag = Truecount = 0while not_feasible_node_flag:# 先用得到满足车辆载重量的函数切出可行解路径print("*******000******")total_path_list = vehicle_capacity_restraint(cur_chrom)# 再使用时间窗判断是否路径也是满足时间窗要求的not_feasible_node_flag, feasible_node_list, new_chrom = time_window_restraint(total_path_list)print("not_feasible_node_flag", not_feasible_node_flag)if not_feasible_node_flag:print("*******001******")cur_chrom = new_chromcount += 1else:print("*******003******")return vehicle_capacity_restraint(new_chrom)if (count > 1) and (cur_chrom == new_chrom):return vehicle_capacity_restraint(new_chrom)  # 使用函数切出路线

算法迭代示意图

遗传算法迭代图如下:

在这里插入图片描述

连续两次运行程序,得到的目标值相同,下面图2比上图1在100代左右就寻找到了结果:

在这里插入图片描述

事不过三,连续三次,目标值开出来的都是478

在这里插入图片描述

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

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

相关文章

将用友U8的数据可视化需要哪些工具?

将金蝶U8的数据可视化需要一个奥威BI数据可视化工具&#xff0c;以及一套专为用友U8打造的标准化BI数据分析方案。 奥威BI SaaS平台&#xff1a;一键链接用友U8&#xff0c;立得报表 别的BI软件围绕用友U8的数据做可视化&#xff1a;1、准备配置环境&#xff1b;2、下载安装配…

JMeter做http接口功能测试

1. 普通的以key-value传参的get请求 e.g. 获取用户信息 添加http请求&#xff1b;填写服务器域名或IP&#xff1b;方法选GET&#xff1b;填写路径&#xff1b;添加参数&#xff1b;运行并查看结果。 2. 以Json串传参的post请求 e.g. 获取用户余额 添加http请求&#xff1b;…

UITesting 界面测试

1. 创建界面测试视图 UITestingBootcampView.swift import SwiftUI/// 界面测试 ViewModel class UITestingBootcampViewModel: ObservableObject{let placeholderText: String "Add name here..."Published var textFiledText: String ""Published var…

『吴秋霖赠书活动 | 第三期』《Python asyncio并发编程》

文章目录 1. 写在前面2. 浅谈asyncio3. Python asyncio并发编程 不再受限于&#xff01;asyncio异步让你的程序在高并发时翱翔自如&#xff01; 声明&#xff1a;赠书活动是博主与出版社达成合作&#xff0c;只属于粉丝的专属福利 本期书籍&#xff1a;《Python asyncio并发编程…

数字货币和区块链:跨境电商的未来之革命

随着全球数字化浪潮的不断涌现&#xff0c;跨境电商正经历着前所未有的革命。其中&#xff0c;数字货币和区块链技术被认为是这场革命的关键驱动力。 它们不仅改变了支付方式&#xff0c;还提供了更安全、高效的交易体验&#xff0c;同时也为跨境电商开启了新的商业模式和机会…

38 WEB漏洞-反序列化之PHPJAVA全解(下)

目录 Java中的API实现序列化和反序列化演示案例WebGoat_Javaweb靶场反序列化测试2020-网鼎杯-朱雀组-Web-think java真题复现 文章参考&#xff1a; https://www.cnblogs.com/zhengna/p/15737517.html https://blog.csdn.net/MCTSOG/article/details/123819548 ysoserial生成攻…

可以更改字体颜色的便签备忘录工具选择用哪个

日常添加笔记记录是一个非常好的习惯&#xff0c;通过笔记来记录一些重要的内容一方面可以帮助大家回顾过去的相关记录&#xff0c;另一方面如果记录的笔记是有关学习类的&#xff0c;还有助于大家随时查看记录的笔记。 多数时候记录笔记内容大家通常会选择一些比较方便易操作…

SQL数据库管理工具RazorSQL mac中文版特点与功能

RazorSQL mac是一款功能强大的SQL数据库管理工具&#xff0c;它支持多种数据库&#xff0c;包括MySQL、Oracle、Microsoft SQL Server、SQLite、PostgreSQL等。 RazorSQL mac 软件特点和功能 多种数据库支持&#xff1a;RazorSQL支持多种数据库&#xff0c;用户可以通过一个工…

Windows 事件日志监控

Windows 事件日志是记录 Microsoft 系统上发生的所有活动的文件&#xff0c;在 Windows 环境中&#xff0c;将记录系统上托管的系统、安全性和应用程序的事件&#xff0c;事件日志提供包含有关事件的详细信息&#xff0c;包括日期、时间、事件 ID、源、事件类型和发起它的用户。…

UE4 材质实操记录

TexCoord的R通道是从左到右的递增量&#xff0c;G通道是从上到下的递增量&#xff0c;R通道减去0.5&#xff0c;那么左边就是【-0.5~0】区间&#xff0c;所以左边为全黑&#xff0c;Abs取绝对值&#xff0c;就达到一个两边向中间的一个递减的效果&#xff0c;G通道同理&#xf…

01. 汇编LED驱动实验

01. 汇编LED驱动实验 汇编原理分析为什么要学习Cortex—A汇编STM32IO初始化流程IMX6UL初始化流程 汇编基础处理器内部数据传输指令存储器访问指令 编写驱动编译程序烧写bin文件 汇编原理分析 为什么要学习Cortex—A汇编 需要用汇编初始化一些SOC外设使用汇编初始化DDR&#x…

QT_day2

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

python 对图片增加边框,logo贴图,获取图片exif参数,填写图片文本内容

完整代码 # 找到个可以下载免费字体的网站https://font.chi删除我naz.com/mi删除我anfei.html from PIL import Image, ImageDraw, ImageFont import exifreaddef photo_exif(image_path):f open(image_path, rb)tags exifread.process_file(f)# 打印所有照片信息&#xff0…

Mac电脑版交互式原型设计软件 Axure RP 8汉化 for mac

Axure RP 8是一款专业快速原型设计软件&#xff0c;它主要用于定义需求、设计功能和界面等&#xff0c;适用于商业分析师、信息架构师、产品经理、IT咨询师、用户体验设计师、交互设计师和UI设计师等用户。 该软件可以快速、高效地创建原型&#xff0c;并支持多人协作设计和版…

【vue3】组件间通讯

1.上级传给下级 父级组件&#xff1a; <ReqTab ref"crontabRef" hide"openCronfalse" fill"crontabFill" :expression"expression" :method"method" ></ReqTab> 函数中赋值&#xff1a; 子组件&#xff1a; …

Android问题笔记 - NoSuchmethodException: could not find Fragment constructor

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

AFL安全漏洞挖掘

安全之安全(security)博客目录导读 ATF(TF-A)/OPTEE之FUZZ安全漏洞挖掘汇总 目录 一、AFL简介 二、AFL的安装 三、代码示例及种子语料库 四、AFL插桩编译 五、AFL运行及测试 六、AFL结果分析 一、AFL简介 模糊测试&#xff08;Fuzzing&#xff09;技术作为漏洞挖掘最有…

【AI视野·今日Robot 机器人论文速览 第五十六期】Tue, 17 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 17 Oct 2023 Totally 60 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Interactive Task Planning with Language Models Authors Boyi Li, Philipp Wu, Pieter Abbeel, Jitendra Malik交互式机器人…

配置 Pod 以使用 PersistentVolume 作为存储

配置 Pod 以使用 PersistentVolume 作为存储 本文将向你介绍如何配置 Pod 使用 PersistentVolumeClaim 作为存储。 以下是该过程的总结&#xff1a; 你作为集群管理员创建由物理存储支持的 PersistentVolume。你不会将该卷与任何 Pod 关联。你现在以开发人员或者集群用户的角色…

Docker安装GitLab及使用图文教程

作者&#xff1a; 宋发元 GitLab安装及使用教程 官方教程 https://docs.gitlab.com/ee/install/docker.html Docker安装GitLab 宿主机创建容器持久化目录卷 mkdir -p /docker/gitlab/{config,data,logs}拉取GitLab镜像 docker pull gitlab/gitlab-ce:15.3.1-ce.0运行GitLa…