禁忌搜索(Tabu Search)算法及matlab实现(非旅行商(TSP)例子)

本文为原创,未经同意,不得转载

最近在自学智能算法,学到禁忌搜索算法时,发现无论是寻找到的相关教材还是CSDN博客中,对于禁忌搜索问题大多是以旅行商城市旅行路径最短为例来讲述的,就产生一种禁忌搜索算法只能对TSP类型的问题进行优化,显而易见,这是一种粗浅的认识。

任何智能算法都是一种寻找目标最优的独特思想,也就是说任何一种智能算法在适当设置参数和编写代码后都可以解决各类问题,只是存在这种算法解决这类问题的难易罢了。

当你读到这篇文章时,如果你还完全不了解禁忌搜索算法,可以先看看相关禁忌搜索文献或者CSDN里其他博主关于禁忌搜索的博客,里面都很详细的禁忌搜索算法的基本原理,在本文中就不在赘述,笔者更想是谈一些有关禁忌搜索的自我理解。

好了,废话不多说,进入到本文的主体。


一、禁忌搜索算法概要

1.一些禁忌搜索算法的见解

禁忌搜索算法说白了就是一种通过在给定的邻域内,运用确定的规则进行搜索,并通过相应的适应度函数对所搜索到的点进行比较寻优,最终找到目标函数的最优解。

禁忌搜索算法比较依赖初始值和邻域生成规则,两者选取不当,可能会陷入到局部最优当中。

禁忌搜索算法的基本构成是:初始值、目标函数、邻域产生规则、邻域搜索规则、禁忌表、特赦规则以及适应度函数。

2.禁忌搜索算法的基本流程

①设置初始值inittial_point

②将初始值赋给now_point;同时计算初始值的适应度函数,并将算出的值当做当前的目标最优值now_best;

③判断是否达到终止条件,若没有达到进行下步,否则数据输出。

④运用邻域产生规则,利用now_point产生当前的搜索邻域now_area;

⑤运用邻域搜索规则与禁忌表,产生当前邻域now_best的搜索点序列now_point;

⑥对当前点序列进行适应度函数的相关计算后,得到此次相应点的适应度序列shiyi;同时将算完适应度后的当前点序列,通过特赦规则放入到禁忌表中。

⑦如果产生的适应度序列中有优于当前目标最优值now_best的值H,将H赋值给now_best,同时将H点的信息point_H赋值给now_point后,并返回到第③步

⑧如果产生的适应度序列没有优于当前目标最值now_best,返回到第⑤步,即继续在now_area剩余的没有搜索过的邻域中选点。最终会再次出现两种情况:A、搜索到适应度值优于now_best的点H,则返回到第⑦步;B、now_area中所有的点都搜索了,但仍旧没有找到适应度值优于now_best的点,此时退而求其次选择当前邻域now_area中适应度值最优的点P的信息point_p赋值给now_point后返回到第③步。

3.禁忌搜索算法的一种改进

由于禁忌搜索算法十分依赖于初始值的选取,初始值选择不当会陷入到局部最优值当中,同时每次产生的邻域的大小是该算法搜索能力大小的体现,产生的邻域大,则搜索能力强。因此,一种改进的方式是动态的邻域生成规则,即当程序得到的目标最优值在迭代一定代数后仍旧不发生改变时,扩大邻域的大小,再次进行搜索可以跳出局部最优值。

二、matlab代码实现

1.问题描述

确定非线性二元函数f(x,y)的最大值

f(x,y)=3*(1-x)^2*exp(-x^2-(y+1)^2)-10*(x/5-x^3-y^5)*exp(-x^2-y^2)-1/3^exp(-(x+1)^2-y^2)

函数图像如下

可以看到该函数图像具有三个谷峰,对于没有改进的禁忌搜索算法,初值的选取十分重要,一旦选取不当便会陷入到局部最优值。

2.matlab代码

算法中将该函数用作适应度函数。如下是算法中的目标函数代码及画图用到的目标函数代码

①算法中的目标函数

function h=f(x,y)
h=3*(1-x)^2*exp(-x^2-(y+1)^2)-10*(x/5-x^3-y^5)*exp(-x^2-y^2)-1/3^exp(-(x+1)^2-y^2);
end

②画图用到的目标函数

function h=f1(x,y)
h=3*(1-x).^2.*exp(-x.^2-(y+1).^2)-10*(x./5-x.^3-y.^5).*exp(-x.^2-y.^2)-1./3.^exp(-(x+1).^2-y.^2);
end

③邻域生成函数

function s=producelinyu(x,y,h,SL)
s=cell(SL,SL);
m=(SL+1)/2;
for i=1:SL
    for j=1:SL
        s{i,j}=[x+h*(i-m),y+h*(j-m)];
    end
end
s{m,m}=inf;
end

