蟻群演算法原理詳解和matlab程式碼
1原理:
螞蟻在尋找食物源的時候,能在其走過的路徑上釋放一種叫資訊素的激素,使一定範圍內的其他螞蟻能夠察覺到。當一些路徑上通過的螞蟻越來越多時,資訊素也就越來越多,螞蟻們選擇這條路徑的概率也就越高,結果導致這條路徑上的資訊素又增多,螞蟻走這條路的概率又增加,生生不息。這種選擇過程被稱為螞蟻的自催化行為。
對於單個螞蟻來說,它並沒有要尋找最短路徑,只是根據概率選擇;對於整個蟻群系統來說,它們卻達到了尋找到最優路徑的客觀上的效果。這就是群體智慧。
2應用
蟻群演算法用來解決最短路徑問題,並真的在旅行商問題(TSP,一個尋找最短路徑的問題)上取得了比較好的成效。目前,也已漸漸應用到其他領域中去,在圖著色問題、車輛排程問題、積體電路設計、通訊網路、資料聚類分析
3引數
蟻群演算法的引數的調節主要影響搜尋能力和搜尋速度,即**收斂程度和收斂速度。**
3.1螞蟻數量m:
設M表示城市數量,m表示螞蟻數量。
m的數量很重要,因為m過大時,會導致搜尋過的路徑上資訊素變化趨於平均,這樣就不好找出好的路徑了;
m過小時,易使未被搜尋到的路徑資訊素減小到0,這樣可能會出現早熟,沒找到全域性最優解。
一般上,在時間等資源條件緊迫的情況下,螞蟻數設定為城市數的1.5倍較穩妥。
3.2資訊素因子alpha:
資訊素因子反映了螞蟻在移動過程中所積累的資訊量在指導蟻群搜尋中的相對重要程度,
其值過大,螞蟻選擇以前走過的路徑概率大,搜尋隨機性減弱;
值過小,等同於貪婪演算法,使搜尋過早陷入區域性最優
實驗發現,資訊素因子選擇[1,4]區間,效能較好。
3.3啟發函式因子(期望啟發因子)beta:
啟發函式實際上為路徑的倒數,啟發函式因子為啟發函式的指數。因此beta越大,路徑越長的路選擇概率越小。
啟發函式因子反映了啟發式資訊在指導蟻群搜尋過程中的相對重要程度,其大小反映的是蟻群尋優過程中先驗性和確定性因素的作用強度。
過大時,雖然收斂速度會加快,但隨機性不高,容易陷入區域性路徑最優;
過小時,容易陷入隨機搜尋,找不到最優解。
實驗研究發現,當啟發函式因子為[3,4.5]時,綜合求解效能較好。
3.4資訊素揮發因子:
資訊素揮發因子表示資訊素的消失水平,它的大小直接關係到蟻群演算法的全域性搜尋能力和收斂速度
過小時,殘留資訊素多,無效路徑被搜尋;
過多時,有效路徑可能也被忽略,
實驗發現,當屬於[0.2,0.5]時,綜合性能較好。
3.5資訊素常數:
這個引數為資訊素強度,表示螞蟻迴圈一週時釋放在路徑上的資訊素總量,其作用是為了充分利用有向圖上的全域性資訊反饋量,使演算法在正反饋機制作用下以合理的演化速度搜索到全域性最優解。
值越大,螞蟻在已遍歷路徑上的資訊素積累越快,有助於快速收斂。
實驗發現,當值屬於[10,1000]時,綜合性能較好。
3.6最大迭代次數:
最大迭代次數值過小,可能導致演算法還沒收斂就已結束;
過大則會導致資源浪費。一般最大迭代次數可以取100到500次。
一般來講,建議先取200,然後根據執行程式檢視演算法收斂的軌跡來修改取值。
3.7組合引數設計策略:
通常可以按照以下策略來進行引數組合設定:
- 確定螞蟻數目,螞蟻數目與城市規模之比約為1.5;
- 引數粗調,即調整取值範圍較大的α,β及Q;
- 引數微調,即調整取值範圍較小的ρ
4步驟
- 步驟1:引數初始化,包括蟻群規模(m只螞蟻)、資訊素因子、啟發函式因子、資訊素揮發因子、資訊素常數、最大迭代次數等,以及將資料讀入程式,並進行預處理:比如將城市的座標資訊轉換為城市間的距離矩陣。
- 步驟2:構造解空間。隨機將螞蟻放於不同出發點,對每個螞蟻計算其下個訪問城市,直到有螞蟻訪問完所有城市。
- 步驟3:更新資訊素。對路徑上的資訊素濃度進行更新。 同時計算各螞蟻經過的路徑長度Lk,記錄當前迭代次數最優解。
- 步驟4:判斷是否達到最大迭代次數,若否,返回步驟2;是,結束程式。
- 步驟5:輸出結果,並根據需要輸出尋優過程中的相關指標,如執行時間、收斂迭代次數等。
4.1 轉移概率
某條未走過的路的概率,佔所有的比例。
此處也是演算法不斷改進的地方。計算方式不同,影響結果
計算出轉移概率,就通過轉移策略選擇到底走哪條路。
程式碼中使用的是最簡單的輪盤賭法:概率越大的路徑,被選中的概率越大。
% 輪盤賭法選擇下一個訪問城市
Pc = cumsum(P); %cumsum,元素累加即求和 輪盤賭法的必用函式
target_index = find(Pc >= rand); %可能不止一個大於rand產生的0-1之間的隨機數。但是隻有第一個是我們要選擇的道路。
target = allow(target_index(1));%選第一個
4.2資訊素更新方法:
後一次搜尋的資訊素是本次所有螞蟻釋放資訊素的和,以及上次路徑殘留的資訊素。
此處也是演算法不斷改進的地方。
包括全域性更新和區域性更新的不同策略,套用不同公式。
5程式碼
%% I. 清空環境變數
clear all
clc
%% II. 匯入資料 31個城市的座標
%load citys_data.mat
citys=[
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
];
%% III. 計算城市間相互距離
n = size(citys,1);
D = zeros(n,n);
for i = 1:n
for j = 1:n
if i ~= j
D(i,j) = sqrt(sum((citys(i,:) - citys(j,:)).^2));
else
D(i,j) = 1e-4; %用很小的值代替 0 公式需要
end
end
end
%% IV. 初始化引數
m = 50; % 螞蟻數量
alpha = 1; % 資訊素重要程度因子
beta = 5; % 啟發函式重要程度因子
rho = 0.1; % 資訊素揮發因子
Q = 1; % 常係數
Eta = 1./D; % 啟發函式
Tau = ones(n,n); % 資訊素矩陣
Table = zeros(m,n); % 路徑記錄表 m個螞蟻走過的路徑
iter = 1; % 迭代次數初值
iter_max = 200; % 最大迭代次數
Route_best = zeros(iter_max,n); % 各代最佳路徑
Length_best = zeros(iter_max,1); % 各代最佳路徑的長度
Length_ave = zeros(iter_max,1); % 各代路徑的平均長度
%% V. 迭代尋找最佳路徑
while iter <= iter_max
% 隨機產生各個螞蟻的起點城市
start = zeros(m,1);
for i = 1:m %50個螞蟻隨機產生的起始城市位置
temp = randperm(n);
start(i) = temp(1);
end
Table(:,1) = start; %初始位置
citys_index = 1:n; %城市索引取出來
% 逐個螞蟻路徑選擇
for i = 1:m
% 逐個城市路徑選擇
for j = 2:n
tabu = Table(i,1:(j - 1)); % 已訪問的城市集合(禁忌表)
allow_index = ~ismember(citys_index,tabu); %沒有訪問過的城市取出來
allow = citys_index(allow_index); % 待訪問的城市集合
P = allow;
% 計算城市間轉移概率
for k = 1:length(allow)
P(k) = Tau(tabu(end),allow(k))^alpha * Eta(tabu(end),allow(k))^beta; %end代表最後一個元素 對應公式
end
P = P/sum(P);
% 輪盤賭法選擇下一個訪問城市
Pc = cumsum(P);
target_index = find(Pc >= rand);
target = allow(target_index(1));
Table(i,j) = target; %記錄下來,新增新訪問的城市
end
end
% 計算各個螞蟻的路徑距離
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
% 計算最短路徑距離及平均距離
if iter == 1
[min_Length,min_index] = min(Length);
Length_best(iter) = min_Length;
Length_ave(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_ave(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
% 更新資訊素
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;
% 迭代次數加1,清空路徑記錄表
iter = iter + 1;
Table = zeros(m,n);
end
%% VI. 結果顯示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距離:' num2str(Shortest_Length)]);
disp(['最短路徑:' num2str([Shortest_Route Shortest_Route(1)])]);
%% VII. 繪圖 1960009019 l13299109228
figure(1)
plot([citys(Shortest_Route,1);citys(Shortest_Route(1),1)],...
[citys(Shortest_Route,2);citys(Shortest_Route(1),2)],'o-');
grid on
for i = 1:size(citys,1)
text(citys(i,1),citys(i,2),[' ' num2str(i)]);
end
text(citys(Shortest_Route(1),1),citys(Shortest_Route(1),2),' 起點');
text(citys(Shortest_Route(end),1),citys(Shortest_Route(end),2),' 終點');
xlabel('城市位置橫座標')
ylabel('城市位置縱座標')
title(['蟻群演算法優化路徑(最短距離:' num2str(Shortest_Length) ')'])
figure(2)
plot(1:iter_max,Length_best,'b',1:iter_max,Length_ave,'r:')
legend('最短距離','平均距離')
xlabel('迭代次數')
ylabel('距離')
title('各代最短距離與平均距離對比')
ref