1. 程式人生 > >MATLAB蟻群演算法TSP詳細註釋

MATLAB蟻群演算法TSP詳細註釋

某大神寫的MATLAB蟻群演算法解TSP程式,自己看了好久才看懂,所以加上了更加詳細的註釋,借花獻佛了吧

實現函式

function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ACATSP(C,NC_max,m,Alpha,Beta,Rho,Q)
%%-------------------------------------------------------------------------
%% 主要符號說明
%% C n個城市的座標,n×2的矩陣
%% NC_max 最大迭代次數
%% m 螞蟻個數
%% Alpha 表徵資訊素重要程度的引數
%% Beta 表徵啟發式因子重要程度的引數
%% Rho 資訊素蒸發係數
%% Q 資訊素增加強度係數
%% R_best 各代最佳路線
%% L_best 各代最佳路線的長度
%%=========================================================================
%%第一步:變數初始化
n=size(C,1);%n表示問題的規模(城市個數)
D=zeros(n,n);%D表示完全圖的賦權鄰接矩陣
for i=1:n
for j=i:n %計算一半間距,因為是對稱矩陣
if 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;      %i=j時不計算,應該為0,但後面的啟發因子要取倒數,用eps(浮點相對精度)表示
end
D(j,i)=D(i,j);   %對稱矩陣
end
end
Eta=1./D;          %Eta為啟發因子,這裡設為距離的倒數
Tau=ones(n,n);     %Tau為資訊素矩陣,任意一條路徑
Tabu=zeros(m,n);   %儲存並記錄路徑的生成,m只螞蟻的路徑,一條路徑即n個城市的排序
NC=1;               %迭代計數器,記錄迭代次數
R_best=zeros(NC_max,n);       %各代最佳路線,NC_max次迭代
L_best=inf.*ones(NC_max,1);   %各代最佳路線的長度, infinity無窮大,初始值為無窮大
L_ave=zeros(NC_max,1);        %各代路線的平均長度
%%開始迭代計算
while NC<=NC_max        %停止條件之一:達到最大迭代次數,停止
%%第二步:將m只螞蟻放到n個城市上
Randpos=[];   %隨即存取
for i=1:(ceil(m/n))     %
Randpos=[Randpos,randperm(n)];  %randperm,n個最大值為n的正整數的隨機排列,得到ceil(m/n)個1-n的隨機排列。即螞蟻被平均隨機分配到個城市
end
Tabu(:,1)=(Randpos(1,1:m))';    %螞蟻初位置,各螞蟻被平均隨機分配到個城市
%%第三步:m只螞蟻按概率函式選擇下一座城市,完成各自的周遊;第i螞蟻開始選擇訪問第j城市
for j=2:n     %所在城市不計算
for i=1:m     %每隻螞蟻分別計算
visited=Tabu(i,1:(j-1)); %記錄當前只螞蟻已訪問的城市,避免重複訪問
J=zeros(1,(n-j+1));      %設定陣列,記錄待訪問的城市
P=J;                     %對於當前螞蟻,待訪問城市的選擇概率分佈
Jc=1;
for k=1:n
if length(find(visited==k))==0   %開始時,螞蟻還未訪問的城市,放入待訪問矩陣
J(Jc)=k;
Jc=Jc+1;                         %訪問的城市個數自加1
end
end
%下面計算待選城市的概率分佈,第k個城市
for k=1:length(J)
P(k)=(Tau(visited(end),J(k))^Alpha)*(Eta(visited(end),J(k))^Beta);%visited(end)當前所在城市
end
P=P/(sum(P));
%按概率原則選取下一個城市
Pcum=cumsum(P);     %cumsum,0-1的區間上按概率分配區間的大小
Select=find(Pcum>=rand); %rand 0-1隨機數,隨機數落在哪個區間就選擇哪個城市  %這個方法厲害厲害了
to_visit=J(Select(1));
Tabu(i,j)=to_visit; %記錄i螞蟻訪問的j城市·
end
end
if NC>=2
Tabu(1,:)=R_best(NC-1,:);
end
%%第四步:記錄本次迭代最佳路線
L=zeros(m,1);     %開始距離為0,m*1的列向量
for i=1:m
R=Tabu(i,:);
for j=1:(n-1)
L(i)=L(i)+D(R(j),R(j+1));    %原距離加上第j個城市到第j+1個城市的距離
end
L(i)=L(i)+D(R(1),R(n));      %一輪下來後走過的距離
end
L_best(NC)=min(L);           %最佳距離取最小
pos=find(L==L_best(NC));     %讀出最佳螞蟻,可能有幾個
R_best(NC,:)=Tabu(pos(1),:); %此輪迭代後的最佳路線
L_ave(NC)=mean(L);           %此輪迭代後的平均距離
NC=NC+1                      %迭代繼續
%%第五步:更新資訊素
Delta_Tau=zeros(n,n);        %開始時資訊素為n*n的0矩陣
for i=1:m
for j=1:(n-1)
Delta_Tau(Tabu(i,j),Tabu(i,j+1))=Delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);          
%此次迴圈在路徑(i,j)上的資訊素增量,第i螞蟻的資訊素在路徑上平均分配
end
Delta_Tau(Tabu(i,n),Tabu(i,1))=Delta_Tau(Tabu(i,n),Tabu(i,1))+Q/L(i);
%此次迴圈在整個路徑上的資訊素增量
end
Tau=(1-Rho).*Tau+Delta_Tau; %考慮資訊素揮發,更新後的資訊素
%%第六步:禁忌表清零
Tabu=zeros(m,n);             %%直到最大迭代次數
end
%%第七步:輸出結果
Pos=find(L_best==min(L_best)); %找到最佳路徑(非0為真)
Shortest_Route=R_best(Pos(1),:) %最大迭代次數後最佳路徑
Shortest_Length=L_best(Pos(1)) %最大迭代次數後最短距離
subplot(1,2,1)                  %繪製第一個子圖形
DrawRoute(C,Shortest_Route)     %畫路線圖的子函式
subplot(1,2,2)                  %繪製第二個子圖形
plot(L_best)
hold on                         %保持圖形
plot(L_ave,'r')
title('平均距離和最短距離')     %標題
function DrawRoute(C,R)
%%=========================================================================
%% DrawRoute.m
%% 畫路線圖的子函式
%%-------------------------------------------------------------------------
%% C Coordinate 節點座標,由一個N×2的矩陣儲存
%% R Route 路線
%%=========================================================================
N=length(R);
scatter(C(:,1),C(:,2));
hold on
plot([C(R(1),1),C(R(N),1)],[C(R(1),2),C(R(N),2)],'g')
hold on
for ii=2:N
plot([C(R(ii-1),1),C(R(ii),1)],[C(R(ii-1),2),C(R(ii),2)],'g')
hold on
end
title('旅行商問題優化結果 ')

具體呼叫

C=[0,0,2,4,4,6,8,8,3,4,6,3;
   0,8,4,0,6,4,0,8,3,7,7,9];
C=C';
NC_max=400;
m=32;
Alpha=1;
Beta=1;
Rho=0.2;
Q=20;
ACATSP(C,NC_max,m,Alpha,Beta,Rho,Q);