④邻域搜索选点,生成点序列函数

function n=selectpoint(linyu,tab,SL,N,L,xlim,ylim)
for i=1:SL
    for j=1:SL
        if linyu{i,j}(1)==inf||linyu{i,j}(1)<xlim(1)||linyu{i,j}(1)>xlim(2)||linyu{i,j}(2)<ylim(1)||linyu{i,j}(2)>ylim(2)
            linyu{i,j}=inf;
        end
    end
end
tp=1;tpmax=(SL+1)^2;
for i=1:N
    kp=randi(SL,1,2);
    while(linyu{kp(1),kp(2)}(1)==inf||panduan(linyu,kp(1),kp(2),tab,L)==0)
        kp=randi(SL,1,2);
        tp=tp+1;
        if tp>tpmax
            break;
        end
    end
    if tp>tpmax
        n{i}=inf;
        continue;
    end
    n(i)=linyu(kp(1),kp(2));
    linyu{kp(1),kp(2)}=inf;
    tp=1;
end
end

⑤禁忌表函数

function tab=tabutable(L,n,tab1)
tab=tab1;
N=length(n);
for i=1:N
    if n{i}==inf
        continue;
    end
    for j=1:L
        if tab{j,2}==0||tab{j,3}==L+1
            kj=j;
            break;
        end
    end
    tab(kj,1)=n(i);tab{kj,2}=1;
    for j=1:L
        if tab{j,2}==1;
            tab{j,3}=tab{j,3}+1;
        end
        if tab{j,3}==L+2
            tab{j,3}=2;
        end
    end
end
    

⑥在邻域中搜某一点时,判断是否在禁忌表函数

function op=panduan(linyu,ki,kj,tab,L)
num=0;
for i=1:L
    if tab{i,1}==inf
        num=num+0;
    else
        num=num+1;
    end
end

if num==0
    op=1;
else
    for i=1:L
        if tab{i,1}(1)==inf
            continue;
        end
        if linyu{ki,kj}(1)==tab{i,1}(1)&&linyu{ki,kj}(2)==tab{i,1}(2)
            op=0;
            break;
        else
            op=1;
        end
    end
end
end

⑦判断某一邻域是否全部搜索完函数

function op=ifexitpoint(n)
num=0;
for i=1:length(n)
    if n{i}==inf
        num=num+0;
    else
        num=num+1;
    end
end
op=num;
end

⑧邻域动态变化函数

function [sl,edgepoint]=changelinyu(beststatus,SL,E)
num=1;k=1;
for i=1:length(beststatus)-1
    if abs(beststatus(i)-beststatus(i+1))<=E
        num=num+1;
        knum=num;
        ki(k)=i+1;
    else
        num=1;
        continue;
    end
    if knum>9
        k=k+1;
    end
end
if knum>9&&knum<14
    sl=SL+6;
else
    sl=SL;
end
for i=1:length(ki)
    edgepoint(i)=beststatus(ki(i));
end
end

⑨主函数

clear all;
clc;
%设置禁忌搜索算法的初始参数
h=0.1;%步长,代表整个禁忌搜索的整个邻域的精度
SL=5;%搜索邻域的长度(本算法中邻域生成方法必须保证SL为奇数)
N=10;%禁忌候选解的个数
L=500;%禁忌表的长度
K=100;%迭代次数
E=1e-6;
%所求函数的理论图像
x=-3:0.1:3;xlim=[x(1),x(length(x))];
y=-3:0.1:3;ylim=[y(1),y(length(y))];
xL=max(x)-min(x);
yL=max(y)-min(y);
[X,Y]=meshgrid(x,y);
ff=f1(X,Y);
figure(1);
surf(X,Y,ff);

%初始化禁忌表
tabu=cell(L,3);
for i=1:L
    tabu{i,1}=inf;
    tabu{i,2}=0;
    tabu{i,3}=1;
end
tab=tabu;
%设置搜索初始点
initial_x=0.4;initial_y=0.4;

best_x=initial_x;
best_y=initial_y;
beststatus(1)=f(best_x,best_y);
now_x=initial_x;
now_y=initial_y;
for k=1:K
    linyu=producelinyu(now_x,now_y,h,SL);
    n=selectpoint(linyu,tab,SL,N,L,xlim,ylim);
    op=ifexitpoint(n);
    kstart=0;kop=1;
    %clear shiyin;
    partbest=-inf;
    shiyin=-inf*ones(floor(SL^2/N)+1,N,k);
    while(op~=0)
        for i=1:N
            if n{i}(1)==inf
                continue;
            end
            shiyin(kop,i,k)=f(n{i}(1),n{i}(2));
        end
        [next_max,tp]=max(shiyin(kop,:,k));
        next_x=n{tp}(1);next_y=n{tp}(2);
        if next_max>partbest
            partbest=next_max;
            partbest_x=next_x;
            partbest_y=next_y;
        end
        if partbest>=beststatus(k)
            beststatus(k+1)=next_max;
            best_x=next_x;
            best_y=next_y;
            now_x=next_x;
            now_y=next_y;
            n{tp}=inf;
            tab=tabutable(L,n,tab);
            kstart=1;
            break;
        else
            kop=kop+1;
            tab=tabutable(L,n,tab);
            n=selectpoint(linyu,tab,SL,N,L,xlim,ylim);
            op=ifexitpoint(n);
            if kop>=floor(SL^2/N)+1
                break;
            end
        end
    end
    if kstart==1
        continue;
    else
        now_x=partbest_x;
        now_y=partbest_y;
        beststatus(k+1)=beststatus(k);
    end
    [SL,edgepoint{k,1}]=changelinyu(beststatus,SL,E);
end
figure(2);
plot(1:K+1,beststatus);

3.结果显示

主函数中倒数第四行[SL,edgepoint{k,1}]=changelinyu(beststatus,SL,E);为将禁忌搜索算法改进的重要算法。将其注释掉,即变成未改进的禁忌搜索算法。

所有方法都迭代100代,选取下图的四个点分别运用两种禁忌算法计算,四个点的分布图如下。

上图是四点分布周测图,下图为俯视图(等高图)

①未改进的禁忌搜索算法

选取初始点(3,3)

选取初始点(2,-1)

选取初始点(-1.4,-1.3)

选取(0.4,0.4)

注:这里也可能收敛到最优值7.14但是几率很小,大概50次中有一两次。

③改进的禁忌搜索算法

选取点(3,3)

选取点(2,-1)

选取点(-1.4,-1.3)

选取点(0.4,0.4)

三、结论

显而易见,通过上面的对比,可以很清晰的看到未改进的禁忌搜索算法极易陷入到局部最优值当中,而改进的禁忌搜索法可以跳出局部最优值而找到全局最优值(但有时也无法跳出局部最优值,此时再次重新运行1次主程序即可)。

值的注意的是:虽然未改进的禁忌搜索算法依赖于初始值的选取并且极易陷入到局部最优值,但是花费的时间很少;然而改进的禁忌搜索算法虽然可以跳出局部最优值,但是程序花费的时间较长,此问题改进的禁忌算法运行一次大概2分钟左右。这仅仅是一个比较简单的目标优化,若是一个十分复杂的问题,那时间肯定呈指数倍的增长。并且相同的问题运用遗传算法进行编程,很快就能够算出全局最优解。

因此,禁忌搜索法(局部搜索算法)一般不用做全局搜索最优解,而是作为全局搜索算法(如遗传算法)的后续操作,即全局搜索算法得到最优值作为禁忌搜索法的初始值而在局部更加精确的搜索全局最优解。

  • 8
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
禁忌搜索算法Tabu Search)是一种启发式搜索算法,用于解决组合优化问题。它通过维护一个禁忌表来避免搜索过程中陷入局部最优解,并通过引入禁忌策略来探索更广泛的解空间。 以下是禁忌搜索算法的一种可能的MATLAB实现: ```matlab function [bestSolution, bestCost] = tabuSearch(initialSolution, costFunction, tabuListSize, maxIterations) currentSolution = initialSolution; bestSolution = currentSolution; bestCost = costFunction(currentSolution); tabuList = zeros(tabuListSize, numel(initialSolution)); for iter = 1:maxIterations neighbors = generateNeighbors(currentSolution); bestNeighbor = []; bestNeighborCost = inf; for i = 1:numel(neighbors) neighbor = neighbors{i}; neighborCost = costFunction(neighbor); if ~isTabu(neighbor, tabuList) && neighborCost < bestNeighborCost bestNeighbor = neighbor; bestNeighborCost = neighborCost; end end currentSolution = bestNeighbor; tabuList = updateTabuList(tabuList, currentSolution); if bestNeighborCost < bestCost bestSolution = bestNeighbor; bestCost = bestNeighborCost; end end end function neighbors = generateNeighbors(solution) % 生成当前解的邻居解 % 实现略 end function isTabu = isTabu(solution, tabuList) % 判断当前解是否在禁忌表中 % 实现略 end function updatedTabuList = updateTabuList(tabuList, solution) % 更新禁忌表 % 实现略 end ``` 在上述代码中,`initialSolution`是初始解,`costFunction`是评估解的成本函数,`tabuListSize`是禁忌表的大小,`maxIterations`是最大迭代次数。算法通过生成邻居解、判断解是否在禁忌表中以及更新禁忌表来实现禁忌搜索的过程。 请注意,上述代码只是禁忌搜索算法的一种简单实现,具体的实现方式可能因问题而异。你可以根据具体的问题需求进行相应的修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值