基于禁忌搜索算法的TSP搜索算法

304 篇文章 189 订阅
13 篇文章 8 订阅

一、TSP问题概述

请参考这里

二、禁忌搜索算法

1、基本原理

  • 禁忌搜索算法(Tabu Search,TS)是由美国科罗拉多大学的Fred Glover教授于1986年提出的可用于有效解决组合优化问题的一种智能优化算法。
  • 禁忌搜索算法模拟人的思维方式,并引入一个禁忌表,记录下已经搜索过的局部最优解,在下一次的搜索中,有意识地避开它(但不是完全隔绝)。以此来跳出局部最优,从而最终实现全局最优。

2、参数设置

  • 禁忌表(Tabu List)
    禁忌表是用来存放禁忌对象的一个容器,放入禁忌表中的禁忌对象在解禁之前不能被再次搜索。

  • 禁忌长度(Tabu Length)
    禁忌长度就是每个禁忌表对象的生存时间,也称为禁忌对象的任期;搜索过程每迭代一次,禁忌表中各个禁忌对象的任期就自动减1,当某一禁忌对象的禁忌长度为0时,就将其从禁忌表中删除。

  • 特赦准则(Aspiration Criterion)
    迭代的某一步会出现候选集上的某一个元素被禁止搜索,但是若解禁该元素,则会使评价函数有所改善。

3、算法特点

(1)新解不是在当前解的邻域中随机产生,它或是优于“best so far”的解,或是非禁忌的最佳解,因此选取优良解的概率远远大于其他解。
(2)由于它的记忆功能(禁忌表)和特赦准则,且在搜索中可以接受非劣解,故有利于全局最优。

4、算法流程

在这里插入图片描述

图1 TS算法的流程图

三、MATLAB程序实现

1、问题描述

假设有意旅行商要拜访全国31个省会城市(不包括港澳台),从一个城市出发,需要经过,所有城市后,回到出发地。每个城市只能经过一次,要求选择一个最短路径。
在这里插入图片描述

表1 各个城市的坐标

在这里插入图片描述

图2 31个城市分布图

2、禁忌搜索算法求解

(1)初始化参数、置空禁忌表。初始化城市规模n=31,禁忌长度TabuL=22,候选解的个数Ca=200,最大迭代次数iter_max=1000,citys表示31个城市的坐标等参数。代码如下:

load citys_data.mat;
n = size(citys, 1);                   % 城市数目
D = zeros(n);                         % 距离矩阵
Tabu = zeros(n);                      % 禁忌表
TabuL = round(sqrt(n*(n-1)/2));       % 禁忌长度
Ca = 200;                             % 候选集的个数(全部邻域解个数)
Canum = zeros(Ca, n);                 % 候选解集合
S0 = randperm(n);                     % 随机产生初始解
bestsofar = S0;                       % 当前最佳解
BestL = Inf;                          % 当前最佳解距离
iter = 1;                             % 初始迭代次数
iter_max = 1000;                      % 最大迭代次数

(2)求两两城市相互之间的距离矩阵D,随机产生一组初始解,计算适应度值(即路径距离),赋值给bestsofar。其中:
D i , j = ( x i − x j ) 2 + ( y i − y j ) 2 (1) D_{i,j}=\sqrt{(x_i-x_j)^2+(y_i-y_j)^2}\tag{1} Di,j=(xixj)2+(yiyj)2 (1) D i , j = [ D 1 , 1 D 1 , 2 ⋯ D 1 , 31 D 2 , 1 D 2 , 2 ⋯ D 2 , 31 ⋮ ⋮ ⋮ D 31 , 1 D 31 , 2 ⋯ D 31 , 31 ] (2) D_{i,j}=\begin{bmatrix} D_{1,1} & D_{1,2} & \cdots & D_{1,31} \\ D_{2,1} & D_{2,2}& \cdots & D_{2,31} \\ \vdots & \vdots & & \vdots \\ D_{31,1} & D_{31,2} & \cdots & D_{31,31}\\ \end{bmatrix}\tag{2} Di,j=D1,1D2,1D31,1D1,2D2,2D31,2D1,31D2,31D31,31(2)代码如下:

%% 计算距离矩阵
for i = 1:n
    for j = i+1:n
        D(i, j) = sqrt(sum((citys(i, :)-citys(j, :)).^2));
        D(j, i) = D(i, j);
    end
