蚁群算法(Ant Colony Optimization , ACO)

本文详细介绍了蚁群算法的原理,包括信息素挥发与增强、蚂蚁路径选择的概率公式,以及算法的伪代码和流程图。通过Matlab实现旅行商问题的求解,展示了算法在解决实际问题中的应用,并探讨了参数设置对算法性能的影响。此外,还提供了不同信息素增量模型的比较。
摘要由CSDN通过智能技术生成

在这里插入图片描述

作者:非妃是公主
专栏:《智能优化算法》
博客地址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)= sJk(i)[τis(t)]α[ηis]β[τi,j(t)]α[ηi,j(t)]β,0,jJk(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=1mΔτ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. 算法伪代码

  1. 参数初始化。令时间 t=0,初始化循环次数 N c N_c Nc,设置最大循环次数 G G G,将m各蚂蚁随机至于n个城市上,初始化每条边上的信息素含量等,具体看后面代码。
  2. 循环次数 N c = N c + 1 N_c=N_c+1 Nc=Nc+1
  3. 蚂蚁的禁忌表索引号 k = 1 k=1 k=1
  4. 蚂蚁数目 k = k + 1 k=k+1 k=k+1
  5. 蚂蚁个体根据状态转移概率公式,来选择下一步的城市 J ∈ { J k ( i ) } J\in \{J_k(i)\} J{Jk(i)}
  6. 将选择好的城市添加到禁忌表中来。
  7. 将所有城市都遍历完,即 k < m k<m k<m,跳转到第 4 步,否则执行第 8 步。
  8. 记录本次最佳路线。
  9. 根据公式(2,3,4)更新每条路径上的信息量。
  10. 若满足算法结束条件,即 N c ≥ G N_c\geq G NcG,则结束循环并输出程序优化结果,否则清空禁忌表,跳转到第 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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cherries Man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值