SA模拟退火求解TSP问题

SA模拟退火求解TSP问题

算法介绍

import numpy as np
import random as rd
from matplotlib import pyplot as plt
import seaborn as sns

plt.rcParams['font.serif'] = 'Times New Roman'#显示字体
plt.rcParams['axes.unicode_minus'] = False#显示正负号
plt.rcParams['font.size'] ='20'#设置字体大小

#计算车城市距离
def Dis(loc):
    Dis = []
    for i in range(loc.shape[0]):
        Dis_ = []
        for j in range(loc.shape[0]):
            distance = np.sqrt(np.power(loc[i] - loc[j], 2).sum())
            Dis_.append(distance)
        Dis.append(Dis_)
    return np.array(Dis)
#路径图
def draw(path, loc):
    x = []
    for node in path:
        x.append(loc[node])
    x = np.array(x)
    plt.plot(x[:, 0], x[:, 1],color='blue')
    plt.scatter(x[:, 0], x[:, 1], s=15, color='black')
    plt.show()
#CA_算法
class CA_TSP():
    def __init__(self,path,dis,loc,iteration ,T = 150,alpha=0.95,plot=True):
        """
        :param path: 初始路径
        :param loc: 城市坐标位置
        :param iteration: 退火迭代次数
        :param T: 初始温度
        :param plot: 是否绘图
        :param dis: 城市之间的距离
        :param flag:是偶计算需要城市之间的距离
        :param alpha:退火速度
        :param loc:城市坐标
        """
        self.path = path
        self.iteration = iteration
        self.plot = plot
        self.T = T
        self.dis =dis
        self.alpha =alpha
        self.loc = loc
    # 计算路线距离从a点到b点(闭合成圈)
    def length(self,path,dis):
        length = 0
        for node1, node2 in zip(path[:-1], path[1:]):
            length += dis[node1][node2]
        length = length + dis[path[-1]][path[0]]#闭合总长
        return length

    # 随机交换路径中的两个点,产生新的路径
    def New_path(self,path):
        if rd.random()>0.5:
            node = rd.sample(path, 2)
            path_ = []
            for i in range(len(path)):
                path_.append(path[i])
            temp = path[node[1]]
            path_[node[1]] = path[node[0]]
            path_[node[0]] = temp
            return path_
        #三角换效果一般#可能是参数选取的原因
        else:
            node = rd.sample(path, 3)
            path_ = []
            for i in range(len(path)):
                path_.append(path[i])
            temp0 = path[node[0]]
            temp1 = path[node[1]]
            temp2 = path[node[2]]
            path_[node[0]]=temp2
            path_[node[1]]=temp0
            path_[node[2]]=temp1
            return path_
    #主程序
    def run(self):
        l = []
        while self.T > 1:
            for i in range(self.iteration):
                newPath = self.New_path(self.path)  # 比较路径
                distanceDif = self.length(newPath, self.dis) - self.length(self.path, self.dis)  # 距离差值
                if distanceDif < 0:
                    self.path = newPath  # 接受新的解
                else:  # 以概率exp(-ΔT/T)接受新的解
                    if rd.random() < np.exp(- distanceDif / self.T):  # random()方法返回随机生成的一个实数,它在[0,1)范围内
                        self.path = newPath
            l.append(self.length(self.path, self.dis))
            self.T = self.alpha * self.T
            # print(f'当前温度{self.T}',end='\n')
        print(f'最优路径-->>:{np.round(self.path,2)}')
        print(f'最优解 -->>:{self.length(self.path, self.dis)}')
        if self.plot:#收敛曲线与路径线路图
            plt.rcParams['font.sans-serif'] = ['SimHei']
            sns.set_style('white')
            sns.despine(top=True, right=True, )
            plt.grid(alpha=0.5)
            plt.plot(l,color='blue')
            s=r'路径是闭合总长,但绘图并没有闭合,以便看出首尾'
            plt.title(s)
        # plt.tight_layout()
        plt.show()
        return self.path, l
if __name__=='__main__':
    #测试数据1
    # loc = np.array([[565.0,575.0],[25.0,185.0],[345.0,750.0],[945.0,685.0],[845.0,655.0],
    #                         [880.0,660.0],[25.0,230.0],[525.0,1000.0],[580.0,1175.0],[650.0,1130.0],
    #                         [1605.0,620.0],[1220.0,580.0],[1465.0,200.0],[1530.0,  5.0],[845.0,680.0],
    #                         [725.0,370.0],[145.0,665.0],[415.0,635.0],[510.0,875.0],[560.0,365.0],
    #                         [300.0,465.0],[520.0,585.0],[480.0,415.0],[835.0,625.0],[975.0,580.0],
    #                         [1215.0,245.0],[1320.0,315.0],[1250.0,400.0],[660.0,180.0],[410.0,250.0],
    #                         [420.0,555.0],[575.0,665.0],[1150.0,1160.0],[700.0,580.0],[685.0,595.0],
    #                         [685.0,610.0],[770.0,610.0],[795.0,645.0],[720.0,635.0],[760.0,650.0],
    #                         [475.0,960.0],[95.0,260.0],[875.0,920.0],[700.0,500.0],[555.0,815.0],
    #                         [830.0,485.0],[1170.0, 65.0],[830.0,610.0],[605.0,625.0],[595.0,360.0],
    #                         [1340.0,725.0],[1740.0,245.0]])
    #存入本地文件数据
    loc = np.loadtxt(r'./location.txt', dtype='float')
    loc_N =loc.shape[0]
    path = list(range(loc_N))
    rd.shuffle(path)  # 初始路径
    dis = Dis(loc)#计算城市距离
    path,l = CA_TSP(path,dis,iteration=10000,T = 1000,plot=True,alpha=0.96,loc=loc).run()#返回路径与每次迭代的结果
    draw(path, loc)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值