Matlab【旅行商问题】—— 基于模拟退火算法的无人机药品配送路线最优化

news2024/11/18 11:01:51

文章目录

    • 问题描述
    • 模拟退火算法
      • Metropolis准则
      • 算法流程图:
    • Demo1:只考虑累计距离,通过模拟退火算法求解最短路径
      • matlab代码:
      • 最优解之一:
      • 适应度进行曲线:
    • Demo1:考虑每个站点的病人数量,优先给病人数量多的站点配送,同时兼顾累计最短距离
      • matlab代码:
      • 最优解之一:
      • 适应度进行曲线:
      • 最优解搜索过程:

问题描述

某市引进一架专业大型无人机用于紧急状态下的药品投递,每个站点只能投放一次,可选择指派任意站点的无人机起飞出发完成投递任务,但必须在配送完毕后返回原来的站点。站点地理位置坐标(单位为公理)如下图所示。每个站点及容纳的病人数量见附件.mat数据,现要求通过数学建模,在保证速度和优先救治病人数量多的站点前提下,提供药品紧急配送策略,具体问题如下:

请制订无人机的飞行路线,使尽可能多的病人尽早得到救治。
在这里插入图片描述

模拟退火算法

模拟退火算法是一种基于随机搜索的优化算法,其灵感来源于铸炼工具时,先将固体加热至高温后缓慢冷却,就能使固体获得更好的韧性(可弯折),其原理是退火降温过程中固体内部的晶粒能够以较低的能量重新排列,模拟退火算法就是模拟加热后的退火过程。它的目标是在解空间中寻找全局最优解或接近最优解的解(不一定能找到全局最优,可能是比较接近全局最优的局部最优)。

在模拟退火算法中,首先随机生成一个初始解,然后通过一系列的状态转移来搜索更优的解。状态转移的过程(即马尔可夫链)中,算法会引入一个控制参数(温度),使得算法在搜索过程中能够以一定的概率接受劣解,从而避免陷入局部最优解。随着搜索的进行,温度会逐渐降低,接受劣解的概率也会逐渐减小,最终收敛到全局最优解或接近最优解。

Metropolis准则

模拟退火的主要思想是:在搜索区间随机游走(即随机选择点),再利用Metropolis抽样准则,使随机游走逐渐收敛于局部最优解。而温度是Metropolis算法中的一个重要控制参数,可以认为这个参数的大小控制了随机过程向局部或全局最优解移动的快慢。

Metropolis准则是用于决定在Metropolis算法中是否接受状态转移的准则。根据Metropolis准则,状态转移被接受的概率为1或 e x p ( − Δ E / T ) ) exp(-ΔE/T)) exp(ΔE/T)),其中ΔE表示当前状态与下一个状态的能量差,T表示当前的温度。

具体来说,
如果ΔE小于0,即下一个状态的能量比当前状态更低,那么状态转移被接受(被接受的概率为1);
如果ΔE大于0,即下一个状态的能量比当前状态更高,那么状态转移被接受的概率为 e x p ( − Δ E / T ) exp(-ΔE/T) exp(ΔE/T)即有一定概率放弃状态转移).

当温度较高时,接受劣解的概率较高,有助于跳出局部最优解;当温度较低时,接受劣解的概率较低,有助于收敛到全局最优解。

Metropolis准则的核心思想是通过接受概率来探索状态空间,从而达到对系统的采样和模拟。这种准则在Metropolis算法中起到了重要的作用,使得算法能够在搜索过程中兼顾探索和利用,从而更好地找到系统的平衡分布。

算法流程图:

在这里插入图片描述

Demo1:只考虑累计距离,通过模拟退火算法求解最短路径

先通过Demo1,感受一下模拟退火算法处理旅行商问题的优化过程。

matlab代码:

clc,clear,close all;
%% ------------------------------------------------------------------------
%加载数据
load data_all.mat
data = zeros(25,2);
data(:,1) = data_all(:,2);
data(:,2) = data_all(:,3);
%% ------------------------------------------------------------------------
%模拟退火参数设置
n = size(data,1);  %站点数量
T = 100*n;         %初始温度
L = 100;           %马尔可夫链长度
K = 0.99;          %衰减参数
%% ------------------------------------------------------------------------
%站点坐标结构体
cp = struct([]);
for i = 1:n
    cp(i).x = data(i,1);
    cp(i).y = data(i,2);
end
le = 1;            %迭代次数
len(le) = funcp(cp,n);
figure(1);
while T > 0.001    %停止迭代温度
    %多次迭代扰动,温度降低前多次实验
    for i = 1:L
        %计算原路线距离
        len1 = funcp(cp,n);
        %产生随机扰动
        %随机置换两个不同站点的坐标
        p1 = floor(1+n*rand());
        p2 = floor(1+n*rand());
        while p1 == p2
            p1 = floor(1+n*rand());
            p2 = floor(1+n*rand());
        end
        tmp_cp = cp;
        tmp = tmp_cp(p1);
        tmp_cp(p1) = tmp_cp(p2);
        tmp_cp(p2) = tmp;
        %% ----------------------------------------------------------------
        %计算新路线总距离
        len2 = funcp(tmp_cp,n);
        %% ----------------------------------------------------------------
        %新老距离的差值,相当于能量
        delta_e = len2-len1;
        %% ----------------------------------------------------------------
        %若新路线好于旧路线,用新路线代替旧路线
        if delta_e < 0
            cp = tmp_cp;
        else
            %依概率选择是否接收新解
            if exp(-delta_e/T) > rand()
                cp = tmp_cp;
            end
        end
    end
    le = le+1;
    %% --------------------------------------------------------------------
    %计算新路线距离
    len(le) = funcp(cp,n);
    %温度不断下降
    T =T*K;
    for i = 1:n-1
        plot([cp(i).x, cp(i+1).x], [cp(i).y, cp(i+1).y], "o-","LineWidth", 1.2);
        hold on;
        grid on;
    end
    plot([cp(n).x, cp(1).x], [cp(n).y, cp(1).y],'ro--',"LineWidth", 1.5);
    title(['优化最短距离:', num2str(len(le))]);
    disp(['优化最短距离:', num2str(len(le))])
    hold off;
    pause(0.001);
end
figure(2);
plot(len, 'LineWidth', 1.1)
grid on;
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进行曲线')
disp('优化结束')
%% ------------------------------------------------------------------------
%计算路线总长度函数
function len = funcp(cp,n)
len = 0;
for i = 1:n-1
    len = len+sqrt((cp(i).x-cp(i+1).x)^2+(cp(i).y-cp(i+1).y)^2);  %累计欧氏距离
end
len = len+sqrt((cp(n).x-cp(1).x)^2+(cp(n).y-cp(1).y)^2);
end

最优解之一:

由于模拟退火算法的优化过程具有随机性,所以得到的解不一定就是全局最优,但肯定比瞎猜一个局部最优要好。可以重复运行几次程序,观察最优解的变化,正常应该差距不大。
在这里插入图片描述
只考虑距离的情况不用考虑路线顺序,因为正反走都是一样的距离。

适应度进行曲线:

在这里插入图片描述
可见适应度随着退火过程逐渐趋于稳定的最优解,算法具有收敛性。

Demo1:考虑每个站点的病人数量,优先给病人数量多的站点配送,同时兼顾累计最短距离

新建目标值变量tar,tar包含了累计距离变量len的大小,且加入了病人数量这个变量var,并乘以权重10,用1000-var是为了反向考虑优化过程中需要使得目标值tar越来越小:

tar = tar+sqrt((cp(i).x-cp(i+1).x)^2+(cp(i).y-cp(i+1).y)^2)+10*(1000-var(i)); 

matlab代码:

clc,clear,close all;
%% ------------------------------------------------------------------------
%加载数据
load data_all.mat
data = zeros(25,2);
data(:,1) = data_all(:,2);
data(:,2) = data_all(:,3);
var = data_all(:,4);
%% ------------------------------------------------------------------------
%模拟退火参数设置
n = size(data,1);  %站点数量
T = 100*n;         %初始温度
L = 100;           %马尔可夫链长度
K = 0.99;          %衰减参数
%% ------------------------------------------------------------------------
%站点坐标结构体
cp = struct([]);
for i = 1:n
    cp(i).x = data(i,1);
    cp(i).y = data(i,2);
end
le = 1;            %迭代次数
[tar(le), len(le)] = funcp(cp,n);
figure(1);
while T > 0.001    %停止迭代温度
    %多次迭代扰动,温度降低前多次实验
    for i = 1:L
        %计算原路线距离
        [tar1, ~] = funcp(cp,n);
        %产生随机扰动
        %随机置换两个不同站点的坐标
        p1 = floor(1+n*rand());
        p2 = floor(1+n*rand());
        while p1 == p2
            p1 = floor(1+n*rand());
            p2 = floor(1+n*rand());
        end
        tmp_cp = cp;
        tmp = tmp_cp(p1);
        tmp_cp(p1) = tmp_cp(p2);
        tmp_cp(p2) = tmp;
        %% ----------------------------------------------------------------
        %计算新路线总距离
        [tar2, ~] = funcp(tmp_cp,n);
        %% ----------------------------------------------------------------
        %新老距离的差值,相当于能量
        delta_e = tar2-tar1;
        %% ----------------------------------------------------------------
        %若新路线好于旧路线,用新路线代替旧路线
        if delta_e < 0
            cp = tmp_cp;
        else
            %依概率选择是否接收新解
            if exp(-delta_e/T) > rand()
                cp = tmp_cp;
            end
        end
    end
    le = le+1;
    %% --------------------------------------------------------------------
    %计算新路线距离
    [tar(le), len(le)] = funcp(cp,n);
    %温度不断下降
    T =T*K;
    for i = 1:n-1
        plot([cp(i).x, cp(i+1).x], [cp(i).y, cp(i+1).y], "o-","LineWidth", 1.2);
        hold on;
        grid on;
    end
    plot([cp(n).x, cp(1).x], [cp(n).y, cp(1).y],'r-.',"LineWidth", 1.5);
    for k = 1:n
        text(data(k,1)+0.5,data(k,2)+0.75,num2str(var(k)),'fontsize',10);
    end
    title(['优化最短距离:', num2str(len(le))]);
    disp(['优化最短距离:', num2str(len(le))])
    disp(['起点坐标:', num2str([cp(1).x, cp(1).y])])
    disp(['最后一个站点坐标:', num2str([cp(n).x, cp(n).y])])
    hold off;
    pause(0.001);
end
figure(2);
plot(tar, 'LineWidth', 1.1)
grid on;
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进行曲线')
disp('优化结束')
%% ------------------------------------------------------------------------
%计算目标函数和路线总长度函数
function [tar, len] = funcp(cp,n)
tar = 0;
len = 0;
for i = 1:n-1
    tar = tar+sqrt((cp(i).x-cp(i+1).x)^2+(cp(i).y-cp(i+1).y)^2)+10*(1000-var(i)); 
    len = len+sqrt((cp(i).x-cp(i+1).x)^2+(cp(i).y-cp(i+1).y)^2);
end
tar = tar+sqrt((cp(n).x-cp(1).x)^2+(cp(n).y-cp(1).y)^2)+10*(1000-var(1));
len = len+sqrt((cp(n).x-cp(1).x)^2+(cp(n).y-cp(1).y)^2);
end

最优解之一:

在这里插入图片描述
查看路线的起点和终点(最后一个配送站点):

