数学建模——模拟退火算法解决TSP问题
1 模拟退火简介
热能变化
热能上升以一定的概率去调整,直到静止状态
2 路径数据及程序
2.1数据 verify_order_position_10.csv
1476786 43.013425 -81.2768629
1476794 42.9923696 -81.2742454
1476933 42.983249 -81.2848146
1477049 43.0104333 -81.2735103
1477050 43.0104333 -81.2735103
1477051 43.0104333 -81.2735103
1477093 43.0180602 -81.281657
1477110 42.9861887 -81.2970252
1477119 42.9503241 -81.2864436
1477553 43.013425 -81.2768629
2.2程序
# 模拟退火算法————解TSP问题
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 20 18:41:02 2020
@author: andrew
"""
import pandas as pd
import math
import random
import matplotlib.pyplot as plt
import sys
import copy
import time
#初始温度 结束温度
T0 = 30
Tend = 1e-8
#循环控制常数
L = 50
#温度衰减系数
a = 0.98
def init_dis_matrix(length):
# 初始化距离矩阵
distance_matrix = [[0 for col in range(length)] for raw in range(length)]
return distance_matrix
def load_position(file_name):
# 读入城市的位置
data = pd.read_csv(file_name,names=['index','lat','lon'])
city_x = data['lat'].tolist()
city_y = data['lon'].tolist()
return city_x,city_y
#构建初始参考距离矩阵
def getdistance(city_x,city_y,n_len,distance):
for i in range(n_len):
for j in range(n_len):
x = pow(city_x[i] - city_x[j], 2)
y = pow(city_y[i] - city_y[j], 2)
distance[i][j] = pow(x + y, 0.5)
for i in range(n_len):
for j in range(n_len):
if distance[i][j] == 0:
distance[i][j] = sys.maxsize
#计算总距离
def cacl_best(rou,n_len,distence):
sumdis = 0.0
for i in range(n_len-1):
sumdis += distence[rou[i]][rou[i+1]]
sumdis += distence[rou[n_len-1]][rou[0]]
return sumdis
def getnewroute(route, time,n_len):
# 得到新的路径
# 如果是偶数次,二变换法
current = copy.copy(route)
if time % 2 == 0:
u = random.randint(0, n_len-1)
v = random.randint(0, n_len-1)
temp = current[u]
current[u] = current[v]
current[v] = temp
#如果是奇数次,三变换法
else:
temp2 = random.sample(range(0, n_len), 3)
temp2.sort()
u = temp2[0]
v = temp2[1]
w = temp2[2]
w1 = w + 1
temp3 = [0 for col in range(v - u + 1)]
j =0
for i in range(u, v + 1):
temp3[j] = current[i]
j += 1
for i2 in range(v + 1, w + 1):
current[i2 - (v-u+1)] = current[i2]
w = w - (v-u+1)
j = 0
for i3 in range(w+1, w1):
current[i3] = temp3[j]
j += 1
return current
def draw(best,city_x,city_y,n_len):
# 画出路径图
result_x = [0 for col in range(n_len+1)]
result_y = [0 for col in range(n_len+1)]
for i in range(n_len):
result_x[i] = city_x[best[i]]
result_y[i] = city_y[best[i]]
result_x[n_len] = result_x[0]
result_y[n_len] = result_y[0]
print(result_x)
print(result_y)
# 将地点坐标恢复到以前的数值
result_x_new = [x/1000 for x in result_x]
result_y_new = [y/1000 for y in result_y]
plt.xlim(42.9, 43.1) # 限定横轴的范围
plt.ylim(-81.26, -81.30) # 限定纵轴的范围
plt.plot(result_x_new, result_y_new, marker='>', mec='r', mfc='w',label=u'Route')
plt.legend() # 让图例生效
plt.margins(0)
plt.subplots_adjust(bottom=0.15)
plt.xlabel(u"x") # X轴标签
plt.ylabel(u"y") # Y轴标签
plt.title("route plan") # 标题
plt.show()
plt.close(0)
def solve(file_name):
city_x,city_y = load_position(file_name) # list
n_len = len(city_x) # 10
city_x = [x*1000 for x in city_x]
city_y = [x*1000 for x in city_y]
distence = init_dis_matrix(n_len) # 初始化距离矩阵
getdistance(city_x,city_y,n_len,distence) #得到距离矩阵
route = random.sample(range(0, n_len), n_len) # 初始路径
total_dis = cacl_best(route,n_len,distence) # 初始距离
print("初始路线:", route)
print("初始距离:", total_dis)
#新解
newroute = []
new_total_dis = 0.0
best = route
best_total_dis = total_dis
t = T0 # 令温度为初始温度
while True:
if t <= Tend:
break
for rt2 in range(L):
newroute = getnewroute(route, rt2,n_len) # 得到新的路径
new_total_dis = cacl_best(newroute,n_len,distence) # 得到新的路径距离
delt = new_total_dis - total_dis # 新旧路径差值
# 差值小于0则将最好路径及最好路径总长重新赋值
if delt <= 0:
route = newroute
total_dis = new_total_dis
if best_total_dis > new_total_dis:
best = newroute
best_total_dis = new_total_dis
# 差值大于零则变换到步骤二,随意后的状态采纳概率值是否重新赋值
elif delt > 0:
p = math.exp(-delt / t)
ranp = random.uniform(0, 1)
if ranp < p:
route = newroute
total_dis = new_total_dis
t = t * a # 温度下降
print("现在温度为:", t)
print("最佳路线:", best)
print("最佳距离:", best_total_dis)
draw(best,city_x,city_y,n_len)
return best
if __name__=="__main__":
start = time.time()
best = solve('verify_order_postion_20.csv')
end = time.time()
print('time : ',end-start)
print(best)
3 程序运行结果
最佳路径