模拟退火算法(SA)求解旅行商问题(TSP)python

news2024/12/23 14:35:32

目录

一、模拟退火算法求解TSP(city14)的python代码

二、city14的运行结果

三、 模拟退火算法求解TSP(city30)的python代码

四、city30的运行结果


一、模拟退火算法求解TSP(city14)的python代码

import random
import numpy as np
import math
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False


'''计算路径总路程的函数'''
def fitness(n,X,Y,X0):
    '''
    :param n: 城市数量
    :param X: n个城市的横坐标
    :param Y: n个城市的纵坐标
    :param X0: 一个解向量
    :return: 总路程
    '''
    s=0
    for i in range(n):
        if i!=n-1:
            s=s+np.sqrt((X[X0[i]]-X[X0[i+1]])**2+(Y[X0[i]]-Y[X0[i+1]])**2)
        else:
            s=s+np.sqrt((X[X0[i]]-X[X0[0]])**2+(Y[X0[i]]-Y[X0[0]])**2)
    return s


'''定义领域搜索运算操作——交换操作'''
def exchange(X0,q):
    '''
    :param X0: 一个解向量
    :param q: 指定的需要交换的数的两个位置的列表,列表长度为2
    :return: 一个领域解
    '''
    X1=X0.copy()
    temp=X1[q[0]]
    X1[q[0]]=X1[q[1]]
    X1[q[1]]=temp
    return X1


'''定义随机产生初始解的函数'''
def initialX0(n):
    '''
    :param n: 城市数量
    :return: 一个初始解
    '''
    X0=random.sample(range(n),n)
    return X0


'''模拟退火算法——TSP'''
def SA_TSP(n,X,Y,n_TK,r,T_f):
    '''
    :param n: 城市数量
    :param X: n个城市的横坐标
    :param Y: n个城市的纵坐标
    :param n_TK: 内循环的迭代次数
    :param T_down: 降温变化
    :param T_f: 终止温度
    :return: 最优路径和最短距离
    '''

    '''产生一个初始解'''
    X0=initialX0(n)
    print("初始解:\n{}".format(X0))
    print("初始解的总路程:\n{}".format(fitness(n,X,Y,X0)))

    '''初始温度'''
    T0=1000

    '''存储历史最优路径'''
    X_min=[]
    X_min.append(X0)

    '''存储历史最优距离'''
    s_min=[]
    s_min.append(fitness(n,X,Y,X0))

    k=0

    while T0>T_f:
        for i in range(n_TK):
            #随机产生两个位置
            q=random.sample(range(n),2)
            #领域运算得到一个随机领域解
            X1=exchange(X0,q)
            #计算初始解和随机领域解的目标函数值
            s1=fitness(n,X,Y,X0)
            s2=fitness(n,X,Y,X1)

            #更新历史最优解
            if s2<min(s_min):
                s_min.append(s2)
                X_min.append(X1)
            else:
                s_min.append(s_min[-1])
                X_min.append(X_min[-1])

            '''判断是否更新解'''
            if s2<s1:
                X0=X1
            else:
                E=math.exp(-(s2-s1)/T0)
                R=random.uniform(0,1)
                if E>R:
                    X0=X1

            k=k+1

        '''降温'''
        T0=T0*r

    '''绘制优化过程'''
    plt.plot(range(k+1),s_min)
    plt.grid()
    plt.title("模拟退火算法——TSP的优化过程")
    plt.xlabel("迭代次数")
    plt.ylabel("总路程")
    plt.show()

    '''绘制路线图'''
    #最优路径
    W=X_min[-1]
    for i in range(n):
        if i!=n-1:
            plt.plot([X[W[i]],X[W[i+1]]],[Y[W[i]],Y[W[i+1]]],c='plum')
        else:
            plt.plot([X[W[i]],X[W[0]]],[Y[W[i]],Y[W[0]]],c='plum')
    plt.scatter(X,Y,c='red')
    plt.title("路线图")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.show()

    return X_min[-1],s_min[-1]



'''主函数'''
if __name__=="__main__":

    '''城市的数量'''
    n=14

    '''定义14个城市的坐标'''
    city_x=[16.47,16.47,20.09,22.39,25.23,22.00,20.47,17.20,16.30,14.05,16.53,21.52,19.41,20.09]
    city_y=[96.10,94.44,92.54,93.37,97.24,96.05,97.02,96.29,97.38,98.12,97.38,95.59,97.13,92.55]

    '''内循环的迭代次数'''
    n_Tk=200

    '''降温变化'''
    r=0.9

    '''终止温度'''
    T_f=0.001

    '''模拟退火算法求解TSP'''
    Xmin,smin=SA_TSP(n,city_x,city_y,n_Tk,r,T_f)

    print("最优路径:\n{}".format(Xmin))
    print("最短距离:\n{}".format(smin))

二、city14的运行结果

 

三、 模拟退火算法求解TSP(city30)的python代码

import random
import numpy as np
import math
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False


'''计算路径总路程的函数'''
def fitness(n,X,Y,X0):
    '''
    :param n: 城市数量
    :param X: n个城市的横坐标
    :param Y: n个城市的纵坐标
    :param X0: 一个解向量
    :return: 总路程
    '''
    s=0
    for i in range(n):
        if i!=n-1:
            s=s+np.sqrt((X[X0[i]]-X[X0[i+1]])**2+(Y[X0[i]]-Y[X0[i+1]])**2)
        else:
            s=s+np.sqrt((X[X0[i]]-X[X0[0]])**2+(Y[X0[i]]-Y[X0[0]])**2)
    return s


'''定义领域搜索运算操作——交换操作'''
def exchange(X0,q):
    '''
    :param X0: 一个解向量
    :param q: 指定的需要交换的数的两个位置的列表,列表长度为2
    :return: 一个领域解
    '''
    X1=X0.copy()
    temp=X1[q[0]]
    X1[q[0]]=X1[q[1]]
    X1[q[1]]=temp
    return X1


'''定义随机产生初始解的函数'''
def initialX0(n):
    '''
    :param n: 城市数量
    :return: 一个初始解
    '''
    X0=random.sample(range(n),n)
    return X0


'''模拟退火算法——TSP'''
def SA_TSP(n,X,Y,n_TK,r,T_f):
    '''
    :param n: 城市数量
    :param X: n个城市的横坐标
    :param Y: n个城市的纵坐标
    :param n_TK: 内循环的迭代次数
    :param T_down: 降温变化
    :param T_f: 终止温度
    :return: 最优路径和最短距离
    '''

    '''产生一个初始解'''
    X0=initialX0(n)
    print("初始解:\n{}".format(X0))
    print("初始解的总路程:\n{}".format(fitness(n,X,Y,X0)))

    '''初始温度'''
    T0=2000

    '''存储历史最优路径'''
    X_min=[]
    X_min.append(X0)

    '''存储历史最优距离'''
    s_min=[]
    s_min.append(fitness(n,X,Y,X0))

    k=0

    while T0>T_f:
        for i in range(n_TK):
            #随机产生两个位置
            q=random.sample(range(n),2)
            #领域运算得到一个随机领域解
            X1=exchange(X0,q)
            #计算初始解和随机领域解的目标函数值
            s1=fitness(n,X,Y,X0)
            s2=fitness(n,X,Y,X1)

            #更新历史最优解
            if s2<min(s_min):
                s_min.append(s2)
                X_min.append(X1)
            else:
                s_min.append(s_min[-1])
                X_min.append(X_min[-1])

            '''判断是否更新解'''
            if s2<s1:
                X0=X1
            else:
                E=math.exp(-(s2-s1)/T0)
                R=random.uniform(0,1)
                if E>R:
                    X0=X1

            k=k+1

        '''降温'''
        T0=T0*r

    '''绘制优化过程'''
    plt.plot(range(k+1),s_min)
    plt.grid()
    plt.title("模拟退火算法——TSP的优化过程")
    plt.xlabel("迭代次数")
    plt.ylabel("总路程")
    plt.show()

    '''绘制路线图'''
    #最优路径
    W=X_min[-1]
    for i in range(n):
        if i!=n-1:
            plt.plot([X[W[i]],X[W[i+1]]],[Y[W[i]],Y[W[i+1]]],c='plum')
        else:
            plt.plot([X[W[i]],X[W[0]]],[Y[W[i]],Y[W[0]]],c='plum')
    plt.scatter(X,Y,c='red')
    plt.title("路线图")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.show()

    return X_min[-1],s_min[-1]



