禁忌搜索算法(Tabu Search or Taboo Search,TS)是一种迭代搜索算法,靠记忆来引导算法的搜索过程。
1 算法原理
主要包含2个方面:局部领域搜索、禁忌搜索,在领域搜索的基础上,通过禁忌准则来避免重复搜索,通过藐视准则来赦免一些被禁忌的优良状态,以实现全局优化。
1.1 局部领域搜索
局部领域搜索是基于贪婪准则持续在当前的领域中进行搜索,找到局部最优解。大致方法是选定一个可行解,并产生领域解集,逐一比较和的目标值,选出最优解更新,直到找不到更优为止,记为。
1.2 禁忌搜索
在局部搜索的基础上,建立禁忌表,记录近几次迭代过程中的移动(所谓移动,即产生领域解的变化),凡是处于禁忌表中的移动是不允许的,来避免算法重复访问最近几次已经访问过的解,从而防止陷入局部最优解。注意禁忌表记录可能是解,也可以是产生领域解的移动或变化。
1.3 藐视准则
藐视准则是为了不错过最优解。
一般来说,通过设置存在时间或禁忌表长度来实现特赦以前出现过的最优解相关移动。
2 算法流程
在此之前需要对解进行区分,当前解,领域解(领域中最优的解),候选解,全局最优解(也叫bestsofar)。以旅行商问题为例,当经过移动(随机交换2个城市的访问顺序)会产生,比好,就会升级成。
步骤1 生成初始解和置禁忌表tabu为空
步骤2 从当前解产生若干领域解,并确定若干候选解
步骤3 如果优于,则更新=和将对应的禁忌对象加入禁忌表tabu,否则基于禁忌表tabu从中选出次优解,更新和tabu
步骤4 更新=和基于藐视准则更新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
结果