【纠错】遗传算法求解VRP计算车辆容量限制的代码有bug

news2024/9/24 5:29:41

关联文章

关联的博客文章为:《遗传算法求解带时间窗的VRP问题(python)》

原出错函数

源程序代码如下:

def vehicle_capacity_restraint(chrom):
    # 计算一条染色体的车辆容量限制
    individual = copy.deepcopy(chrom)
    split_flag_node = True
    total_path_list = []
    while split_flag_node:
        vehicle_load_list = demand_quantity[0, individual]
        cumsum_list = np.cumsum(vehicle_load_list)
        if len(np.where(cumsum_list > vehicle_capacity_max)[0]) != 0: # 累加值大于车辆容量的位置
            split_flag_node = np.where(cumsum_list > vehicle_capacity_max)[0][0]
        else:
            # 生成的染色体刚好够一辆车运输
            split_flag_node = False
            path_list = [0] * (len(individual) + 2)  # 前后两个配送中心节点
            path_list[1:-1] = copy.deepcopy(individual)
            total_path_list.append(path_list)
        if split_flag_node:
            path_list = [0] * (split_flag_node + 2)  # 前后两个配送中心节点
            path_list[1:-1] = copy.deepcopy(individual[:split_flag_node])
            total_path_list.append(path_list)
            individual = individual[split_flag_node:]
    return total_path_list

运行其他的算例发现如下错误:

total_path_list [[0, 1, 2, 0], [0, 4, 0], [0, 8, 5, 0], [0, 6, 0], [0, 7, 0]]
total_path_list [[0, 5, 0]]
population [[ 1  2  4  8  5  6  7  3  9 10]
 [ 5 10  3  7  6  9  4  1  2  8]]
total_path_list [[0, 1, 2, 0], [0, 4, 0], [0, 8, 5, 0], [0, 6, 0], [0, 7, 0]]
routes [1, 2, 4, 8, 5, 6, 7]

分析错误表象为:使用函数vehicle_capacity_restraint()不能很好的根据车辆的最大容量限制切割染色体,根据容量限制插入配送中心节点0。

如下为算例10个需求服务点的需求配送量:
在这里插入图片描述
车辆的最大载重量vehicle_capacity_max = 3。

在某些场景下该函数切出来的车辆路径是正确的,需要车辆的载重量扩大点

vehicle_capacity_max = 5的场景下计算是可行的,如下:

total_path_list [[0, 10, 0], [0, 4, 1, 2, 0], [0, 9, 3, 0], [0, 8, 5, 0], [0, 6, 7, 0]]
total_path_list [[0, 8, 5, 0], [0, 10, 0], [0, 7, 6, 0], [0, 2, 3, 0], [0, 1, 4, 9, 0]]
population [[10  4  1  2  9  3  8  5  6  7]
 [ 8  5 10  7  6  2  3  1  4  9]]
total_path_list [[0, 10, 0], [0, 4, 1, 2, 0], [0, 9, 3, 0], [0, 8, 5, 0], [0, 6, 7, 0]]
routes [10, 4, 1, 2, 9, 3, 8, 5, 6, 7]

当vehicle_capacity_max = 3的场景,函数vehicle_capacity_restraint()计算会出现错误,不能正确的根据车辆容量限制切割配送路线,如下:

chrom [ 8  2  7  5  4 10  9  6  1  3]
split_flag_node 2
split_flag_node 2
split_flag_node 1
total_path_list [[0, 8, 2, 0], [0, 7, 5, 0], [0, 4, 0]]

代码捉虫

修改代码如下:

def vehicle_capacity_restraint(chrom):
    print("chrom", chrom)
    # 计算一条染色体的车辆容量限制
    individual = copy.deepcopy(chrom)
    split_node_flag = True
    split_node_index = -1
    total_path_list = []
    while split_node_flag:
        vehicle_load_list = demand_quantity[0, individual]
        cumsum_list = np.cumsum(vehicle_load_list)
        print("cumsum_list", cumsum_list)
        if len(np.where(cumsum_list > vehicle_capacity_max)[0]) != 0:  # 累加值大于车辆容量的位置
            print("111", np.where(cumsum_list > vehicle_capacity_max)[0])
            split_node_index = np.where(cumsum_list > vehicle_capacity_max)[0][0]
        else:
            if len(cumsum_list) == 0:
                split_node_flag = False
                continue
            else:
                if split_node_index == -1:
                    print("222")
                    split_node_flag = False
                    # 生成的染色体刚好够一辆车运输
                    path_list = [0] * (len(individual) + 2)  # 前后两个配送中心节点
                    path_list[1:-1] = copy.deepcopy(individual)
                    total_path_list.append(path_list)
        if (split_node_index) != 0 and (split_node_index != -1):
            print("split_node_index", split_node_index)
            path_list = [0] * (split_node_index + 2)  # 前后两个配送中心节点
            path_list[1:-1] = copy.deepcopy(individual[:split_node_index])
            total_path_list.append(path_list)
            individual = individual[split_node_index:]
        elif len(cumsum_list) == 0:
            split_node_flag = False
            continue
        elif split_node_index != -1:
            print("333", split_node_index)
            path_list = [0] * (1 + 2)  # 前后两个配送中心节点
            path_list[1] = copy.deepcopy(individual[0])
            total_path_list.append(path_list)
            individual = individual[1:]
        else:
            pass
    print("total_path_list", total_path_list)
    return total_path_list

满足第一种场景,vehicle_capacity_max = 22 # 车辆的最大载重量,即刚好使用一辆车可以装满所有10个需求节点的货物,运输路线只有一条,即total_path_list [[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 0]]:

chrom [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]
cumsum_list [ 1.   4.5  6.5  7.5 10.5 12.5 14.5 16.  20.  21.5]
222
total_path_list [[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 0]]

Process finished with exit code 0

满足第二种场景,vehicle_capacity_max = 1 # 车辆的最大载重量,车辆的运输能力极小时,函数vehicle_capacity_restraint()也能正确的工作,得到极大值,也就是派10辆车完成运输任务,如下结果total_path_list [[0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 1, 0]]

chrom [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]
cumsum_list [ 1.   4.5  6.5  7.5 10.5 12.5 14.5 16.  20.  21.5]
111 [1 2 3 4 5 6 7 8 9]
split_node_index 1
cumsum_list [ 3.5  5.5  6.5  9.5 11.5 13.5 15.  19.  20.5]
111 [0 1 2 3 4 5 6 7 8]
333 0
cumsum_list [ 2.   3.   6.   8.  10.  11.5 15.5 17. ]
111 [0 1 2 3 4 5 6 7]
333 0
cumsum_list [ 1.   4.   6.   8.   9.5 13.5 15. ]
111 [1 2 3 4 5 6]
split_node_index 1
cumsum_list [ 3.   5.   7.   8.5 12.5 14. ]
111 [0 1 2 3 4 5]
333 0
cumsum_list [ 2.   4.   5.5  9.5 11. ]
111 [0 1 2 3 4]
333 0
cumsum_list [2.  3.5 7.5 9. ]
111 [0 1 2 3]
333 0
cumsum_list [1.5 5.5 7. ]
111 [0 1 2]
333 0
cumsum_list [4.  5.5]
111 [0 1]
333 0
cumsum_list [1.5]
111 [0]
333 0
cumsum_list []
total_path_list [[0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 1, 0]]

Process finished with exit code 0

满足第三种场景,vehicle_capacity_max = 5 # 车辆的最大载重量,也就是没有修改函数前,函数能实现的计算功能。

chrom [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]
cumsum_list [ 1.   4.5  6.5  7.5 10.5 12.5 14.5 16.  20.  21.5]
111 [2 3 4 5 6 7 8 9]
split_node_index 2
cumsum_list [ 2.   3.   6.   8.  10.  11.5 15.5 17. ]
111 [2 3 4 5 6 7]
split_node_index 2
cumsum_list [ 3.   5.   7.   8.5 12.5 14. ]
111 [2 3 4 5]
split_node_index 2
cumsum_list [2.  3.5 7.5 9. ]
111 [2 3]
split_node_index 2
cumsum_list [4.  5.5]
111 [1]
split_node_index 1
cumsum_list [1.5]
split_node_index 1
cumsum_list []
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]]

Process finished with exit code 0