'''主函数'''
if __name__=="__main__":

    '''城市的数量'''
    n=30

    '''定义30个城市的坐标'''
    city_x=[41, 37, 54, 25, 7, 2, 68, 71, 54, 83, 64, 18, 22, 83, 91, 25, 24, 58, 71, 74, 87,
            18, 13, 82, 62, 58, 45,41,44, 4]
    city_y=[94, 84, 67, 62, 64, 99, 58, 44, 62, 69, 60, 54, 60, 46, 38, 38, 42, 69, 71, 78, 76,
            40, 40, 7, 32, 35, 21,26,35, 50]

    '''内循环的迭代次数'''
    n_Tk=300

    '''降温变化'''
    r=0.9

    '''终止温度'''
    T_f=0.001

    '''模拟退火算法求解TSP'''
    Xmin,smin=SA_TSP(n,city_x,city_y,n_Tk,r,T_f)

    print("最优路径:\n{}".format(Xmin))
    print("最短距离:\n{}".format(smin))

四、city30的运行结果

 

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

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

相关文章

中文编程开发语言工具构件说明:屏幕截取构件的编程操作

屏幕截取 用于截取指定区域的图像。 图 标&#xff1a; 构件类型&#xff1a;不可视 重要属性 l 截取类型 枚举型&#xff0c;设置在截取屏幕时的截取类型。包括&#xff1a;全屏幕、指定区域、活动窗口三种。当全屏幕截取时相当于执行了硬拷屏&#xff08;PrintScre…

优化Scrum敏捷需求管理流程,敏捷需求如何管理。

​优化敏捷需求管理流程的方法可以参照如下&#xff1a; 明确需求 。在项目开始时&#xff0c;要确保清楚地理解客户需求&#xff0c;明确项目的目标和范围&#xff0c;以便能够在敏捷迭代中快速响应需求变更。 使用用户故事 。采用用户故事的方式&#xff0c;让客户和开发团…

虚拟化、容器与Docker基本介绍以及安装部署(Docker 基本管理)

目录 1 Docker 概述 1.1 Docker与虚拟机的区别 1.2 容器在内核中支持2种重要技术 1.3 Docker核心概念 2 安装 Docker 2 Docker 镜像操作 2.1 搜索镜像 2.2 获取镜像 2.3 镜像加速下载 2.4 查看镜像信息 2.4.1 查看下载的镜像文件信息 2.4.2 查看下载到本地的所有镜像…

【STL】bitset的模拟实现

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;C进阶 ⭐代码仓库&#xff1a;C进阶 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

HTML5有哪些新特性?移除了哪些元素?

HTML5引入了许多新特性&#xff0c;以下是其中一些主要的新特性&#xff1a; 1&#xff1a;语义化元素&#xff1a;HTML5引入了一些新的语义化元素&#xff0c;如 <header>、<footer>、<nav>、<article>、<section>等&#xff0c;使得页面结构…

计算机组成原理 new09 定点数的移位运算

