【matlab 路径规划】基于改进遗传粒子群算法的药店配送路径优化

一 背景介绍

本文分享的是一个基于订单合并的订单分配和路径规划联合优化,主要背景是骑手根据客户需求,从药店取药之后进行配送,配送的过程中考虑路径的长度、客户的服务时间窗、车辆的固定成本等要素,经过建模和优化得到最优的配送方案。

二 模型介绍

2.1基本假设

配送的具体流程和现实情况,建立的数学模型基于以下假设条件:
(1)O2O 药品零售平台旗下的各个门店能够满足已下单顾客的需求量,即不存在供不应
求的情况。
(2)已知消费者下单商品数量、地理位置及时间窗和每个消费者的需求量不会发生变化
(3)骑手在每个配送点服务时间恒定且相同,由于服务时间较短所以忽略不计。
(4)骑手从药店出发,中途不可返回药店取货,完成所有的配送任务后需要返回药店。
(5)在骑手对各配送点进行配送的过程中,不考虑交通堵塞、车辆故障、天气恶劣等突
发状况的影响。

2.2目标函数

在这里插入图片描述

2.3 约束条件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三 算法介绍

遗传算法是一种模拟自然进化过程的优化算法,用于解决优化问题。它模拟了生物进化的过程,通过对优良个体的选择、交叉和变异,逐步优化解的质量,最终找到最优解。

遗传算法的基本步骤包括:

  1. 初始化种群:随机生成一组初始解作为种群,通常采用随机数生成的方式。

  2. 适应度评价:根据问题的具体要求,采用适应度函数对每个个体进行评估,得到其适应度值。

  3. 选择操作:根据个体的适应度值,按照一定的选择概率选择优良个体作为父代,通常采用轮盘赌选择方法。

  4. 交叉操作:从选出的父代个体中选取一对个体,通过某种交叉方式生成新的个体。

  5. 变异操作:对新生成的个体进行一定的变异操作,改变其基因的值,增加种群的多样性。

  6. 更新种群:将新生成的个体加入到种群中,得到更新后的种群。

  7. 终止条件判断:判断是否满足终止条件,如达到最大迭代次数或找到满足要求的解。

  8. 返回最优解:返回种群中适应度最好的个体作为最优解。

遗传算法通过迭代优化的方式,不断改进解的质量,寻找到全局最优解或较好的局部最优解。它在解决复杂问题、搜索空间大的问题等方面具有很好的性能。

四 算例分析

算例1 本文使用30个节点的算例,1个配送节点 29个需求节点(分为三个优先级)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

车辆编号.1: 0 -> 7 -> 1 -> 12 -> 15 -> 24 -> 22 -> 11 -> 27 -> 26 -> 29 ->
25 -> 0 到达时间节点: 0 - 4.7 - 9.9 - 11.4 - 12.4 - 14.9 - 15.6 - 17.4 -
19.6 - 24 - 26.7 - 28.4 - 33.7 min 行驶距离: 8413.36 m, 总时间: 33.7 min; 行驶成本 (C1): 21.03, 惩罚成本 (C2): 50.88
------------------------------------------------------------- 车辆编号.2: 0 -> 8 -> 19 -> 0 到达时间节点: 0 - 7.9 - 10.2 - 19.7 min 行驶距离: 4931.47
m, 总时间: 19.7 min; 行驶成本 (C1): 12.33, 惩罚成本 (C2): 29.59
------------------------------------------------------------- 车辆编号.3: 0 -> 18 -> 13 -> 4 -> 5 -> 16 -> 28 -> 0 到达时间节点: 0 - 2.5 - 6 - 7.5 -
10.1 - 13.6 - 15.1 - 16.6 min 行驶距离: 4138.40 m, 总时间: 16.6 min; 行驶成本 (C1): 10.35, 惩罚成本 (C2): 29.81
------------------------------------------------------------- 车辆编号.4: 0 -> 10 -> 6 -> 9 -> 20 -> 0 到达时间节点: 0 - 5.9 - 10 - 12.4 - 15.5 -
20.1 min 行驶距离: 5020.18 m, 总时间: 20.1 min; 行驶成本 (C1): 12.55, 惩罚成本 (C2): 33.81
------------------------------------------------------------- 车辆编号.5: 0 -> 23 -> 17 -> 14 -> 21 -> 30 -> 0 到达时间节点: 0 - 6.2 - 7.2 - 8.2 -
11.8 - 20.5 - 22.8 min 行驶距离: 5695.44 m, 总时间: 22.8 min; 行驶成本 (C1): 14.24, 惩罚成本 (C2): 37.93
------------------------------------------------------------- 车辆编号.6: 0 -> 2 -> 3 -> 0 到达时间节点: 0 - 1.5 - 5.7 - 9.5 min 行驶距离: 2363.65 m,
总时间: 9.5 min; 行驶成本 (C1): 5.91, 惩罚成本 (C2): 14.18

