基于禁忌搜索算法(TS)的TSP(Python实现)
本篇文章是博主在最化优学习、人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在最优化算法:
最优化算法(1)---《基于禁忌搜索算法(TS)的TSP(Python实现)》
基于禁忌搜索算法(TS)的TSP(Python实现)
目录
基于禁忌搜索算法(TS)的TSP(Python实现)
1.项目介绍
2.程序代码
3.运行结果
1.项目介绍
基于禁忌搜索算法(TS)的TSP(Traveling Salesman Problem,旅行商问题),涉及一种用于解决TSP的优化方法。TSP是一个经典的组合优化问题,目标是寻找一条最短路径,使得旅行商可以访问每个城市恰好一次并返回起点城市。
TS算法作为一种启发式优化算法,在TSP求解中具有广泛的应用。相较于传统的穷举或贪婪算法,TS算法通过引入禁忌列表和邻域结构来更全面地探索解空间,从而更有可能找到较为优秀的近似最优解。
禁忌搜索算法从一个初始解开始,在每次迭代中根据邻域结构生成新的解,并根据目标函数对其质量进行评估。若新解优于当前最优解且未出现在禁忌列表中,则接受该解作为当前最优解;否则,寻找下一个最佳候选解。同时,禁忌列表会记录一段时间内禁止选择的解,以避免陷入循环或重复访问相似解的情况。
在TSP问题上,邻域结构通常包括交换两个城市的位置、翻转子路径等操作,而目标函数则是路径长度。禁忌搜索通过不断迭代搜索和更新禁忌列表,逐步改进当前路径,直至满足结束条件为止。
在基于TS算法求解TSP问题时,禁忌搜索的核心思想包括以下几个方面:
- 禁忌列表:记录已经探索过的路径或解,以避免下一步重复探索相同的路径或解。
- 邻域结构:定义了TSP解空间中可行解之间的相邻关系,如通过交换、插入等操作生成新的解。
- 目标函数:通常是TSP问题中路径长度的计算,用于评估每个解的质量。
TS算法求解TSP的基本步骤包括:
- 初始化:随机生成初始路径
- 迭代搜索:根据邻域结构和目标函数,通过禁忌搜索不断调整路径,并更新禁忌列表,记录当前最优路径
- 终止条件:达到预设的迭代次数或满足特定条件时结束搜索,返回最优路径
通过利用TS算法求解TSP问题,可以有效地寻找到较为优秀的旅行路线,虽不能保证找到全局最优解,但通常能获得接近最优解的结果。
2.程序代码
""""
题目:基于禁忌搜索算法的TSP
作者:Rainbook
最终修改时间:2023.12.30
"""
import math
import random
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
import numpy as npplt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False # 处理负号显示异常# 计算路径距离,即评价函数
def calFitness(line, dis_matrix):dis_sum = 0dis = 0for i in range(len(line)):if i < len(line) - 1:dis = dis_matrix.loc[line[i], line[i + 1]] # 计算距离dis_sum = dis_sum + diselse:dis = dis_matrix.loc[line[i], line[0]]dis_sum = dis_sum + disreturn round(dis_sum, 1)def traversal_search(line, dis_matrix, tabu_list):# 邻域随机遍历搜索traversal = 0 # 搜索次数traversal_list = [] # 存储局部搜索生成的解,也充当局部禁忌表traversal_value = [] # 存储局部解对应路径距离while traversal <= traversalMax:pos1, pos2 = random.randint(0, len(line) - 1), random.randint(0, len(line) - 1) # 交换点# 复制当前路径,并交换生成新路径new_line = line.copy()new_line[pos1], new_line[pos2] = new_line[pos2], new_line[pos1]new_value = calFitness(new_line, dis_matrix) # 当前路径距离# 新生成路径不在全局禁忌表和局部禁忌表中,为有效搜索,否则继续搜索if (new_line not in traversal_list) & (new_line not in tabu_list):traversal_list.append(new_line)traversal_value.append(new_value)traversal += 1return min(traversal_value), traversal_list[traversal_value.index(min(traversal_value))]def greedy(CityCoordinates, dis_matrix):'''贪婪策略构造初始解'''# 出来dis_matrixdis_matrix = dis_matrix.astype('float64')for i in range(len(CityCoordinates)): dis_matrix.loc[i, i] = math.pow(10, 10)line = [] # 初始化now_city = random.randint(0, len(CityCoordinates) - 1) # 随机生成出发城市line.append(now_city) # 添加当前城市到路径dis_matrix.loc[:, now_city] = math.pow(10, 10) # 更新距离矩阵,已经过城市不再被取出for i in range(len(CityCoordinates) - 1):next_city = dis_matrix.loc[now_city, :].idxmin() # 距离最近的城市line.append(next_city) # 添加进路径dis_matrix.loc[:, next_city] = math.pow(10, 10) # 更新距离矩阵now_city = next_city # 更新当前城市return line# 画路径图
def draw_path(line, CityCoordinates):x, y = [], []for i in line:Coordinate = CityCoordinates[i]x.append(Coordinate[0])y.append(Coordinate[1])for j in range(len(line) - 1):plt.quiver(x[j], y[j], x[j + 1] - x[j], y[j + 1] - y[j], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.quiver(x[-1], y[-1], x[0] - x[-1], y[0] - y[-1], color='r', width=0.005, angles='xy', scale=1,scale_units='xy')plt.title('基于禁忌搜索算法的TSP')# plt.figure()# plt.plot(x, y,color='r', alpha=0.8, linewidth=0.8)# plt.xlabel('x')# plt.ylabel('y')plt.show()if __name__ == '__main__':# 随机生成城市信息nCity = 50CityCoordinates = np.random.uniform(0, 2000, [nCity, 2]) # uniform()生成nCity个二维数组,数值范围是0到2000# 参数设置CityNum = nCity # 城市数量MinCoordinate = 0 # 二维坐标最小值MaxCoordinate = 101 # 二维坐标最大值tabu_limit = 50 # 禁忌长度,该值应小于(CityNum*(CityNum-1)/2)iterMax = 200 # 迭代次数traversalMax = 100 # 每一代局部搜索次数tabu_list = [] # 禁忌表tabu_time = [] # 禁忌次数best_value = math.pow(10, 10) # 较大的初始值,存储最优解best_line = [] # 存储最优路径# 计算城市之间的距离dis_matrix = pd.DataFrame(data=None, columns=range(len(CityCoordinates)), index=range(len(CityCoordinates)))for i in range(len(CityCoordinates)):xi, yi = CityCoordinates[i][0], CityCoordinates[i][1]for j in range(len(CityCoordinates)):xj, yj = CityCoordinates[j][0], CityCoordinates[j][1]dis_matrix.iloc[i, j] = round(math.sqrt((xi - xj) ** 2 + (yi - yj) ** 2), 2)# 贪婪构造line = greedy(CityCoordinates, dis_matrix)value = calFitness(line, dis_matrix) # 初始路径距离# 存储当前最优best_value, best_line = value, linebest_value_list = []best_value_list.append(best_value)# 更新禁忌表tabu_list.append(line)tabu_time.append(tabu_limit)itera = 0while itera <= iterMax:new_value, new_line = traversal_search(line, dis_matrix, tabu_list)if new_value < best_value: # 优于最优解best_value, best_line = new_value, new_line # 更新最优解best_value_list.append(best_value)print('第%d次:当前优解为' % (itera+1))print(best_line)line, value = new_line, new_value # 更新当前解# 更新禁忌表tabu_time = [x - 1 for x in tabu_time]if 0 in tabu_time:tabu_list.remove(tabu_list[tabu_time.index(0)])tabu_time.remove(0)tabu_list.append(line)tabu_time.append(tabu_limit)itera += 1# 路径顺序print("-------最优解为:")print(best_line)# 画路径图draw_path(best_line, CityCoordinates)
3.运行结果
参考资料来源:CSDN、百度搜索、维基百科等
文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者关注VX公众号:Rain21321,联系作者。
相关文章:

基于禁忌搜索算法(TS)的TSP(Python实现)
本篇文章是博主在最化优学习、人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在最优化算…...
Linux shell 网络掩码地址转CIDR
例子: ./1.sh 255.255.255.0 ./1.sh 255.255.255.128 ./1.sh 255.255.0.0 源实现: #!/bin/bashnetmask_to_cidr() {local IFSlocal -a octetslocal i0local cidr0IFS. read -r -a octets <<< "$1"for octet in "${octets[]}…...

C#,煎饼排序问题(Pancake Sorting Problem)算法与源代码
1 煎饼排序问题 给定一个未排序的数组,任务是对给定数组进行排序。您只能在阵列上执行以下操作。 翻转(arr,i):将数组从0反转为i 示例: 输入:arr[]{23、10、20、11、12、6、7} 输出:…...

13.西瓜书——半监督学习
1.概述 (1) 纯半监督学习 (Pure Semi-Supervised Learning) 纯半监督学习是一种典型的半监督学习方法,它的主要特点是同时利用有标签数据和无标签数据进行模型训练。目标是通过整合这两种类型的数据来提高模型的泛化性能。在这个过程中&#…...

C++进阶之路---继承(二)
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、继承与友元 友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。 class Student; class Per…...

C及C++每日练习(3)
选择题: 1.以下程序的输出结果是() #include <stdio.h> main() { char a[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, *p; int i; i 8; p a i; printf("%s\n", p - 3); } A.6 B. 6789 C. 6 D.789 对于本题࿰…...

黑马点评-附近商户实现
GEO数据结构 Redis在3.2版本中加入了对GEO的支持,允许存储地理坐标信息,根据经纬度来检索数据。 GEO本质上是基于sortedSet实现的,在Sorted Set中,每个成员都是与一个分数(score)相关联的,这个分数用于对成员进行排序…...

安装nginx:手动安装和yum安装
本文在centos7.9下分别尝试了yum安装和手动安装,记录一下试验过程。为后来者少踩点坑。 下载 下载地址:链接 。建议下载稳定版本,也就是Stable Version,这里下载的是 nginx-1.24.0 # 我下载在如下文件夹 mkdir/opt/apps cd /op…...

【C++ STL详解】——string类
目录 前言 一、string类对象的常见构造 二、string类对象的访问及遍历 1.下标【】(底层operator【】函数) 编辑 2.迭代器 3.范围for 4.at 5.back和front 三、string类对象的容量操作 1.size 和 length 2.capacity 3.empty 4.clear 5.res…...

MatplotlibPython 1 3.7
放大数据,如果想仔细看某一行的数据的时候 可以调不同的颜色,图片的长宽高,以及线的种类 plt.figure 这个命令下的所有东西都在这个figure里面 plt.xlim 改变坐标轴的范围 plt.xlabel 改变坐标轴的总名称 plt.xticks 换单位 plt.yt…...
深入理解 Dubbo:构建分布式服务治理体系
目录 1. 介绍 2. Dubbo 的核心概念 2.1 服务提供者(Provider)与服务消费者(Consumer) 2.2 注册中心(Registry) 2.3 监控中心(Monitor) 3. Dubbo 的功能特性 3.1 远程调用&…...
唤起原生IOS和安卓Android app的方法
大家好我是咕噜美乐蒂,很高兴又和大家见面了! 要唤起原生 iOS 或 Android 应用程序,你可以使用以下方法: 唤起原生 iOS 应用程序 在 iOS 上,你可以使用自定义 URL 方案或 Universal Links 来唤起原生应用程序。以下…...

RabbitMQ的web控制端介绍
2.1 web管理界面介绍 connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况channels:通道,建立连接后,会形成通道,消息的投递、获取…...

GitHub登不上:修改hosts文件来解决(GitHub520,window)
参考链接:GitHub520: 本项目无需安装任何程序,通过修改本地 hosts 文件,试图解决: GitHub 访问速度慢的问题 GitHub 项目中的图片显示不出的问题 花 5 分钟时间,让你"爱"上 GitHub。 (gitee.com) GitHub网站…...

01-DevOps代码上线-git入门及gitlab远程仓库
一、准备学习环境 10.0.0.71-gitlab 2c2g-20GB 10.0.0.72-jenkins 2c2g-20GB 10.0.0.73-sonarqube 1c1g-20GB 10.0.0.74-nexus 1c1g-20GB 10.0.0.75-dm 1c1g-20GB (模拟写代码服务器) 在centos系统中&…...

EdgeX Foundry 安全模式安装部署
文章目录 一、安装准备1.官方文档2. 克隆服务器3.安装 Docker4.安装 docker-compose 二、安装部署1.docker-comepse2.启动 EdgeX Foundry3.访问 UI3.1. consul3.2. EdgeX Console EdgeX Foundry # EdgeX Foundryhttps://iothub.org.cn/docs/edgex/ https://iothub.org.cn/docs…...

网络安全-appcms-master
一、环境 gethub上面自己找appcms-master 二、分析一下源码以及闯关思路 首先是有一个函数循环以及函数过滤,我们的post会将我们所传的所有val值去进行一个循环,之后通过htmlspecialchars这个函数进行过滤和转换所以val值不能通过单双引号闭合注入的方…...
ThreadLocal 与 synchronized 区别
我的理解 目的都是为了一个大前提:操作内容的线程安全。 任务不同:synchronized 解决的是多线程下线程操作权限的问题,以及原子性的保证。通过对锁的竞争,达到对资源的访问有序。 ThreadLocal是解决的事多线程下资源的隔离问题,即…...

灵魂指针,教给(二)
欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看,已成习惯 创作不易,多多支持! 目录 一、数组名的理解 二、使用指针访问数组 三、一维数组传参本质 四、冒泡排序 五、二级指针 六、指针数组 七、指针数组…...
线程安全--浅谈Ad-hoc与加锁的区别
浅谈Ad-hoc 与加锁 两者要解决的都是对对象的语义混乱操作,即有个count进行累加操作。 我的理解/文心一言的反馈如下: 加锁是保证我们对同一个count在多线程下的访问有序,即“读写-修改-写入”具有原子性。 而Ad-hoc机制就是通过程序员自己定义一个私有…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

负载均衡器》》LVS、Nginx、HAproxy 区别
虚拟主机 先4,后7...

渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...