基于模拟退火算法(SA)的TSP(Python实现)

        本篇文章是博主在最化优学习、人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在最优化算法:

       最优化算法(2)---《基于模拟退火算法(SA)的TSP(Python实现)》

基于模拟退火算法(SA)的TSP(Python实现)

目录

基于模拟退火算法(SA)的TSP(Python实现)

1.项目介绍      

算法介绍:

算法的核心思想包括以下几个方面:

SA算法求解TSP的基本思路包括:

2.程序代码

3.运行结果


1.项目介绍      

        基于模拟退火算法(Simulated Annealing, SA)的TSP(Traveling Salesman Problem,旅行商问题),我们涉及一种用于解决TSP的启发式优化方法。TSP是一个经典的组合优化问题,旨在寻找一条最短路径,使得旅行商可以访问每个城市恰好一次并返回起点城市。

算法介绍:

        模拟退火算法(SA)是一种经典的全局优化算法,其灵感来自固体材料的退火过程。在物理学中,高温下的固体粒子具有较高的动能,可以跳出局部能量最小值,而随着温度降低,粒子逐渐趋向稳定状态。这种原理启发了模拟退火算法的设计思想,即通过在初始阶段接受较差解的方式,逐渐减小接受较差解的概率,从而逼近全局最优解。

        在TSP问题上,SA算法通过定义合适的状态空间和能量函数,并结合退火策略,能够很好地应用于寻找最优旅行路径。初始解可以通过随机生成初始路径得到,状态空间可以定义为对当前路径进行微小的变化(如交换城市顺序),而能量函数通常是路径长度的计算。退火策略包括控制温度参数和退火速度,以在搜索空间中进行状态的变化,并逐步接近最优解。

        在SA算法求解TSP时,关键的一点是合理设置退火过程中的温度下降速率和终止条件,以确保算法能够在合理的时间内收敛到较优解。

算法的核心思想包括以下几个方面:

  1. 初始解:随机生成初始旅行路径
  2. 状态空间:定义了TSP解空间中可行解之间的相邻关系,如通过交换、翻转等操作生成新的解
  3. 能量函数:通常是TSP问题中路径长度的计算,用于评估每个解的质量
  4. 退火策略:通过控制温度参数和退火速度,在搜索空间中进行状态的变化,从而逐步接近最优解

SA算法求解TSP的基本思路包括:

  • 初始化:随机生成初始路径
  • 退火过程:在退火过程中,根据能量函数和温度参数,接受或拒绝新的解,并降低温度以逐步收敛到全局最优解
  • 终止条件:达到预设的迭代次数或满足特定条件时结束搜索,返回最优路径

        通过利用SA算法求解TSP问题,可以有效地寻找到较为优秀的旅行路线,尽管无法保证找到全局最优解,但通常能够获得接近最优解的结果。


2.程序代码

