实现论文
《基于模拟退火算法的旅行商问题的实现》
链接:https://pan.baidu.com/s/1scdDvKvUviEVEeQC8fweRg
提取码:k38b
实验目的
旅行商问题 TSP 是一类典型的 NP 完全问题, 围绕着这个问题有各种不同的求解方法,已 有的算法例如动态规划法、分支限界法、回溯法等,这些精确式方法都是指数级的,根本无法 解决目前的实际问题,贪心法是近似方法,无法达到比较满意的近似比。 常用的遗传算法也 是求解这类问题的常用方法之一。 由于该问题的解是一种特殊的序列,所以遗传算法在求 解该问题时的性能也并不理想。 模拟退火算法具有描述简单、使用灵活、运用广泛、运行效 率高和较少受到初始条件约束等优点,是解决旅行商问题的一种很好的算法。
基本思路
(1)给定初始温度 T0,及初始点 x,计算该点的函数 值 f(x);
(2)随机产生扰动 Δx,得到新点 x′=x+Δx,计算新 点函数值 f(x′),及函数值差 Δf=f(x′)-f(x);
(3)若 Δf≤0,则接受新点,作为下一次模拟的初始点;
(4)若 Δf>0,则计算新点接受概率:p(Δf)=exp(-Δf K·T),产生[0,1] 区间上均匀分布的伪随机数 r, r∈[0,1], 如果 p(Δf)≥r,则接受新点作为下一次模拟的初始点; 否则放弃新点, 仍取原来的点作为下一次模拟的初始 点。
以上步骤称为 Metropolis 过程。 按照一定的退火方案逐渐降低温度,重复 Metropolis 过程, 就构成了模拟退火算法。 当系统温度足够低 时, 就认为达到了全局最优状态。 按照热力学分子运动 理论, 粒子作无规则运动时, 它具有的能量带有随机 性, 温度较高时, 系统的内能较大, 但是对某个粒子而言, 它所具有的能量较小。 因此算法要记录整个退火过 程中出现的能量较小的点。
基本流程
代码实现
import random
import math
def N(x):
data=x.copy()
a=random.randint(0,29)
b=random.randint(0,29)
while b == a:
b=random.randint(0,29)
if a < b:
flaga=a
flagb=b
else:
flaga=b
flagb=a
data[flaga],data[flagb]=data[flagb],data[flaga]
return data
def f(data,coordinate):
dis=0
for i in range(1,len(data)):
dis+=math.sqrt((coordinate[data[i]-1][0]-coordinate[data[i-1]-1][0])**2+\
(coordinate[data[i]-1][1]-coordinate[data[i-1]-1][1])**2)
return dis
if __name__ == "__main__":
n=30
l=int(n*(n-1)/2)
t=n*l
a=0.93
coordinate=[[40, 32], [93, 55], [38, 39], [11, 43], [32, 68], [54, 75], [19, 15], [56, 30], \
[16, 21], [77, 51], [48, 81], [68, 1], [99, 35], [73, 24], [62, 77], [90, 43], \
[87, 90], [96, 40], [72, 61], [78, 9], [96, 82], [61, 64], [61, 46], [86, 90], \
[20, 78], [5, 59], [88, 71], [96, 2], [95, 57], [12, 28]]
x=[i for i in range(1,31)]
dis=f(x,coordinate)
flag=0
time=1
while flag < 100:
for i in range(l):
newx=N(x)
newdis=f(newx,coordinate)
detaf=newdis-dis
if detaf <=0 :
x=newx.copy()
dis=newdis
else:
p=math.exp(-detaf/t)
if p >= random.random():
x=newx.copy()
dis=newdis
t=a*t
flag+=1
print("当前最优解为:",x)
print("距离为:",dis)