元启发式算法 | 禁忌搜索(Tabu Search)解决TSP问题(Python)

本文介绍禁忌搜索算法解决旅行商问题(TSP),包括算法原理、Python实现细节,并探讨了算法性能与参数设置的关系。

[元启发式算法]禁忌搜索(Tabu Search)解决TSP问题(Python)

完整代码见github

1.Tabu Search基本概念

禁忌搜索(Tabu Search,TS,以下简称TS) 是一种基于邻域搜索策略的元启发式算法,由Fred W. Glover 在1986提出[1],并于1989构建[2][3]。应用于各类组合优化问题。

禁忌搜索的核心思想: 从一个初始解出发,按一系列规则对邻域进行探索,对已搜索过的途径和局部最优解进行记录(建立禁忌表,tabu list),并在进一步的迭代搜索中尽量避开这些对象(不是绝对禁止循环),减少重复搜索,从而保证对不同的有效搜索途径的探索,提高搜索效率。

禁忌搜索涉及到的几个概念。邻域(neighborhood)、禁忌表(tabu list)、禁忌长度(tabu length)、候选解(candidate)、藐视准则(aspiration criterion)(有的也叫特赦规则)

2. Tabu Search算法实现细节

以TSP(Traveling Salesman Problem)问题为例,0号为起始点,需要依次拜访1,2,…10号,最终返回0号,求最短路径。已知各个点坐标位置,各个点的位置如下图所示。解的形式表示为一个列表,如:route=[1,2,3,4,5,6,7,8,9,10].
在这里插入图片描述
(这里用是随机生成一系列坐标点。)

邻域(neighborhood):邻域一般定义为由给定转化规则对给定的问题域上每结点进行转化所得到的问题域上结点的集合。那么在这里即1-10号点的排列组合。
候选解(candidate):从邻域中选择若干个目标值或评价值最佳的邻居作为候选解。候选解集合的生成规则一定程度上决定了搜索的方向和邻域大小,十分关键。候选集过大增加计算内存和计算时间,过小容易过早陷入局部最优。候选集的选择一般由邻域中的邻居组成,可以选择所有邻居,也可以选择表现较好的邻居,还可以随机选择几个邻居。这里我们采用两两交换法则生成候选解集合。
禁忌表(tabu list):记录最优候选解和对应元素,这些元素在下次搜索时将不会被考虑。
禁忌长度(tabu length):禁忌表的最大长度。
藐视准则(aspiration criterion):禁忌搜索算法中,迭代的某一步会出现候选集的某一个元素被禁止搜索,但是若解禁该元素,则会使评价函数有所改善,因此我们需要设置一个特赦规则,当满足该条件时该元素从禁忌表中跳出。
评价函数(evaluation):评价解的好坏。在这里即路径距离。

禁忌搜索算法核心问题:
禁忌对象:禁掉谁?根据受禁对象的不同选择,可行解是一禁禁一个;还是一禁禁掉一大片。主要对禁忌范围,及搜索范围有影响
禁忌长度:禁多久?禁掉的东西什么时候放出来?禁忌长度过短,会导致循环;禁忌长度过长,会导致计算时间过长。
候选集: 邻域中可行解的选取?候选集的大小,过大增加计算内存和计算时间,过小过早陷入局部最优。

python代码实现,可直接运行。

from itertools import combinations
import os,sys,copy
import numpy as np
import time
import matplotlib.pyplot as plt
from GetData import *

class Tabu():
    def __init__(self,disMatrix,max_iters=50,maxTabuSize=10):
        """parameters definition"""
        self.disMatrix = disMatrix
        self.maxTabuSize = maxTabuSize
        self.max_iters = max_iters
        self.tabu_list=[]

    def get_route_distance(self,route):
        '''
        Description: function to calculate total distance of a route. evaluate function.
        parameters: route : list
        return : total distance : folat
        '''        
        routes = [0] + route + [0]    # add the start and end point 
        total_distance = 0
        for i,n in enumerate(routes):
            if i != 0 :
                total_distance = total_distance +  self.disMatrix[last_pos][n] 
            last_pos = n
        return total_distance

    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值