一、蟻群算法
1.基本原理
蟻群算法(Ant Colony Optimization,ACO)是一種基於種群尋優的啟發式搜索算法,有意大利學者M.Dorigo等人於1991年首先提出。該算法受到自然界真實蟻群集體在覓食過程中行為的啟發,利用真實蟻群通過個體間的信息傳遞、搜索從蟻穴到食物間的最短路徑等集體尋優特征,來解決一些離散系統優化中的困難問題。
經過觀察發現,螞蟻在尋找食物的過程中,會在它所經過的路徑上留下一種被稱為信息素的化學物質,信息素能夠沉積在路徑上,並且隨着時間逐步揮發。在螞蟻的覓食過程中,同一蟻群中的其他螞蟻能夠感知到這種物質的存在及其強度,后續的螞蟻會根據信息素濃度的高低來選擇自己的行動方向,螞蟻總會傾向於向信息素濃度高的方向行進,而螞蟻在行進過程中留下的信息素又會對原有的信息素濃度予以加強,因此,經過螞蟻越多的路徑上的信息素濃度會越強,而后續的螞蟻選擇該路徑的可能性就越大。通常在單位時間內,越短的路徑會被越多的螞蟻所訪問,該路徑上的信息素強度也越來越強,因此,后續的螞蟻選擇該短路徑的概率也就越大。經過一段時間的搜索后,所有的螞蟻都將選擇這條最短的路徑,也就是說,當蟻巢與食物之間存在多條路徑時,整個蟻群能夠通過搜索螞蟻個體留下的信息素痕跡,尋找到蟻巢和食物之間的最短路徑。
蟻群算法中,螞蟻個體作為每一個優化問題的可行解。首先隨機生成初始種群,包括確定解的個數、信息素揮發系數、構造解的結構等。然后構造蟻群算法所特有的信息素矩陣每只媽蟻執行螞蚊移動算子后,對整個群體的螞蟻做一評價,記錄最優的螞蟻。之后算法根據信息素更新算子更新信息素矩陣,至此種群的一次選代過程完成。整個螞蟻群體執行一定次數的選代后退出循環、輸出最優解。
2.術語介紹
(1)螞蟻個體。每只螞蟻稱為一個單獨的個體,在算法中作為一個問題的解。
(2)螞蟻群體。一定數量的螞蟻個體組合在一起構成一個群體,螞蟻是群體的基本單位。
(3)群體規模。群體中個體數目的總和稱為群體規模,又叫種群大小。
(4)信息素。信息素是螞蟻在所經過的路徑上所釋放的一種化學物質,后來的螞蟻根據路徑上的信息素的強度選擇路徑。
(5)螞蟻移動算子。螞蟻在尋優過程中通過螞蟻移動算子來改善基因位,向最優解靠近。
(6)信息素更新算子。螞蟻算法中,種群在每次迭代過程中,通過信息素更新算子來改變信息素矩陣,為螞蟻移動算子提供基礎。
3.基本流程
(1)算法流程圖
(2)算法描述
①初始化蟻群。初始化蟻群參數,包括設置螞蟻數量、螞蟻解的結構、信息素揮發系數等。
②構造信息素矩陣。
③每只螞蟻執行螞蟻移動算子。螞蟻依據前面螞蟻所留下的信息素,修改自己的解結構,完成一次循環。
④依據適應度值對螞蟻進行排序,對前n個解執行局部搜索算子。
⑤評價蟻群。根據目標函數對每只螞蟻的適應度值做一評價,並記錄最優解。
⑥根據信息素更新算子更新信息素矩陣。
⑦若滿足終止條件,即最短路徑,輸出最優解;否則,信息素揮發,算法繼續進行步驟③。
4.算法特點
(1)自組織。組織力或組織指令是來自於系統的內部。 在抽象意義上講,自組織就是在沒有外界作用下使得系統熵減小的過程(即是系統從無序到有序的變化過程)。
(2)並行搜索。每只螞蟻搜索的過程彼此獨立,僅通過信息激素進行通信。 在問題空間的多點同時開始進行獨立的解搜索,不僅增加了算法的可靠性,也使得算法具有較強的全局搜索能力。
(3)正反饋。螞蟻能夠最終找到最短路徑,直接依賴於最短路徑上信息激素的堆積,而信息激素的堆積卻是一個正反饋的過程。
二、ACO解決TSP問題
1.算法步驟
(1)算法流程圖
(2)算法描述
①初始化(各個參數): 在計算之初需要對相關的參數進行初始化,如螞蟻數量m、信息素因子α、啟發函數因子β、信息素揮發因子ρ、信息素常數Q、最大迭代次數iter_max等等。
②構建解空間: 將各個螞蟻隨機地放置於不同的出發點,對每個螞蟻k(k=1,2,……,m),計算其下一個待訪問的城市,直到所有螞蟻訪問完所有的城市。
③更新信息素: 計算各個螞蟻經過的路徑長度L,記錄當前迭代次數中的最優解(最短路徑)。同時,對各個城市連接路徑上的信息素濃度進行更新。
④判斷是否終止: 若迭代次數小於最大迭代次數則迭代次數加一,清空螞蟻經過路徑的記錄表,並返回步驟二;否則終止計算,輸出最優解。
2.參數設置
參數 | 含義 | 取值 | 過大 | 過小 |
m | 螞蟻數量 | 一般設置為目標數的1.5倍 | 每條路徑上信息素趨於平均,正反饋作用減弱,從而導致收斂速度減慢 |
可能導致一些從未搜索過的路徑信息素濃度減小為0,導致過早收斂,解的全局最優性降低 |
Q | 信息素常量 |
一般取值在[10,1000] |
會使蟻群的搜索范圍減小容易過早的收斂,使種群陷入局部最優 |
每條路徑上信息含量差別較小,容易陷入混沌狀態 |
iter_max | 最大迭代次數 | 一般取[100,500],建議取200 | 運算時間過長 |
可選路徑較少,使種群陷入局部最優 |
ɑ | 信息素因子 |
通常[1, 4]之間 | 螞蟻選擇以前已經走過的路可能性較大,容易使隨機搜索性減弱 | 蟻群易陷入純粹的隨機搜索,使種群陷入局部最優 |
β | 啟發函數 因子 |
通常[0, 5]之間 | 雖然收斂速度加快,但是易陷入局部最優 |
蟻群易陷入純粹的隨機搜索,很難找到最優解 |
ρ | 信息素揮發因子 | 通常[0.2, 0.5]之間 | 信息素揮發較快,容易導致較優路徑被排除 |
各路徑上信息素含量差別較小,收斂速度降低 |
3.構建解空間
將各個螞蟻隨機地置於不同的出發地,對每個螞蟻k ( k = 1 , 2 , ⋯ , m ) ,按照輪盤賭法得到下面的轉移概率公式計算其下一個待訪問的城市,直到所有螞蟻訪問完所有的城市。
上式中,i ,j 分別為起點和終點;
ηij(t)=1/dij 是啟發函數,值兩點i,j路徑距離的倒數;
τij(t)為時間 t 時由 i 到 j 的信息素濃度;
allowedk為尚未訪問過的節點的集合。
4.更新信息素
根據信息素更新策略的不同,Dorigo M 提出了三種不同的基本蟻群算法模型,分別稱之為蟻量系統(ant-quantity system)模型、蟻密系統(ant-density system)模型、蟻周系統(ant-cycle system)模型。三種模型的差別僅在於 ∆τij 的表達式不同,這里采用蟻周模型。
5.判斷是否終止
蟻群算法中的終止條件:是否達到迭代次數。 一次迭代就是指m只螞蟻都走完所有的城市,即存在m個搜索路徑。 將所有路徑進行比較,選擇長度最短的路徑,做出這一次迭代的可視化結果,更新信息素。並將當前的最短路徑與過往的最短路徑長度進行對比,同時迭代次數加1. 然后判斷當前迭代次數是否等於設置的迭代次數。如果等於則停止迭代,否則進行下一次迭代。
6.編碼實現
% I.清空環境變量 clear all clc % II. 符號說明 %{ iter_max -- 最大迭代次數 m -- 螞蟻數量,一般設置為目標數的1.5倍 D(i,j) -- 城市i和j之間的距離 Eta(i, j) = 1./ D(i, j) -- 啟發函數 alpha -- 表征信息素重要程度的參數,通常[1, 4]之間 beta -- 表征啟發函數重要程度的參數,通常[0, 5]之間 rho -- 信息素揮發因子,通常[0.1,0.2, 0.5]之間 Q -- 常系數 route_best -- 各代最佳的路線 length_best -- 各代最佳路線的長度 length_average -- 各代的平均長度 %} % III.導入數據 load cities.mat % IV. 計算城市建的距離(歐式距離) n = size(cities,1); %城市個數 D = zeros(n,n); for i = 1:n for j = i+1:n %D(i,j) = sqrt(sum((cities(1,:)-cities(j,:)).^2)); D(i, j) = sqrt((cities(i, 1) - cities(j, 1))^2 + (cities(i, 2) - cities(j, 2))^2); D(j,i) = D(i,j); end D(i,i) = 1e-4; end % V. 初始化參數 m = 50; % 螞蟻數量 alpha = 1; %信息素重要程度因子 beta = 5; % 啟發函數重要程度因子 rho = 0.1; % 信息素揮發因子 Q = 20; %常系數 Eta = 1./D; % 啟發函數 Tau = ones(n,n); %信息素矩陣,Tau(i, j)表示邊(i, j)的信息素量,一開始都為1 Table = zeros(m,n); %路徑記錄表 iter = 1; %迭代次數初值 iter_max = 200; %最大迭代次數 route_best = zeros(iter_max,n); %各代最佳路徑 length_best = zeros(iter_max,1); %各代最佳路徑長度 length_average = zeros(iter_max,1); %各代路徑的平均長度 % VI.迭代尋找最佳路徑 while iter <= iter_max %step 1,隨機產生各個螞蟻的起點城市 start = zeros(m,1); for i = 1:m temp = randperm(n); %1-n的隨機數 start(i) = temp(1); end Table(:,1) = start; %Table第一列即是所有螞蟻的起點城市 cities_index = 1:n; %所有城市索引的一個集合 %step 2,逐個螞蟻路徑選擇 for i = 1:m %逐個城市路徑選擇 for j = 2:n visited = Table(i,1:(j-1)); % 螞蟻i已訪問的城市集合(禁忌表) allow_index = ~ismember(cities_index, visited); allow = cities_index(allow_index); % 存放待訪問的城市集合 P = allow; % 計算城市間轉移概率 for k = 1:length(allow) P(k) = Tau(visited(end), allow(k))^alpha * Eta(visited(end), allow(k))^beta; end P = P / sum(P); % 輪盤賭法選擇下一個訪問城市 Pc = cumsum(P); target_index = find(Pc>=rand); target = allow(target_index(1)); Table(i, j) = target; end end % step 3,計算各個螞蟻的路徑距離 Length = zeros(m, 1); for i = 1:m Route = Table(i, :); for j = 1: (n-1) Length(i) = Length(i) + D(Route(j), Route(j+1)); end Length(i) = Length(i) + D(Route(n), Route(1)); end % step 4,計算最短路徑距離及平均距離 if iter == 1 [min_Length, min_index] = min(Length); length_best(iter) = min_Length; length_average(iter) = mean(Length); route_best(iter, :) = Table(min_index, :); else [min_Length, min_index] = min(Length); length_best(iter) = min(length_best(iter-1), min_Length); length_average(iter) = mean(Length); if length_best(iter) == min_Length route_best(iter, :) = Table(min_index, :); else route_best(iter, :) = route_best((iter-1), :); end end % step 5,更新信息素 Delta_Tau = zeros(n, n); % 逐個螞蟻計算 for i = 1:m % 逐個城市計算 for j = 1:(n-1) Delta_Tau(Table(i, j), Table(i, j+1)) = Delta_Tau(Table(i, j), Table(i, j+1)) + Q/Length(i); end Delta_Tau(Table(i, n), Table(i, 1)) = Delta_Tau(Table(i, n), Table(i, 1)) + Q/Length(i); end Tau = (1-rho) * Tau + Delta_Tau; %step 6,迭代次數加1, 清空路徑記錄表 iter = iter + 1; Table = zeros(m, n); end % VII. 結果顯示 [Shortest_Length, index] = min(length_best); Shortest_Route = route_best(index, :); disp(['最短距離', num2str(Shortest_Length)]); disp(['最短路徑', num2str([Shortest_Route Shortest_Route(1)])]); % VIII. 繪圖 figure(1); plot([cities(Shortest_Route,1);cities(Shortest_Route(1),1)],... [cities(Shortest_Route,2);cities(Shortest_Route(1),2)],'o-'); grid on; for i = 1:size(cities,1) text(cities(i,1),cities(i,2),[' ' num2str(i)]); end text(cities(Shortest_Route(1),1),cities(Shortest_Route(1),2),' 起點'); text(cities(Shortest_Route(end),1),cities(Shortest_Route(end),2),' 終點'); xlabel('城市位置橫坐標') ylabel('城市位置縱坐標') title(['蟻群算法優化路徑(最短距離:' num2str(Shortest_Length) ')']) figure(2) plot(1:iter_max,length_best,'b',1:iter_max,length_average,'r:') legend('最短距離','平均距離') xlabel('迭代次數') ylabel('距離') title('各代最短距離與平均距離對比')
7.實驗結果
運行結果:
1 最短距離15601.9195 2 最短路徑14 12 13 11 23 16 5 6 7 2 4 8 9 10 3 18 17 19 24 25 20 21 22 26 28 27 30 31 29 1 15 14
三、參考文獻
1.cities.mat文件
2.基於蟻群算法的旅行商問題(TSP)的優化,CSDN博主「~心升明月~」