模拟退火–TSP求解
原始数据格式 (bayg29.csv) 坐标x,y
6734,1453
2233,10
5530,1424
401,841
3082,1644
7608,4458
7573,3716
7265,1268
6898,1885
1112,2049
5468,2606
5989,2873
4706,2674
4612,2035
6347,2683
6107,669
7611,5184
7462,3590
7732,4723
5900,3561
4483,3369
6101,1110
5199,2182
1633,2809
4307,2322
675,1006
7555,4819
7541,3981
3177,756
7352,4506
7545,2801
3245,3305
6426,3173
4608,1198
23,2216
7248,3779
7762,4595
7392,2244
3484,2829
6271,2135
4985,140
1916,1569
7280,4899
7509,3239
10,2676
6807,2993
5185,3258
3023,1942
求解代码
"""
模拟退火算法法求解TSP问题
随机在(0,101)二维平面生成20个点
距离最小化
"""
import math
import random
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
def load_position(file_name):
data = pd.read_csv(file_name, header=None)
city_x = data.iloc[:, 0].tolist()
city_y = data.iloc[:, 1].tolist()
return city_x, city_y
def calFitness(line,dis_matrix):
dis_sum = 0
dis = 0
for i in range(len(line)):
if i<len(line)-1:
dis = dis_matrix.loc[line[i],line[i+1]]
dis_sum = dis_sum+dis
else:
dis = dis_matrix.loc[line[i],line[0]]
dis_sum = dis_sum+dis
return round(dis_sum,1)
def traversal_search(line, dis_matrix, random_change):
i = 0
line_value,line_list = [],[]
while i<=100:
new_line = line.copy()
exchange_max = random.randint(1,random_change)
exchange_time = 0
while exchange_time <= exchange_max:
pos1,pos2 = random.randint(0,len(line)-1),random.randint(0,len(line)-1)
new_line[pos1],new_line[pos2]=new_line[pos2],new_line[pos1]
exchange_time += 1
new_value = calFitness(new_line,dis_matrix)
line_list.append(new_line)
line_value.append(new_value)
i+=1
return min(line_value),line_list[line_value.index(min(line_value))]
def greedy(CityCoordinates,dis_matrix):
'''贪婪策略构造初始解'''
dis_matrix = dis_matrix.astype('float64')
for i in range(len(CityCoordinates)):dis_matrix.loc[i,i]=math.pow(10,10)
line = []
now_city = random.randint(0,len(CityCoordinates)-1)
line.append(now_city)
dis_matrix.loc[:,now_city] = math.pow(10,10)
for i in range(len(CityCoordinates)-1):
next_city = dis_matrix.loc[now_city,:].idxmin()
line.append(next_city)
dis_matrix.loc[:,next_city] = math.pow(10,10)
now_city = next_city
return line
def draw_path(line,CityCoordinates):
x,y= [],[]
for i in line:
Coordinate = CityCoordinates[i]
x.append(Coordinate[0])
y.append(Coordinate[1])
x.append(x[0])
y.append(y[0])
plt.plot(x, y,'r-', color='#4169E1', alpha=0.8, linewidth=0.8)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
if __name__ == '__main__':
fileName = 'bayg29.csv'
city_x, city_y = load_position(fileName)
CityNum = len(city_x)
MinCoordinate = 0
MaxCoordinate = 1000
random_change = 10
Tend = 0.1
T = 100
beta = 0.99
best_value = math.pow(10,10)
best_line = []
CityCoordinates = [(city_x[i], city_y[i]) for i in range(len(city_x))]
dis_matrix = pd.DataFrame(data=None,columns=range(len(CityCoordinates)),index=range(len(CityCoordinates)))
for i in range(len(CityCoordinates)):
xi,yi = CityCoordinates[i][0],CityCoordinates[i][1]
for j in range(len(CityCoordinates)):
xj,yj = CityCoordinates[j][0],CityCoordinates[j][1]
dis_matrix.iloc[i,j] = round(math.sqrt((xi-xj)**2+(yi-yj)**2),2)
line = greedy(CityCoordinates,dis_matrix)
value = calFitness(line,dis_matrix)
best_value,best_line = value,line
draw_path(best_line,CityCoordinates)
while T >= Tend:
new_value,new_line = traversal_search(line,dis_matrix,random_change)
if new_value <= best_value:
best_value,best_line = new_value,new_line
line,value = new_line,new_value
elif random.random() < math.exp(-(new_value-value)/T):
line,value = new_line,new_value
print('当前最优值 %.1f' % (best_value))
T *= beta
print(best_line)
draw_path(best_line,CityCoordinates)
结果展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/190169e2681fb7677c611e43962a55c3.png)
[4, 25, 2, 28, 8, 5, 11, 27, 0, 23, 7, 26, 15, 12, 20, 1, 19, 9, 3, 14, 17, 13, 16, 21, 10, 18, 24, 6, 22]
当前最优值 10125.1