優化算法之蟻羣算法

今天爲大家講解第三種啓發式優化算法——蟻羣算法。蟻羣算法是根據螞蟻覓食的行爲得到的一種優化算法,螞蟻在覓食的過程中會在行進的道路上留下信息素,信息素越濃,表示該條路徑到食物的距離越短,通過這種方式螞蟻可以快速找到大量的食物,下面給出通過蟻羣算法解決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

運行結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章