欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TSP问题--禁忌搜索算法

程序员文章站 2022-05-20 20:25:48
...

禁忌搜索(Tabu Search)算法是一种亚启发式(meta-heuristic)随机搜索算法,它从一个初始可行解出发,选择一系列的特定搜索方向(移动)作为试探,选择实现让特定的目标函数值变化最多的移动。为了避免陷入局部最优解,TS采用了一种灵活的“记忆”技术,对已经进行的优化过程进行记录和选择,指导下一步的搜索方向,这就是Tabu表的建立。

禁忌搜索算法的步骤如下:
1.选定一个初始解X,给定一个禁忌表H。
2.若满足停止条件,则停止计算;否则,在X的邻域中选出满足禁忌要求(当某个解足够好的时候,可以打破这个禁忌准则)的候选集CANX,在CANX中选择一个评价最佳的解Xbest,令X=Xbest,更新禁忌表H,重复步骤2。

用TS解TSP问题的代码如下:

#禁忌搜索算法解TSP问题
import numpy as np
import random as rd
import copy

def disCal(path):
    dis = 0
    for i in range(len(path)-1):
        dis += distmat[path[i]][path[i+1]]
    dis += distmat[path[0]][path[-1]]
    return dis

def swap2(sol):
    neighbor = []
    for i in range(len(sol)):
        for j in range(i + 1, len(sol)):
            s = copy.deepcopy(sol)
            x = s[j]
            s[j] = s[i]
            s[i] = x
            neighbor.append(s)
    return neighbor

distmat = np.array([[0,350,290,670,600,500,660,440,720,410,480,970],
                 [350,0,340,360,280,375,555,490,785,760,700,1100],
                 [290,340,0,580,410,630,795,680,1030,695,780,1300],
                 [670,360,580,0,260,380,610,805,870,1100,1000,1100],
                 [600,280,410,260,0,610,780,735,1030,1000,960,1300],
                 [500,375,630,380,610,0,160,645,500,950,815,950],
                 [660,555,795,610,780,160,0,495,345,820,680,830],
                 [440,490,680,805,735,645,495,0,350,435,300,625],
                 [720,785,1030,870,1030,500,345,350,0,475,320,485],
                 [410,760,695,1100,1000,950,820,435,475,0,265,745],
                 [480,700,780,1000,960,815,680,300,320,265,0,585],
                 [970,1100,1300,1100,1300,950,830,625,485,745,585,0]])

if __name__ == '__main__':
    solution = [i for i in range(distmat.shape[0])]
    rd.shuffle(solution)                #随机产生初始解
    shortestDistance = disCal(solution)
    tabuList = []                       #禁忌表
    iterx, iterxMax = 0, 50
    while iterx < iterxMax:
        canSolution = swap2(solution)
        k = []
        shorterDistance = float("inf")
        for i in range(len(canSolution)):
            if disCal(canSolution[i]) < shorterDistance:
                shorterDistance = disCal(canSolution[i])
                k.append(i)
        for i in range(len(k)):
            if disCal(canSolution[k[len(k)-i-1]]) < shortestDistance:
                shortestDistance = disCal(canSolution[k[len(k)-i-1]])
                solution = canSolution[k[len(k)-i-1]]
                break
            else:
                if canSolution[k[len(k)-i-1]] not in tabuList:
                    solution = canSolution[k[len(k)-i-1]]
                    break
        if len(tabuList) < 6:
            tabuList.append(solution)
        else:
            tabuList.pop(0)
            tabuList.append(solution)
        iterx += 1
    print(solution)
    print(disCal(solution))