算例2 本文使用10个节点的算例,1个配送节点 9个需求节点(分为三个优先级)

在这里插入图片描述
**

车辆编号.1: 0 -> 2 -> 3 -> 1 -> 5 -> 4 -> 7 -> 8 -> 9 -> 6 -> 0 到达时间节点:
0 - 1.5 - 5.7 - 13.8 - 15.3 - 16.9 - 18.5 - 22.1 - 27.2 - 29.5 - 32.4
min 行驶距离: 8090.30 m, 总时间: 32.4 min; 行驶成本 (C1): 20.23, 惩罚成本 (C2):
54.26

**

六 项目分享

部分源码

clc
clear
close all
tic % 保存当前时间

dataloader
%% 初始化问题参数
CustomerNum = size(Position, 1) - 1; % 需求点个数

%% 需求点绘图
figure
hold on
xx = Position(:, 1);
yy = Position(:, 2);
idx1 = find(order_priority == 1);
idx2 = find(order_priority == 2);
idx3 = find(order_priority == 3);
scatter(xx(idx1), yy(idx1), 25, 'filled', 'go', 'DisplayName', '第一优先级')
scatter(xx(idx2), yy(idx2), 25, 'filled', 'bo', 'DisplayName', '第二优先级')
scatter(xx(idx3), yy(idx3), 25, 'filled', 'yo', 'DisplayName', '第三优先级')
scatter(xx(1), yy(1), 200, 'filled', 'rp', 'DisplayName', '药店')
legend
title('需求点散点图')

%% 初始化算法参数
NIND = 1000; % 粒子数量
MAXGEN = 100; % 最大迭代次数
mutation_prob = 0.05; % 变异概率
crossover_prob = 0.8; % 交叉概率
tournament_size = 5; % 锦标赛规模

%% 为预分配内存而初始化的0矩阵
Population = zeros(NIND, CustomerNum * 2 + 1); % 预分配内存,用于存储种群数据
PopDistance = zeros(NIND, 1); % 预分配矩阵内存
GbestDisByGen = zeros(MAXGEN, 1); % 预分配矩阵内存

penalty_costs = zeros(NIND, 1);
travel_costs = zeros(NIND, 1);
vehicle_costs = zeros(NIND, 1);
total_distances = zeros(NIND, 1);
penalty_orders = cell(NIND, 1);

for i = 1:NIND
    %% 初始化各粒子
    Population(i, :) = InitPop(CustomerNum, Distance, setting); % 使用GRASP算法生成TSP路径

    %% 计算路径长度
    PopDistance(i) = CalcDis(Population(i,:),Distance,TimeWindow,order_priority,setting); % 计算路径长度
end
%% 存储Pbest数据
Pbest = Population; % 初始化Pbest为当前粒子集合
PbestDistance = PopDistance; % 初始化Pbest的目标函数值为当前粒子集合的目标函数值

%% 存储Gbest数据
[mindis, index] = min(PbestDistance); % 获得Pbest中
Gbest = Pbest(index, :); % 初始Gbest粒子
GbestDistance = mindis; % 初始Gbest粒子的目标函数值

%% 开始迭代
gen = 1;