满足第四种场景,vehicle_capacity_max = 100 # 车辆的最大载重量,当车辆最大载重量即运输能力极大时,函数也能够很好的计算配送路线,total_path_list [[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 0]]

chrom [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]
cumsum_list [ 1.   4.5  6.5  7.5 10.5 12.5 14.5 16.  20.  21.5]
222
total_path_list [[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 0]]

Process finished with exit code 0

运用实例

vehicle_capacity_max = 5 # 车辆的最大载重量

目标函数如下:

# 目标函数:使用车辆数量最少+车辆的总行驶距离最小。
# 约束条件:车辆载重量限制+硬时间窗限制
# 由于出动一辆车的固定成本远远大于车辆的行驶成本,
# 所以,本文将车辆数最小作为最小总成本的主要目标 ,而将路程最小作为次要目标 。

def main_target_func(chrom):
    # 使用车辆数量最少
    vehice_num = 0
    routes = get_feasible_route(chrom)
    print("routes", routes)
    for path in routes:
        for node in path[1:-1]:
            if node == 0:
                vehice_num += 1
    return vehice_num


def minor_target_func(chrom):
    # 车辆的总行驶距离最小
    # 适应度函数是总路线长度最小
    routes = get_feasible_route(chrom)
    total_length = 0
    for route in routes:
        total_length += get_route_length(route)
    target_value = total_length
    return target_value


def calculate_fitness(chrom):
    target_value = 0.6*main_target_func(chrom) + 0.4*minor_target_func(chrom)
    return target_value

遗传算法计算得到如下的结果即算法迭代图形:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Simian使用方法

1.下载 链接1:官网下载 链接2:压缩包 2.操作 1.双击exe启动 2.打开控制台,winR 输入cmd 3.输入操作语句 G:\1111\simian-2.5.10\bin\simian-2.5.10.exe -includes"G:\1111\test\*.cpp" -threshold3 > output.txt G:\1111\si…

Vuex中多个参数显示undefined的解决方案

笔者今天在使用Vuex中的mutations改变state里面的全局状态的值,获取到的数据却怎么都是第一个参数是可以获取到,但是第二个就获取不到,就显示undefined 问题代码 mutations: {multiparameter(state,id,newStatus) {console.log("数据的Key&#x…

【Java】java中的集合框架组成部分

集合框架中 单列与多列的区别 单列——一行只有一列数据 多列(双列)——一行两列数据 key value 集合框架组成部分: 1. Collection(存放单列数据) List 接口——存放数据可以允许重复的 ArrayList 底层基于 数组 数据结构实现LinkedList 底层基于 链表 数据结构实现…

seq“ 和 “time“ 字段

在RTP(Real-time Transport Protocol)报文中,"seq" 和 "time" 字段分别表示以下内容: 1. **Seq(Sequence Number)字段**:Seq字段是RTP头部中的一个16位字段,用…

Python---练习:判断是否为一个合法三角形(if else)

案例 判断是否为一个合法三角形 需求:输入三角形的3边,如果两边的长度大于第三条边,则代表是一个合法三角形 思路: 先确定什么是一个合法三角形-----就是任意两边的和,大于第三边。 就像下图,a b 展…

分享一个基于Python+Django的高校食堂外卖点餐系统的设计实现(源码、调试、开题、lw、ppt)

💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…

Hadoop3教程(二十四):Yarn的常用命令与参数配置实例

文章目录 (132)YARN常用命令查看任务查看日志查看容器查看节点状态rmadmin更新配置查看队列 (133)生产环境核心配置参数(135)生产环境核心参数配置案例(140/141)Tool接口案例参考文献…

Flink之Window窗口机制

窗口Window机制 窗口概述窗口的分类是否按键分区按键分区窗口非按键分区 按照驱动类型按具体分配规则滚动窗口Tumbling Windows滑动窗口 Sliding Windows会话窗口 Session Windows全局窗口 Global Windows 时间语义窗口分配器 Window Assigners时间窗口计数窗口例子 窗口函数 W…

一篇文章带你弄懂编译和链接

一篇文章带你弄懂编译和链接 文章目录 一篇文章带你弄懂编译和链接一、环境二、翻译环境1.编译①预处理②编译③汇编 2.链接 三、运行环境 一、环境 翻译环境和运行环境 翻译环境:源代码被转换成可执行的机器指令。 运行环境:用于实际执行代码。 二、…

使用 Android Studio 开发一款弹钢琴app

A. 项目描述 本项目主要实现了【钢琴键盘的模拟】、【弹奏引导】以及【乐曲库】等功能。 钢琴键盘模拟:提供全尺寸键盘,并且根据用户的喜好来调整键盘的颜色样式。 弹奏引导:用户可以根据键盘上的提示符号 👆 来学习演奏。对于钢…

Win32 简单日志实现

简单实现日志保存, 支持设置日志文件数量, 单个日志文件大小上限, 自动超时保存日志, 日志缓存超限保存 CLogUtils.h #pragma once#include <string> #include <windows.h> #include <vector> #include <map> #include <mutex> #include <tc…

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

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

【Docker从入门到入土 1】Docker管理命令

Part1 一、容器1.1 虚拟化技术的演变1.2 容器简介1.3 为什么要用到容器&#xff1f;1.4 常用的容器引擎1.5 容器和虚拟机 二、Docker2.1 什么是docker&#xff1f;&#xff08;面试题&#xff09;2.2 Docker和虚拟机的区别&#xff08;面试常问&#xff0c;记住&#xff09;2.3…

SLAM 14 notes

4.23 推导 f ( x ) f(x) f(x)在点a处的泰勒展开 f ( x ) ∑ n 0 ∞ f ( n ) a n ! ( x − a ) n f(x) \sum_{n0}^\infty \frac{f^{(n)}a}{n!}(x-a)^n f(x)∑n0∞​n!f(n)a​(x−a)n l n x lnx lnx的n阶导数 l n ( n ) x ( − 1 ) n − 1 ( n − 1 ) ! x n ln^{(n)}x \fr…

C++进阶语法之函数和指针【学习笔记(二)】

文章目录 1、C 函数1.1 函数的定义1.2 函数原型&#xff08;function prototypes&#xff09;1.3 参数&#xff08;parameter&#xff09;——值传递&#xff08;pass by value&#xff09;1.4 重载&#xff08;overloading&#xff09;1.5 函数传参——传递数组&#xff08;ar…

drawio都能做那些事情和模板示例

drawio都能做那些事情和模板示例 你可以使用drawio&#xff0c;并使用drawio提供的扩展模板库和大量的形状库&#xff0c;针对很多不同的工业领域创建不同类型的图表。 针对如下的内容中的所有的图&#xff0c;均可以下载源文件并导入到drawio中再次编辑&#xff08;供学习者…

如何远程通过内网穿透实现微信公众号在本地的完整调试

文章目录 前言1. 配置本地服务器2. 内网穿透2.1 下载安装cpolar内网穿透2.2 创建隧道 3. 测试公网访问4. 固定域名4.1 保留一个二级子域名4.2 配置二级子域名 5. 使用固定二级子域名进行微信开发 前言 在微信公众号开发中&#xff0c;微信要求开发者需要拥有自己的服务器资源来…

什么是兼容性测试? 重要性是什么?

在数字化时代&#xff0c;用户使用各种不同类型的设备和操作系统来访问应用程序和网站。为了确保用户体验的一致性和应用程序的可用性&#xff0c;兼容性测试变得至关重要。本文将深入探讨兼容性测试的概念及重要性。 一、什么是兼容性测试? 兼容性测试是一种软件测试方法&…

混入组件 (mixin)

1 什么是混入以及作用 *混入 (mixin) 提供了一种非常灵活的方式&#xff0c;来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时&#xff0c;所有混入对象的选项将被“混合”进入该组件本身的选项。作用&#xff1a;主要作用是继承和封装…

【python】什么是网络爬虫?

什么是网络爬虫&#xff1f; 网络爬虫是一种自动化程序&#xff0c;用于从互联网上抓取信息。这些信息可以是文本、图像、视频、数据表格等各种形式的数据。爬虫程序通过模拟浏览器的行为&#xff0c;自动访问网页、抓取内容&#xff0c;并将其保存或处理。这对于数据挖掘、搜索…