禁忌搜索算法

禁忌搜索算法(Tabu Search or Taboo Search,TS)是一种迭代搜索算法,靠记忆来引导算法的搜索过程。

1 算法原理

主要包含2个方面:局部领域搜索、禁忌搜索,在领域搜索的基础上,通过禁忌准则来避免重复搜索,通过藐视准则来赦免一些被禁忌的优良状态,以实现全局优化。

1.1 局部领域搜索

局部领域搜索是基于贪婪准则持续在当前的领域中进行搜索,找到局部最优解。大致方法是选定一个可行解x^{0},并产生领域解集x^{neighour},逐一比较x^{0}x^{neighbour}的目标值,选出最优解更新x^{0},直到找不到更优为止,记为x^{best}

1.2 禁忌搜索

在局部搜索的基础上,建立禁忌表,记录近几次迭代过程中的移动(所谓移动,即产生领域解的变化),凡是处于禁忌表中的移动是不允许的,来避免算法重复访问最近几次已经访问过的解,从而防止陷入局部最优解。注意禁忌表记录可能是解,也可以是产生领域解的移动或变化。

1.3 藐视准则

藐视准则是为了不错过最优解。

一般来说,通过设置存在时间或禁忌表长度来实现特赦以前出现过的最优解相关移动。

2 算法流程

在此之前需要对解进行区分,当前解x^{now},领域解x^{neighour}(领域中最优的解),候选解x^{candidate},全局最优解x^{best}(也叫bestsofar)。以旅行商问题为例,当x^{now}经过移动(随机交换2个城市的访问顺序)会产生x^{neighour}x^{neighour}x^{now}好,x^{neighour}就会升级成x^{candidate}

 步骤1   生成初始解x^{now}和置禁忌表tabu为空 

步骤2    从当前解产生若干领域解x^{neighour},并确定若干候选解x^{candidate}

步骤3    如果x^{candidate}优于x^{now},则更新x^{now}=x^{candidate}和将x^{candidate}对应的禁忌对象加入禁忌表tabu,否则基于禁忌表tabu从x^{candidate}中选出次优解,更新x^{now}和tabu

步骤4    更新x^{best}=x^{now}和基于藐视准则更新tabu

步骤5    判断结束或继续步骤2-5

3 关键参数

初始解

适配值函数

领域结构

从一个解通过“移动”产生另一个解的途径,常用方法互换、插值、逆序

禁忌对象