while gen <= MAXGEN
    %% 选择算子(锦标赛选择)
    new_population = zeros(size(Population));
    for i = 1:NIND
        new_population(i, :) = Selection(Population, PopDistance, tournament_size); % 锦标赛选择
    end
    Population = new_population;

    %% 每个粒子更新
    for i = 1:NIND
        %% 粒子与Pbest交叉
        if rand < crossover_prob
            Population(i, 2:end-1) = Crossover(Population(i, 2:end-1), Pbest(i, 2:end-1)); % 交叉
        end

        % 新路径长度变短则记录至Pbest
         PopDistance(i) = CalcDis(Population(i,:),Distance,TimeWindow,order_priority,setting); % 计算路径长度
        if PopDistance(i) < PbestDistance(i) % 若新路径长度变短
            Pbest(i, :) = Population(i, :); % 更新Pbest
            PbestDistance(i) = PopDistance(i); % 更新Pbest距离
        end

        %% 根据Pbest更新Gbest
        [mindis, index] = min(PbestDistance); % 找出Pbest中最短距离
        if mindis < GbestDistance % 若Pbest中最短距离小于Gbest距离
            Gbest = Pbest(index, :); % 更新Gbest
            GbestDistance = mindis; % 更新Gbest距离
        end

        %% 粒子与Gbest交叉
        if rand < crossover_prob
            Population(i, 2:end-1) = Crossover(Population(i, 2:end-1), Gbest(2:end-1));
        end

        % 新路径长度变短则记录至Pbest
        PopDistance(i) = CalcDis(Population(i,:),Distance,TimeWindow,order_priority,setting); % 计算路径长度
        if PopDistance(i) < PbestDistance(i) % 若新路径长度变短
            Pbest(i, :) = Population(i, :); % 更新Pbest
            PbestDistance(i) = PopDistance(i); % 更新Pbest距离
        end

        %% 粒子自身变异
        if rand < mutation_prob
            Population(i, :) = Mutate(Population(i, :), Distance); % 传递Distance矩阵
        end

        % 新路径长度变短则记录至Pbest
        PopDistance(i) = CalcDis(Population(i,:),Distance,TimeWindow,order_priority,setting); % 计算路径长度
        if PopDistance(i) < PbestDistance(i) % 若新路径长度变短
            Pbest(i, :) = Population(i, :); % 更新Pbest
            PbestDistance(i) = PopDistance(i); % 更新Pbest距离
        end

        %% 根据Pbest更新Gbest
        [mindis, index] = min(PbestDistance); % 找出Pbest中最短距离
        if mindis < GbestDistance % 若Pbest中最短距离小于Gbest距离
            Gbest = Pbest(index, :); % 更新Gbest
            GbestDistance = mindis; % 更新Gbest距离
        end
    end

    %% 显示此代信息
    fprintf('迭代次数 = %d, 最小成本 = %.2f   \n', gen, GbestDistance)

    %% 存储此代最短距离
    GbestDisByGen(gen) = GbestDistance;

    %% 更新迭代次数
    gen = gen + 1;
end

% 删去路径中多余1
for i = 1:length(Gbest) - 1
    if Gbest(i) == Gbest(i + 1)
        Gbest(i) = 0; % 相邻位都为1时前一个置零
    end
end
Gbest(Gbest == 0) = []; % 删去多余零元素

Gbest = Gbest - 1; % 编码各减1,与文中的编码一致

%% 计算结果数据输出到命令行
disp('-------------------------------------------------------------')
toc % 显示运行时间
TextOutput(Gbest, Distance, TimeWindow, setting); % 显示最优路径
disp('-------------------------------------------------------------')

%% 迭代图
figure
plot(GbestDisByGen, 'LineWidth', 2) % 展示目标函数值历史变化
xlim([1 gen - 1]) % 设置 x 坐标轴范围
set(gca, 'LineWidth', 1)
xlabel('迭代次数')
ylabel('最小成本')
title('遗传粒子群迭代曲线图')

%% 绘制实际路线
DrawPath(Gbest, Position, idx1, idx2, idx3)

