模拟退火算法求解TSP问题(python)

简介: 模拟退火算法求解TSP问题(python)

👉TSP旅行商问题

旅行商问题大家都应该非常熟悉了,解法也很多,比如贪婪算法、Dijkstra算法等等,本文参考《MATLAB智能算法30个案例分析(第2版)》中第19章的内容,利用模拟退火算法求解TSP问题并给出了python实现版本

TSP问题描述如下:

👉TSP模拟退火算法

关于模拟退火算法的原理,书籍和文章均比较多,这里就不再赘述,大家可以参考其他博文,或阅读《MATLAB智能算法30个案例分析(第2版)》这本书。

👉程序及运行结果(笔者python环境为3.7)

import copy
import math
import random
import matplotlib.pyplot as plt
# 初始温度
T0 = 1000
# 终止温度
Tend = 1e-3
# 个温度下的迭代次数(链长)
L = 200
# 降温速率
q = 0.9
# 各个城市的坐标
X = [(16.4700, 96.1000),
     (16.4700, 94.4400),
     (20.0900, 92.5400),
     (22.3900, 93.3700),
     (25.2300, 97.2400),
     (22.0000, 96.0500),
     (20.4700, 97.0200),
     (17.2000, 96.2900),
     (16.3000, 97.3800),
     (14.0500, 98.1200),
     (16.5300, 97.3800),
     (21.5200, 95.5900),
     (19.4100, 97.1300),
     (20.0900, 92.5500)]
# 构建距离矩阵
def build_distance():
    # 初始化城市距离矩阵
    distance = [[0 for _ in range(len(X))] for _ in range(len(X))]
    # 计算各个城市之间的距离
    for i in range(len(X)):
        pos1 = X[i]
        for j in range(i+1, len(X)):
            pos2 = X[j]
            distance[i][j] = pow((pow(pos1[0] - pos2[0], 2) + pow(pos1[1] - pos2[1], 2)), 0.5)
            distance[j][i] = distance[i][j]
    return distance
# 产生新的路径解
def gen_new_path(path):
    new_path = copy.copy(path)
    # 随机产生两个索引
    idx1 = random.randint(0, len(path) - 1)
    idx2 = random.randint(0, len(path) - 1)
    # 交换路径中的两个城市
    temp = new_path[idx1]
    new_path[idx1] = new_path[idx2]
    new_path[idx2] = temp
    return new_path
# 计算路径总距离
def path_distance(path, distance):
    total_distance = 0.0
    # 循环路径上所有城市进行计算,到最后一个城市返回出发城市
    for i in range(len(path)):
        if i == len(path) - 1:
            total_distance += distance[path[i]][path[0]]
        else:
            total_distance += distance[path[i]][path[i + 1]]
    return total_distance
# Metropolis准则函数
def metropolis(old_path, new_path, distance, t):
    # 路径的能量即路径上各城市距离之和
    # 新路径的能量函数和旧路径的能量函数之差
    delta = path_distance(new_path, distance) - path_distance(old_path, distance)
    # 若新路径能量低于旧路径,则接受新路径解
    if delta < 0:
        return copy.copy(new_path), path_distance(new_path, distance)
    # 若新路径能量高于旧路径,则按exp(-delta/t)概率接受新路径解
    if math.exp(-delta/t) >= random.uniform(0, 1):
        return copy.copy(new_path), path_distance(new_path, distance)
    # 不接受新路径解
    return copy.copy(old_path), path_distance(old_path, distance)
# 绘制结果
def draw_result(best, file_name="tsp_sa"):
    # 各个城市的横纵坐标
    x = [pos[0] for pos in X]
    y = [pos[1] for pos in X]
    # 绘图中文设置
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文标签
    plt.rcParams['axes.unicode_minus'] = False
    # 清空画布
    plt.clf()
    # 绘制箭头
    for i in range(len(X)):
        # 箭头开始坐标
        start = X[best[i]]
        # 箭头结束坐标
        end = X[best[i + 1]] if i < len(best) - 1 else X[best[0]]
        plt.arrow(start[0], start[1], end[0] - start[0], end[1] - start[1], head_width=0.2, lw=1, length_includes_head=True)
    # 绘制城市编号
    for i in range(len(X)):
        plt.text(x[best[i]], y[best[i]], "{}".format((best[i] + 1)), size=15, color="r")
    plt.xlabel(u"横坐标")
    plt.ylabel(u"纵坐标")
    plt.savefig(file_name + ".png", dpi=800)
# 绘制进化过程
def draw_evolution(evolution):
    x = [i for i in range(len(evolution))]
    # 清空画布
    plt.clf()
    plt.plot(x, evolution)
    plt.savefig('tsp_sa_evolution.png', dpi=800)
