【改进篇】Python实现VRP常见求解算法——蚁群算法(ACO)

news2024/9/22 13:42:39

基于python语言,实现经典蚁群算法(ACO)对车辆路径规划问题(CVRP)进行求解, 优化代码结构,改进Split函数

目录

  • 往期优质资源
  • 1. 适用场景
  • 2. 改进效果对比
    • 2.1实验结果
    • 2.2 改进前后算法性能对比
  • 3. 求解结果
  • 4. 改进内容
  • 5. 部分代码
  • 6. 完整代码
  • 参考

往期优质资源

CVRP系列
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDVRP系列
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
VRPTW系列
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
HVRP系列
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDHFVRPTW系列
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法

1. 适用场景

  • 求解CVRP
  • 车辆类型单一
  • 车辆容量不小于需求节点最大需求
  • 单一车辆基地

2. 改进效果对比

这里做了简单的参数敏感性分析,比较不同参数组合下两个版本code的最优值与求解时间的差异。具体为:1)设定信息素挥发因子为0.1,0.3三个不同等级;2)设定信息启发式因子为1,2,3,4,5不同值;3)设定期望启发式因子为1,2,3,4,5不同值,其他参数固定不变:最大迭代次数为300,车辆容量为80。

2.1实验结果

rho=0.1:
在这里插入图片描述
rho=0.3:
在这里插入图片描述

2.2 改进前后算法性能对比

求解时间对比(红色为改进后,蓝色为改进前):
在这里插入图片描述
行驶距离对比(红色为改进后,蓝色为改进前):
在这里插入图片描述

可以直观看出,改进后算法求解时间略有增加, 平均增加3.10%,目标函数平均优化1.38%

3. 求解结果

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

(2)车辆路径
在这里插入图片描述
(3)输出文件

在这里插入图片描述

4. 改进内容

本期代码在前期代码的基础上做了以下改进:

  • 增加距离矩阵,减少代码中重复计算节点间距离代码
  • 引入文献中基于图论的Split方法,在给定节点id序列时,可求得最优分割方案

除了以上关键改动之外,还对代码做了细小调整。

5. 部分代码

(1)数据结构

# 数据结构:解
class Sol():
    def __init__(self):
        self.node_no_seq=None # 解的编码
        self.obj=None # 目标函数
        self.action_id=None # 算子id
        self.route_list=None # 解的解码
        self.route_distance = None  # 车辆路径的长度集合
# 数据结构:网络节点
class Demand():
    def __init__(self):
        self.id = 0 # 节点id
        self.x_coord = 0 # 节点平面横坐标
        self.y_coord = 0  # 节点平面纵坐标
        self.demand = 0 # 节点需求
# 数据结构:全局参数
class Model():
    def __init__(self):
        self.best_sol = None # 全局最优解
        self.demand_dict = {}  # 需求节点集合
        self.demand_id_list = []
        self.sol_list = []  # 解的集合
        self.depot = None # 车场节点
        self.number_of_nodes = 0 # 需求节点数量
        self.vehicle_cap = 80 # 车辆最大容量
        self.distance_matrix = {}
        self.popsize = 100 # 种群规模
        self.alpha = 2 # 信息启发式因子
        self.beta = 3 # 期望启发式因子
        self.Q = 100 # 信息素总量
        self.rho = 0.5 # 信息素挥发因子
        self.tau = {} # 弧信息素集合
        self.vehicle_cap=0  # 车辆最大容量

(2)距离矩阵

def calDistanceMatrix(model):
    for i in range(len(model.demand_id_list)):
        f_n = model.demand_id_list[i]
        for j in range(i + 1, len(model.demand_id_list)):
            t_n = model.demand_id_list[j]
            dist = math.sqrt((model.demand_dict[f_n].x_coord - model.demand_dict[t_n].x_coord) ** 2
                             + (model.demand_dict[f_n].y_coord - model.demand_dict[t_n].y_coord) ** 2)
            model.distance_matrix[f_n, t_n] = dist
            model.distance_matrix[t_n, f_n] = dist
            model.tau[f_n, t_n] = 100
            model.tau[t_n, f_n] = 100

        dist = math.sqrt((model.demand_dict[f_n].x_coord - model.depot.x_coord) ** 2
                         + (model.demand_dict[f_n].y_coord - model.depot.y_coord) ** 2)
        model.distance_matrix[f_n, model.depot.id] = dist
        model.distance_matrix[model.depot.id, f_n] = dist

(3)路径提取

def extractRoutes(node_no_seq,P,depot_id):
    route_list = []
    route = []
    p = P[node_no_seq[0]]
    for node_seq in node_no_seq:
        if P[node_seq] == p:
            route.append(node_seq)
        else:
            route.insert(0,depot_id)
            route.append(depot_id)
            route_list.append(route)
            route = [node_seq]
            p = P[node_seq]
    return route_list

(4)蚁群移动

# 蚂蚁移动
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_seq
        sol.obj,sol.route_list,sol.route_distance=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):
    if len(SE_List) == 1:
        return SE_List[0]
    prob=np.zeros(len(SE_List))
    for i,node_no in enumerate(SE_List):
        eta=1/model.distance_matrix[current_node_no,node_no]
        tau=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)]

(5)收敛曲线

# 绘制目标函数收敛曲线
def plotObj(obj_list):
    plt.rcParams['font.sans-serif'] = ['SimHei']  #show chinese
    plt.rcParams['axes.unicode_minus'] = False  # Show minus sign
    plt.plot(np.arange(1,len(obj_list)+1),obj_list)
    plt.xlabel('Iterations')
    plt.ylabel('Obj Value')
    plt.grid()
    plt.xlim(1,len(obj_list)+1)
    plt.show()

(6)车辆路径

# 绘制优化车辆路径
def plotRoutes(model):
    for route in model.best_sol.route_list:
        x_coord=[]
        y_coord=[]
        for node_no in route:
            x_coord.append(model.demand_dict[node_no].x_coord)
            y_coord.append(model.demand_dict[node_no].y_coord)
        plt.plot(x_coord,y_coord,marker='s',color='b',linewidth=0.5)
    plt.show()

(7)输出结果

# 输出结果
def outPut(model):
    work=xlsxwriter.Workbook('result.xlsx')
    worksheet=work.add_worksheet()
    worksheet.write(0, 0, 'id')
    worksheet.write(0, 1, 'route')
    worksheet.write(0, 2, 'distance')
    worksheet.write(0, 3, 'total_distance')
    worksheet.write(1,3,model.best_sol.obj)
    for id,route in enumerate(model.best_sol.route_list):
        r=[str(i)for i in route]
        worksheet.write(id + 1, 0, f'v{str(id + 1)}')
        worksheet.write(id + 1, 1, '-'.join(r))
        worksheet.write(id + 1, 2, model.best_sol.route_distance[id])
    work.close()

6. 完整代码

如有错误,欢迎交流。
有偿获取

参考

  1. A simple and effective evolutionary algorithm for the vehicle routing problem

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

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

相关文章

臻图信息构建数字孪生港口船舶停靠管理系统,赋能港口创新发展

我国的港口不仅是船只停靠的避风港&#xff0c;也是现代渔业发展和管理的中心。随着国内港口业的不断发展&#xff0c;国务院在《现代综合运输体系发展“十四五”规划》中提出&#xff0c;要自动化、数字化、智能化等技术来完善监管体系建设。 ​ 随着科技兴港战略的提出&…

“零”代码改动,静态编译让太乙Stable Diffusion推理速度翻倍

作者&#xff5c;梁德澎 AI 作图领域的工具一直不尽人意&#xff0c;直到去年 8 月 Stable Diffusion 开源&#xff0c;成为AI 图像生成领域无可争辩的划时代模型。 为了提升其推理效率&#xff0c;OneFlow 首度将 Stable Diffusion 模型加速至“一秒出图”时代&#xff0c;极…

2023牛客寒假算法基础集训营2(11/12)

Tokitsukaze and abn (easy)Tokitsukaze and abn (medium)要使abn&#xff0c;那么转换一下就是bn-a&#xff0c;所以只需要计算[n-L,n-R]和[L,R]相交的部分即可AC代码&#xff1a;#include <bits/stdc.h> using namespace std; using LL long long; int main() {ios::s…

6. 基本数据类型

1. Python 中的变量不需要声明 每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 counter 100 # 整型 mile…

关于Win11打开文档总是提示“选择一个程序打开”的问题

这边异常情况&#xff1a; 使用的360浏览器下载回来的文档、微信下载回来的文档都会出现标题所说的问题。 问题产生的原因&#xff1a; 初期在重装电脑后&#xff0c;将自带的一些安装系统后的第三方软件卸载掉了&#xff0c;也包括QQ浏览器。 可是在win11默认应用中看到了…

第五章SpringFramework之AOP

文章目录AOP概念及相关术语概述为什要用 AOP相关术语横切关注点Advice通知Join Point连接点Point CUT 切入点切面目标代理基于注解的SpringAOP准备工作切入点表达式语法重用切入点表达式对应的切面前置通知返回通知异常通知后置通知环绕通知切面的优先级总结Spring AOP 的实现步…

27.Isaac教程--局部建图

26.Isaac教程-局部建图 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 局部地图是机器人周围直接环境的基于网格的简化表示。 这些简化的世界表示对于安全地规划机器人附近的静态和动态障碍物至关重要。 局部建图管道将来自连接到机器人的不同传…

信息服务上线渗透检测网络安全检查报告和解决方案2(安装文件信息泄漏、管理路径泄漏、XSS漏洞、弱口令、逻辑漏洞、终极上传漏洞升级)

系列文章目录 信息服务上线渗透检测网络安全检查报告和解决方案 文章目录系列文章目录前言一、XSS漏洞漏洞危害解决方案1.参数过滤2.Cookie设置HttpOnly二、安装文件目录信息泄漏漏洞证明解决方案三、后台管理路径泄漏、暴力破解、明文传输漏洞证明解决方案四、逻辑漏洞漏洞验证…

LINUX学习之文件处理常用命令(三)

ls 命令描述 ls命令是linux系统中用来列出文件和目录的常用命令&#xff0c;它可以显示文件和目录的名称、权限、大小、修改时间等信息 以下是ls命令的常用参数: -a &#xff1a;列出全部的文件&#xff0c;连同隐藏文件-d &#xff1a;仅列出文件目录&#xff0c;而不是列…

【K哥爬虫普法】辛苦钱被中间商抽走八成,还因此锒铛入狱

我国目前并未出台专门针对网络爬虫技术的法律规范&#xff0c;但在司法实践中&#xff0c;相关判决已屡见不鲜&#xff0c;K 哥特设了“K哥爬虫普法”专栏&#xff0c;本栏目通过对真实案例的分析&#xff0c;旨在提高广大爬虫工程师的法律意识&#xff0c;知晓如何合法合规利用…

【Python百日进阶-数据分析】Day229 - plotly的动画

文章目录一、动画1.1 基本动画1.2 使用 Plotly Express 制作动画条形图1.3 当前动画限制和注意事项二、为动画添加控制按钮2.1 简单的播放按钮2.2 曲线上的移动点2.3 沿平面曲线移动 Frenet 框架2.4 使用滑块和按钮三、MRI 体积切片的可视化一、动画 使用 Plotly Express 制作…

23种设计模式(九)——抽象工厂模式【对象创建】

文章目录 意图什么时候使用抽象工厂真实世界类比解决方案抽象工厂模式的实现抽象工厂模式的优缺点亦称: Abstract Factory 意图 抽象工厂是创建型设计模式,它强调了一系列相关产品对象(属于同一个产品族)的创建过程,它和工厂方法模式的侧重点不同,工厂方法模式更加侧重于…

JUC面试(四)——ABA问题

ABA问题 从AtomicInteger引出下面的问题 CAS -> Unsafe -> CAS底层思想 -> ABA -> 原子引用更新 -> 如何规避ABA问题 假设现在有两个线程&#xff0c;分别是T1 和 T2&#xff0c;然后T1执行某个操作的时间为10秒&#xff0c;T2执行某个时间的操作是2秒&#…

Python---人生重开模拟器(简版)

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些python的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 人生重开模拟器思维导图前言一、设置初始属性1.…

〖百宝书-思维锻炼③〗——三心理论——成功的来源

大家好&#xff0c;我是涵子&#xff0c;今天我们来聊聊三心理论。 &#x1f4ac; 人生格言&#xff1a;Stay foolish, stay kind.&#x1f4ac; &#x1f4eb; 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;和大家一起学习&#xff0c;一起进步&#x1f440; &a…

Ae 效果详解:CC Snowfall

效果/模拟/CC SnowfallEffects/Simulation/CC Snowfall示例CC Snowfall &#xff08;下雪效果&#xff09;&#xff0c;可用来模拟带景深、光效和运动模糊的下雪效果。Flakes 雪花片数用于设置雪花片的数量。默认值 10000。Size 大小用于设置雪花片的大小。默认值 3.00。Variat…

连续系统PID的Simulink仿真-3

利用简化S函数&#xff0c;实现连续系统PID的Simulink仿真-2中S函数同样的功能。利用S函数简化形式实现被控对象的表达、控制器的设计及仿真结果的输出。在简化S函数中&#xff0c;flag-0时为S函数初始化&#xff0c;其中 sys包括6个参数:第1个参数表示连续系统的阶数;第2个参数…

DBCO-PEG-4ARM,四臂聚乙二醇二苯基环辛炔,4Arm PEG-DBCO

●中文名&#xff1a;四臂-聚乙二醇-二苯基环辛炔 ●英文名&#xff1a;4Arm PEG-DBCO&#xff0c;DBCO PEG 4ARM ●外观以及性质&#xff1a; ​4Arm PEG-DBCO产物呈固体或粘性液体&#xff0c;取决于PEG分子量&#xff0c;高分子DBCO功能化PEG&#xff0c;“点击化学"…

【JavaScript】事件相关知识详解

&#x1f4bb; 【JavaScript】事件相关知识详解&#x1f3e0;专栏&#xff1a;JavaScript &#x1f440;个人主页&#xff1a;繁星学编程&#x1f341; &#x1f9d1;个人简介&#xff1a;一个不断提高自我的平凡人&#x1f680; &#x1f50a;分享方向&#xff1a;目前主攻前端…

CES 2023:高通从移动互联深入布局未来智驾

作为全球规模最大、影响最为广泛的国际消费电子展&#xff0c;CES曾经因为三年疫情而无奈中断&#xff0c;如今终于在2023年1月重返美国拉斯维加斯。而不管是CES 2023的3200多家参展企业&#xff0c;还是数量超过10万的现场观众&#xff0c;当他们走出位于拉斯维加斯会议中心西…