一、蟻群算法
蟻群算法是在20世紀90年代由澳大利亞學者Marco Dorigo等人通過觀察蟻群覓食的過程,發現眾多螞蟻在尋找食物的過程中,總能找到一條從螞蟻巢穴到食物源之間的最短路徑。隨后他們在螞蟻巢穴到食物源之間設置了一個障礙,一段時間以后發現螞蟻又重新走出了一條到食物源最短的路徑。通過對這種現象的不斷研究,最后提出了蟻群算法。蟻群算法在解決旅行商問題(即TSP問題)時,取得了比較理想的結果。
二、基本人工蟻群算法原理
運用人工蟻群算法求解TSP問題時的基本原理是:將m個螞蟻隨機地放在多個城市,讓這些螞蟻從所在的城市出發,n步(一個螞蟻從一個城市到另外一個城市為1步)之后返回到出發的城市。如果m個螞蟻所走出的m條路經對應的中最短者不是TSP問題的最短路程,則重復這一過程,直至尋找到滿意的TSP問題的最短路徑為止。為了說明這一個算法下面用一個算法流程圖來表示一下:
三、 蟻群算法中涉及到的參數及其符號:
:螞蟻數量,約為城市數量的1.5倍。如果螞蟻數量過大,則每條路徑上的信息素濃度趨於平均,正反饋作用減弱,從而導致收斂速度減慢;如果過小,則可能導致一些從未搜索過的路徑信息素濃度減小為0,導致過早收斂,解的全局最優性降低
:信息素因子,反映了螞蟻運動過程中積累的信息量在指導蟻群搜索中的相對重要程度,取值范圍通常在[1, 4]之間。如果信息素因子值設置過大,則容易使隨機搜索性減弱;其值過小容易過早陷入局部最優
:啟發函數因子,反映了啟發式信息在指導蟻群搜索中的相對重要程度,取值范圍在[3, 4.5]之間。如果值設置過大,雖然收斂速度加快,但是易陷入局部最優;其值過小,蟻群易陷入純粹的隨機搜索,很難找到最優解
:信息素揮發因子,反映了信息素的消失水平,相反的反映了信息素的保持水平,取值范圍通常在[0.2, 0.5]之間。當取值過大時,容易影響隨機性和全局最優性;反之,收斂速度降低
:信息素常數,表示螞蟻遍歷一次所有城市所釋放的信息素總量。越大則收斂速度越快,但是容易陷入局部最優;反之會影響收斂速度
:城市數量
:城市i到城市j之間的距離
:t時刻,城市i與城市j之間的信息素濃度
:t時刻,螞蟻k從城市i向城市j轉移的概率
:啟發函數,表示螞蟻從城市i轉移到城市j的期望程度,這里我們取值為
:螞蟻k待訪城市的集合,初始時刻中有個元素,即排除掉螞蟻一開始所在城市以外的其他城市,隨着時間推移,其中的城市越來越少,直到為空,表示遍歷完所有的城市
:表示在所有螞蟻遍歷完所有城市時,第k只螞蟻對城市i與城市j之間信息素濃度總增加量的貢獻量
:表示所有螞蟻遍歷完所有城市時,城市i與城市j之間信息素濃度的累積增加量
:表示螞蟻k遍歷完所有城市后經歷的總路程長度
接下來給出三個公式:
公式一:
從公式中可以看出信息素因子為信息素濃度的指數,啟發函數因子為啟發函數的指數,這樣便很好理解這兩個參數所起到的作用了,分別決定了信息素濃度以及轉移期望對於螞蟻k從城市i轉移到城市j的可能性的貢獻程度。
公式二:
這個公式反映了信息素濃度的迭代更新規律,可以看出,所有螞蟻遍歷完一次所有城市后,當前信息素濃度由兩部分組成,第一部分即上次所有螞蟻遍歷完所有城市后路徑上信息素的殘留,第二部分為本次所有螞蟻遍歷完所有城市后每條路徑上的信息素的新增量。
公式三:
公式三反映了每只螞蟻對於自己經過的城市之間路徑上信息素濃度的貢獻量,可以看出,其經歷的路程越長,則對於沿途上信息素濃度的貢獻量也就越低,如果盡力的路程越短,則對於沿途上信息素濃度的貢獻量也就越高
四、代碼及其實現
citys_data里面儲存着35個城市的坐標
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
3211 2975
1479 3665
2646 2556
2830 3140
1072 1700
代碼部分:
%% 旅行商問題(TSP)優化
%% 清空環境變量
clear all
clc
%% 導入數據
load citys_data.mat
%% 計算城市間相互距離
fprintf('Computing Distance Matrix... \n');
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;
end
end
end
%% 初始化參數
fprintf('Initializing Parameters... \n');
m = 50; % 螞蟻數量
alpha = 0.9; % 信息素重要程度因子
beta = 5; % 啟發函數重要程度因子
rho = 0.1; % 信息素揮發因子
Q = 1; % 常系數
Eta = 1./D; % 啟發函數
Tau = ones(n,n); % 信息素矩陣
Table = zeros(m,n); % 路徑記錄表
iter = 1; % 迭代次數初值
iter_max = 150; % 最大迭代次數
Route_best = zeros(iter_max,n); % 各代最佳路徑
Length_best = zeros(iter_max,1); % 各代最佳路徑的長度
Length_ave = zeros(iter_max,1); % 各代路徑的平均長度
%% 迭代尋找最佳路徑
figure;
while iter <= iter_max
fprintf('迭代第%d次\n',iter);
% 隨機產生各個螞蟻的起點城市
start = zeros(m,1);
for i = 1:m
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
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,清空路徑記錄表
% figure;
%最佳路徑的迭代變化過程
[Shortest_Length,index] = min(Length_best(1:iter));
Shortest_Route = Route_best(index,:);
plot([citys(Shortest_Route,1);citys(Shortest_Route(1),1)],...
[citys(Shortest_Route,2);citys(Shortest_Route(1),2)],'o-');
pause(0.3);
iter = iter + 1;
Table = zeros(m,n);
% end
end
%% 結果顯示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距離:' num2str(Shortest_Length)]);
disp(['最短路徑:' num2str([Shortest_Route Shortest_Route(1)])]);
%% 繪圖
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('各代最短距離與平均距離對比')
五、α,β,ρ對該實驗的影響
1.α對實驗的影響
在m=50,β=5,ρ=0.1恆定的情況下
α=0.7
α=0.8
α=0.9
α=1
啟發因子α的數值的改變,所求得最短路徑也隨之變化,它表現的是螞蟻在搜索路徑的運動過程中對所積累的信息量指導蟻群搜索當中的相對重要度,對算法的隨機性有影響,並且可以導致算法過早陷入局部最優中。α過小,收斂速度慢,且容易陷入局部最優中;α過大,局部最短路徑上正反饋作用強,過早收斂。α=0.8時,最短距離最短,算法性能最佳。
2.β對實驗的影響
在m=50,α=0.8,ρ=0.1恆定的情況下
β=4
β=4.3
β=4.5
β=4.8
β=5
期望啟發因子β的數值的改變,所求得得最短路徑隨之變化,它表現的是啟發式信息在指導蟻群搜索過程之中相對重要的程度,它的大小影響着蟻群在整個尋短過程中的先驗性和確定性。β過小,蟻群陷入純粹的隨機搜索,很難找到最優解;β過大時,收斂速度增快。β=4.5時,最短距離最短,算法性能最佳。
3.ρ對實驗的影響
當m=50,α=0.8,β=5恆定不變時
ρ=0.1
ρ=0.2
ρ=0.3
ρ=0.4
ρ=0.5
ρ對蟻群算法的搜索能力和收斂速度有影響。ρ過小時,在各路徑上殘留的信息素過多,導致無效的路徑繼續被搜索,影響到算法的收斂速率;ρ過大時,無效的路徑雖然可以被排除搜索,但是不能保證有效的路徑也會被放棄搜索,影響到最優質的搜索,使收斂速度降低,並且影響到算法的全局搜索能力。ρ=0.1時,最短距離最大,算法性能最佳。
六、總結
通過多次實驗分析,驗證和確定了數值范圍,由以上實驗結果可以看出,參數的初始設置對算法的影響非常之大。