【背包问题】禁忌搜索求解0/1背包问题【Matlab源码 329期】

一、简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在组合优化问题的求解中,禁忌搜索(tabu search, TS)是众多元启发式算法中最为常用和有效的方法之一。我们以“寻找中国最高的山”作为例子,解释禁忌搜索的核心思路。
这个比喻中有几个核心的喻体和它们对应的本体:
山——solution
山的高度——objective value
山的轮廓——featuring attributes
小范围内的最高峰——local optimum
全中国最高的山——best solution (with largest objective value)
爬到一座山顶后,四下张望,可以看到附近的紧邻的其他山——neighbors/neighborhood

首先,我们的徐霞客同志在地图上随意指一个土坡,作为他搜索旅程的开端(initial solution)。我们用传送门把徐霞客传送到这个点,然后他就开始一个土坡、一个土坡地搜索了。每一步,他都尽量找一个比当前土坡更高的山坡,就这样他一步步地找到了海拔1400米的庐山,四下看去,附近几百公里已经没有更高的山了,即庐山是附近区域内的局部最高峰(local optimum)。但它很可能并不是全中国的最高峰,因此想要不被困在庐山附近的山脉(trapped in local optima), 徐霞客需要先去往海拔低的山(inferior solution),然后才能到达下一个更高的山峰——这里出现了TS的第一个核心特征:允许搜索过程中的解出现劣化,不一定每一步都要更好。

就这样,徐霞客先走下坡路、再走上坡路,找到了1900米的黄山,已经有进步了,但同样的,稍作停留,徐霞客继续出发了,再接再厉地又找到了2000米的恒山和3000米的峨嵋山。徐霞客携带测高仪(用来计算目标函数),所以不用真的爬上山顶。徐霞客主要忙碌的是:不停的被传送,然后从某一个点出发寻找附近的山(开始local search),一个区域可能有成千上万座山。

现在问题来了,徐霞客从峨嵋山出发,再往下找,很可能不知不觉地又走到了黄山、庐山这些他已经去过的山,费了很大的工夫爬到山顶,发现都是“故地重游”。于是,徐霞客决定去过的山在短期内就不再去了。这个时候, 有两个问题需要解决:1.怎么在爬山之前确定这座山有没有爬过呢(当然,徐霞客是没有地图或者GPS的)?徐霞客的办法是,每去一座山就把它的轮廓画下来。以后遇到一座山的时候,先拿出手里的画对比一下,如果与手中某张画的轮廓很相似,就不用再爬了,因为这座山很有可能是来过的,爬到山顶也不会有新的收获。事实上,要判断两座山是否完全一致,需要对比它们的每一块石头、每一棵树,但这样效率显然太低了,于是就简化为对比两座山的轮廓——这里的轮廓,其实就是对山的一种抽象,我们称之为解的特征点(featuring attributes)。如果两个解的特征点一致,我们就当作它们是同一个解(当然,这种抽象的方法也是有弊端的,稍后我们会谈到); 2.是否去过的山就永远不再去了呢?其实从地质学的角度来看,一座高山的附近很可能有另一座高山,所以即使眼前这座山爬过了,通过它可能可以间接抵达附近的另一座没有去过的高山。所以并不是说回头草就一定不能吃,长远来看可能还是有价值的。

结合上面两个问题,徐霞客改进了他的搜索策略: 每爬完一座山就把它的轮廓画下来,接下来每到达一座山的时候先判断是否有相似轮廓的,如果有就直接绕过去。同时, 手里只保留固定数量的几张图纸(这里的“张数”就是tabu list length,禁忌名单的长度越长,允许重新爬一座山的间隔就越长),新加进来一张图纸,就必须舍弃掉手中现有的最早的那张图纸。因此,即使某一座山已经爬过了,但由于是发生很早以前的、图纸已经丢掉了,是允许再爬一次的。

在这种策略的指导下,徐霞客明显提升了搜索的效率,大量的重复的山被成功地跳过了。但是,随之而来还有一个问题:轮廓相似的两座山,就一定是同一座山么?显然不是的。因为把实体的“山”抽象到“山的轮廓”这个步骤,丢失了大量的细节,因此同一个轮廓是有可能对应不止一座山的。那么, 假设现在徐霞客来到一座山的山脚下,抬头一看它的轮廓和手里的黄山很像。但是测了一下高度,有4700米(黄山才1900米),那显然就不是黄山了,而是昆仑!——这种情况下,即使这座山和黄山的轮廓是一样的,也一定是座新的山,即使它还在“禁忌列表”中,但它被“特赦”了(activates aspiration criteria)。那么,昆仑山附近可能有另一座没有去过的高山。

