作者:非妃是公主
专栏:《智能优化算法》
博客地址:https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
专栏推荐
专栏名称 | 专栏地址 |
---|---|
软件工程 | 专栏——软件工程 |
计算机图形学 | 专栏——计算机图形学 |
操作系统 | 专栏——操作系统 |
软件测试 | 专栏——软件测试 |
机器学习 | 专栏——机器学习 |
数据库 | 专栏——数据库 |
算法 | 专栏——算法 |
序
蚁群算法(Ant Colony Optimization , ACO)也是一种群体智能算法,主要模拟了蚂蚁的觅食行为来解决离散优化问题,非常经典的就是TSP问题,它可以很好地解决。(收敛性很好,性能很好)
一、蚁群觅食过程
蚂蚁觅食完全是随机选择路径,但是,他们会释放一种化学性物质——信息素。信息素会随着时间的推移而消逝,蚂蚁会在路径中不断释放信息素。如果每只蚂蚁在单位距离留下的信息素相同,那么较短路径上残留的信息素浓度就会相对较高,这被后来的蚂蚁选择的概率就大,从而导致了一个正反馈的过程。
这里存在一个问题,为什么越短的路径信息素浓度就会越高呢? 本人在学习这个算法的时候是有这个疑问的,直到我看到了下面这种图。
其中圆圈代表蚂蚁释放的信息素,A和D是起点和终点,两只蚂蚁选择不同的路径去走。
假设他们速度相同,这时候你会发现,路径短的那只蚂蚁已经走到终点了,但是路径长的蚂蚁还在半路上。
注意,这时候选择B路劲的蚂蚁要搬着食物回来了,如下图:
在这种情况下,信息素浓度就发现了明显的差异。后面其它蚂蚁会受到高浓度信息素的影响,他们会更倾向于选择B路径。因此,信息素浓度差就拉开了,最终信息素含量最高的那条路,就是最短的(最优点)。
这就很好地回答了上面的疑问,简言之,蚂蚁不仅要去,还要回来呀,回来使得最短路径的信息素浓度高于其它路径了。
根据这个原理,我们就设计出了蚁群算法(Ant Colony Optimization , ACO),算法的具体原理如下。
二、算法原理
蚂蚁对路径的选择主要依据信息素,信息素的变化主要有以下 2 个原因:
- 挥发:信息素会随着时间的推移而衰减。
- 增强:会随着蚂蚁走过这条路径而增强。
每只蚂蚁根据信息素浓度和启发式信息选择下一步怎么走。
根据这两个因素,我们可以得到下一步走各个城市的概率,如下:
p i , j k ( t ) = { [ τ i , j ( t ) ] α [ η i , j ( t ) ] β ∑ s ∈ J k ( i ) [ τ i s ( t ) ] α ⋅ [ η i s ] β , 当 j ∈ J k ( i ) 时 0 , 其它 (1) p_{i,j}^k(t)= \begin{cases} \frac{[\tau_{i,j}(t)]^{\alpha}[\eta_{i,j}(t)]^{\beta}}{\sum_{s\in J_k(i)}[\tau_{is}(t)]^{\alpha}\cdot[\eta_{is}]^{\beta}},\quad & 当j\in J_k(i)时\\ 0, \quad & 其它 \end{cases} \tag{1} pi,jk(t)=⎩ ⎨ ⎧∑s∈Jk(i)[τis(t)]α⋅[ηis]β[τi,j(t)]α[ηi,j(t)]β,0,当j∈Jk(i)时其它(1)
其中,
J
k
(
i
)
=
{
1
,
2
,
.
.
.
,
n
}
J_k(i)=\{1,2,...,n\}
Jk(i)={1,2,...,n}表示蚂蚁 k
允许选择的城市集合(走过了的城市这一次周期就不会再走了,不放在
J
k
J_k
Jk 中);
τ i , j ( t ) \tau_{i,j}(t) τi,j(t)表示蚂蚁第 t t t 次迭代时候,地点 i i i 到地点 j j j 上的信息素浓度;
η i , j \eta_{i,j} ηi,j 是一个启发式因子,表示蚂蚁从城市 i 到城市 j 之间的距离倒数,通常用城市 i 到城市 j之间距离的倒数来表示。
各路径上的信息素更新如下:
τ i , j ( t + 1 ) = ( 1 − ρ ) ⋅ τ i , j ( t ) + Δ τ i , j (2) \tau_{i,j}(t+1)=(1-\rho)\cdot\tau_{i,j}(t)+\Delta\tau_{i,j} \tag{2} τi,j(t+1)=(1−ρ)⋅τi,j(t)+Δτi,j(2)
其中, ρ \rho ρ( 0 < ρ < 1 0<\rho<1 0<ρ<1)表示信息素浓度的衰减系数, 1 − ρ 1-\rho 1−ρ表示信息素浓度的持久性系数; Δ τ i , j \Delta\tau_{i,j} Δτi,j表示本次迭代中边 ij 上信息素的增量,即:
Δ τ i , j = ∑ k = 1 m Δ τ i j k (3) \Delta\tau_{i,j}=\sum_{k=1}^{m}\Delta\tau_{ij}^k \tag{3} Δτi,j=k=1∑mΔτijk(3)
其中, Δ τ i j k \Delta\tau_{ij}^k Δτijk 表示第 k 只蚂蚁在本次迭代中留在边 ij 上的信息素量,如果蚂蚁 k 没有经过边 ij,那么 Δ τ i , j k \Delta\tau_{i,j}^k Δτi,jk 的值为0;
信息素增量 Δ τ i , j k \Delta\tau_{i,j}^k Δτi,jk 定义如下:
Δ τ i , j k = { Q L k , 当蚂蚁 k 在本次周永中经过边 i j 时 0 , 其它 (4) \Delta\tau_{i,j}^k= \begin{cases} \frac{Q}{L_k},\quad & 当蚂蚁 k 在本次周永中经过边 ij 时\\ 0, \quad & 其它 \end{cases} \tag{4} Δτi,jk={LkQ,0,当蚂蚁k在本次周永中经过边ij时其它(4)
其中,Q为正常数, L k L_k Lk表示第k只蚂蚁在本次周游中所走过路径的长度。这个信息素增量模型叫做 ant-cycle 模型。
除此之外,还有其它的信息素增量模型,比如 ant-quantity 模型,如下:
Δ τ i , j k = { Q d i , j , 当蚂蚁 k 在本次周永中经过边 i j 时 0 , 其它 (5) \Delta\tau_{i,j}^k= \begin{cases} \frac{Q}{d_{i,j}},\quad & 当蚂蚁 k 在本次周永中经过边 ij 时\\ 0, \quad & 其它 \end{cases} \tag{5} Δτi,jk={di,jQ,0,当蚂蚁k在本次周永中经过边ij时其它(5)
ant-density 模型如下:
Δ τ i , j k = { Q , 当蚂蚁 k 在本次周永中经过边 i j 时 0 , 其它 (6) \Delta\tau_{i,j}^k= \begin{cases} Q,\quad & 当蚂蚁 k 在本次周永中经过边 ij 时\\ 0, \quad & 其它 \end{cases} \tag{6} Δτi,jk={Q,0,当蚂蚁k在本次周永中经过边ij时其它(6)
但是,试验结果标明,ant-cycle 模型比其它两种模型有更好的性能。这是因为,ant-cycle 模型利用了全局信息更新路径上的信息素量,而 ant-quantity 模型和 ant-density 模型仅使用了局部信息。
三、算法详细流程
1. 算法伪代码
- 参数初始化。令时间 t=0,初始化循环次数 N c N_c Nc,设置最大循环次数 G G G,将m各蚂蚁随机至于n个城市上,初始化每条边上的信息素含量等,具体看后面代码。
- 循环次数 N c = N c + 1 N_c=N_c+1 Nc=Nc+1
- 蚂蚁的禁忌表索引号 k = 1 k=1 k=1。
- 蚂蚁数目 k = k + 1 k=k+1 k=k+1
- 蚂蚁个体根据状态转移概率公式,来选择下一步的城市 J ∈ { J k ( i ) } J\in \{J_k(i)\} J∈{Jk(i)}
- 将选择好的城市添加到禁忌表中来。
- 将所有城市都遍历完,即 k < m k<m k<m,跳转到第 4 步,否则执行第 8 步。
- 记录本次最佳路线。
- 根据公式(2,3,4)更新每条路径上的信息量。
- 若满足算法结束条件,即 N c ≥ G N_c\geq G Nc≥G,则结束循环并输出程序优化结果,否则清空禁忌表,跳转到第 2 步开启下一次周游。
2. 算法流程图
算法流程图,如下图所示:
四、详细参数设置
这些参数一般都是大了也不行,小了效果也不好,一般经过大量试验,满足一定的统计规律,如下。
1. 信息素启发式因子 α \alpha α
- 值越大:选择之前走过的路的可能性越大,收敛快,但随机性下降,容易陷入局部最优。
- 值越小:也不行,主要受第二项 β \beta β 影响,陷入贪婪搜索。
一般取 [ 1 , 4 ] [1,4] [1,4] 之间。
2. 期望启发因子 β \beta β
和上面相互制衡的,所以效果基本就是反着的。
- 值越大:陷入贪婪搜索。
- 值越小:随机性下降,算法缺乏探索性。
一般取值 [ 3 , 5 ] [3,5] [3,5]。
算法要获得最优解,就要在 α \alpha α 和 β \beta β 之间选择一个比较好的搭配关系,才能避免模型陷入局部最优。
3. 信息素衰减系数 ρ \rho ρ
信息素浓度衰减系数,取 [ 0 , 1 ] [0, 1] [0,1] 之间的数。
- 值过大:信息素挥发相对变多,随机性强,收敛慢。
- 值过小:挥发相对少,随机性弱,容易陷入局部最优。
4. 蚂蚁数目 m m m
蚁群算法的种群规模。
- 太大了:不容易收敛,计算时间长;
- 太小了:丧失全局性,陷入局部最优解。
一般取 [ 10 , 50 ] [10,50] [10,50]。
5. 信息素强度 Q Q Q
可以任意选取,现有研究标明,不会对算法最终结果产生明显影响(因为,我们概率计算的时候是相对的大小,而Q是对所有蚂蚁来讲的一个参数,所以影响有限)
6. 最大进化代数 G G G
- 太大了,浪费时间和计算资源,收敛慢。
- 太小了陷入局部最优。
一般 G 选择 [ 100 , 500 ] [100,500] [100,500]。
五、Matlab仿真实例
1. 问题
旅行商问题,假设有一个旅行商人,要拜访全国31个省会城市,他选择所要走的路径,限制是每个城市智能拜访一次,而且最后要回到原来触发的城市。
求解:所有路径中长度最小的路径。
31 个省会城市的位置坐标数据如下:
[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]
2. 分析
利用蚁群算法进行求解。
生成 1 个蚂蚁种群,给所有路径初始化信息素浓度。同时,信息素浓度的更新根据蚂蚁的路线。蚂蚁的路线选择又根据信息素浓度和启发因子。
启发因子就是两个省会之间距离的倒数。
这样就将 TSP 问题转换为模拟蚂蚁的觅食过程。
参数设置见代码开头。
3. Matlab代码实现
matlab源码已经逐行注释,逻辑较为简洁,对算法详细实现感兴趣的话,可以进行阅读。
%%%%%%%%%%%%%%%%%%%%蚁群算法解决TSP问题%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all; %清除所有变量
close all; %清图
clc; %清屏
m=50; %蚂蚁个数
Alpha=1; %信息素重要程度参数
Beta=5; %启发式因子重要程度参数
Rho=0.1; %信息素蒸发系数
G_max=200; %最大迭代次数
Q=100; %信息素增加强度系数
C=[1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;...
3238 1229;4196 1044;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 2376;...
3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;...
2370 2975]; %31个省会城市坐标
%%%%%%%%%%%%%%%%%%%%%%%%第一步:变量初始化%%%%%%%%%%%%%%%%%%%%%%%%
n=size(C,1); %n表示问题的规模(城市个数)
D=zeros(n,n); %D表示两个城市距离间隔矩阵
for i=1:n
for j=i: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; % 设置为最接近0的浮点误差
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(G_max,n); % 各代最佳路线
L_best=inf.*ones(G_max,1); % 各代最佳路线的长度
figure(1); % 优化解
while NC<=G_max
%%%%%%%%%%%%%%%%%%第二步:将m只蚂蚁放到n个城市上%%%%%%%%%%%%%%%%
Randpos=[];
for i=1:(ceil(m/n)) % 这里是每个城市平均来放置的,做到公平
Randpos=[Randpos,randperm(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; % J 的索引
for k=1:n % 遍历所有城市
if length(find(visited==k))==0 % 如果没有访问到
J(Jc)=k; % 把他加入到 J 中去
Jc=Jc+1; % 更新 Jc
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); % 从前到后进行累加
Select=find(Pcum>=rand); % 进行了一个轮盘赌
to_visit=J(Select(1)); % 获取轮盘赌选到的元素
Tabu(i,j)=to_visit; % 第 i 只蚂蚁的第 j 个城市就选择轮盘赌选到的这个
end
end
if NC>=2 % 如果有原始数据
Tabu(1,:)=R_best(NC-1,:); % 这一步就是在这一轮加入了上一轮最好的解
end
%%%%%%%%%%%%%%%%%%%第四步:记录本次迭代最佳路线%%%%%%%%%%%%%%%%%%
L=zeros(m,1); % 用来记录每只蚂蚁这轮走过的距离
for i=1:m % 遍历所有的蚂蚁
R=Tabu(i,:); % 获取这只蚂蚁的路线
for j=1:(n-1) % 遍历这条路线中两两城市之间的边
L(i)=L(i)+D(R(j),R(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),:); % 获取最佳路线,并跟踪记录在 R_best 中
%%%%%%%%%%%%%%%%%%%%%%%%%第五步:更新信息素%%%%%%%%%%%%%%%%%%%%%%
Delta_Tau=zeros(n,n); % 定义信息素的增量
for i=1:m
for j=1:(n-1) % 第 i 个蚂蚁对它的路线的贡献
Delta_Tau(Tabu(i,j),Tabu(i,j+1))=...
Delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);
end
Delta_Tau(Tabu(i,n),Tabu(i,1))=... % 第 i 个蚂蚁对头尾顶点连线的贡献
Delta_Tau(Tabu(i,n),Tabu(i,1))+Q/L(i);
end
Tau=(1-Rho).*Tau+Delta_Tau; % 更新信息素,持久量 + 增量
%%%%%%%%%%%%%%%%%%%%%%%第六步:禁忌表清零%%%%%%%%%%%%%%%%%%%%%%
Tabu=zeros(m,n); % 清空 m 只蚂蚁的禁忌表
%%%%%%%%%%%%%%%%%%%%%%%%%历代最优路线%%%%%%%%%%%%%%%%%%%%%%%%%%
for i=1:n-1 % 绘制历代最优路线的图
plot([ C(R_best(NC,i),1), C(R_best(NC,i+1),1)],... % 绘制 n-1 条边
[C(R_best(NC,i),2), C(R_best(NC,i+1),2)],'bo-');
hold on;
end
plot([C(R_best(NC,n),1), C(R_best(NC,1),1)],... % 连接首尾边
[C(R_best(NC,n),2), C(R_best(NC,1),2)],'ro-');
title(['优化最短距离:',num2str(L_best(NC))]); % title 是这一代的最短距离
hold off;
pause(0.005); % 停止 0.005s 给程序员看以下 ^-^
NC=NC+1; % 更新代数
end
%%%%%%%%%%%%%%%%%%%%%%%%%%第七步:输出结果%%%%%%%%%%%%%%%%%%%%%%%%%%
Pos=find(L_best==min(L_best)); % 寻找最优索引
Shortest_Route=R_best(Pos(1),:); % 获取最佳路线
Shortest_Length=L_best(Pos(1)); % 获取最佳路线长度
figure(2), % 增加 1 个 figure,显示适应度曲线变化
plot(L_best) % 显示图像
xlabel('迭代次数') % x轴标签
ylabel('目标函数值') % y轴标签
title('适应度进化曲线') % 图标 title
4. 求解效果
优化后的最优路线如下:
值得注意的是,蚁群算法在解决TSP问题时收敛性非常好,每次都可以很好地收敛到最优解。
适应度曲线变化如下:
the end……
蚁群算法(Ant Colony Optimization , ACO)到这里就要结束啦~~到此既是缘分,欢迎您的点赞、评论、收藏!关注我,不迷路,我们下期再见!!
😘😘😘 我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
💞💞💞 内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
👋👋👋 我们相互交流,共同进步!
注:本文由
非妃是公主
发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/129507112