蚁群算法应用之tsp

%算法的第一步是先初始化
clear 
m=50;                                   %蚂蚁总数
alpha=1;                                %信息度启发因子
beta=2;                                 %期望值启发式因子
Rho=0.6;                                %信息素挥发因子 
NC_max=100;                             %最大循环次数
Q=80;                                   %信息素增量     
C=[5.326,2.558;
   4.276,3.452; 
   4.819,2.624; 
   3.165,2.457;
   0.915,3.921;
   4.637,6.026; 
   1.524,2.261;
   3.447,2.111;
   3.548,3.665; 
   2.649,2.556;
   4.399,1.194;
   4.660,2.949; 
   1.479,4.440; 
   5.036,0.244;
   2.830,3.140;
   1.072,3.454;
   5.845,6.203;
   0.194,1.767;
   1.660,2.395;
   2.682,6.072];%20个城市
% 初始化
n=size(C,1);                            %表示n个城市    取C的行数20
D=zeros(n,n);                           %全是0的20阶矩阵
for i=1:n
    for j=1:n
        if i~=j                         %表示同一个城市之间的距离不存在    i!=j
        D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
        else
         D(i,j)=eps;			%eps≈0,无限小
        end
       % D(j,i)=D(i,j);
    end
end
Eta=1./D;                               %城市与城市之间的能见度,在基于概率转移时用到这个参数   D内元素全部取倒数
Nc=1;                                   %循环计数器
Tau=ones(n,n);                          %信息素浓度矩阵——n*n的单位阵  20*20
Tabu=zeros(m,n);                        %禁忌表  ——m*n的零阵   50*20
Road_best=zeros(NC_max,n);              %每次循环最佳路径 最大循环次数*n个城市零阵 	0 		 100*20
Roadlength_best=inf.*ones(NC_max,1);    %每次循环最佳路径的长度  最大循环次数*1 单位阵 		值为无限大100*1		
Roadlength_ave=zeros(NC_max,1);         %每次循环的路径的平均值		100*1
%将蚂蚁随机分布在n个城市
while Nc<=NC_max                        %小于最大循环次数就继续执行100
    randpos=[];                        
    for i=1:(ceil(m/n))                 %分多少次将蚂蚁分布完   1-3
        randpos=[randpos,randperm(n)];  %循环产生的是20个城市的随机数,一行60个1-20的随机数
    end
    Tabu(:,1)=(randpos(1,1:m));         %取前m个城市编号		Tabu所有行第一列的值为randpos第一行前50列的值
