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()
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
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:
if rd.random() < np.exp(- distanceDif / self.T):
self.path = newPath
l.append(self.length(self.path, self.dis))
self.T = self.alpha * self.T
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.show()
return self.path, l
if __name__=='__main__':
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)