end

(3)定义初始解的邻域映射为2-opt形式,即初始解路径中随机交换两个城市。代码如下:

i = 1;
A = zeros(Ca,2);            % 交换的城市矩阵,2002%% 求邻域解中交换的城市矩阵
% 将一个2002列的A阵用随机的方式填满,且没有任意两组数是相等的
while i <= Ca
    r = ceil(n*rand(1,2));         % 随机交换两个城市
    if r(1) ~= r(2)
        A(i, 1) = max(r(1), r(2));
        A(i, 2) = min(r(1), r(2));
        if i == 1
            flag = 0;
        else
            for j = 1:i-1
                if A(i, 1) == A(j, 1) && A(i, 2) == A(j, 2)
                    flag = 1;
                    break;
                else
                    flag = 0;
                end
            end
        end
        if ~flag
            i = i + 1;
        end
    end
end
%% 产生邻域解
% 保留前BestCanum个最好候选解
BestCanum = Ca/2;
BestCa = Inf * ones(BestCanum, 4);
F = zeros(1, Ca);
for i = 1:Ca
    Canum(i, :) = S0;
    Canum(i, [A(i, 2), A(i, 1)]) = S0([A(i, 1), A(i, 2)]);  % 交换A(i, 1)A(i, 2)列的元素
    F(i) = fitness(D, Canum(i, :));
    if i <= BestCanum    % 选取候选集
        BestCa(i, 1) = i;       %1列保存序号
        BestCa(i, 2) = F(i);   %2列保存适应度值(路径距离)
        BestCa(i, 3) = S0(A(i, 1));     %3列保存交换后的数据
        BestCa(i, 4) = S0(A(i, 2));     %4列保存交换后的数据
    else
        for j = 1:BestCanum   % 更新候选集
            if F(i) < BestCa(j, 2)
                BestCa(j, 1) = i;
                BestCa(j, 2) = F(i);
                BestCa(j, 3) = S0(A(i, 1));
                BestCa(j, 4) = S0(A(i, 2));
                break;
            end
        end
    end
end
% 对候选集按照适应度值进行升序排列
[value, index] = sort(BestCa(:, 2));
SBest = BestCa(index, :);
BestCa = SBest;                     % 选取前100个比较好的候选解

(4)判断选出的解是否满足特赦准则。代码如下:

%% 特赦准则
if BestCa(1,2) < BestL     % 候选解比最佳值都还小,那么不管在不在禁忌表中,都是一样的操作
    % 在禁忌表中,全部减1,特赦出来,放在最后;
    % 不在禁忌表中,全部减1,放在最后;
    BestL = BestCa(1, 2);               % BestL当前最优解适配值
    S0 = Canum(BestCa(1,1), :);     % 最优解的替换
    bestsofar = S0;
    % 更新禁忌表
    for i = 1:n
        if Tabu(i, :) ~= 0
            Tabu(i, :) = Tabu(i, :)-1;
        end
    end
    Tabu(BestCa(1, 3), BestCa(1, 4)) = TabuL;         % 更新禁忌表,把特赦的这个放在最末端
else                 % 候选解中最佳的解 仍然没有比目前最佳值更优,则:
    for i = 1:BestCanum                        % 遍历候选集
        if Tabu(BestCa(i, 3), BestCa(i, 4)) == 0  % BestCa就是从小到大排列的,选取第一个不在禁忌表中的解,即禁忌长度为0
            S0 = Canum(BestCa(i, 1), :);         % 则释放,并作为下一次迭代的初始解
            for j = 1:n
                if Tabu(j, :) ~= 0
                    Tabu(j, :) = Tabu(j, :)-1;
                end
            end
            Tabu(BestCa(i, 3), BestCa(i, 4)) = TabuL;   % 放到禁忌表最末端
            break;  %  立刻跳出for循环,因为已经选中不在禁忌表中的最佳解了
        end
    end
end

3、仿真结果

在这里插入图片描述

图3 TS算法优化路径

在这里插入图片描述

图4 适应度进化曲线

代码下载链接:
链接:https://pan.baidu.com/s/1I6c_cCdmZdtJbtg27NWpkg?pwd=9x41
提取码:9x41

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

心️升明月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值