文章目录 原码/正数反码/正数补码的算术移位负数反码的算术移位负数补码的算术移位算术移位总结符号扩展算术移位的应用真值的算术移位逻辑移位逻辑移位的运用 循环移位不带进位位的循环移位(小循环)带进位位的循环移位(大循环)原码定点一位乘法原码定点一位乘法(手算) (这里我…

【Qt控件之QToolBox】介绍及使用

概述 QToolBox类提供了一个列式的带有选项卡的小部件条目。工具箱是一个小部件&#xff0c;以一个列式的选项卡显示在上方&#xff0c;并在当前选项卡下方显示当前的小部件条目。每个选项卡在选项卡列中有一个索引位置。选项卡的小部件条目是一个QWidget。 每个小部件条目都有…

婚纱摄影行业,还在使用电梯广告?不如试试大数据精准营销

以武汉为例&#xff0c;婚纱摄影的以薇拉&#xff0c;青禾&#xff0c;韩国艺匠&#xff0c;果石&#xff0c;等品牌为主&#xff0c;竞争尤其惨烈&#xff0c;婚纱摄像婚庆行业主要依赖于线下推广&#xff08;如依靠与酒店、婚礼策划等上下游产业合作&#xff09;&#xff0c;…

Google Colab免费GPU使用教程

目录 前言一、Google Colab介绍二、使用步骤1、创建谷歌云盘2、创建一个新的Colab Notebook3、设置免费的GPU4、挂载Google Drive5、运行代码 三、防止掉线措施四、参考 前言 有时候本地跑代码可能耗时比较久&#xff0c;而且还会耽误你本地电脑的使用&#xff0c;购买云服务器…

智能矩阵系统解决的问题?

智能矩阵系统可以解决的问题多种多样&#xff0c;它主要通过人工智能技术应用于矩阵系统&#xff0c;解决一些传统方法难以处理的问题。 以下是一些常见的应用场景&#xff1a; 1. 数据管理&#xff1a;智能矩阵系统可以有效地管理大量的数据&#xff0c;包括数据的存储、检索…

【已解决】Unity 使用NPOI 写word文档报错:System.TypeLoadException:……0.86.0.518

报错显示 System.TypeLoadException: Could not resolve type with token 01000080 from typeref (expected class ICSharpCode.SharpZipLib.Zip.UseZip64 in assembly ICSharpCode.SharpZipLib, Version0.86.0.518, Cultureneutral, PublicKeyToken1b03e6acf1164f73) at NPOI.…

C++初阶--类与对象(1)

文章目录 类的引入类的定义访问限定符类成员的注意事项变量名的冲突 类的实例化类成员的声明与定义类的大小this指针特性 总结 类的引入 在c语言中&#xff0c;我们会这样写一个栈&#xff1a; struct Stack {int* a;int top;int capacity; };void StackInit(struct Stack* p…

利用Bootstrap的分页组件实现分页效果

在网页开发过程中&#xff0c;如果碰到内容过多的情况&#xff0c;一般都会使用分页处理。 在<ul>元素上添加pagination类&#xff0c;在<li>元素上添加page-item类&#xff0c;在超链接中添加 page-link类&#xff0c;即可实现一个简单的分页。 目录 00-基础知识…

STM32项目工程的搭建

视频连接&#xff1a; [2-1]--入门 新建工程 及 工程搭建 -------------_哔哩哔哩_bilibili 1.STM32开发方式 1.标志库 表示直接调用已经写好的程序&#xff0c;通过类似于函数调用直接使用即可。 2.HAL库 程序员自己手动的操作寄存器进行编程 2.工程模板 3.搭建工程的步骤 1…

微信小程序OA会议系统数据交互

前言 经过我们所写的上一文章&#xff1a;微信小程序会议OA系统其他页面-CSDN博客 在我们的是基础面板上面&#xff0c;可以看到出来我们的数据是死数据&#xff0c;今天我们就完善我们的是数据 后台 在我们去完成项目之前我们要把我们的项目后台准备好资源我放在我资源中&…

Memcached和Memcache安装(64位win10)

Memcached和Memcache安装&#xff08;64位win10&#xff09; 一、Memcached和Memcache的区别&#xff1a;   网上关于Memcached和Memcache的区别的理解众说纷纭&#xff0c;我个人的理解是&#xff1a;   Memcached是一个内存缓存系统&#xff0c;而Memcache是php的一个扩展…

虚假KeePass网站利用Google Ads和Punycode推送恶意软件

导语 近日&#xff0c;一起利用Google Ads和Punycode进行恶意软件传播的事件引起了广泛关注。该事件利用虚假KeePass下载网站&#xff0c;通过Punycode编码伪装成KeePass密码管理器的官方域名&#xff0c;并在Google Ads广告中推广&#xff0c;诱导用户下载恶意软件。这种新型的…

C++初阶(四)类和对象

文章目录 一、面向过程和面向对象初步认识二、类的引入三、类的定义1、类的概述2、类的两种定义3、成员变量命名规则的建议 四、类的访问限定符及封装1、访问限定符2、封装 五、类的作用域六、类的实例化七、类对象模型1、如何计算类对象的大小2、 类对象的存储方式猜测3、 验证…

【rust/树莓派】使用rppalembedded-graphics控制st7789 LCD屏幕

说在前面 树莓派版本&#xff1a;4bLCD模块&#xff1a;ST7789V2 240*280 LCD树莓派系统&#xff1a;Linux raspberrypi 5.15.76-v8 #1597 SMP aarch64 GNU/Linuxrust版本&#xff1a;rustc 1.73.0 模块详情 某雪的1.69inch LCD模块&#xff0c;包含杜邦线 准备工作 树莓派…

JavaSE编程题目练习(一)

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名Coder&#xff0c;欢迎关注小弟&#xff01; 博主小留言&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟Cool&#xff0…