禁忌搜索算法总结

禁忌搜索算法简介

禁忌搜索(Tabu Search,TS)是一种现代启发式算法,由美国科罗拉多大学教授Fred Glover在1986年左右提出的,是一个用来跳脱局部最优解的搜索方法。

算法基于局部搜索算法改进而来,通过引入禁忌表来克服局部搜索算法容易陷入局部最优的缺点,具有全局寻优能力。

局部搜索算法

局部搜索算法从一个初始解开始,通过邻域动作,产生其邻居解,判断邻居解的质量,根据某种策略,来选择邻居解,重复上述过程,至到达终止条件。

针对局部邻域搜索,为了实现全局优化,可尝试的途径有:

  • 以可控性概率接受劣解来逃逸局部极小,如模拟退火算法;
  • 扩大邻域搜索结构,如TSP的2opt扩展到k-opt;
  • 多点并行搜索,如进化计算;
  • 采用TS的禁忌策略尽量避免迂回搜索,它是一种确定性的局部极小突跳策略。

基本思想

  • 避免在搜索过程中的循环

  • 只进不退的原则,通过禁忌表实现

  • 不以局部最优作为停止准则

标记已经解得的局部最优解或求解过程,并在进一步的迭代中避开这些局部最优解或求解过程。局部搜索的缺点在于,太过于对某一局部区域以及其邻域的搜索,导致一叶障目。为了找到全局最优解,禁忌搜索就是对于找到的一部分局部最优解,有意识地避开它,从而或得更多的搜索区域。

基本构成部分

禁忌表

禁忌表的作用:防止搜索出现循环。记录前若干步走过的点、方向或目标值,禁止返回;表是动态更新的,表的长度称为Tabu-Size(禁忌长度)。

禁忌长度

指在之后多少个循环内禁用某个产生邻域的规则(禁忌对象)。

就禁忌长度的选择而言,禁忌长度越短,机器内存占用越少,解禁范围更大(搜索范围上限越大),但很容易造成搜索循环(实际去搜索的范围却很小),过早陷入局部最优。禁忌长度过长又会导致计算时间过长。

特赦规则

通俗定义:对于在禁忌的对象,如果出现以下情况,不论现在对象的禁忌长度如何,均设为0

  • 基于评价值的规则,若出现一个解的目标值好于前面任何一个最佳候选解,可特赦;
  • 基于最小错误的规则,若所有对象都被禁忌,特赦一个评价值最小的解;
  • 基于影响力的规则,可以特赦对目标值影响大的对象。
候选集

一次循环中产生领域解的数目。

候选集的大小,过大增加计算内存和计算时间,过小过早陷入局部最优。候选集的选择一般由邻域中的邻居组成,可以选择所有邻居,也可以选择表现较好的邻居,还可以随机选择几个邻居。

评价函数

即代价函数,衡量目标解的好坏。评价函数分为直接评价函数和间接评价函数。

终止规则

一些直观的终止规则:

  • 确定步数终止,无法保证解的效果,应记录当前最优解;
  • 频率控制原则,当某一个解、目标值或元素序列的频率超过一个给定值时,终止计算;
  • 目标控制原则,如果在一个给定步数内,当前最优值没有变化,可终止计算。

算法流程

流程

代码示例

禁忌搜索算法求解中国TSP问题:查看代码出处

%%一个旅行商人要拜访全国31个省会城市,且每个城市只能拜访一次,求所有路径之中的最小值

%%%禁忌搜索算法求解TSP问题%%%%%%%%%%%%%%%%%%%%%
function [BestShortcut,theMinDistance]=TabuSearch
clear;
clc;
Clist=[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];%全国31个省会城市坐标

CityNum=size(Clist,1);%TSP问题的规模,即城市数目
dislist=zeros(CityNum); 
for i=1:CityNum
    for j=1:CityNum
        dislist(i,j)=((Clist(i,1)-Clist(j,1))^2+(Clist(i,2)-Clist(j,2))^2)^0.5;       
    end
end
TabuList=zeros(CityNum);                      % (tabu list)
TabuLength=round((CityNum*(CityNum-1)/2)^0.5);%禁忌表长度(tabu length)
Candidates=200;                               %候选集的个数 (全部领域解个数)
CandidateNum=zeros(Candidates,CityNum);       %候选解集合
S0=randperm(CityNum);                         %随机产生初始解
BSF=S0;                                       %best so far;
BestL=Inf;                                    %当前最佳解距离
p=1;                                         %记录迭代次数
StopL=2000;                                  %最大迭代次数