# 模拟退火算法
def simulated_annealing():
    # 城市距离矩阵
    distance = build_distance()
    # 城市个数
    city_cnt = len(distance)
    # 初始化城市路径,这里可以随机生成,也可以跟书中的初始路径保持一致
    # path = random.sample(range(0, city_cnt), city_cnt)
    path = [10, 13, 2, 8, 5, 3, 12, 6, 7, 0, 11, 4, 1, 9]
    # 绘制初始路径
    draw_result(path, "init_path")
    # 初始路线长度
    total_distance = path_distance(path, distance)
    print("初始路线:", [p + 1 for p in path])
    print("初始总距离:", total_distance)
    # 温度
    t = T0
    # 进化过程,每一次迭代的路径总距离
    evolution = []
    # 循环直到冷却后停止
    while t > Tend:
        for _ in range(L):
            # 产生新路径
            new_path = gen_new_path(path)
            # 更新最佳路径及对应的距离
            path, total_distance = metropolis(path, new_path, distance, t)
            # 更新进化过程
            evolution.append(total_distance)
        # 降温
        t = t * q
    # 打印退火后信息
    print("结束温度为:", t)
    print("最佳路线:", [p + 1 for p in path])
    print("最佳距离:", total_distance)
    # 绘制最佳路径
    draw_result(path, "tsp_sa_best")
    # 绘制进化过程
    draw_evolution(evolution)
if __name__ == "__main__":
    simulated_annealing()

程序打印信息如下:

初始路线: [11, 14, 3, 9, 6, 4, 13, 7, 8, 1, 12, 5, 2, 10]
初始总距离: 56.0122140089359
结束温度为: 0.0009120344560464498
最佳路线: [14, 2, 1, 10, 9, 11, 8, 13, 7, 12, 6, 5, 4, 3]
最佳距离: 29.340520066994227

运行结果下图所示:

路径总距离随着迭代的进行逐步稳定,如下图所示:

笔者水平有限,若有不对的地方欢迎评论指正

相关文章
|
15天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
72 4
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
1月前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
287 55
|
25天前
|
存储 缓存 监控
局域网屏幕监控系统中的Python数据结构与算法实现
局域网屏幕监控系统用于实时捕获和监控局域网内多台设备的屏幕内容。本文介绍了一种基于Python双端队列(Deque)实现的滑动窗口数据缓存机制,以处理连续的屏幕帧数据流。通过固定长度的窗口,高效增删数据,确保低延迟显示和存储。该算法适用于数据压缩、异常检测等场景,保证系统在高负载下稳定运行。 本文转载自:https://www.vipshare.com
120 66
|
2月前
|
搜索推荐 Python
利用Python内置函数实现的冒泡排序算法
在上述代码中,`bubble_sort` 函数接受一个列表 `arr` 作为输入。通过两层循环,外层循环控制排序的轮数,内层循环用于比较相邻的元素并进行交换。如果前一个元素大于后一个元素,就将它们交换位置。
148 67
|
2月前
|
存储 搜索推荐 Python
用 Python 实现快速排序算法。
快速排序的平均时间复杂度为$O(nlogn)$,空间复杂度为$O(logn)$。它在大多数情况下表现良好,但在某些特殊情况下可能会退化为最坏情况,时间复杂度为$O(n^2)$。你可以根据实际需求对代码进行调整和修改,或者尝试使用其他优化策略来提高快速排序的性能
139 61
|
2月前
|
算法 数据安全/隐私保护 开发者
马特赛特旋转算法:Python的随机模块背后的力量
马特赛特旋转算法是Python `random`模块的核心,由松本真和西村拓士于1997年提出。它基于线性反馈移位寄存器,具有超长周期和高维均匀性,适用于模拟、密码学等领域。Python中通过设置种子值初始化状态数组,经状态更新和输出提取生成随机数,代码简单高效。
130 63
|
1月前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
190 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
12天前
|
算法 决策智能
基于SA模拟退火优化算法的TSP问题求解matlab仿真,并对比ACO蚁群优化算法
本项目基于MATLAB2022A,使用模拟退火(SA)和蚁群优化(ACO)算法求解旅行商问题(TSP),对比两者的仿真时间、收敛曲线及最短路径长度。SA源于金属退火过程,允许暂时接受较差解以跳出局部最优;ACO模仿蚂蚁信息素机制,通过正反馈发现最优路径。结果显示SA全局探索能力强,ACO在路径优化类问题中表现优异。
|
22天前
|
算法 网络协议 Python
探秘Win11共享文件夹之Python网络通信算法实现
本文探讨了Win11共享文件夹背后的网络通信算法,重点介绍基于TCP的文件传输机制,并提供Python代码示例。Win11共享文件夹利用SMB协议实现局域网内的文件共享,通过TCP协议确保文件传输的完整性和可靠性。服务器端监听客户端连接请求,接收文件请求并分块发送文件内容;客户端则连接服务器、接收数据并保存为本地文件。文中通过Python代码详细展示了这一过程,帮助读者理解并优化文件共享系统。
|
27天前
|
存储 算法 Python
文件管理系统中基于 Python 语言的二叉树查找算法探秘
在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
50 5

热门文章

最新文章