蟻羣算法(包含TSP問題的matlab代碼實現)

蟻羣算法(ACA , Ant Colony Algorithm)

1 算法背景

 蟻羣算法是由Marco Dorigo於1992年在他的博士論文中提出,其靈感來源於螞蟻在尋找食物過程中發現路徑的行爲。蟻羣算法是一種用來尋找優化路徑的概率型算法,本質上是進化算法中的一種啓發式全局優化算法。

 在螞蟻覓食的過程中,單個螞蟻行爲比較簡單,你可能發現不了什麼特別的,但是整個蟻羣的行爲卻整體體現出了一些智能。蟻羣可以在不同的環境中,尋找到最短到達食物源的路徑。在找食物的過程中,螞蟻會在走過的路徑中釋放一種“信息素”的物質,用來標識自己的行走路徑,螞蟻具有感知能力,會沿着信息素濃度高的路徑行走。而每個螞蟻走過都會釋放信息素,這也就是一種正反饋機制,信息素越濃,走的螞蟻越多,走的螞蟻越多,信息素越濃,最後整個蟻羣都會沿着最短的路徑尋找食物。

2 算法思想

        蟻羣算法的基本思想就是選擇信息素濃度最大的路徑走,碰到還沒走過的路,就隨機挑選一條路走。用螞蟻行走的路徑表示待優化問題的可行解,整個螞蟻羣體的所有路徑構成待優化問題的解空間。我們可以理解爲螞蟻的信息素含量在一次覓食過程中是一定量的,路徑越長,信息素的含量濃度越小,路徑越短,信息素的濃度越大。隨着時間的推移以及正反聵機制,路徑最短的信息素濃度會越來越大,最終整個蟻羣都會集中到最佳的路徑上,也就是待優化問題的最優解。

3 算法步驟

蟻羣算法的步驟可以歸納爲:

(1)對相關參數進行初始化;
(2)隨機將螞蟻放於不同出發點,對每個螞蟻計算其下個訪問城市,直到有螞蟻訪問完所有城市。
(3)計算各螞蟻經過的路徑長度,記錄當前迭代次數最優解,同時對路徑上的信息素濃度進行更新。
(4)判斷是否達到最大迭代次數,若否,返回步驟2;是,結束程序。
(5)輸出結果,並根據需要輸出尋優過程中的相關指標。

算法流程圖如下:

 

4 算法應用

蟻羣算法主要用來解決路徑規劃等離散優化問題,如調度問題、旅行商問題等。下面以旅行商問題爲例,進行詳細的介紹:

旅行商問題即TSP問題(Travelling Salesman Problem,TSP)又譯爲旅行推銷員問題、貨郎擔問題,是數學領域中著名問題之一。

TSP問題:假設有一個旅行商人要拜訪n個城市,需選擇一條路線,要求所有城市走一遍回到起點,同時使所走路程最短。

(可以提取出來關鍵信息:每個結點只能走一次;所有結點必須經過;最短路徑;最後回到起點)

5 算法實現

解決的問題:一個旅行商人要拜訪全國31個省會城市,需要選擇最短一條路線,要求所有城市走一遍回到起點。以座標的形式記錄城市的位置數據。

使用蟻羣算法,用matlab實現TSP問題代碼如下:

%% 解決的問題:一個旅行商人要拜訪全國31個省會城市,需要選擇最短的路徑
clear all; 
close all;
clc ;   
%% 第一步:變量初始化
m=50;    % m 螞蟻個數
Alpha=1;  % Alpha表徵信息素重要程度的參數
Beta=5;  %Beta表徵啓發式因子重要程度的參數
Rho=0.1; % Rho信息素蒸發係數
NC_max=200; %最大迭代次數
Q=100;         %信息素增加強度係數

C=[
1304 2312;
3639 1315;
4177 2244;
3712 1399;
3488 1535;
3326 1556;
3238 1229;
4196 1004;
4312 790;
4386 570;
3007 1970;
2562 1756;
2788 1491;
2381 1676;
1332 695;
3715 1678;
3918 2179;
4061 2370;
3780 2212;
3676 2578;
4029 2838;
4263 2931;
3429 1908;
3507 2367;
3394 2643;
3439 3201;
2935 3240;
3140 3550;
2545 2357;
2778 2826;
2370 2975
];    %31個省會座標數據
% R_best 各代最佳路線
% L_best 各代最佳路線的長度
n=size(C,1);%n個城市
D=zeros(n,n);%D表示完全圖的賦權鄰接矩陣

%% 計算每個城市之間的距離
for i=1:n
    for j=1: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);   %存儲並記錄路徑的生成
NC=1;               %迭代計數器,記錄迭代次數
R_best=zeros(NC_max,n);       %各代最佳路線
L_best=inf.*ones(NC_max,1);   %各代最佳路線的長度  %inf 正無窮
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)產生1-n的隨機數
    end
    Tabu(:,1)=(Randpos(1,1:m))';   %將路徑矩陣裏面的第一列隨機初始到一個城市
    
    %第三步:m只螞蟻按概率函數選擇下一座城市,完成各自的周遊
    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   %開始時置0
                    J(Jc)=k;
                    Jc=Jc+1;                         %訪問的城市個數自加1
                end
            end
            %下面計算待選城市的概率分佈
            for k=1:length(J)
                P(k)=(Tau(visited(end),J(k))^Alpha)*(Eta(visited(end),J(k))^Beta);
            end
            P=P/(sum(P));
            %按概率原則選取下一個城市
            Pcum=cumsum(P);     %cumsum,元素累加即求和
            Select=find(Pcum>=rand); %若計算的概率大於原來的就選擇這條路線
            to_visit=J(Select(1));
            Tabu(i,j)=to_visit;
        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)上的信息素增量
        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)); %找到最佳路徑
Shortest_Route=R_best(Pos(1),:) %最大迭代次數後最佳路徑
Shortest_Length=L_best(Pos(1)) %最大迭代次數後最短距離

figure(1) 
plot(L_best)
xlabel('迭代次數')
ylabel('最短路徑長度')
title('每代最短路徑長度進化曲線')

figure(2)
%繪製第一個子圖形,路線圖
subplot(1,2,1)                 
N=length(Shortest_Route);
scatter(C(:,1),C(:,2)); %繪製閃點圖
 hold on
 plot([C(Shortest_Route(1),1),C(Shortest_Route(N),1)],[C(Shortest_Route(1),2),C(Shortest_Route(N),2)],'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
title('旅行商最短路線結果圖 ')

%繪製第二個子圖形
subplot(1,2,2)                  
plot(L_best)
hold on                         %保持圖形
plot(L_ave,'r')
legend('最短距離','平均距離')
title('平均距離和最短距離')     %標題

實驗結果如圖:

6 算法優缺點

優點:

  • 正反饋,可以較快發現較好解
  • 啓發式搜索,反映了搜索中的先驗性、確定性因素的強度
  • 魯棒性強,不易受個體影響

缺點:

  • 需要較長搜索時間
  • 容易出現停滯現象

7 算法改進

蟻羣算法的改進可以從以下方面進行考慮:

(1)搜索速度改進,引入偵察蟻、工蟻。

(2)搜索策略改進,加入擾動、添加牽引力引導螞蟻朝全局最優搜索。

 

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