即放入禁忌表中的变化元素,可以是状态本身(解本身)或状态分量(领域结构中的移动

候选解选择

切记要选择充分,保证在领域内充分搜索

禁忌表

一般是先进先出的队列

禁忌长度

禁忌对象在禁忌表中的任期,可以是常量也可以是变量

藐视准则

搜索策略

终止准则

4 仿真实例

旅行商问题(TSP问题)

假设1个旅行商要对31个省会城市进行拜访,要求距离最短,不能重复拜访,且最终要回到出发城市。

31个城市坐标:

  [1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;
    3238 1229;4196 1044;4312 790  ;4386 570  ;3007 1970;2562 1756;
    2788 1491;2381 1676;1332 695  ;3715 1678;3918 2179;4061 2370;
    3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;3507 2376;
    3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;
    2370 2975];

代码

close all;
clear all;
clc;
%%%%%初始化参数
C = [1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;
    3238 1229;4196 1044;4312 790 ;4386 570 ;3007 1970;2562 1756;
    2788 1491;2381 1676;1332 695 ;3715 1678;3918 2179;4061 2370;
    3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;3507 2376;
    3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;
    2370 2975];
n=size(C,1);
D=zeros(n);
for i=1:n
    for j=1:n
        D(i,j)=((C(i,1)-C(j,1))^2 + (C(i,2)-C(j,2))^2)^0.5;
    end
end
tabu=zeros(n);
tabuL=21;
Ca=200;
canum=zeros(Ca,n);
s0=randperm(n);
bestsofar=s0;
bestlen=func1(D,bestsofar,n);
g=1;
G=1000;
%%%%%算法循环
while g<G
    %%%%%产生领域解canum,产生200个,只取前100
    %%%%%确保交换不重复
    A=zeros(Ca,2);
    p=1;
    while p<=Ca
        A(p,:)=ceil(rand(1,2)*n);
        while A(p,1)==A(p,2)   
            A(p,:)=ceil(rand(1,2)*n);
        end
        temp1=min(A(p,1),A(p,2));
        A(p,2)=max(A(p,1),A(p,2));
        A(p,1)=temp1;
        if p==1
            k=0;%查重
        else
            for j=1:p-1
                if A(p,1)==A(j,1) && A(p,2)==A(j,2)
                    k=1;
                    break;
                else
                    k=0;
                end
            end
        end  
        if k==0
            p=p+1;
        end
    end
    for i=1:Ca
        canum(i,:)=s0;
        canum(i,[A(i,1),A(i,2)])=s0([A(i,2),A(i,1)]);
        canumlen(i)=func1(D,canum(i,:),n);
    end
    [canumlen,index]=sort(canumlen);
    canum=canum(index,:);
    A=A(index,:);
    bestca=canum(1:Ca/2,:);
    %%%%%藐视准则
    if canumlen(1) < bestlen    %领域解更优
        bestlen=canumlen(1);
        s0=bestca(1,:);
        bestsofar=s0;
        for i=1:n
            for j=1:n
                if tabu(i,j)~=0
                    tabu(i,j)=tabu(i,j)-1;
                end
            end
        end
        tabu(A(1,1),A(1,2))=tabuL;
    else
        for k=1:Ca/2
            if tabu(A(k,1),A(k,2))==0
                s0=bestca(k,:);
                for i=1:n
                    for j=1:n
                        if tabu(i,j)~=0
                            tabu(i,j)=tabu(i,j)-1;
                        end
                    end
                end
                tabu(A(k,1),A(k,2))=tabuL;
                break;
            end
        end
    end
    arrbestlen(g)=bestlen;
    g=g+1;    
end
%%%%%画图
for i=1:n-1
    plot([C(bestsofar(i),1),C(bestsofar(i+1),1)],[C(bestsofar(i),2),C(bestsofar(i+1),2)],'o-');
    hold on;
end
plot([C(bestsofar(n),1),C(bestsofar(1),1)],[C(bestsofar(n),2),C(bestsofar(1),2)],'ro-');
title([num2str(g),'次最短距离:',num2str(bestlen)]);
hold off;
%%%%%输出优化结果
figure;
plot(arrbestlen);
xlabel('迭代次数');
ylabel('目标函数值');
title('适应度进化曲线');
%%%%%路径长度函数
function result = func1(D,f,N)
    len=D(f(1),f(N));
    for j=2:N
        len=D(f(j),f(j-1))+len;
    end
    result=len;
end

结果

禁忌搜索是一种用于解决组合优化问题的算法,可以通过某种搜索策略在候选解空间中寻找最优解。禁忌搜索算法中的一些关键概念包括邻域、候选集合、禁忌表、评价函数、特赦规则和终止规则。 在禁忌搜索算法中,邻域是指给定任意可行解x后,通过一个映射关系N(x)来获取x的邻居,邻居是指在可行解空间中与x相邻的解。候选集合通常由邻域中的邻居组成,可以通过不同的方法生成。禁忌表由禁忌对象和禁忌长度组成,禁忌对象是指在搜索过程中被禁止搜索的元素,禁忌长度是指禁忌表能够接受的最多禁忌对象的数量。评价函数用来评价当前解的好坏,例如在TSP问题中可以使用总旅程距离作为评价指标。特赦规则是用来判断是否可以解除禁忌对象的规则,当特定条件满足时,禁忌对象可以被解禁。终止规则用来确定何时停止搜索迭代,可以根据局部最优解的变化、评价函数的差别或者迭代次数来进行判断。 禁忌搜索算法的具体过程可以通过举例来详细说明。假设我们要解决一个车辆路径规划问题(CVRP),其中车辆类型是单一的且车辆容量不小于需求节点的最大需求。我们可以使用禁忌搜索算法来求解该问题。 具体的算法过程如下: 1. 初始化初始解x1和历史最优解为x1,计算初始解的评价函数值f(x1)。 2. 在x1的邻域中生成候选集合,例如通过两两交换法则生成候选集合。 3. 对于候选集合中的每个元素,判断是否在禁忌表中,如果在禁忌表中则跳过该元素。 4. 对于候选集合中的每个元素,计算其解的评价函数值,并更新历史最优解和禁忌表。 5. 根据特赦规则判断是否解除禁忌对象。 6. 根据终止规则判断是否停止迭代,例如当迭代次数超过100次时停止迭代。 7. 输出历史最优解作为最终解。 以上是禁忌搜索算法的一个简单示例,实际应用中可能会根据具体问题进行调整和优化。禁忌搜索算法的优点是可以在大规模组合优化问题中找到较好的解,但也需要根据具体问题进行参数调节和算法设计。在Python中,可以使用相应的库或自行编写代码来实现禁忌搜索算法。有参考笔记和代码可以供参考。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [3. Python实现VRP常见求解算法——禁忌搜索(TS)](https://blog.csdn.net/qq_36744449/article/details/120022655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NPC_0001

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

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

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

打赏作者

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

抵扣说明:

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

余额充值