tabu=[2 0 0 0''''0 0;
	  	  4 0 0 0''''0 0;
	  	  ''''	50*20
          7 4 0 0''''0 0;
          8 6 0 0''''0 0;]
%j=2结束后更新禁忌表          
    tabu=[2 3 0 0''''0 0;
	  	  4 1 0 0''''0 0;
	  	  ''''	50*20
          7 4 0 0''''0 0;
          8 6 0 0''''0 0;]
%每只蚂蚁基于概率选择转移去下一个j城市    
    for j=2:n                           %从第二个城市开始选择	2-20	     j=2	j=3
        for i=1:m                      		1-50			i=1	i=2
            visited=Tabu(i,1:(j-1));    %表示已经经过的城市,初始化是出发城市	Tabu(1,1:1)	一行一行走 	visited=2	visited=4		Tabu(1,1:2)			visited=2	3
            J=zeros(1,(n-j+1));         %存放还没有经过的城市  1*19的零阵	1*18的零阵
            P=J;                        
            Jc=1;                      %Jc是J数组的下标
            for k=1:n                   %1-20
                if length(find(visited==k))==0  %查找已经经过的城市里面有没有k			在vistited中找到k,返回一维坐标,length求返回的数列长度
		      		J(Jc)=k;            %没有的话,就把城市k记录进未经过城市矩阵里面	j=2i=1时 J=1,3,4....,20 	i=2时J=1,2,3,5,.....20	j=3 i=1 时J=1,4....,20
		            Jc=Jc+1;           
		        end
		    end
%计算待选城市的概率
           for k=1:length(J)            %1-19		1-18
               P(k)=(Tau(visited(end),J(k))^alpha)*(Eta(visited(end),J(k))^beta);  	%end是矩阵中最后一个	P为1*19的零阵Tau(2,1)*Eta(2,1)....Tau(2,20)*Eta(2,20)				Tau(4,1)*Eta(4,1)	....Tau(4,19)*Eta(4,19)		Tau(3,1)*Eta(3,1)	....Tau(3,20)*Eta(3,20)		
               %目前经过的城市到下一个所有城市的概率大小
           end
           P=P/sum(P);			%P内19个元素均为概率
           %按照概率选取下一个城市
           Pcum=cumsum(P);              %按行累加
           select=find(Pcum>=rand);     %大扇面被选中的概率大,同时小扇面也有被选中的可能
           to_visit=J(select(1));      %返回第一个选中的扇面即城市号
          %j一轮结束后更新禁忌表        
           Tabu(i,j)=to_visit;          %禁忌表将第一只蚂蚁的第二个城市号记录下来	 Tabu(1,2)	Tabu(2,2)		Tabu(1,3)
        end
    end
    if Nc>=2                           
        Tabu(1,:)=Road_best(Nc-1,:);     %Tabu第一行取上一次的最优路径
    end
%记录本次迭代最佳路线
  L=zeros(m,1);		%50*1		50个距离
  for i=1:m		%1-50
      R=Tabu(i,:);                      %第一只蚂蚁的路线赋给矩阵R		1*20
      for j=1:(n-1)           %1-19          
          L(i)=L(i)+D(R(j),R(j+1));     %每一只蚂蚁所走的路径长度
      end
      L(i)=L(i)+D(R(1),R(n));           %加上最后一个点到起始点的路径
  end
  Roadlength_best(Nc)=min(L);           %本次循环的所有路径中的最短路径放在Roadlength_best中
  pos=find(L==Roadlength_best(Nc));     %在50个蚂蚁中找出最短路径的所有蚂蚁	蚂蚁号的集合
  Road_best(Nc,:)=Tabu(pos(1),:);       %只取第一只最短路径蚂蚁的路径		1*20		最终100*20
  Roadlength_ave(Nc)=mean(L);           %本次循环所有路径的平均值 	mean取列的平均值		1*1	最终100*1
  Nc=Nc+1;                              
  % 跟新信息素
  delta_Tau=zeros(n,n);                %20*20
  for i=1:m                             %1-50
      for j=1:(n-1)				%1-19
          delta_Tau(Tabu(i,j),Tabu(i,j+1))=delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);			%delta_Tau(Tabu(1,1),Tabu(1,2))=delta_Tau(Tabu(1,1),Tabu(1,2))+Q/L(1);		delta_Tau(Tabu(1,2),Tabu(1,3))=delta_Tau(Tabu(1,2),Tabu(1,3))+Q/L(1);		delta_Tau(Tabu(1,19),Tabu(1,20))=delta_Tau(Tabu(1,19),Tabu(1,20))+Q/L(1);
      end
      delta_Tau(Tabu(i,n),Tabu(i,1))=delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);		%此时j=19		delta_Tau(Tabu(1,20),Tabu(1,1))=delta_Tau(Tabu(1,19),Tabu(1,20))+Q/L(1);
  end
  Tau=(1-Rho).*Tau+delta_Tau;          %这里运用的是蚁周模型         点乘		注意Tau的用法是双参决定路线浓度
% 禁忌表清零                                 
  Tabu=zeros(m,n);                   
end
pos=find(Roadlength_best==min(Roadlength_best));	%将最短的最优路径的所有下标取出
shortest_route=Road_best(pos(1),:);			%20个城市号		1*20			5( 0.915,3.921) 	7	9	12	19	8	4	17。。。。2	13	15(2.830,3.140)
shortest_length=Roadlength_best(pos(1));		%路线长度
 
figure(1)		%创建窗口
subplot(1,2,1)	%画在一行两列的两幅图中的第一幅
N=length(R);	%N=20
scatter(C(:,1),C(:,2));	%画散点图
hold on	%你在当前图的轴(坐标系)中画了一幅图,再画另一幅图时,原来的图还在,与新图共存,都看得到
plot([C(shortest_route(N),1),C(shortest_route(1),1)],[C(shortest_route(N),2),C(shortest_route(1),2)],'g');		%生成的图形是以序号为横坐标、数组y的数值为纵坐标画出的折线	plot([2.830,0.915],[3.140,3.921],'g')	g是绿色
hold on
for ii=2:N
    plot([C(shortest_route(ii-1),1),C(shortest_route(ii),1)],[C(shortest_route(ii-1),2),C(shortest_route(ii),2)],'g');
    hold on
end
grid on	%打开网格
title('TSP问题优化结果');
xlabel('x')
ylabel('y')
subplot(1,2,2)		%画在一行两列的两幅图中的第二幅
plot(Roadlength_best)
hold on
plot(Roadlength_ave)
grid on
title('平均距离与最短距离')
legend('Roadlength\_best','Roadlength\_ave')	%用指定的文字string在当前坐标轴中对所给数据的每一部分显示一个图例
xlabel('cycle-index')
ylabel('length')

你可能感兴趣的:(蚁群算法应用之tsp)