>> disp(['起点坐标:', num2str([cp(1).x, cp(1).y])])
起点坐标:18  28
>> disp(['最后一个站点坐标:', num2str([cp(n).x, cp(n).y])])
最后一个站点坐标:21  30

适应度进行曲线:

在这里插入图片描述

最优解搜索过程:

在这里插入图片描述

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

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

相关文章

Visual modflow Flex地下水数值模拟及参数优化、抽水实验设计与处理、复杂的饱和/非饱和地下水流分析

专题一 地下水数值软件的操作流程、建模步骤和所需资料处理及相关注意事项 [1] Visual MODFLOW Flex特征 [2] Visual MODFLOW Flex软件界面及模块 [3] 地下水数值模拟的建模步骤及数据需求 专题二 模型建模操作方法 技巧、真实案例演练、特殊问题处理 [1] 直接模型建模的操…

深入浅出设计模式 - 装饰者模式

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

Python桌面应用开发之PyQt

文章目录 引言&#xff1a;桌面应用开发三大框架介绍一、PyQT介绍二、安装三、使用教程(1)基础窗口(2)分区布局窗口(类似于html中div的使用)(3)栅格布局窗口(类似于html中的table)(4)表单布局窗口(类似于html中的form)(5)事件函数与事件过滤器(6)信号和槽四、实战示例(1)状态栏…

跨链协议悄然升级

当前加密产业公链百家争鸣&#xff0c;群雄割据&#xff0c;每条公链都拥有自身的忠实用户。 然而&#xff0c;公链与公链之间仿佛一座座孤岛&#xff0c;无法进行无缝的交流和联系&#xff0c;仅能通过跨链桥经由在两条不同的链上运用不同处理机制来协助转移用户的资产。但&a…

【深度学习 | CNN】“深入解析卷积神经网络与反卷积:从原理到应用的全面指南” (从一维、二维、三维讲解)

🤵‍♂️ 个人主页: @AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍 🙋‍♂️声明:本人目前大学就读于大二,研究兴趣方向人工智能&硬件(虽然硬件还没开始玩…

MySQL数据库的MHA高可用集群部署及故障切换(图文详解!绝对详细!!)

目录 一、MHA概述 1、MHA简介 2、MHA 的组成 &#xff08;1&#xff09;MHA Node&#xff08;数据节点&#xff09; &#xff08;2&#xff09;MHA Manager&#xff08;管理节点&#xff09; 3、MHA 的特点 二、 搭建MySQLMHA 1、实验思路 2、修改mysql节点的主机名 3&…

JS 事件委托

JavaScript事件委托&#xff08;Event delegation&#xff09;又叫事件代理&#xff0c;是一种在父元素上监听事件&#xff0c;然后通过事件冒泡机制来处理子元素的事件的技术。通过事件委托&#xff0c;可以避免为每个子元素都绑定事件处理程序&#xff0c;提高性能并简化代码…

SC7504运算放大器(OPA)可pin对pin兼容OPA4350

SC750x 系列轨至轨 CMOS 运算放大器针对低电压单电源运行进行了优化。轨至轨输入和输出、低噪声(5nV/√Hz) 和高速运行(38MHz, 22V/μs) 使得运算放大器非常适合驱动模数 (A/D) 转换器。可pin对pin兼容OPA4350。而且也适用于手机功率放大器 (PA) 控制环路和视频处理&#xff08…

【嵌入式Qt开发入门】初识Qt——Linux下安装Qt

Qt 是什么&#xff1f; Qt 是一个跨平台的 C开发库。主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;简 称 GUI&#xff09;程序。 Qt 虽然经常被当做一个 GUI 库&#xff0c;用来开发图形界面应用程序&#xff0c;但这并不是 Qt 的全部&#xff1b…

Win11总是出现BitLocker恢复,想要彻底关闭它该如何操作?

win11解除bitlocker加密方法一&#xff1a; 1、首先按下键盘“WinR”打开运行(如图所示)。 2、打开运行后&#xff0c;在其中输入“control”并点击“确定”打开控制面板(如图所示)。 3、打开后&#xff0c;进入“bitlocker驱动器加密”(如图所示)。 4、随后展开被加密的磁盘&…

Pycharm报错Non-zero exit code (2)

问题现象&#xff1a; 通常我们拿到一个Python项目后&#xff0c;项目中有requirement.txt文件&#xff0c;里面有列出需要安装的三方库&#xff0c;使用pycharm直接安装这些库时&#xff0c;报错&#xff1a;Non-zero exit code (2) 解决方案&#xff1a; 第一种临时解决方案&…

模糊图片秒转高清图,分享几个免费方法!

相信大家都曾经遇到过拍摄的老旧照片放大后变得模糊不清的情况。然而&#xff0c;由于这些照片是我们自己拍摄的&#xff0c;我们也无法在网上找到并下载原始高清图像。那么&#xff0c;有没有什么方法可以修复这种模糊不清的照片呢&#xff1f;当然&#xff0c;很多人可能会说…

计算机硬件

硬盘 固态硬盘&#xff08;SSD&#xff09;拥有比机械硬盘&#xff08;HDD&#xff09;更快的读写速度。目前大多数机器使用的是SATA总线标准&#xff0c;实际最高传输约为600MB/s。而支持PCIe总线&#xff0c;NVMe协议的SSD&#xff0c;实际传输速度将超过1000MB/s。 当前采…

KDG5V-8-33C330N200-EX-H-M-U-H1-20比例方向阀控制器

与外置电子放大器一起使用&#xff0c;在智能控制系统和液压系统之间提供接口。这是一种非常实用的方法&#xff0c;用于控制执行器的方向和速度&#xff0c;同时消除了机器负载的快速加速和减速所引起的冲击。除了提高机器的性能和寿命外&#xff0c;通过将方向和流量控制能力…

【UE5 Cesium】04-Cesium for Unreal 将不同地区的倾斜摄影作为不同子关卡

上一篇&#xff1a;【UE5 Cesium】03-Cesium for Unreal 添加本地数据集 步骤 1. 新建一个空白关卡 保存新建的关卡&#xff0c;命名为“Globe” 添加地图 再添加“Cesium SunSky”和“DynamicPawn” 在大纲中选中“Globe&#xff08;编辑器&#xff09;”&#xff0c;然后勾…

深入浅出设计模式 - 享元模式

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

初始Git

文章目录 前言技术目标协作目标 一、提出问题二、如何解决版本控制器注意事项 三、Git安装Linux-centosLinux-ubuntu 四、Git基本操作创建Git本地仓库配置Git 总结 前言 技术目标 掌握Git企业级应用,深刻理解Git操作过程与操作原理,理解工作区,暂存区,版本库的含义.掌握Git版…

LC-1595. 连通两组点的最小成本(状态压缩DP(记忆化搜索==>动态规划))

1595. 连通两组点的最小成本 难度困难86 给你两组点&#xff0c;其中第一组中有 size1 个点&#xff0c;第二组中有 size2 个点&#xff0c;且 size1 > size2 。 任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出&#xff0c;其中 cost[i][j] 是第一组中的点 …

FineReport学习3

冻结行列&#xff08;冻结表头&#xff09; 创建多数据源之间的关联 给单元格添加过滤条件&#xff0c;让 ds2 的「客户ID」等于 ds1 的「客户ID」&#xff0c;这样两数据集就关联起来 复杂多源报表

.NETCore项目在Windows下构建Docker镜像并本地导出分发到CentOS系统下

在Windows下使用Docker&#xff0c;我们选择Docker Desktop这个软件&#xff0c;非常方便。 Docker Desktop介绍及安装 Docker Desktop是适用于Mac、Linux或Windows环境的一键安装应用程序&#xff0c;使您能够构建和共享容器化应用程序和微服务。 它提供了一个简单的GUI&…