700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 禁忌搜索算法(tabu search)解决TSP及其Matlab代码

禁忌搜索算法(tabu search)解决TSP及其Matlab代码

时间:2023-02-18 18:27:47

相关推荐

禁忌搜索算法(tabu search)解决TSP及其Matlab代码

1、算法简介

禁忌搜索算法TS(Tabu search),顾名思义核心在于“禁忌”,简单来说就是在某一个过程中把一些不太好的操作给禁止了,直到搜索到一个“最优秀”的。它是在1986年由美国Fred Glover教授提出的,主要是为了提高寻优过程中的全面搜索的能力。

禁忌搜索算法通过模拟人类智能的记忆特点,引入存储结构和相应的禁忌准则来避免迂回循环,通过特赦准则来释放禁忌表中较优的个体,进而保证多样性的搜索来尽可能达到问题的最优解。

2、算法核心概念

禁忌表(TabuList):是用来存放禁忌对象的表。它是TS算法的核心,禁忌表的值在每一次迭代过程中都会完成一次更新。禁忌对象可以是TSP中的路径长度、城市顺序等等。

禁忌长度(TabuLength):禁忌表中存放的数值即为禁忌长度,它规定了禁忌对象的生存时间,一旦达到其禁忌长度,则会被解除禁忌状态。禁忌长度的选取有静态和动态选取两种方法,静态选取会事先固定禁忌长度,而动态选取则会根据迭代过程而发生变化。

特赦准则:是在搜索过程中,发现有解比当前最优解更优时执行替换最优解的操作,或者在搜索过程中全部候选解都在“禁忌”状态,能够释放特定解的操作。

领域解:在初始解的基础上,按照一定的方向对初始解进行移动所形成的新解,称为领域解。不重复的移动次数称为领域的规模。

候选解:候选解就是领域解中较为优秀的一部分解。若候选解所选的规模较小,算法则会过早收敛,造成局部最优解的情况,若候选解所选规模较大,算法则会浪费较多的时间和空间来搜索最优解。

3、算法流程

禁忌搜索算法的一般流程如下:

(1)初始化TS算法的参数,按照准则生成问题的初始解,生成0禁忌表;

(2)判断是否满足终止条件,若是,则结束算法,输出结果

(3)根据算法的特性生成领域解,并从中选择合适规模大小的候选解;

(4)判断候选解中的最优解Next是否满足特赦准则,若满足特赦准则,则用Next替代当前最优解Before,并更新禁忌表,令Next对应的禁忌对象的禁忌长度为最长,即禁忌时间最长;若不满足特赦准则,进行(4)步骤;

(5)判断候选解中禁忌状态情况,找出候选解中处于“非禁忌”状态的禁忌对象,并把该禁忌对象对应的解赋给当前最优解,同时设置该禁忌对象的禁忌时间为最长;

(6)转(2);

4、实例及Matlab代码

接下来,利用Tabu Search算法来解决TSP问题。假设有48个随机分布的城市如下图所示,一个旅行商从一个城市出发,遍历完所有城市,要求其旅行距离最短。在这一过程中,禁忌对象为互换城市对,就是在解中把两个城市的位置调换。

function TspTBout = TSPTabusearch(xy,dmat,TabuLength,IterNum,showProg,showResult)%运用禁忌搜索算法解决TSP问题nargs = 6;%检查函数输入for i = nargin:nargs-1 %nargin代表函数已输入参数个数switch i case 0 %产生城市坐标xy =[488,814;1393,595;2735,2492;4788,4799;4825,1702;789,2927;4853,1120;4786,3757;2427,1276;4002,2530;710,3496;2109,4455;4579,4797;3962,2737;4798,694;3279,747;179,1288;4246,4204;4670,1272;3394,4072;3789,1218;3716,4647;1962,1750;3278,983;856,1256;3531,3081;160,2367;1385,1759;231,4155;486,2927;4118,2749;3475,4586;1586,1430;4752,3787;173,3769;2194,1903;1908,2840;3828,380;3976,270;935,2654;2449,3896;2228,4671;3232,650;3547,2845;3774,2347;1381,60;3399,1686;3276,811];case 1%计算距离矩阵N = size(xy,1);a =meshgrid(1:N);%生成N*N升序矩阵dmat = reshape(sqrt(sum((xy(a,:)-xy(a',:)).^2,2)),N,N);% '为矩阵的转置,reshape把数据生成N*N的矩阵case 2%设置禁忌长度(禁忌时间)TabuLength = round((N*(N-1)/2)^0.5);%round四舍五入case 3%设置迭代次数IterNum = 1e3;case 4%是否展示迭代过程showProg = 1;case 5%是否展示最终结果showResult = 1;otherwiseendend%对输入参数进行检查[N,~] = size(xy);%城市个数、维数[nr,nc] = size(dmat);%距离矩阵的行数和列数if N~=nr || N~=ncerror('城市坐标或距离矩阵输入有误')endshowProg = logical(showProg(1));%将数值转变为逻辑值showResult = logical(showResult(1));%画出城市位置分布图figure(1);plot (xy(:,1),xy(:,2),'k.');title('城市坐标位置');%% 禁忌搜索算法参数设置TabuList = zeros(N);%禁忌表设置为城市互换对,为N*N的矩阵,矩阵中的值代表禁忌长度,初始禁忌长度为0CandidatesNum = 200; %领域解的个数,由领域解选出候选解Candidates = zeros(CandidatesNum,N);%领域解集合S0 = randperm(N);%随机产生一个初始解Broute = S0;%当前最佳的路劲Bdist = Inf;%当前最佳路径总距离BLHistory = zeros(IterNum,1);%记录最优路径长度%% 禁忌搜索循坏for iter = 1:IterNum%% 以下生成城市互换对矩阵Twocity[200,2]Twocity = zeros(CandidatesNum,2);i = 1;while i<= CandidatesNumM = ceil(N*rand(1,2));%随机生成两个城市序号if M(1) ~= M(2)Twocity(i,1) = max(M(1),M(2));%最小值存在1,最大值存在2Twocity(i,2) = min(M(1),M(2));if i ==1isa = 0;%是否生成相同的城市互换对,1为生成了elsefor j = 1:i-1if Twocity(i,1)==Twocity(j,1)&&Twocity(i,2)==Twocity(j,2)%若相同isa =1;break;elseisa =0;endendendif ~isa %若生成的城市对与之前的都不相同则可以继续生成城市对i =i+1;endendend%% 产生领域解,选取前100个为候选解 %保留前100个最好领域解为候选解BestCandNum = 100;%定义一个表格,四列,分别存储领域解序号i,路径长度L(i),Twocity(i,1),Twocity(i,2)BCandidate = Inf * ones(BestCandNum,4);L = zeros(1,CandidatesNum);%相当于产生一个S0的解,包含有200个领域解,从中找出最佳的100个才是候选解for i = 1:CandidatesNumCandidates(i,:) = S0;%领域解Candidates(i,[Twocity(i,2),Twocity(i,1)]) = S0([Twocity(i,1),Twocity(i,2)]);%在当前解S0上交换两个城市的位置%计算当前领域解路径的距离L(i) = CalDistofS(dmat,Candidates(i,:));%选出100个最好的领域解充当候选解if i<= BestCandNumBCandidate(i,1) = i;BCandidate(i,2) = L(i);BCandidate(i,3) = S0(Twocity(i,1));BCandidate(i,4) = S0(Twocity(i,2));elsefor j =1:BestCandNumif L(i) < BCandidate(j,2)%领域解超出100个,则需要比较选取较小距离的BCandidate(j,1) = i;BCandidate(j,2) = L(i);BCandidate(j,3) = S0(Twocity(i,1));BCandidate(j,4) = S0(Twocity(i,2));break;endendendend%根据距离,对候选解进行排序[~,Index] = sort(BCandidate(:,2));%Index是BCandidate中距离升序排列后的索引SBest = BCandidate(Index,:);BCandidate = SBest;% 此时的BCandidate是按第二列路径长度升序排列的%% 特赦准则是否满足,更新禁忌表if BCandidate(1,2)< Bdist%如果小于当前最优Bdist = BCandidate(1,2);%当前最优解变为候选解中的第BCandidate(1,1)行S0 = Candidates(BCandidate(1,1),:);Broute = S0;for m = 1:Nfor n = 1:Nif TabuList(m,n) ~=0TabuList(m,n) = TabuList(m,n) -1;%更新禁忌表,禁忌长度减1endendendTabuList(BCandidate(1,3),BCandidate(1,4)) = TabuLength;%更新禁忌表else %若没有找到比当前最优解更好的解for i = 1:BestCandNumif TabuList(BCandidate(i,3),BCandidate(i,4)) == 0%如果已经解禁了S0 = Candidates(BCandidate(i,1),:);for m = 1:Nfor n = 1:Nif TabuList(m,n) ~=0TabuList(m,n) = TabuList(m,n) -1;%更新禁忌表,禁忌长度减1endendendTabuList(BCandidate(i,3),BCandidate(i,4)) = TabuLength;%更新禁忌表break;endendend%更新当前最好解的距离值BLHistory(iter,1) = Bdist;if showProgfigure(2);for i = 1:(N-1)plot([xy(Broute(i),1),xy(Broute(i+1),1)],[xy(Broute(i),2),xy(Broute(i+1),2)],'bo-');%画出路线图hold on;endplot([xy(Broute(N),1),xy(Broute(1),1)],[xy(Broute(N),2),xy(Broute(1),2)],'ro-');%画出终点到起点的线title(['迭代次数:', num2str(iter),'最短距离:',num2str(Bdist)]);hold off;endendif showResultBestroute = Broute;MinLength = Bdist;figure(3);plot(BLHistory,'b');%画出最优路径长度与迭代次数的关系xlabel('迭代次数');ylabel('当前最优路径长度');title('最优路径长度变化曲线图');grid;hold on; endif nargout%如果需要输出结果TspTBout{1} = Bestroute;TspTBout{2} = MinLength;endfunction L = CalDistofS(dmat,S)dist = 0;n = size(S,2);for k = 1:(n-1)dist = dist +dmat(S(k),S(k+1));%中间路径的距离endL = dist + dmat(S(n),S(1));%回到起点的距离endend

由于代码有较多的注释,就不在解释太多了,直接上结果图吧!

若有小伙伴对机器人任务分配算法较为兴趣的,可以在下面评论交流一波,纯属互相学习!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。