问题描述
利用模拟退火算法。求解30个城市的TSP问题。两城市之间距离用直角坐标系中的两点距离公式。
{41,94},{37,84},{54,67},{25,62},{7,64},{2,99},{68,58},{71,44},{54,62},{83,69}
{64,60},{18,54},{22,60},{83,46},{91,38},{25,38},{24,42},{58,69},{71,71},{74,78}
{87,76},{18,40},{13,40},{82,7},{62,32},{58,35},{45,21},{41,26},{44,35},{4,50}
思路
模拟退火简介
- (1)随机挑选一个单元k,并给它一个随机的位移,求出系统因此而产生的能量变化ΔEk。
- (2)若ΔEk⩽0,该位移可采纳,而变化后的系统状态可作为下次变化的起点;
若ΔEk>0,位移后的状态可采纳的概率为
式中T为温度,然后从(0,1)区间均匀分布的随机数中挑选一个数RR,若R<Pk,则将变化后的状态作为下次的起点;否则,将变化前的状态作为下次的起点。 - (3)转第(1)步继续执行,知道达到平衡状态为止。
TSP问题
模拟退火的关键是在一定概率P下接受比当前差的状态,而概率P又与当前状态有关,当前状态越差,接受概率P越大,当前状态越好,接受概率P越小。
TSP问题,
- 初始化,模拟退火中用温度来观察程序进程,这里模拟温度,设置
t0=100
,从100°开始降温,程序停止条件t0==1
,温度下降的速率为alpha=0.9
,在每个温度状态下,程序要尝试随机生成路径TIME
次,TIME=1000
- 创建城市坐标矩阵
points
,point[i][0]
表示第i个城市的x坐标,point[i][1]
表示第i个城市的y坐标 - 先随机生成一条路径
way
,通过函数calWayDis(way)
计算路径总长度waydis
- 再随机选择2个城市
city1
和city2
,交换way
中这两个城市的位置,形成新的路径tempway
tempway[city1],tempway[city2]=tempway[city2],tempway[city1]
calWayDis(tempway)
计算tempway
的路径长度tempdis
- 对比:
1.如果:
新的路径长度更小,更新路径,
并与当前最小路径对比:
如果小于当前最小路径,更新最小路径与最小值
if tempdis<waydis:
way = tempway.copy()
waydis = tempdis
if tempdis<bestdis:
bestway = tempway.copy()
bestdis = tempdis
draw(bestway,bestdis)
2. 如果:
新的路径长度不小于现有路径长度,则根据模拟退火的概率,去接受
if tempdis>waydis:
if np.random.rand()<np.exp(-(tempdis-waydis)/(t0)):
way = tempway.copy()
waydis = tempdis
- 步骤4、5、6在某个t0状态,迭代TIME次,每次
way
会交换两个城市生成tempway
,然后t0=t0*alph
,温度状态改变,重复步骤4、5、6,直到t0=1,得到目前最优的路径
while t0>t[0]:
步骤4
步骤5
步骤6
t0 *= alpha
- 打印出得到的最优解,路径和路径长度
代码
import numpy as np
import matplotlib.pyplot as plt
import pdb
import imageio
import shutil
import os
# 生成距离矩阵
def getDismat(points):
dismat = np.zeros((N,N))
for i in range(N):
for j in range(i,N):
dismat[i][j] = dismat[j][i] = np.linalg.norm(points[i]-points[j])
return dismat
def init():
alpha = 0.9
t = (1,100)
TIME = 1000
way = np.arange(N)
waydis = calWayDis(way