TSP问题在数学建模比赛中考察较多,而网上提供的代码通常是MATLAB版本,我用python复现了一下,以下是python代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as ns #其实可以不用nx库
from math import*
from random import*
import matplotlib
matplotlib.rcParams['font.family']='SimHei'
matplotlib.rcParams['axes.unicode_minus']=False #这两行代码要一起复制,同时导入mpl库
#导入数据
data=pd.read_excel("D:\数学建模\算法\模拟退火算法\\testdata.xlsx",header=None)
new_data=data.values
matri=np.zeros((144,144))
def Changeapath(ori): #采用赌轮盘法,从而启发式地路径
p1=0.33;p2=0.33;
p=np.random.random()
if p<p1:
x1,x2=randint(0,143),randint(0,143)
m=ori[x1]
ori[x1]=ori[x2]
ori[x2]=m
elif p1+p2>p>=p1:
x1,x2,x3=randint(0,143),randint(0,143),randint(0,143)
k=ori[x1:x2+1]
np.delete(ori,k)
np.insert(ori,x3,k)
elif p>=p1+p2:
x1,x2=randint(1,143),randint(1,143)
t=ori[x2:x1-1:-1]
ori[x1:(x2+1)]=t
return ori
def calculength(path):
ori_len=0
for i in range(0,143):
ori_len+=matri[path[i]][path[i+1]]
return ori_len
for i in range(0,144):
for j in range(0,144):
matri[i][j]=round(sqrt((new_data[j][0]-new_data[i][0])**2+(new_data[j][1]-new_data[i][1])**2),4)
#无需蒙特卡罗模拟,定义初始路径
ori_nodes=np.random.randint(0,143,size=144)
T0=100;T=T0;maxgen=1000;Lk=500;alpha=0.95;minimum=0xffffff;min_result=calculength(ori_nodes)
resultset=[]
for i in range(maxgen):
for j in range(Lk):#每一个温度下重复Lk次
path=Changeapath(ori_nodes)
leng=calculength(path)
if leng<minimum:
ori_nodes=path
minimum=leng
else:
p=exp((minimum-leng)/T)
if random()<p:
ori_nodes=path
minimum=leng
#为避免陷入局部最优,再定义一个最小化参数
if minimum<min_result:
min_result=minimum
best_path=path
resultset.append(min_result)
T=alpha*T
x=np.arange(1,len(resultset)+1)
plt.rcParams.update({'figure.autolayout': True})
plt.plot(x,resultset,color='blue',linewidth=0.7)
plt.xlabel("循环次数")
plt.ylabel("路径长度")
plt.style.use('fivethirtyeight')
plt.axhline(644461.5988000002,linestyle='--',color='red',linewidth=0.5)
plt.text(0,644462,"644461.5988000002",fontsize=10)
plt.annotate("$(394, 644461.6)$",
xy=(394, 644461.5988000002), xycoords='data',
xytext=(514, 650000), textcoords='data',
arrowprops=dict(facecolor='black', shrink=1),
fontsize=12)
plt.savefig("TSP用模拟退火所求结果.png",dpi=400)
plt.show()
![请添加图片描述](https://img-blog.csdnimg.cn/279dfe9ccd794d2088be0aa0362e2f11.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBARHVvbHVvbHVvcw==,size_20,color_FFFFFF,t_70,g_se,x_16)
求解结果如下,
启发式算法求得的往往是近似解,且解不稳定。
红色虚线为最接近最优解的近似解。