""""
题目:基于模拟退火算法的TSP
姓名:Rainbook
最终修改时间:2023.12.30
"""
import math                         # 导入模块 math
import random                       # 导入模块 random
import pandas as pd                 # 导入模块 pandas 并简写成 pd
import numpy as np                  # 导入模块 numpy 并简写成 np YouCans
import matplotlib.pyplot as plt     # 导入模块 matplotlib.pyplot 并简写成 pltplt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 处理负号显示异常np.set_printoptions(precision=4)
pd.set_option('display.max_rows', 20)
pd.set_option('expand_frame_repr', False)
pd.options.display.float_format = '{:,.2f}'.format# 子程序:初始化模拟退火算法的控制参数
def initParameter():tInitial = 100.0                # 设定初始退火温度(initial temperature)tFinal = 1                    # 设定终止退火温度(stop temperature)nMarkov = 1000                # Markov链长度,也即内循环运行次数alfa = 0.98                 # 设定降温参数,T(k)=alfa*T(k-1)return tInitial, tFinal, alfa, nMarkov# 子程序:读取TSPLib数据
def read_TSPLib(fileName):res = []with open(fileName, 'r') as fid:for item in fid:if len(item.strip())!=0:res.append(item.split())loadData = np.array(res).astype('int')      # 数据格式:i Xi YiCity = loadData[:,1::]return City# 子程序:计算各城市间的距离,得到距离矩阵
def getDistMat(nCities, City):distMat = np.zeros((nCities,nCities))       # 初始化距离矩阵for i in range(nCities):for j in range(i,nCities):# np.linalg.norm 求向量的范数(默认求 二范数),得到 i、j 间的距离distMat[i][j] = distMat[j][i] = round(np.linalg.norm(City[i]-City[j]))return distMat                              # 城市间距离取整(四舍五入)# 子程序:计算 TSP 路径长度
def calTourMileage(tourGiven, nCities, distMat):mileageTour = distMat[tourGiven[nCities-1], tourGiven[0]]   # dist((n-1),0)for i in range(nCities-1):                                  # dist(0,1),...dist((n-2)(n-1))mileageTour += distMat[tourGiven[i], tourGiven[i+1]]return round(mileageTour)                     # 路径总长度取整(四舍五入)# 绘制 TSP 路径图
def plot_tour(tour, value, City):num = len(tour)x0, y0 = City[tour[num - 1]]x1, y1 = City[tour[0]]plt.scatter(int(x0), int(y0), s=15, c='r')      # 绘制城市坐标点 C(n-1)plt.plot([x1, x0], [y1, y0], c='b')             # 绘制旅行路径 C(n-1)~C(0)for i in range(num - 1):x0, y0 = City[tour[i]]x1, y1 = City[tour[i + 1]]plt.scatter(int(x0), int(y0), s=15, c='r')  # 绘制城市坐标点 C(i)plt.plot([x1, x0], [y1, y0], c='b')         # 绘制旅行路径 C(i)~C(i+1)plt.xlabel("Total mileage of the tour:{:.1f}".format(value))plt.title("Optimization tour of TSP{:d}".format(num))  # 设置图形标题plt.show()# 交换操作算子
def mutateSwap(tourGiven, nCities):# 在 [0,n) 产生 2个不相等的随机整数 i,ji = np.random.randint(nCities)          # 产生第一个 [0,n) 区间内的随机整数while True:j = np.random.randint(nCities)      # 产生一个 [0,n) 区间内的随机整数if i!=j: break                      # 保证 i, j 不相等tourSwap = tourGiven.copy()             # 将给定路径复制给新路径 tourSwaptourSwap[i], tourSwap[j] = tourGiven[j],tourGiven[i] # 交换 城市 i 和 j 的位置————简洁的实现方法return tourSwapdef SA_TSP(coordinates ):# 模拟退火算法参数设置tInitial,tFinal,alfa,nMarkov = initParameter()      # 调用子程序,获得设置参数nCities = coordinates.shape[0]              # 根据输入的城市坐标 获得城市数量 nCitiesdistMat = getDistMat(nCities, coordinates)  # 调用子程序,计算城市间距离矩阵nMarkov = nCities                           # Markov链 的初值设置tNow = tInitial                          # 初始化 当前温度(current temperature)# 初始化准备tourNow  = np.arange(nCities)   # 产生初始路径,返回一个初值为0、步长为1、长度为n 的排列valueNow = calTourMileage(tourNow,nCities,distMat) # 计算当前路径的总长度 valueNowtourBest = tourNow.copy()                          # 初始化最优路径,复制 tourNowvalueBest = valueNow                                # 初始化最优路径的总长度,复制 valueNowrecordBest = []                                     # 初始化 最优路径记录表recordNow = []                                     # 初始化 最优路径记录表# 开始模拟退火优化过程iter = 0                        # 外循环迭代次数计数器while tNow >= tFinal:           # 外循环,直到当前温度达到终止温度时结束# 在当前温度下,进行充分次数(nMarkov)的状态转移以达到热平衡for k in range(nMarkov):    # 内循环,循环次数为Markov链长度# 产生新解:tourNew = mutateSwap(tourNow, nCities)      # 通过 交换操作 产生新路径valueNew = calTourMileage(tourNew,nCities,distMat) # 计算当前路径的总长度deltaE = valueNew - valueNow# 接受判别:按照 Metropolis 准则决定是否接受新解if deltaE < 0:                          # 更优解:如果新解的目标函数好于当前解,则接受新解accept = Trueif valueNew < valueBest:            # 如果新解的目标函数好于最优解,则将新解保存为最优解tourBest[:] = tourNew[:]valueBest = valueNewelse:                                   # 容忍解:如果新解的目标函数比当前解差,则以一定概率接受新解pAccept = math.exp(-deltaE/tNow)    # 计算容忍解的状态迁移概率if pAccept > random.random():accept = Trueelse:accept = False# 保存新解if accept == True:                      # 如果接受新解,则将新解保存为当前解tourNow[:] = tourNew[:]valueNow = valueNew# 平移当前路径,以解决变换操作避开 0,(n-1)所带来的问题,并未实质性改变当前路径。tourNow = np.roll(tourNow,2)                # 循环移位函数,沿指定轴滚动数组元素# 完成当前温度的搜索,保存数据和输出recordBest.append(valueBest)                # 将本次温度下的最优路径长度追加到 最优路径记录表recordNow.append(valueNow)                  # 将当前路径长度追加到 当前路径记录表print('迭代次数i:{}, 当前温度(i):{:.2f}, 当前路径长度:{:.1f}, 最优路径长度:{:.1f}'.format(iter+1, tNow, valueNow, valueBest))# 缓慢降温至新的温度,iter = iter + 1tNow = tNow * alfa                              # 指数降温曲线:T(k)=alfa*T(k-1)return tourBestdef Draw_City(City, X):X = list(X)X.append(X[0])  # 再最后再回到出发的城市coor_x = []coor_y = []for i in X:i = int(i)coor_x.append(City[i][0])  # 按照最优路径顺序将所有城市的x轴坐标写入coor_x中coor_y.append(City[i][1])plt.figure(1)for i in range(len(X) - 1):plt.quiver(coor_x[i], coor_y[i], coor_x[i + 1] - coor_x[i], coor_y[i + 1] - coor_y[i],color='r', width=0.005, angles='xy', scale=1, scale_units='xy')plt.quiver(coor_x[-1], coor_y[-1], coor_x[0] - coor_x[-1], coor_y[0] - coor_y[-1],color='r', width=0.005, angles='xy', scale=1, scale_units='xy')plt.title('基于模拟退火算法的TSP')plt.show()if __name__ == '__main__':# 随机生成城市信息nCity = 50City = np.random.uniform(0, 2000, [nCity, 2])  # uniform()生成nCity个二维数组,数值范围是0到2000# 执行算法Best_X = SA_TSP(City)# 画路径图Draw_City(City, Best_X)