figure(1);
stop = uicontrol('style','toggle','string'...
,'stop','background','white');
tic;                                         %用来保存当前时间
%%%%%%%%%%%%%%%%%%%%%%禁忌搜索循环%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
while p<StopL
    if Candidates>CityNum*(CityNum-1)/2
        disp('候选解个数不大于n*(n-1)/2!');
        break;
    end
    ALong(p)=Fun(dislist,S0);      %当前解适配值
    
    i=1;
    A=zeros(Candidates,2);          % 解中交换的城市矩阵

    %以下while的 是生成随机的200 X 2  的矩阵矩阵A。每一个元素都是在1-31之间的
    while i<=Candidates        
        M=CityNum*rand(1,2);
        M=ceil(M);
        if M(1)~=M(2)
            A(i,1)=max(M(1),M(2));
            A(i,2)=min(M(1),M(2));
                if i==1
                isa=0;
            else
                for j=1:i-1
                    if A(i,1)==A(j,1) && A(i,2)==A(j,2)
                        isa=1;
                        break;
                    else
                        isa=0;
                    end
                end
            end 
            if ~isa
               i=i+1;
            else 
            end            
        else 
        end
    end
    %%%%%%%%产生领域解%%%%%%%%%%%%%%%%%%%%%%%
    BestCandidateNum=100;%保留前BestCandidateNum个最好候选解
    BestCandidate=Inf*ones(BestCandidateNum,4);
    F=zeros(1,Candidates);
    
    %这相当于是产生一个S0的邻域...
    for i=1:Candidates
        CandidateNum(i,:)=S0;  %候选解集合。
        CandidateNum(i,[A(i,2),A(i,1)])=S0([A(i,1),A(i,2)]);
        F(i)=Fun(dislist,CandidateNum(i,:));
        if i<=BestCandidateNum
            BestCandidate(i,2)=F(i);
            BestCandidate(i,1)=i;
            BestCandidate(i,3)=S0(A(i,1));
            BestCandidate(i,4)=S0(A(i,2));   
        else
            for j=1:BestCandidateNum
                if F(i)<BestCandidate(j,2)
                    BestCandidate(j,2)=F(i);
                    BestCandidate(j,1)=i;
                    BestCandidate(j,3)=S0(A(i,1));
                    BestCandidate(j,4)=S0(A(i,2));
                    break;
                end            
            end
        end
    end
    %对BestCandidate 
    [JL,Index]=sort(BestCandidate(:,2)); 
    SBest=BestCandidate(Index,:);
    BestCandidate=SBest;
    %%%%%%%%%%%%%%%%%%%%%%%藐视准则%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      if BestCandidate(1,2)<BestL
        BestL=BestCandidate(1,2);
        S0=CandidateNum(BestCandidate(1,1),:);        
        BSF=S0;
        for m=1:CityNum
            for n=1:CityNum
                if TabuList(m,n)~=0
                    TabuList(m,n)=TabuList(m,n)-1;      % 更新禁忌表
                end
            end
        end
        TabuList(BestCandidate(1,3),BestCandidate(1,4))=TabuLength;   % 更新禁忌表
    else  
        
for i=1:BestCandidateNum
            if  TabuList(BestCandidate(i,3),BestCandidate(i,4))==0
                S0=CandidateNum(BestCandidate(i,1),:);                
            for m=1:CityNum
                for n=1:CityNum
                    if TabuList(m,n)~=0
                        TabuList(m,n)=TabuList(m,n)-1;                % 更新禁忌表
                    end
                end
            end        
            TabuList(BestCandidate(i,3),BestCandidate(i,4))=TabuLength;       % 更新禁忌表
            break;
            end
        end
      end
    
      
   
    ArrBestL(p)=BestL; 
    
    
    for i=1:CityNum-1
        plot([Clist(BSF(i),1),Clist(BSF(i+1),1)],[Clist(BSF(i),2),Clist(BSF(i+1),2)],'bo-');
        hold on;
    end
    plot([Clist(BSF(CityNum),1),Clist(BSF(1),1)],[Clist(BSF(CityNum),2),Clist(BSF(1),2)],'ro-');
    title(['迭代次数:',int2str(p),' 优化最短距离:',num2str(BestL)]);
    hold off;
    pause(0.005);
    if get(stop,'value')==1
        break;
    end
    %存储中间结果为图片
    if (p==1||p==5||p==10||p==20||p==60||p==150||p==400||p==800||p==1500||p==2000)
        filename=num2str(p);
        fileformat='jpg';
        saveas(gcf,filename,fileformat);
    end 
    p=p+1;                                                          %迭代次数加1
end
toc;                                         %用来保存完成时间
BestShortcut=BSF;                            %最佳路线
theMinDistance=BestL;                        %最佳路线长度
set(stop,'style','pushbutton','string','close', 'callback','close(gcf)');

figure(2);
plot(ArrBestL,'b');
xlabel('迭代次数');
ylabel('目标函数值');
title('适应度进化曲线');
grid;
hold on;


%%figure(3)
%%plot(toc-tic,'b');
%%grid;
%%title('运行时间');
%%legend('Best So Far','当前解');

%%%%%适配值函数%%%%%%%%%%%%%%%%%%%%%
function F=Fun(dislist,s)   
DistanV=0;
n=size(s,2);
for i=1:(n-1)
    DistanV=DistanV+dislist(s(i),s(i+1));
end
    DistanV=DistanV+dislist(s(n),s(1));      
F=DistanV;
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值