模拟退火算法解决TSP实例

本文参考了以下文章:(也建议直接去看他们的文章,我这里只是提供了python版本的代码和初学者需要的一些代码注释

模拟退火算法理论:https://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html

模拟退火算法实例:https://blog.csdn.net/baimafujinji/article/details/52573630

关于模拟退火算法之前只看理论,到头来还是一知半解,而今抬手编程,发现很简单的一个实例就能让你记得更牢,何乐而不为?
源码是C++的,我看懂了之后通过重新编写python程序来达到熟练理解的目的;另外,我在实例的基础上添加了详细注释,便于初学者理解。

'''
该代码通过模拟退火算法来寻找旅行商问题(TSP)的近似最优解
'''
import math
import random
import time

T = 5000  # 初始温度
DELTA = 0.8  # 温度衰减率

# 内循环内的两个限制
ILOOP = 500  # 内循环最大循环次数
LIMIT = 200  # 内循环中失败的最大次数
# 外循环的两个限制
OLOOP = 10  # 外循环最大循环次数
EPS = 1e-8  # 达到最低温度时退出循环


class Path:
    def __init__(self, cities=[], len=0):
        self.cities = cities
        self.len = len


# 计算两点距离
def distance(x, y):
    return math.sqrt(pow(x[0] - y[0], 2) + pow(x[1] - y[1], 2))


# 构建距离矩阵
def getDistMatrix(a, n):

    distMatrix = [[0] * n for i in range(n)]

    for i in range(n - 1):
        for j in range(i + 1, n):
            distMatrix[i][j] = distMatrix[j][i] = distance(a[i], a[j])

    # for i in range(n):
    #     for j in range(n):
    #         print(distMatrix[i][j]," ")
    #     print()

    return distMatrix


# 初始化路径
def get_init_path(a, n, distMatrix):
    initPath = Path()  # 路径
    for i in range(n - 1):
        initPath.cities.append(i)
        initPath.len = initPath.len + distMatrix[i][i + 1]
    initPath.cities.append(n - 1)
    print(initPath.cities, ": ", initPath.len)
    return initPath


# 随机产生新路径
def get_next_path(n, curPath):
    newPath = Path()
    newPath.cities = curPath.cities
    # 随机取两个不同随机数
    random.seed(time.time())
    x = random.randint(0, n - 1)
    random.seed(time.time())
    y = random.randint(0, n - 1)
    while x == y:
        x = random.randint(0, n - 1)
        y = random.randint(0, n - 1)

    # 采用两点位置交换法产生新路径
    temp = newPath.cities[x]
    newPath.cities[x] = newPath.cities[y]
    newPath.cities[y] = temp

    for i in range(n - 1):
        newPath.len = newPath.len + distMatrix[newPath.cities[i]][newPath.cities[i + 1]]

    return newPath


# 搜索
def search(n, curPath, T):
    loop_L = 0
    bad_num = 0
    while True:
        loop_L = loop_L + 1
        for i in range(ILOOP):
            nextPath = get_next_path(n, curPath)
            dE = nextPath.len - curPath.len
            if dE < 0:
                curPath = nextPath
                print(curPath.cities, ": ", curPath.len)
                bad_num = 0
                bad_bad_num = 0
            else:
                p = math.exp((-1) * dE / T)
                r = random.random()
                if p > r:
                    curPath = nextPath 
                    print(curPath.cities, ": ", curPath.len)
                # 不论随机取到到的较差解有没有被采纳,都要记一次失败
                bad_num = bad_num + 1
            # 如果失败次数超过限制时,则应该退出
            if bad_num > LIMIT:
                bad_bad_num = bad_bad_num + 1
                break

        if bad_bad_num > OLOOP or T < EPS:
            break
        # 每次外循环结束就更新一下温度值
        T = T * DELTA

    print(curPath.cities, ": ", curPath.len)
    return curPath.len


# 打印结果


if __name__ == '__main__':
    # 输入
    a = [[1, 0], [0, 6], [2, 3], [5, 4], [6, 1], [7, 5], [8, 2]]
    n = len(a)
    # 构建距离矩阵
    distMatrix = getDistMatrix(a, n)
    # 初始化路径
    initPath = get_init_path(a, n, distMatrix)
    # 搜索
    minLen = search(n, initPath, T)
    # 打印结果
    print("所以最短路径是", minLen)

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我有明珠一颗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值