初窥蚁群算法
(持续更新。。。。)
更新:再看蚁群算法
前言
蚁群算法适合解决各类路径优化问题,如旅行商问题(Traveling Salesman Problem, TSP)、车辆路径问题(Vehicle Routing Problem, VRP)等,也被应用于调度、网络优化、分类等多个领域。
因为其独特的集体协作特性和优秀的搜索能力,蚁群算法是一个非常受欢迎且实用的全局优化方法(但并不保证一定能得到全局最优解)。在使用蚁群算法时,研究者和工程师通常需要通过试验或根据经验来调整相关参数以达到最佳的性能。
一、蚁群算法是什么?
蚁群算法(Ant Clony Optimization, ACO)是一种群智能算法,它是由一群无智能或有轻微智能的个体(Agent)通过相互协作而表现出智能行为,从而为求解复杂问题提供了一个新的可能性。蚁群算法最早是由意大利学者Colorni A., Dorigo M. 等于1991年提出。经过20多年的发展,蚁群算法在理论以及应用研究上已经得到巨大的进步。
蚁群算法是一种仿生学算法,是由自然界中蚂蚁觅食的行为而启发的。在自然界中,蚂蚁觅食过程中,蚁群总能够按照寻找到一条从蚁巢和食物源的最优路径。蚂蚁在移动过程中会在其路径上释放信息素,其他蚂蚁会感知这些信息素并概率性地跟随这些路径。信息素浓度高的路径会吸引更多蚂蚁跟随,因而这条路径的信息素浓度会进一步增强。然而,信息素也会随时间蒸发,这意味着不经常有蚂蚁通过的路径其信息素浓度会减少。这种机制自然形成了一种正反馈过程,帮助蚂蚁群体找到从巢穴到食物源之间的最短路径。
二、算法原理
(1) 基本原理
- 蚁群在觅食时,每只蚂蚁在走过的路径上会留下一种称为信息素的物质在路径分叉口时面临选择:走左边路径还是右边路径?
- 选择的概率:蚂蚁在选择路径时总是倾向于信息素浓度高的方向移动。
- 一只蚂蚁的信息素总量视为有限的常数,则蚂蚁走过的路径越短、留在路径上的信息素浓度越高。
- 信息素本身会随着时间不断挥发。
可以推导与现实相符的出结论:
- 距离长的路径走过的蚂蚁少、后期信息素浓度增加量小于挥发量,总的变化是减少的
- 距离短的路径走过的蚂蚁多、后期信息素浓度增加量大于挥发量,总的变化是增加的
因此形成了一个正反馈迭代:距离短的路径信息素浓度高⇒后续蚂蚁选择该路径的概率更大⇒距离短的路径上信息素浓度进一步升高,如此正反馈,整个蚁群最终走在了最短的路径上。
(2) 符号说明
符号 | 含义 |
---|---|
m \boldsymbol{m} m | 蚂蚁数量 \boldsymbol{蚂蚁数量} 蚂蚁数量 |
α \boldsymbol{\alpha } α | 信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度 \boldsymbol{信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度} 信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度 |
β \boldsymbol{\beta} β | 启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度 \boldsymbol{启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度} 启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度 |
ρ \boldsymbol{\rho } ρ | 信息素挥发因子,反映了信息素的消失水平,相反的反映了信息素的保持水平 \boldsymbol{信息素挥发因子,反映了信息素的消失水平,相反的反映了信息素的保持水平} 信息素挥发因子,反映了信息素的消失水平,相反的反映了信息素的保持水平 |
Q \boldsymbol{Q} Q | 信息素常数,表示蚂蚁遍历一次所有城市所释放的信息素总量 \boldsymbol{信息素常数,表示蚂蚁遍历一次所有城市所释放的信息素总量} 信息素常数,表示蚂蚁遍历一次所有城市所释放的信息素总量 |
n \boldsymbol{n} n | 城市数量 \boldsymbol{ 城市数量} 城市数量 |
d i j \boldsymbol{d}_{\boldsymbol{ij}} dij | 城市 i 到城市 j 之间的距离。 \boldsymbol{城市\ i到城市\ j之间的距离。} 城市 i到城市 j之间的距离。 |
τ i j ( t ) \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) τij(t) | t 时刻,城市 i 与城市 j 之间的信息素浓度 \ \boldsymbol{t时刻,城市\ i与城市\ j之间的信息素浓度} t时刻,城市 i与城市 j之间的信息素浓度 |
p i j k ( t ) \boldsymbol{p}_{\boldsymbol{ij}}^{\boldsymbol{k}}\left( \boldsymbol{t} \right) pijk(t) | t 时刻,蚂蚁 k 从城市 i 向城市 j 转移的概率 \ \boldsymbol{t时刻,蚂蚁\ k从城市\ i向城市\ j转移的概率} t时刻,蚂蚁 k从城市 i向城市 j转移的概率 |
η i j ( t ) \boldsymbol{\eta }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) ηij(t) | 启发函数,表示蚂蚁从城市 i 转移到城市 j 的期望程度,这里我们取值为 1 / d i j \boldsymbol{启发函数,表示蚂蚁从城市\ i转移到城市\ j的期望程度,这里我们取值为1/d}_{\boldsymbol{ij}}\boldsymbol{} 启发函数,表示蚂蚁从城市 i转移到城市 j的期望程度,这里我们取值为1/dij |
a l l o w k \boldsymbol{allow}_{\boldsymbol{k}} allowk | 蚂蚁 k 待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市 \boldsymbol{蚂蚁\ k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市} 蚂蚁 k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市 |
△ τ i j k ( t ) \bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}^{\boldsymbol{k}}\left( \boldsymbol{t} \right) △τijk(t) | 表示在所有蚂蚁遍历完所有城市时,第 k 只蚂蚁对城市 i 与城市 j 之间信息素浓度总增加量的贡献量 \boldsymbol{表示在所有蚂蚁遍历完所有城市时,第k只蚂蚁对城市i与城市j之间信息素浓度总增加量的贡献量} 表示在所有蚂蚁遍历完所有城市时,第k只蚂蚁对城市i与城市j之间信息素浓度总增加量的贡献量 |
△ τ i j \bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}} △τij | 表示所有蚂蚁遍历完所有城市时,城市 i 与城市 j 之间信息素浓度的累积增加量 \boldsymbol{表示所有蚂蚁遍历完所有城市时,城市i与城市j之间信息素浓度的累积增加量} 表示所有蚂蚁遍历完所有城市时,城市i与城市j之间信息素浓度的累积增加量 |
L k \boldsymbol{L}_{\boldsymbol{k}} Lk | 表示蚂蚁 k 遍历完所有城市后经历的总路程长度 \boldsymbol{表示蚂蚁k遍历完所有城市后经历的总路程长度} 表示蚂蚁k遍历完所有城市后经历的总路程长度 |
以上为本博客内容的全部符号及含义解释,不需要强行记忆,可根据后文算法核心公式解析一步步进行理解!
(3) 算法核心公式
- 公式一:蚂蚁对于下一个路径的选择 p i j k ( t ) = { τ i j ( t ) Σ s ∈ a l l l o w k τ i s ( t ) , j ∈ a l l o w k 0 , j ∋ a l l o w k \boldsymbol{p}_{\boldsymbol{ij}}^{\boldsymbol{k}}\left( \boldsymbol{t} \right) =\left\{ \begin{array}{l} \frac{\boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right)}{\underset{\boldsymbol{s}\in \boldsymbol{alllow}_{\boldsymbol{k}}}{\boldsymbol{\Sigma }}\boldsymbol{\tau }_{\boldsymbol{is}}\left( \boldsymbol{t} \right)}\ ,\ \boldsymbol{j}\in \boldsymbol{allow}_{\boldsymbol{k}}\\ \ \ \ \ \ \ 0\ \ \ \ \ \ \ ,\ \boldsymbol{j}\ni \boldsymbol{allow}_{\boldsymbol{k}}\\ \end{array} \right. pijk(t)={s∈alllowkΣτis(t)τij(t) , j∈allowk 0 , j∋allowk τ i j ( t ) : t 时刻,城市 i 与城市 j 之间的信息素浓度 \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) :\ \boldsymbol{t时刻,城市\ i与城市\ j之间的信息素浓度} τij(t): t时刻,城市 i与城市 j之间的信息素浓度 a l l o w k : 蚂蚁 k 待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市 \boldsymbol{allow}_{\boldsymbol{k}}:\boldsymbol{蚂蚁\ k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市} allowk:蚂蚁 k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市
该公式含义为蚂蚁基于其未到达的城市集合选择下一个前往的城市,利用信息素含量作为概率依据,前往某个未到达城市的概率由其本身的信息素及所有未到达城市的信息素总和所决定,充分体现了自然界中蚂蚁选择前进方向的自然原理。
公式缺点:
1. 该公式只考虑信息素浓度对蚂蚁选择路径概率的影响;
2. 最初几次迭代时每条路径的信息素浓度都很低,选择路径的随机性大;
3. 每条路径都可能有不少蚂蚁,导致蚁群的搜索范围过大,收敛速度过慢。
- 修改后的公式一 p i j k ( t ) = { [ τ i j ( t ) ] α [ η i j ( t ) ] β Σ s ∈ a l l l o w k [ τ i s ( t ) ] α [ η i s ( t ) ] β , j ∈ a l l o w k 0 , j ∋ a l l o w k \boldsymbol{p}_{\boldsymbol{ij}}^{\boldsymbol{k}}\left( \boldsymbol{t} \right) =\left\{ \begin{array}{l} \frac{\left[ \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) \right] ^{\boldsymbol{\alpha }}\left[ \boldsymbol{\eta }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) \right] ^{\boldsymbol{\beta }}}{\underset{\boldsymbol{s}\in \boldsymbol{alllow}_{\boldsymbol{k}}}{\boldsymbol{\Sigma }}\left[ \boldsymbol{\tau }_{\boldsymbol{is}}\left( \boldsymbol{t} \right) \right] ^{\boldsymbol{\alpha }}\left[ \boldsymbol{\eta }_{\boldsymbol{is}}\left( \boldsymbol{t} \right) \right] ^{\boldsymbol{\beta }}}\ ,\ \boldsymbol{j}\in \boldsymbol{allow}_{\boldsymbol{k}}\\ \ \ \ \ \ \ \ \ \ \ \ \ 0\ \ \ \ \ \ \ \ \ \ \ \ ,\ \boldsymbol{j}\ni \boldsymbol{allow}_{\boldsymbol{k}}\\ \end{array} \right. pijk(t)=⎩ ⎨ ⎧s∈alllowkΣ[τis(t)]α[ηis(t)]β[τij(t)]α[ηij(t)]β , j∈allowk 0 , j∋allowk α : 信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度 \boldsymbol{\alpha :信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度} α:信息素因子,反映了蚂蚁运动过程中积累的信息量在指导蚁群搜索中的相对重要程度 β : 启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度 \boldsymbol{\beta :启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度} β:启发函数因子,反映了启发式信息在指导蚁群搜索中的相对重要程度 d i j : 城市 i 到城市 j 之间的距离 \boldsymbol{d}_{\boldsymbol{ij}}:\boldsymbol{城市\ i到城市\ j之间的距离} dij:城市 i到城市 j之间的距离 τ i j ( t ) : t 时刻,城市 i 与城市 j 之间的信息素浓度 \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) :\ \boldsymbol{t时刻,城市\ i与城市\ j之间的信息素浓度} τij(t): t时刻,城市 i与城市 j之间的信息素浓度 p i j k ( t ) : t 时刻,蚂蚁 k 从城市 i 向城市 j 转移的概率 \boldsymbol{p}_{\boldsymbol{ij}}^{\boldsymbol{k}}\left( \boldsymbol{t} \right) :\ \boldsymbol{t时刻,蚂蚁\ k从城市\ i向城市\ j转移的概率} pijk(t): t时刻,蚂蚁 k从城市 i向城市 j转移的概率 η i j ( t ) : 启发函数,表示蚂蚁从城市 i 转移到城市 j 的期望程度,这里我们取值为 1 / d i j \boldsymbol{\eta }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) :\boldsymbol{启发函数,表示蚂蚁从城市\ i转移到城市\ j的期望程度,这里我们取值为1/d}_{\boldsymbol{ij}}\boldsymbol{} ηij(t):启发函数,表示蚂蚁从城市 i转移到城市 j的期望程度,这里我们取值为1/dij a l l o w k : 蚂蚁 k 待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市 \boldsymbol{allow}_{\boldsymbol{k}}:\boldsymbol{蚂蚁\ k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市} allowk:蚂蚁 k待访城市的集合,随着时间推移,其中的城市越来越少,直到为空,表示遍历完所有的城市
修改后的公式不仅考虑了信息素的影响因素,更重要的是引入了启发函数的概念,大大推进了该算法的进步。
为了加快算法的收敛速度以及蚂蚁的选择准确性,我们选择给蚂蚁开一副“天眼”,利用我们已知的数据去促使蚂蚁在前期更容易选择更近的道路(并不代表每次选择最短的路径就是全局最优解,这是贪心的思想),不会导致纯随机的选择结果,蚂蚁拥有该作弊器后在全局来看可以更快的选择更优的路径规划,最终尽量帮助蚁群找到全局最优解。
该公式中的信息素因子及启发函数因子的大小对于算法的收敛性具有很大影响,过高的信息素因子数值将导致蚂蚁放弃“天眼”,在前期的选择偏于随机;过高的启发函数因子数值将导致蚂蚁容易基于贪心的思想进行搜索,而贪心在大多数优化问题中并不能找到全局最优解(解决方法待更新)。
- 公式一:路径上信息素的更新 { τ i j ( t + 1 ) = ( 1 − ρ ) ⋅ τ i j ( t ) + △ τ i j , 0 < ρ < 1 △ τ i j = Σ m k = 1 △ τ i j k △ τ i j k = { Q L k , i f t h e a n t k w e n t t h r o u g h i t o j 0 , e l s e \left\{ \begin{array}{l} \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t}+1 \right) =\left( 1-\boldsymbol{\rho } \right) \cdot \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) +\bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}\ \ ,0<\boldsymbol{\rho }<1\\ \bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}=\underset{\boldsymbol{k}=1}{\overset{\boldsymbol{m}}{\boldsymbol{\Sigma }}}\bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}^{\boldsymbol{k}}\\ \bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}^{\boldsymbol{k}}=\left\{ \begin{array}{l} \frac{\boldsymbol{Q}}{\boldsymbol{L}_{\boldsymbol{k}}}\ ,\ \boldsymbol{if\ the\ ant\ k\ went\ through\ i\ to\ j}\\ 0\ \ \ ,\ \boldsymbol{else}\\ \end{array} \right.\\ \end{array} \right. ⎩ ⎨ ⎧τij(t+1)=(1−ρ)⋅τij(t)+△τij ,0<ρ<1△τij=k=1Σm△τijk△τijk={LkQ , if the ant k went through i to j0 , else
公式分析:
1. τ i j ( t ) \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) τij(t) 是𝑡时刻城市𝑖到城市𝑗的路径的信息素浓度, τ i j ( t + 1 ) \boldsymbol{\tau}_{\boldsymbol{ij}}\left( \boldsymbol{t}+1 \right) τij(t+1)则是下一轮时的浓度.
2.信息素随着时间挥发,所以 τ i j ( t ) \boldsymbol{\tau }_{\boldsymbol{ij}}\left( \boldsymbol{t} \right) τij(t) 乘以介于0到1的系数 ( 1 − ρ ) \left( 1-\boldsymbol{\rho } \right) (1−ρ)3.其中第𝑘只蚂蚁产生的新的信息素浓度为 △ τ i j k \bigtriangleup \boldsymbol{\tau }_{\boldsymbol{ij}}^{\boldsymbol{k}} △τijkQ为常数, L k \boldsymbol{L}_{\boldsymbol{k}} Lk是𝑘只蚂蚁走过的总路径长度。
基于该公式可以对路径上的信息素进行挥发操作,从而保证“无蚁问津”的路径的信息素含量逐步下降从而帮助后面的蚂蚁可以选择更正确的道路。
三、算法实现步骤
四、案例及代码
clear; % 清除所有变量
close; % 清图
clc ; % 清屏
%% x,y坐标
x = [0,272,176,171,650,499,267,703,408,437,491,74,532,...
416,626,42,271,359,163,508,229,576,147,560,35,714,...
757,517,64,314,675,690,391,628,87,240,705,699,258,...
428,614,36,360,482,666,597,209,201,492,294];
y = [0,395,198,151,242,556,57,401,305,421,267,105,525,...
381,244,330,395,169,141,380,153,442,528,329,232,48,...
498,265,343,120,165,50,433,63,491,275,348,222,288,...
490,213,524,244,114,104,552,70,425,227,331];
%% 初始化蚁群参数及数据的预处理
m = 50; % m 蚂蚁个数
A = 2; % A 表征信息素重要程度的参数
B = 4; % B 表征启发式因子重要程度的参数
Rho = 0.1; % Rho 信息素蒸发系数
N_max = 100; % 最大迭代次数
Q = 100; % 信息素总量
% 计算点之间的距离
siz = size(x, 2);
distance = zeros(siz, siz); % 计算点与点之间的距离
for i = 1 : siz - 1
for j = i + 1 : siz
distance(j ,i) = ((x(i) - x(j)) ^ 2 + (y(i) - y(j)) ^ 2) ^ 0.5;
distance(i, j) = distance(j, i);
end
end
E = 1 ./ distance; % 启发因子
Ta = ones(siz, siz); % 初始信息素矩阵
T = zeros(m, siz); % 记录路径的生成
N = 1; % 迭代计数器,记录迭代次数
R_best = zeros(N_max, siz); % 各代最佳路线
L_best = inf.*ones(N_max,1); % 各代最佳路线的长度
S_best = zeros(N_max, 1); % 各代最佳路线分数
%% 开始迭代
while N <= N_max % 停止条件之一:达到最大迭代次数,停止
% 设立初始点为(0, 0)
T(:,1) = ones(m, 1);
S = zeros(m, 1); % 各代路线分数
% m只蚂蚁按概率函数选择下一个景点,完成各自的路线
for j = 2 : siz % 走的次数,所在景点不计算
for i = 1 : m
visited = T(i, 1 : (j - 1)); % 记录已访问景点,避免重复访问
J = zeros(1, (siz - j + 1)); % 待访问的景点
P = J; % 待访问景点的选择概率分布
Jc = 1; % 访问的景点个数
for k = 1 : siz
if isempty(find(visited == k, 1)) % 开始时置0
J(Jc) = k;
Jc = Jc + 1; % 可访问的城市个数自加1
end
end
% 下面计算待选景点的概率分布
for k = 1 : length(J)
P(k) = (Ta(visited(end), J(k)) ^ A) * (E(visited(end), J(k)) ^ B);
end
P = P / sum(P);
% 按概率原则选取下一个景点
select = randsrc(1,1,[J;P]); % 按概率随机选取景点
Select = find(select==J,1);
to_visit = J(Select);
T(i,j) = to_visit;
end
end
% if N >= 2
% T(1,:) = R_best(N-1,:);
% end
% 计算各路线的距离
L = zeros(m, 1); % 开始距离为0,m*1的列向量
for i = 1 : m
R = T(i,:);
for j = 1 : siz-1
L(i) = L(i) + distance(R(j), R(j+1)); % 原距离加上第j个景点到第j+1个景点的距离
end
L(i) = L(i) + distance(R(1), R(siz)); % 一轮下来后走过的距离
end
L_best(N) = min(L); % 最佳距离取最小
% 对距离正向化并打分
max_1 = max(L);
for i = 1 : m
S(i,1) = (max_1 - L(i,1)) * 100;
end
% 记录本次迭代最佳路线
pos = find(max(S) == S, 1);
if isempty(pos)
break;
else
R_best(N,:) = T(pos,:); % 此轮迭代后的最佳路线
S_best(N,1) = max(S);
N = N + 1; % 迭代继续
end
% 更新信息素
Delta_Ta = zeros(siz,siz); % 开始时信息素为n*n的0矩阵
for i = 1 : m
R = T(i,:); % 该迭代中每一条路线
for j = 1 : (siz - 1)
Delta_Ta(R(j),R(j+1)) = Delta_Ta(R(j), R(j+1)) + Q / L(i);
% 此次循环在路径上的信息素增量
end
Delta_Ta(R(siz), R(1)) = Delta_Ta(R(siz), R(1)) + Q / L(i);
end
Ta = (1 - Rho) .* Ta + Delta_Ta; % 考虑信息素挥发,更新后的信息素
% 清零
T = zeros(m, siz);
end
%% 结果
Pos = find(S_best == max(S_best), 1); % 找到最佳路径(非0为真)
Shortest_Route = R_best(Pos,:) ; % 最大迭代次数后最佳路径
Shortest_Length = L_best(Pos) ; % 最大迭代次数后最短距离
求解结果:
最优路线:1 12 19 4 3 21 47 7 30 18 43 9 10 14 33 40 13 6 46 22 20 24 11 28 49 44 34 32 26 45 31 41 15 5 38 37 8 27 39 36 50 17 2 48 23 35 42 16 29 25
最优距离:4354.30357587626
总结
蚁群算法通常由以下几个关键组成部分:
构造解:仿真蚂蚁在问题空间中寻找解,通常是通过概率性的决策和信息素强度指导。
信息素更新:通过增加信息素强度来促进优秀解被更多地搜索到,同时减少信息素浓度来避免过早收敛至局部最优解。
守恒和多样性:一些策略用以维持搜索过程的稳定性和多样性,例如信息素蒸发机制。
合理使用蚁群算法在求解优化问题中将会带来很好的效果!
未完待续。。。