今天爲大家講解第三種啓發式優化算法——蟻羣算法。蟻羣算法是根據螞蟻覓食的行爲得到的一種優化算法,螞蟻在覓食的過程中會在行進的道路上留下信息素,信息素越濃,表示該條路徑到食物的距離越短,通過這種方式螞蟻可以快速找到大量的食物,下面給出通過蟻羣算法解決TSP問題的相關代碼:
function [R_best,RL_best,RL_average] = ACO(M,N,alpha,beta,Rho,Q,Distance)
%蟻羣算法
%{
輸入:
M:螞蟻個數
N:最大迭代次數
alpha:信息素因子
beta:啓發式因子
Rho:信息素揮發因子
Q:信息素增量
Distance:城市之間的距離
輸出:
R_best:每次循環的最優路徑
RL_best:每次循環的最優路徑長度
RL_average:每次循環的平均路徑
日期:
20190907_ZD
%}
Nc = size(Distance,1); %城市個數
Eta = 1./Distance;%啓發函數
T = ones(Nc,Nc);%信息素矩陣
Tabu = zeros(M,Nc);%禁忌表
R_best = zeros(N,Nc);%每次循環的最佳路徑
RL_best = inf.*ones(N,1);%每次循環最佳路徑的長度
RL_average = zeros(N,1);%每次循環最佳路徑的平均值
Count = 1;%循環計數器
%讓螞蟻進行循環
while Count <= N
%首先隨機將M個螞蟻分配到各個城市當中
RandPos = [];
for i = 1:(ceil(M/Nc))
RandPos = [RandPos,randperm(Nc)];%隨機生成大於螞蟻數量的城市編號
end
Tabu(:,1) = RandPos(1,1:M);%將螞蟻隨機分配到各個城市
%讓螞蟻開始周遊各個城市
for j = 2:Nc
for i = 1:M
Visited = Tabu(i,1:(j-1));%各個螞蟻已經訪問的城市
AllCity = 1:Nc;%全部城市編號
NotVisited = setdiff(AllCity,Visited);%未訪問城市編號(直接使用setdiff會增加代碼的計算量增加程序運行時間)
%計算選擇下一個城市的概率
for k = 1:length(NotVisited)
P(k) = (T( Visited(end),NotVisited(k) )^alpha ) * ( Eta( Visited(end),NotVisited(k) )^beta );%計算螞蟻選擇下一個城市的概率
end
%根據輪盤賭算法選擇下一個將要訪問的城市(今天德國總理默克爾來華科了,可惜去不了)
P = P / sum(P);
PSum = cumsum(P);
Select = find(PSum >= rand);
Tabu(i,j) = NotVisited(Select(1));
P = [];%清空概率值
end
end
%記錄本次周遊過程中尋找到的最優路徑
RL = zeros(M,1);
for i = 1:M
R(i,:) = [ Tabu(i,:) , Tabu(i,1) ];%將第一個城市加到路徑最後形成循環路徑
for j = 1:Nc
RL(i) = RL(i) + Distance(R(i,j),R(i,j+1));%計算循環路徑
end
end
[RL_best(Count),label] = min(RL);%最優路徑長度
R_best(Count,:) = Tabu(label,:);%最優路徑
if Count >= 2
if RL_best(Count,:) > RL_best(Count-1,:)
R_best(Count,:) = R_best(Count-1,:);
RL_best(Count) = RL_best(Count-1);
end
end
RL_average(Count) = mean(RL);
Count = Count + 1;
%更新信息素濃度
ChangeT = zeros(Nc,Nc);
for i =1:M
for j = 1:Nc
ChangeT(R(i,j),R(i,j+1)) = ChangeT(R(i,j),R(i,j+1)) + Q/RL(i);
end
end
%信息素揮發
T = (1-Rho).*T+ChangeT;%信息素更新方法是蟻周模型,還有蟻密模型和蟻量模型
%第一週完後,對禁忌表進行清除
Tabu = zeros(M,Nc);
end
[ShortestRL,Label] = min(R_best);
ShortestR = R_best(Label,:);
function Distance = CalDistance(C)
%計算城市之間的距離
%{
輸入:
C:城市座標
輸出:
Distance:城市之間的距離矩陣
日期:
20190907
%}
Nc=size(C,1);%n表示問題的規模(城市個數)
Distance=zeros(Nc,Nc);%D表示完全圖的賦權鄰接矩陣
for i=1:Nc
for j=1:Nc
if i~=j
Distance(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
else
Distance(i,j)=eps; %i=j時不計算,應該爲0,但後面的啓發因子要取倒數,用eps(浮點相對精度)表示
end
Distance(j,i)=Distance(i,j); %對稱矩陣
end
end
運行結果: