模拟退火算法解决旅行商问题(附python代码)

一、算法思路

1、模拟退火算法思路

       模拟退火算法在每次计算后得到一个新解,若新解比当前解更好,则直接接受该情况以及新解,若新解比当前解更差,则以一定的概率接受新解,且这个概率随着时间的推移逐渐降低,直至达到温度下限。这样做使得搜索可能跳出局部最优解,达到全局最优解。

2、利用模拟退火算法(SA)解决旅行商问题。

       在模拟退火过程中,每次迭代都随机选取当前路径中的一段子路径进行翻转,得到新的路径,并计算新路径得到的总距离,接着根据Metropolis准则判断是否接受新的路径,在迭代后更新温度。最后求得的路径并不一定就是最优解,大概率是接近全局最优的局部最优解。

二、伪代码

'''
模拟退火算法解TSP伪代码

def SA_TSP():
    初始化距离矩阵
    得到初始解以及初始距离
    while(true):
        for i in range(迭代次数):
            采用2变换法生成新的路径
            计算新路径的解
            根据Metropolis准则判断是否接受新的路径
        更新温度t
'''

三、算法代码

import random
import matplotlib.pyplot as plt

# 城市坐标范围
M = 1000
# 城市数量
n = 30
# 初始化城市坐标
city_x = random.sample(range(0, M), n)
city_y = random.sample(range(0, M), n)
# 初始化距离矩阵
distance_Citys = [[0 for col in range(M)] for row in range(M)]
# 初始温度,结束温度
t_init = 50
t_final = 1e-7
# 温度衰减系数
a = 0.98
# 迭代次数
markovlen = 10000

# 初始化距离矩阵
def initDistanceMatrix():
    for i in range(n):
        for j in range(n):
            x = pow(city_x[i] - city_x[j], 2)
            y = pow(city_y[i] - city_y[j], 2)
            distance_Citys[i][j] = pow(x + y, 0.5)
            if distance_Citys[i][j] <= 1e-6:
                distance_Citys[i][j] = sys.maxsize

# 计算路径距离
def getDistance(path):
    res = 0
    for i in range(n - 1):
        res += distance_Citys[path[i]][path[i + 1]]
    res += distance_Citys[path[n - 1]][path[0]]
    return res

# 在现有路径上采用2变换法,返回新的路径
def getNewPath(cur_path):
    path = cur_path.copy()
    u = random.randint(0, n - 1)
    v = random.randint(1, n)
    path[u, v + 1] = path[v, u - 1, -1]
    return path


def drawPath(best_path):
    x = [0 for col in range(n + 1)]
    y = [0 for col in range(n + 1)]

    for i in range(n):
        x[i] = city_x[best_path[i]]
        y[i] = city_y[best_path[i]]
    x[n] = x[0]
    y[n] = y[0]

    print("最佳路线为:")
    for i, city in enumerate(list(zip(x, y))):
        print(city, end=', ')
        if i % 10 == 9:
            print()

    plt.xlim(0, 1200)
    plt.ylim(0, 1200)
    plt.plot(x, y, marker='o', mec='r', mfc='w', label='path')
    plt.legend()
    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("SA_TSP")
    plt.show()

def SA_TSP():
    # 获取初始距离矩阵
    initDistanceMatrix()
    # 得到初始解
    cur_path = random.sample(range(0, n), n)
    cur_dis = getDistance(cur_path)
    best_path = cur_path
    best_dis = cur_dis
    t = t_init

    while t < t_final:
        for point in range(markovlen):
            new_path = getNewPath(cur_path)
            new_dis = getDistance(new_path)
            delt = new_dis - cur_dis
            if delt <= 0:  # 表示得到优解
                cur_path = new_path
                cur_dis = new_dis
                if best_dis > cur_dis:
                    best_dis = cur_dis
                    best_path = cur_path
            else:    # 得到较差解
                p = math.exp(-delt / t)
                if random.random() < p:  # 接受差解
                    cur_path = new_path
                    cur_dis = new_dis
        t *= a   # 退火
    print("城市数量:{}, 城市坐标范围:{}, 结果距离为:{:.2f}".format(n, M, best_dis))

    drawPath(best_path)

if __name__ == '__main__':
    SA_TSP()

四、运行结果

模拟退火算法解决旅行商问题(附python代码)_第1张图片

你可能感兴趣的:(python,课程作业)