当前位置: 首页 > news >正文

如何写代码实现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

在这里插入图片描述

相关文章:

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

问题研究背景 使用遗传模拟退火算法求解如下10个卸货点的VRPTW问题。为了使研究的问题更加有意义&#xff0c;本人将时间限理解为服务点一天的具体可以允许配送的时间。 如果不要求车辆从配送中心出发的时间是统一的并且为0时刻&#xff0c;那么就默认第一个配送节点是一定能赶…...

C语言求解汉诺塔问题

完整代码&#xff1a; /*Hanoi(汉诺)塔问题。这是一个古典的数学问题&#xff1a;古代有一个梵塔&#xff0c;塔内有 3 个 座 A&#xff0c;B&#xff0c;C&#xff0c;开始时 A 座上有 64 个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上。有一个老…...

安装LSF

安装需求 基本硬件配置建议&#xff1a; CPU 4核或以上&#xff08;LSF 没有最低 CPU 需求&#xff0c;此处只是建议&#xff09;内存 8G或以上&#xff08; 当没有作业在运行时&#xff0c; Linux x86-64 上集群中的 LSF 守护程序将使用大约 488 MB 内存。&#xff09;交换…...

百度的新想象力在哪?

理解中国大模型&#xff0c;百度是一个窗口。这个窗口的特殊性不仅在于变化本身&#xff0c;而是在于百度本身就是那个窗口。 作者|皮爷 出品|产业家 沿着首钢园北区向西北步行10分钟&#xff0c;就能看到一个高约90米的大跳台&#xff0c;在工业园钢铁痕迹的印衬下&#…...

Linux使用rpm包安装mysql5.7

以前安装过mysql 前言&#xff1a;检查以前是否装有mysql rpm -qa|grep -i mysql安装了会显示&#xff1a;   bt-mysql57-5.7.31-1.el7.x86_64 停止mysql服务和删除之前安装的mysql rpm -e bt-mysql57-5.7.31-1.el7.x86_64查找并删除mysql相关目录 find / -name mysql/va…...

LLDB 三种输出方式 对比及原理探索

前言 当我们的项目过大时,就会使我们项目的编译耗时过长,如何在项目运行时进项代码调试,熟练使用LLDB就可以解决这个难题,大幅度提高我们的开发效率。 什么是 LLDB? LLDB是英文Low Lever Debug的缩写,是XCode内置的为我们开发者提供的调试工具,它与LLVM编译器一起,存…...

基于架构软件设计-架构真题(五十八)

“41”视图主要描述系统逻辑架构。其中&#xff08;&#xff09;视图用于描述对象模型&#xff0c;并说明系统应该为用户提供哪些服务。 过程开发物理逻辑 解析&#xff1a; “41”有逻辑视图、过程视图、物理视图、开发视图和架构的描述。 逻辑视图&#xff1a;设计的对象…...

jvm实现的锁优化

目录 轻量级锁 轻量级锁的工作流程 轻量级锁的解锁 偏向锁 偏向锁的流程&#xff1a; 偏向锁和轻量级锁机区别&#xff1a; 其他优化 自旋锁和自适应自旋锁 锁消除 锁粗化 轻量级锁 “轻量级” 是相对于使用操作系统互斥量来实现的传统锁而言的&#xff0c;因此传统的…...

JMeter做http接口功能测试

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

【安全体系架构】——SIEM架构

什么是SIEM架构&#xff1f; 安全信息与事件管理&#xff08;SIEM&#xff09;架构是一种综合性的安全管理系统&#xff0c;旨在监控、检测、报告和应对安全事件和威胁。SIEM系统集成了多个安全功能&#xff0c;包括日志收集、事件管理、威胁检测和响应&#xff0c;以提供组织…...

nginx acess日志找不到访问记录问题

这个是AI给出的可能得原因&#xff1a; 如果在nginx中找不到你的访问记录&#xff0c;但你确实进行了访问并得到了返回&#xff0c;可能有以下原因&#xff1a; 日志文件位置设置不正确&#xff1a;请确保你的nginx配置文件中的access_log指令指向了正确的日志文件路径。日志文…...

canvas使用

canvas使用 1 canvas绘制基本 1 概念 HTML5<canvas>元素用于图形的绘制&#xff0c;区别于css,它的绘制通过javascript来完成绘制的 <canvas>标签只是图形容器&#xff0c;必须使用及保本来绘制图形 Canvas API主要聚焦与2D图形。同时<canvas>元素的Web…...

PMP认证考试证书领取的通知

各位考生&#xff1a; 2022年6月、7月、8月PMI认证考试证书领取工作已经开始&#xff0c;您可通过以下两种方式领取证书&#xff1a; 1.联系本人所在培训机构&#xff0c;通过培训机构向考点统一代领。 2.在2023年10月20日-10月31日内&#xff0c;登录本网站报名系统个人账户…...

华为云HECS云服务器docker环境下安装nacos

华为云HECS云服务器&#xff0c;安装docker环境&#xff0c;查看如下文章。 华为云HECS安装docker-CSDN博客 一、拉取镜像 docker pull nacos/nacos-server二、宿主机创建挂载目录 执行如下命令&#xff1a; mkdir -p /usr/local/nacos/logs mkdir -p /usr/local/nacos/con…...

Oracle数据库修改序列,Oracle中的主键值和序列中的值对应不上时的处理方式

select max(stu.id) maxid from student stu; //查询student表中id的最大值select XXX_SEQ.nextval from dual; //查询student表中id对应序列XXX_SEQ的下一个值alter sequence XXX_SEQ increment by 1000; //将序列XXX_SEQ步长改为1000&#xff0c;对应 student表中id的最大值s…...

Verilog基础:避免混合使用阻塞和非阻塞赋值

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 “避免在一个always块中混杂阻塞赋值和非阻塞赋值”&#xff0c;这条原则是著名的Verilog专家Cliff Cummings在论文SUNG2000中提出的&#xff0c;这个观点在公众讨…...

04、MySQL-------MyCat实现分库分表

目录 九、MyCat实现分库分表1、分库分表介绍&#xff1a;横向&#xff08;水平&#xff09;拆分**垂直分表**&#xff1a;水平分表&#xff1a;**分库分表** 纵向&#xff08;垂直&#xff09;拆分分表字段选择 2、分库分表操作&#xff1a;1、分析图&#xff1a;2、克隆主从3、…...

开源软件-禅道Zentao

禅道Zentao 简介漏洞复现SQL注入漏洞**16.5****router.class.php SQL注入** **v18.0-v18.3****后台命令执行** 远程命令执行漏洞&#xff08;RCE&#xff09;后台命令执行 简介 是一款开源的项目管理软件&#xff0c;旨在帮助团队组织和管理他们的项目。Zentao提供了丰富的功能…...

Linux生产者消费者模型

生产者消费者模型 生产者消费者模型生产者消费者模型的概念生产者消费者模型的特点生产者消费者模型优点 基于BlockingQueue的生产者消费者模型基于阻塞队列的生产者消费者模型模拟实现基于阻塞队列的生产消费模型 生产者消费者模型 生产者消费者模型的概念 生产者消费者模式就…...

【Qt-20】Qt信号与槽

一、什么是信号和槽 信号是特定情况下被发射的事件&#xff0c;发射信号使用emit关键字&#xff0c;定义信号使用signals关键字&#xff0c;在signals前面不能使用public、private、protected等限定符&#xff0c;信号只用声明&#xff0c;不需也不能对其进行定义实现。另外&am…...

“智能+”时代,深维智信如何借助阿里云打造AI内容生成系统

云布道师 前言&#xff1a; 随着数字经济的发展&#xff0c;线上数字化远程销售模式越来越成为一种主流&#xff0c;销售流程也演变为线上视频会议、线下拜访等多种方式的结合。根据 Gartner 报告&#xff0c;到 2025 年 60% 的 B2B 销售组织将从基于经验和直觉的销售转变为数…...

selenium 自动化测试——WebDriver API

控制浏览器 控制浏览器窗口大小&#xff1a;set_window_size()方法 设置全屏模式下运行&#xff1a;maximize_window()方法 from selenium import webdriver from selenium.webdriver.common.by import By import timedriver webdriver.Chrome() driver.get("http://w…...

【实战】学习 Electron:构建跨平台桌面应用

文章目录 一、Electron 简介二、Electron 的优势1. 学习曲线平缓2. 丰富的生态系统3. 跨平台支持4. 开源和社区支持 三、Electron 的使用1. 安装 Node.js2. 安装 Electron3. 创建项目4. 初始化项目5. 安装依赖6. 创建主进程文件7. 创建渲染进程文件8. 打包应用程序9. 运行应用程…...

Python开发之二维数组空缺值的近邻填充

Python开发之二维数组空缺值的填充 1 实现一&#xff0c;任意位置填充2 实现二&#xff0c;填充内部3 实现三&#xff0c;只填充边缘&#xff0c;不包括四个角 前言&#xff1a;主要实现二维数据里面某一个数据的缺失&#xff0c;用缺失的近邻数据进行均值填充&#xff0c;可以…...

vue使用pdf 导出当前页面,(jspdf, html2canvas )

需要安装两个插件 npm install html2canvas jspdfyarn add html2canvas jspdf<div class"app-container" id"pdfPage"><!--这个放你需要导出的内容--> </div><el-button size"mini" click"onExportPdf">导出…...

【oracle删除表 回滚操作】

oracle数据回滚 oracle表在被误删后&#xff0c;一定时间内&#xff0c;可以采取以下方法进行恢复: 1、先查询数据库当前时间 select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss’) from dual;2、通过当前时间往前推时间&#xff0c;选择想要恢复的时间点 select * from 表名…...

Vue3 + TypeScript

Vue3 TS开发环境创建 1. 创建环境 vite除了支持基础阶段的纯TS环境之外&#xff0c;还支持 Vue TS开发环境的快速创建, 命令如下&#xff1a; $ npm create vitelatest vue-ts-pro -- --template vue-ts 说明&#xff1a; npm create vitelatest 基于最新版本的vite进行…...

软件测试/测试开发丨南科大计算机系本科生获“火焰杯”软件测试高校就业选拔赛一等奖

2022年12月2日&#xff0c;计算机系党总支书记、副系主任王琦副教授在工学院南楼551会议室为19级徐驰同学颁发第二届“火焰杯”软件测试开发选拔赛一等奖奖项&#xff0c;为刘烨庞助理教授颁发赛事优秀指导老师奖项。徐驰同学于2022年4月获得该赛事全国总决赛第一名&#xff0c…...

访问 github 问题解决方法

一、macOS版 PS. Windows 版的还没试&#xff0c;不过应该也差不多 1.基本信息 硬件&#xff1a;MacBook Pro 2017 (A1707) 系统&#xff1a;macOS 13.6 (Ventura) 应用&#xff1a;SwitchHosts 4.1.2 (Releases oldj/SwitchHosts GitHub) hosts内容网站&#xff1a;ht…...

供应QCA8075原装芯片

长期供应各品牌原装芯片&#xff1a; SST39VF040-70-4I-NH AR9344 DC3A BGA USB2422 QFN24 W9751G6KB-251 RTL8211EG-VB-CG HI3535-RBCV100 MX25L25635FMI-10G USB2240I-AEZG EM620FV8BS-70LF HXI15H4G160AF-13K 1PQ8064/BGA-519 USB4604I-1080HN SCB15H2G160A…...