|
|
|
@ -0,0 +1,143 @@
|
|
|
|
|
import numpy as np
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
|
import pdb
|
|
|
|
|
import random as rd
|
|
|
|
|
from math import sqrt, exp
|
|
|
|
|
from os import path
|
|
|
|
|
from matplotlib.lines import Line2D
|
|
|
|
|
import matplotlib.animation as animation
|
|
|
|
|
"旅行商问题 ( TSP , Traveling Salesman Problem )"
|
|
|
|
|
'''
|
|
|
|
|
编写模拟退火算法解旅行商问题
|
|
|
|
|
实现TSP的模拟退火算法函数,输入是矩阵表示的图,输出是路径
|
|
|
|
|
可视化显示中间变化过程
|
|
|
|
|
要有详细的注释
|
|
|
|
|
使用python语言
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
# input
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def loadin_data():
|
|
|
|
|
local_path = path.dirname(__file__)
|
|
|
|
|
with open(local_path + '/../testdata/1.txt', 'r') as f:
|
|
|
|
|
data = f.read()
|
|
|
|
|
data = data.split()
|
|
|
|
|
length = len(data)
|
|
|
|
|
x = []
|
|
|
|
|
y = []
|
|
|
|
|
for i in range(length//2):
|
|
|
|
|
x.append(int(data[2*i]))
|
|
|
|
|
y.append(int(data[2*i+1]))
|
|
|
|
|
f.close()
|
|
|
|
|
# print(data)
|
|
|
|
|
return x, y
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loadin_data()
|
|
|
|
|
x, y = loadin_data()
|
|
|
|
|
#print(x, y)
|
|
|
|
|
path = [x, y]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def distance(path, i, j):
|
|
|
|
|
a = path[0][i]-path[0][j]
|
|
|
|
|
b = path[1][i]-path[1][j]
|
|
|
|
|
return sqrt(a**2+b**2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# distance_matrix = []
|
|
|
|
|
# for i in range(len(x)):
|
|
|
|
|
# distance_matrix.append([])
|
|
|
|
|
# # print(distance_matrix)
|
|
|
|
|
# for i in range(2):
|
|
|
|
|
# for j in range(len(x)):
|
|
|
|
|
# distance_matrix[i].append(distance(path, i, j))
|
|
|
|
|
|
|
|
|
|
# print(distance_matrix[1])
|
|
|
|
|
# print(len(distance_matrix[0]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def exchange(path, a, b):
|
|
|
|
|
path[0][a], path[0][b] = path[0][b], path[0][a]
|
|
|
|
|
path[1][a], path[1][b] = path[1][b], path[1][a]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sum_distance(path):
|
|
|
|
|
sum = 0
|
|
|
|
|
for i in range(len(path[0])-1):
|
|
|
|
|
sum += distance(path, i, i + 1)
|
|
|
|
|
# print(path)
|
|
|
|
|
sum += distance(path, len(path[0]) - 1, 0)
|
|
|
|
|
return sum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ax1 = plt.axes([0,0,1,1])
|
|
|
|
|
# ax2 = plt.axes([0.55,0.05,0.95,0.9])
|
|
|
|
|
fig, ax = plt.subplots()
|
|
|
|
|
def draw_line(path):
|
|
|
|
|
for j in range(len(path[0])-1):
|
|
|
|
|
line1 = [(path[0][j], path[1][j]), (path[0][j+1], path[1][j+1])]
|
|
|
|
|
(line1_xs, line1_ys) = zip(*line1)
|
|
|
|
|
ax.add_line(Line2D(line1_xs, line1_ys, linewidth=1, color='blue'))
|
|
|
|
|
line1 = [(path[0][0], path[1][0]),
|
|
|
|
|
(path[0][len(path[0])-1], path[1][len(path[0])-1])]
|
|
|
|
|
(line1_xs, line1_ys) = zip(*line1)
|
|
|
|
|
ax.add_line(Line2D(line1_xs, line1_ys,linewidth=1, color='blue'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
T = 100
|
|
|
|
|
alpha = 0.95
|
|
|
|
|
iters = 1000
|
|
|
|
|
current = sum_distance(path)
|
|
|
|
|
print(current, '\n')
|
|
|
|
|
next = 0
|
|
|
|
|
count = 0
|
|
|
|
|
xl=[]
|
|
|
|
|
yl=[]
|
|
|
|
|
plt.cla()
|
|
|
|
|
plt.ion()
|
|
|
|
|
while(True):
|
|
|
|
|
if(T < 0.05):
|
|
|
|
|
break
|
|
|
|
|
oldcurrent = current
|
|
|
|
|
for i in range(iters):
|
|
|
|
|
a, b = rd.sample(range(0, len(path[0])), 2)
|
|
|
|
|
newpath=[[],[]]
|
|
|
|
|
for x,y in zip(path[0],path[1]):
|
|
|
|
|
newpath[0].append(x)
|
|
|
|
|
newpath[1].append(y)
|
|
|
|
|
# print(newpath)
|
|
|
|
|
exchange(newpath, a, b)
|
|
|
|
|
# print(newpath)
|
|
|
|
|
next = sum_distance(newpath)
|
|
|
|
|
# print(path)
|
|
|
|
|
# print(newpath)
|
|
|
|
|
# print(next - current)
|
|
|
|
|
if(next < current):
|
|
|
|
|
current = next
|
|
|
|
|
path = newpath.copy()
|
|
|
|
|
elif (rd.random() < exp(-(next - current)/T)):
|
|
|
|
|
current = next
|
|
|
|
|
path = newpath.copy()
|
|
|
|
|
plt.cla()
|
|
|
|
|
draw_line(path)
|
|
|
|
|
ax.plot(path[0], path[1],'ro')
|
|
|
|
|
plt.pause(0.05)
|
|
|
|
|
if(oldcurrent!=current):
|
|
|
|
|
# print(count)
|
|
|
|
|
count += 1
|
|
|
|
|
xl.append(count)
|
|
|
|
|
yl.append(current)
|
|
|
|
|
ax1.plot(xl,yl)
|
|
|
|
|
oldcurrent=current
|
|
|
|
|
|
|
|
|
|
T = alpha * T
|
|
|
|
|
print(T)
|
|
|
|
|
for x,y in zip(path[0],path[1]):
|
|
|
|
|
print("(",x,y,")-->",end='')
|
|
|
|
|
print(current)
|
|
|
|
|
plt.ioff()
|
|
|
|
|
plt.show()
|