禁忌搜索算法求解TSP

TS算法求解TSP问题的matlab代码

本文的禁忌搜索算法是最经典禁忌搜索算法,可以在此基础上进行修改和扩展

主函数

%Author:Chauncy_xu
%Date:2020年4月1日
clc;
clear all;
close all;
[len_side,city]=City;
num_city=size(city,1);%城市数目
gen=1;                                         %记录迭代次数
Num_gen=1000;                                   %最大迭代次数
pop0=randperm(num_city);                       %随机产生初始解
%% 禁忌表设置
TabuList=zeros(num_city);                      %禁忌表
len_Tabu=100;%禁忌表长度
%% 迭代准备
num_candi=400;                                 %全部领域解个数,不能超过30*29/2
candi=zeros(num_candi,num_city);               %邻域集合
best_pop=pop0;                                 %当前最优解
best_dis=Inf;                                  %当前最佳解距离
now_fit=zeros(1,Num_gen);
mem_best=zeros(1,Num_gen); %用于记录每一代的最优值
%% 迭代
while gen<=Num_gen
    now_fit(gen)=Fitness(len_side,pop0);      %当前解适配值
    move=zeros(num_candi,2);          % 准备所有可能的移动城市,200行2列
    %% 产生指定个数的候选解
    %选择邻域的真子集为候选解集
    i=1;%对候选解进行遍历
    while i<=num_candi         %生成随机的200 X 2 的矩阵矩阵,作为邻域
        M=ceil(num_city*rand(1,2));%M是1-30之间的两个正整数
        while M(1)==M(2)
            M(2)=ceil(num_city*rand());%M1M2禁止重复
        end
        move(i,1)=M(1);
        move(i,2)=M(2);
        %% 保证所有的邻域解互不相同
        if i==1
            flag=0;
        else
            for j=1:i-1
                if (move(i,1)==move(j,1) && move(i,2)==move(j,2)) || (move(i,1)==move(j,2) && move(i,2)==move(j,1))
                    flag=1;
                    break;
                else
                    flag=0;
                end
            end
        end 
        if ~flag
            i=i+1;
        end            
    end
    %% 选取一个解邻域的真子集作为候选解
    num_bestcandi=100;%只保留前100个最好候选解
    bestcandi=Inf*ones(num_bestcandi,4);%记录保留的100个候选解的信息
    fit=zeros(1,num_candi);  
    for i=1:num_candi
        candi(i,:)=pop0;  %候选解集合
        candi(i,[move(i,2),move(i,1)])=pop0([move(i,1),move(i,2)]);%进行移动
        fit(i)=Fitness(len_side,candi(i,:));%计算该候选解的适应度值
        if i<=num_bestcandi
            bestcandi(i,2)=fit(i);%第二列存放适应度值
            bestcandi(i,1)=i;%第一列存放序号
            bestcandi(i,3)=pop0(move(i,1));%第三列第四列存放交换的位置
            bestcandi(i,4)=pop0(move(i,2));   
        else
            for j=1:num_bestcandi
                if fit(i)<bestcandi(j,2)
                    bestcandi(j,2)=fit(i);
                    bestcandi(j,1)=i;
                    bestcandi(j,3)=pop0(move(i,1));
                    bestcandi(j,4)=pop0(move(i,2));
                    break;
                end            
            end
        end
    end
    %% 把候选解按照适应度值的升序进行排列
    [~,Index]=sort(bestcandi(:,2)); 
    temp=bestcandi(Index,:);
    bestcandi=temp;
    %% 破禁准则
      if bestcandi(1,2)<best_dis
        best_dis=bestcandi(1,2);%更新当前搜索到的最优值
        pop0=candi(bestcandi(1,1),:); %选择最优解作为当前解     
        best_pop=pop0;               %更新截止目前的最优解
        for m=1:num_city
            for n=1:num_city
                if TabuList(m,n)~=0
                    TabuList(m,n)=TabuList(m,n)-1;      % 更新禁忌表
                end
            end
        end
        TabuList(bestcandi(1,3),bestcandi(1,4))=len_Tabu;   % 更新禁忌表
      else  
        for i=1:num_bestcandi
            if  TabuList(bestcandi(i,3),bestcandi(i,4))==0
            pop0=candi(bestcandi(i,1),:);                
            for m=1:num_city
                for n=1:num_city
                    if TabuList(m,n)~=0
                        TabuList(m,n)=TabuList(m,n)-1;                % 更新禁忌表
                    end
                end
            end        
            TabuList(bestcandi(i,3),bestcandi(i,4))=len_Tabu;       % 更新禁忌表
            break;
            end
        end
      end
    mem_best(gen)=best_dis; %记录每一代的最优值
    gen=gen+1; 
end
%% 输出运行结果
best_pop                           %最佳路线
best_dis 
%figure(2);
plot(mem_best,'k');
xlabel('迭代次数');
ylabel('目标函数值');
title('最小目标函数值变化曲线');
grid;
hold on;

适应值函数

function fit=Fitness(len_side,pop)   
f=0;
len=size(pop,2);
for i=1:(len-1)
    f=f+len_side(pop(i),pop(i+1));
end
    f=f+len_side(pop(len),pop(1));      
fit=f;

City函数

function fit=Fitness(len_side,pop)   
f=0;
len=size(pop,2);
for i=1:(len-1)
    f=f+len_side(pop(i),pop(i+1));
end
    f=f+len_side(pop(len),pop(1));      
fit=f;
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值