%算法的第一步是先初始化
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')