3.运行结果


        参考资料来源:CSDN、百度搜索、维基百科等

        文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者关注VX公众号:Rain21321,联系作者。

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

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

相关文章

希腊证券交易所ATHEX计划在Sui上部署融资功能

希腊证券交易所ATHEX计划将其电子订单簿构建&#xff08;Electronic Book Building &#xff0c;EBB&#xff09;功能部署到Sui上&#xff0c;他们是第一个与区块链公司合作开发此技术的证券交易所。其背后的雅典交易所集团Athens Exchange Group将与Sui的开发公司Mysten Labs合…

一键转发朋友圈!微信快速营销推广必备法宝!

在这个“得私域者得天下”的互联网时代&#xff0c;如何能够在微信上进行快速、高效的营销推广成为了摆在许多人面前的一道难题。 幸运的是&#xff0c;随着微信管理系统的出现&#xff0c;一键转发朋友圈的快速营销推广法宝已经变得触手可及。 首先&#xff0c;微信管理系统…

QT 解决在线安装版本下载速度(以国内镜像启动安装器的方式)

关于Fiddler输入steam的教程&#xff0c;本人试过&#xff0c;无效略过… 正确方式 具体操作方法&#xff1a; 1.方式一、未安装过QT 下载好安装器之后&#xff0c;在安装器&#xff08;qt-unified-windows-x64-4.6.0-online.exe&#xff09;的文件夹中空白处&#xff0c;按…

UVA378 Intersecting Lines 题解

UVA378 Intersecting Lines 题解 怎么这么多点斜式邪教啊。 解法 在计算几何中&#xff0c;我们应该尽可能地避免使用浮点数的计算&#xff0c;尽可能地使用向量计算。 本篇题解默认读者具有向量基础。 为了方便讲解&#xff0c;我们将输入的四个点分别记作 A , B , C , …

20240307-1-前端开发校招面试问题整理JavaScript

前端开发校招面试问题整理【1】——JavaScript 1、JavaScript 基础 Q&#xff1a;介绍 js 的基本数据类型&#xff1f; 基本类型&#xff08;值类型&#xff09;&#xff1a;String&#xff0c;Number&#xff0c;Boolean&#xff0c;Null&#xff0c;Undefined&#xff0c;S…

WinSCP下载安装并结合内网穿透实现固定公网TCP地址访问本地服务器

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

FFmpeg教程(干货快速上手)

什么是FFmpeg&#xff1f; FFmpeg是一款免费、开源的跨平台多媒体处理工具&#xff0c;它支持几乎所有的视频格式和编码标准。FFmpeg包含了一系列的子项目和工具&#xff0c;如ffmpeg命令行工具用于转码和处理视频和音频文件&#xff0c;ffplay用于播放多媒体内容&#xff0c;…

穿越牛熊,股市的春天还有多远?

2023年&#xff0c;资本市场的严冬令无数投资者和机构投资者都感受到了前所未有的压力。VC/PE、公募基金、股权投资类公司等机构&#xff0c;在这一年里业绩普遍不佳&#xff0c;寒意弥漫。VC/PE机构的营业收入普遍呈现负增长&#xff0c;公募基金更是历史上首次连续两年亏损&a…

LeetCode 刷题 [C++] 第3题.无重复字符的最长子串

题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 题目分析 可以使用滑动窗口加哈希表来实现&#xff1a; 使用start和end两个变脸来表示滑动窗口的头部位置和尾部位置&#xff0c;两者开始均为0&#xff1b;借助哈希表来记录已经遍…

Unity 给刚体一个力或速度

创建平面和小球&#xff0c;给力或给速度让其弹起 给小球挂载刚体&#xff08;Rigibdody&#xff09;和脚本 &#xff08;力是累计或者衰减的&#xff0c;直接给速度就是赋值&#xff0c;但如果速度就和力类似了&#xff09; using System.Collections; using System.Collect…

解决 ucore lab3 无法触发 page fault 的问题

问题描述 完成清华大学操作系统实验课 ucore(x86) lab3 时&#xff0c;发现无法触发 page fault 异常&#xff0c;具体来说时 check_pgfault() 函数会在执行如下代码时报错 static void check_pgfault(void) {// ......uintptr_t addr 0x100;assert(find_vma(mm, addr) vma…

three.js 射线Ray,三维空间中绘制线框

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs"></div> <div>{{ res1 }}</div> <div>{{ res2 }}</div><…

serial库串口通讯

前言 Python的pyserial库允许与不同的设备进行通信。 安装 python > 3.4 pip install pyserial 基本流程 import serial# 1. 打开串口 ser serial.Serial()# 2. 设置串口参数&#xff08;例如波特率、数据位、校验位、停止位&#xff09; ser.port /dev/ttyS0 # 这是一…

CDN介绍

概念介绍 CDN Content Delivery Network&#xff0c;缩写&#xff1a;CDN&#xff09;是一种提供更快互联网访问的服务&#xff0c;通过在网络的边缘或核心交换区域部署内容代理服务器来实现。这些服务器利用全局负载调度机制来分发内容&#xff0c;从而构建了一个覆盖范围广…

nRF52832——GPIOTE与外部中断

这里写目录标题 GPIOTE 原理分析GPIOTE 输入事件应用GPIOTE 事件寄存器应用GPIOTE 事件组件的应用&#xff08;库函数&#xff09;GPIOTE PORT 事件应用 GPIOTE 任务应用GPIOTE 任务触发 LED 寄存器操作组件方式进行任务配置 GPIOTE 原理分析 GPIO 任务和时间&#xff08;GPIO…

仿牛客网项目---Elasticsearch分布式搜索引擎

1.什么是ElasticSearch分布式搜索引擎&#xff1f; Elasticsearch是一个开源的分布式搜索引擎&#xff0c;提供实时的、高可用性的搜索和分析解决方案。它支持快速索引和搜索大规模数据&#xff0c;具有分布式架构、RESTful API、基于JSON的查询语言等功能&#xff0c;适用于各…

蓝桥杯集训·每日一题2024 (二分,双指针)

前言&#xff1a; 开学了&#xff0c;平时学习的压力也逐渐大起来了&#xff0c;不过还算可以接受&#xff0c;等到后面阶段考的时候就不一样了&#xff0c;我目前为了转专业退选了很多课&#xff0c;这些课我都需要花时间来刷绩点&#xff0c;不然保研就没有竞争力了。我自己会…

OpenCASCADE+Qt创建建模平台

1、建模平台效果 2、三维控件OCCWidget 将V3d_View视图与控件句柄绑定即可实现3d视图嵌入Qt中&#xff0c;为了方便也可以基于QOpenGLWidget控件进行封装&#xff0c;方便嵌入各种窗体使用并自由缩放。 #ifndef OCCTWIDGET_H #define OCCTWIDGET_H#include <QWidget> #i…

javaWebssh药品进销存信息管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh药品进销存信息管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOM…

Filter过滤器+JWT令牌实现登陆验证

一、背景 我们需要在客户端访问服务器的时候给定用户一定的操作权限&#xff0c;比如没有登陆时就不能进行其他操作。如果他需要进行其他操作&#xff0c;而在这之前他没有登陆过&#xff0c;服务端则需要将该请求拦截下来&#xff0c;这就需要用到过滤器&#xff0c;过滤器可以…