本项目是典型的考虑车辆容量,车辆行驶距离,客户时间窗的车辆路径规划问题。使用了性能相对较好的遗传粒子群算法(GAPSO),代码使用模块化编程,主函数框架相对固定,能够兼容不同类型的优化模型。
需要完整项目源码或者需要定制项目的朋友欢迎咨询。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是声明式编程?发展趋势怎么样的?

一、什么是声明式编程&#xff1f; 声明式编程&#xff08;Declarative programming&#xff09;是一种编程范式&#xff0c;与命令式编程相对立。它主要描述目标的性质&#xff0c;让计算机明白目标&#xff0c;而非具体的执行流程。在声明式编程中&#xff0c;开发者只需声明…

彻底搞懂Kafka生产消费流程,这篇文章就够了!

Hey, 小伙伴们!今天小米给大家带来一篇关于Kafka生产消费基本流程的揭秘,内容超干货!让我们一起揭开Kafka神秘的面纱,探索它的工作原理吧! Producer创建及其内部结构 当我们创建一个Kafka Producer时,Kafka会为我们创建一个叫做Sender的线程,并将其设置为守护线程(Da…

论文解读StyleGAN系列——StyleGANv3

论文&#xff1a;Alias-Free Generative Adversarial Networks&#xff08;2021.06&#xff09; 作者&#xff1a;Tero Karras, Miika Aittala, Samuli Laine, Erik Hrknen, Janne Hellsten, Jaakko Lehtinen, Timo Aila 链接&#xff1a;https://arxiv.org/abs/2106.12423 代码…

计算两个经纬度之间的球面距离(基于Mysql和PHP实现)

计算两个经纬度之间的球面距离 1、MySQL实现方式 - 基于空间函数(ST_Distance_Sphere)实现 前置条件&#xff1a;确保您使用的是 MySQL 8.0 或更高版本&#xff0c;因为较早的版本对地理空间的支持有限。 1.1 创建表和索引 说明&#xff1a;设置 location 为 point 类型 #…

驭码CodeRider将亮相世界人工智能大会,AI 产品、重磅分享,真的很City!

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…

Redis 中 Set 和 Zset 类型

目录 1.Set类型 1.1 Set集合 1.2 普通命令 1.3 集合操作 1.4 内部编码 1.5 使用场景 2.Zset类型 2.1 Zset有序集合 2.2 普通命令 2.3 集合间操作 2.4 内部编码 2.5 使用场景 1.Set类型 1.1 Set集合 集合类型也是保存多个字符串类型的元素&#xff0c;但是和列表类型不同的是&…

LVS+Keepalived 实现高可用负载均衡

前言 在业务量达到一定量的时候&#xff0c;往往单机的服务是会出现瓶颈的。此时最常见的方式就是通过负载均衡来进行横向扩展。其中我们最常用的软件就是 Nginx。通过其反向代理的能力能够轻松实现负载均衡&#xff0c;当有服务出现异常&#xff0c;也能够自动剔除。但是负载…

基于Redisson实现分布式锁

基于redisson实现分布式锁 之前背过分布式锁几种实现方案的八股文&#xff0c;但是并没有真正自己实操过。现在对AOP有了更深一点的理解&#xff0c;就自己来实现一遍。 1、分布式锁的基础知识 分布式锁是相对于普通的锁的。普通的锁在具体的方法层面去锁&#xff0c;单体应…

搜维尔科技:详谈ART的工具追踪技术

您的生产流程中是否已经受益于刀具跟踪系统&#xff1f;您是否意识到它们的价值&#xff1f;因为它们可以优化您的装配顺序&#xff0c;从而节省您的时间和金钱。 目前我们提供两种工具跟踪解决方案&#xff1a; 1.ART与 VERPOSE的解决方案——易于使用的图像识别 安装在工…

探索智能合约在医疗健康领域的革新应用

随着区块链技术的发展&#xff0c;智能合约作为其重要应用之一&#xff0c;在医疗健康领域展示了巨大的潜力和革新性。智能合约是一种基于区块链的自动化执行协议&#xff0c;它可以在无需中介的情况下执行和验证合同。在医疗健康领域&#xff0c;智能合约不仅简化了数据管理和…

房屋租赁管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;中介管理&#xff0c;房屋信息管理&#xff0c;房屋类型管理&#xff0c;租房订单管理&#xff0c;租房信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信息&a…

ctfshow-web入门-命令执行(web66-web70)

目录 1、web66 2、web67 3、web68 4、web69 5、web70 1、web66 show_source 被禁用 highlight_file 发现 flag 不在 flag.php 里面 先使用 scandir() 进行目录扫描&#xff1a; cprint_r(scandir("./")); 当前目录下只有 index.php 和 flag.php 扫一下根目…

图书商城系统java项目ssm项目jsp项目java课程设计java毕业设计

文章目录 图书商城系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 图书商城系统 一、项目演示 图书商城系统 二、项目介绍 语言: Java 数据库&#xff1a;MySQL 技术栈&#xff1a;SpringS…

「ETL趋势」FDL定时任务区分开发/生产模式、API输入输出支持自定义响应解析

FineDataLink作为一款市场上的顶尖ETL工具&#xff0c;集实时数据同步、ELT/ETL数据处理、数据服务和系统管理于一体的数据集成工具&#xff0c;进行了新的维护迭代。本文把FDL4.1.7最新功能作了介绍&#xff0c;方便大家对比&#xff1a;&#xff08;产品更新详情&#xff1a;…

spark shuffle——shuffle管理

ShuffleManager shuffle系统的入口。ShuffleManager在driver和executor中的sparkEnv中创建。在driver中注册shuffle&#xff0c;在executor中读取和写入数据。 registerShuffle&#xff1a;注册shuffle&#xff0c;返回shuffleHandle unregisterShuffle&#xff1a;移除shuff…

LED显示屏跟COB显示屏有哪些不同?

COB显示屏跟LED显示屏的主要区别在于产品的显示效果、封装技术、耐用性、防护力、维护以及制造成本方面的不同&#xff0c;这里所说的LED显示屏主要指的是使用SMD封装的LED显示屏&#xff0c;今天跟随COB显示屏厂家中品瑞科技一起来详细看看具体分析&#xff1a; 一、封装技术 …

视图库对接系列(GA-T 1400)九、视图库对接系列(本级)机动车数据推送

背景 在上几章中,我们已经可以将视图库的平台写到我们的数据库中了。 换句话说就已经接入我们的平台了,这几期的话,我们就对接设备, 将设备的数据接入到我们平台来。 机动车数据推送 接入机动车数据推送相对比较简单,我们只需要实现对应的接口就ok了。 具体如图: 有增…

77. UE5 RPG 创建角色的技能栏

在前面的文章里&#xff0c;我们实现了角色属性技能和场景。接下来&#xff0c;我们要优化角色显示UI&#xff0c;在屏幕底部显示角色血量&#xff0c;蓝量&#xff0c;技能和经验值。 创建新的用户控件 选择创建新的控件蓝图 父类为我们自定义的RPGUserWidget&#xff0c;这…

这样拼板帮你省近万元,堪称PCB工程师成本终结者!

别再被骗了&#xff0c;打PCB板价格高不是单价高&#xff01;而是你的拼板导致利用率太低了&#xff01; 今天给大家讲个小故事&#xff0c;教大家如何省钱...... 一个爽朗的晴天&#xff0c;我听闻同事说有客户对他吐槽打板子价格太高&#xff0c;说着说着就开始吹起了牛逼...…

【论文阅读】VASA-1: Lifelike Audio-Driven Talking FacesGenerated in Real Time

整体框架。不直接生成视频帧&#xff0c;而是在潜在空间中生成整体面部动态和头部运动&#xff0c;条件是音频和其他信号。给定这些运动潜在编码&#xff0c;通过面部解码器生成视频帧&#xff0c;还接受从输入图像中提取的外观和身份特征作为输入。 构建了一个面部潜在空间并…