这么一来,徐霞客又对自己的搜索方法做了改进: 除了禁忌列表(tabu list),他又建了一个特赦列表(aspiration list),针对每一种轮廓,记录了一个截至目前长得像这个轮廓的最高高度。那么未来即使碰到同一个轮廓的山,如果高度超过了这个轮廓下的历史记录,很容易就可以确定它是新的,那么就不用顾虑tabu list了,特赦之。

到这里还没完,徐霞客渐渐意识到,平原地区很可能连绵几百公里都没有收获,而高原地区可能一座山连着一座山,发现新的高峰的概率大得多。也就是说,高山和高山很可能是挨得比较近的,与其在九百六十万平方公里的土地上均匀地投入力气搜索,不如对某些区域多倾注一些精力。因此, 徐霞客每找到一座打破记录的最高峰,就把它的位置详细记录下来,这样他手里就握着第三个列表(回忆一下,第一个是tabu list,第二个aspiration list),现在这第三个列表就叫做elite list,顾名思义,这些都是找到过的“精英”,都是宝。当徐霞客连续几个月没有找到更高的山了,他就会从这个elite list中选择一座山,重新回到那里,试试其他的路,看看有没有可能有突破,同时这次尝试之后,这座山也会被从elite list中删掉,也就是说每座高山只当一次精英,这就是TS中常用的elite strategy(精英策略)。

二、源代码

%禁忌搜索求解0-1背包问题
clear all;close all;
%global a;
%global c;
a=[4,43,83,84,68,92,82,6,44,32,18, 56,83,25,96,70,48,14,58,92];
c=[46,90,72,91,40,75,35,8,54,78,40,77,15,61,17,75,29,75,63,44];
n=20;
b=878;
listlength=15;%禁忌长度
num=1;
bnum=1;
%初始化禁忌表
list=round(rand(1,20));
for i=1:20
    list(i)=0;
end   
fxbest(bnum)=0;%记录每次迭代最好的值
fxlbest(num)=0;%记录当前最好的值
%m=200;
for j=1:200
    k=1;%选择初始可行解
    while(k)    
        x0=round(rand(20,1));%产生初始x(1)->x(20)
        x0(1)=1;%x(1)为起点
        w=a*x0;
        if w<=b
            k=0;
        end
    end  
        if (c*x0)>fxbest(num)           
           fxbest(num)=c*x0;
           xbest=x0;
        end
end
if fxbest(num)>fxlbest(bnum)
    fxlbest(bnum)=fxbest(num);
end
x1=x0;
%nlist=list;
%产生邻域解 禁忌对象选择x的分量,并选择最佳解,
while(num<=500)
    
    [x,p1,p2]=near(x1,list);
    %更新禁忌表
    list=newlist(p1,p2,list);
    x1=x;
    num=num+1;    
    fxbest(num)=c*x1;
    if fxbest(num)>fxlbest(bnum)
        bnum=bnum+1;
        fxlbest(bnum)=fxbest(num);
        xbest=x1;
        list(p1)=0;
        list(p2)=0;
    end
end
function [x,p1,p2]=near(x1,list)
a=[4,43,83,84,68,92,82,6,44,32,18, 56,83,25,96,70,48,14,58,92];
c=[46,90,72,91,40,75,35,8,54,78,40,77,15,61,17,75,29,75,63,44];
b=878;

temp=0;xtemp=0;
for j=1:60
    k=1;%选择初始可行解
    xt=x1;    
         while(k)        
             px=ceil(rand*19)+1;  %[2,20]范围内随机产生一个变异位
             py=ceil(rand*19)+1;
             xt(px)=abs(xt(px)-1);             
            xt(py)=abs(xt(py)-1);
            w=a*xt;
            if w<=b
                k=0;
            end            
         end

三、运行结果

在这里插入图片描述

四、备注

完整代码或者代写添加QQ 912100926
往期回顾>>>>>>
【背包问题】粒子群求解背包问题【Matlab 208期】
【背包问题】遗传算法求解多背包问题【Matlab 209期】
【背包问题】PSO算法求解0/1背包问题【Matlab 328期】

猜你喜欢

转载自blog.csdn.net/m0_54742769/article/details/114291449