[Learning Notes]Ant Colony Optimization——蚁群算法

简介

蚁群算法(Ant Colony Optimization, ACO),又被称为蚂蚁算法,是一种基于概率机制的路径优化方法,主要用于图结构中的最优路径搜索。该算法最初由 Marco Dorigo 于 1992 年在其博士论文 “Ant System: Optimization by a Colony of Cooperating Agents” 中提出,灵感源自蚂蚁在觅食过程中通过信息素寻找最短路径的自然行为。作为一种仿生演化优化技术,蚁群算法在早期研究中展现出良好的性能。针对 PID 控制器参数的优化设计问题,研究将其与遗传算法的优化结果进行对比,仿真结果显示蚁群算法作为一种新型的仿生优化方法,具备较强的实用性和应用潜力。

在自然界中,蚂蚁群体通过信息素(Pheromone)这一化学物质实现间接通信,从而协作寻找从蚁巢到食物源的最优路径。信息素的浓度直接影响蚂蚁的路径选择行为,形成一种基于正反馈的群体智能机制

蚂蚁在搜索食物时路径选择最初具有随机性,但会受到信息素浓度的引导。信息素由蚂蚁个体释放,并在路径上形成浓度梯度。由于较短路径的往返时间更短,单位时间内经过的蚂蚁数量更多,导致信息素积累速度更快。下图展示了蚂蚁通过传递信息素寻找十五的示意图。
蚁群根据信息素觅食的过程

随着时间推移,较短路径上的信息素浓度逐渐超过其他路径。后续蚂蚁倾向于选择信息素浓度较高的路径,形成正反馈循环。同时,信息素存在挥发效应,使得非最优路径上的信息素逐渐消失。最终整个蚁群会收敛到最优路径上。如图所示,路线1以5个单位时间到达了食物处,即可返回,然后经过10个单位时间后返回洞穴,那么路线1上的信息素在此时是路线2的两倍,而之后的蚂蚁在进行前进路线选择的时候,会更倾向于选择路线1,并且随着时间的推移路线1上的信息素增长速率更快,导致后续的蚂蚁又会更大概率选择路线1,形成了一套正反馈机制。这种生物行为被抽象为蚁群优化算法,特别适用于解决组合优化问题。算法模拟了信息素的动态更新机制和路径选择概率,通过多智能体的协同搜索实现全局优化。
在这里插入图片描述
通过模拟自然界中蚂蚁觅食行为的过程,可以构建出相应的抽象模型。这使我们能够将蚁群觅食的实际现象与蚁群优化算法中的各类要素进行一一对应,具体如下表所示。

蚁群觅食现象蚁群优化算法
蚁群搜索空间中的一组解(表示为种群规模 m
觅食空间问题的搜索空间(对应问题规模,即问题的维数 n
信息素信息素浓度变量
蚁集到达食物的一条路径一个有效解
找到的最短路径问题的最优解

算法流程

接下来以求解TSP(旅行商问题)为例,来描述蚁群优化算法的计算流程。
设有一个城市集合 Cn={c1,c2,⋯ ,cn}C_n = \{c_1, c_2, \cdots, c_n\}Cn={c1,c2,,cn},其中 nnn 表示城市的数量。假设任意两个城市之间均存在路径连接,记 dijd_{ij}dij 表示城市 cic_ici 与城市 cjc_jcj 之间的距离,其中 i,j∈{1,2,⋯ ,n}i, j \in \{1, 2, \cdots, n\}i,j{1,2,,n}。该距离为已知参数,可以是预设的数值,或由城市的空间坐标计算得出dij=∣∣ci−cj∣∣d_{ij}=||c_i - c_j||dij=∣∣cicj∣∣。旅行商问题的目标是:从某一指定城市出发,经过所有城市且每个城市仅访问一次,最终回到出发城市,使得所经过路径的总距离最短。该路径构成一个最短的哈密顿回路,即:
min⁡π∈Sn∑k=1ndπ(k),π(k+1),π(n+1)=π(1) \begin{aligned} &\min_{\pi \in S_n}\sum_{k=1}^{n} d_{\pi(k),\pi(k+1)}, & \pi(n+1)=\pi(1) \end{aligned} πSnmink=1ndπ(k),π(k+1),π(n+1)=π(1)
其中,π\piπ 表示城市访问顺序的一个排列,SnS_nSn 表示所有城市排列的集合。

路径构建

AS 中的随机比例规则(random proportional):对于每只蚂蚁kkk,路径记忆向量 RkR^kRk按照访问顺序记录了所有kkk已经经过的城市序号。设蚂蚁kkk当前所在城市为iii,则其选择城市jjj作为下一个访问对象的概率为
pk(i,j)={[τ(i,j)]α[η(i,j)]β∑u∈Jk(i)[τ(i,u)]α[η(i,u)]β,j∈Jk(i)0,其他 \begin{aligned} p_k(i,j) = \begin{cases} \frac{[\tau(i,j)]^\alpha [\eta(i,j)]^\beta}{\sum_{u \in J_k(i)} [\tau(i,u)]^\alpha [\eta(i,u)]^\beta}, & j \in J_k(i) \\ 0, & \text{其他} \end{cases} \end{aligned} pk(i,j)=uJk(i)[τ(i,u)]α[η(i,u)]β[τ(i,j)]α[η(i,j)]β,0,jJk(i)其他
其中,Jk(i)J_k(i)Jk(i)表示城市iii可以直接到达的且又不在蚂蚁访问过的城市序列RkR^kRk中的城市集合。η(i,j)\eta(i,j)η(i,j)是一个启发式信息,通常由η(i,j)=1dij\eta(i,j)=\frac{1}{d_{ij}}η(i,j)=dij1直接计算。τ(i,j)\tau(i,j)τ(i,j)表示弧(i,j)(i,j)(i,j)上的信息素量。α\alphaαβ\betaβ是预先设置的参数用来控制启发式信息和信息素浓度作用的权重关系,对于控制算法的迭代收敛起到很关键的因素。可以看到,当α=0\alpha=0α=0时,AS选择距离最近城市的概率最大,那么会演变成为一个传统的贪心算法;当β=0\beta=0β=0时,则探索过程完全只根据信息素浓度确定路径,算法将快速收敛。

信息素更新

  • 在进行计算时,问题涉及到所有信息的起点都应归一化为τ0\tau_0τ0。如果τ0\tau_0τ0太小,算法容易提前停止迭代,即蚂蚁很快就全部集中在一条局部最优的路径上。反之,如果τ0\tau_0τ0太大,信息素对搜索方向的指导作用太低,也会影响算法性能。一般来说,使用τ0=mCnn\tau_0=\frac{m}{C^{nn}}τ0=Cnnm,"是蚂蚁的个数,CnnC^{nn}Cnn是由贪婪算法构造的路径的长度。
  • 在每轮迭代过程中,问题空间中各条路径上的信息素会发生一定程度的蒸发,即对每条边上的信息素值乘以一个小于 1 的系数。信息素的蒸发反映了自然界中信息素随时间衰减的特性,同时在算法中能够有效防止信息素无限累积,从而加速淘汰质量较差的历史路径。
  • 随后,蚂蚁依据其当前构建路径的质量(通常以路径长度衡量),在其所经过的边上释放新的信息素。路径越短的蚂蚁,其在边上释放的信息素量越大;同一条边被多只蚂蚁选择的频次越高,所累积的信息素也越多,从而进一步提高其被选中的概率。
  • 以上过程不断重复,直至满足算法终止条件。
    具体的,城市iii与城市jjj的相连边上的信息素量(i,j)(i,j)(i,j)按如下公式进行更新:

τ(i,j)=(1−ρ)⋅τ(i,j)+∑k=1mΔτk(i,j)Δτk(i,j)={(Ck)−1,(i,j)∈Rk0,其他 \begin{aligned} &\tau(i,j) = (1 - \rho) \cdot \tau(i,j) + \sum_{k=1}^{m} \Delta \tau_k(i,j) \\ &\Delta \tau_k(i,j) = \begin{cases} (C_k)^{-1}, & (i,j) \in R^k \\ 0, & \text{其他} \end{cases} \end{aligned} τ(i,j)=(1ρ)τ(i,j)+k=1mΔτk(i,j)Δτk(i,j)={(Ck)1,0,(i,j)Rk其他
其中,

  • mmm是蚂蚁的个数;
  • 0<ρ≤10<\rho\leq10<ρ1是信息素的蒸发率,一般设置为0.50.50.5
  • Δτk(i,j)\Delta \tau_k(i,j)Δτk(i,j)表示蚂蚁kkk在其经过的边上释放的信息素量,等于本轮构建路径的长度的倒数;
  • CkC_kCk表示路径的长度,是RkR_kRk中所有的边的长度总和。
    AS 求解 TSP 的流程图和伪代码

最后,我们对路径构建的两种基本方式进行探讨:顺序构建(sequential construction)与并行构建(parallel construction)。

  • 顺序构建是指:在每轮迭代中,所有蚂蚁依次独立完成路径构建。即,当一只蚂蚁从起始城市出发并完成一条完整路径(遍历所有城市并返回起点)后,下一只蚂蚁才开始进行路径构建。在这种方式中,每只蚂蚁在构建路径时,通常会基于当前路径上的信息素状态做出决策。
  • 并行构建则是指:所有蚂蚁在每轮迭代中同时进行路径构建。具体地说,每一“步”中,所有蚂蚁根据当前所处城市和状态转移规则选择下一个城市,并同步前进一步,直至所有蚂蚁均完成路径构建。该方式更贴近自然界中蚂蚁集体行为的同步性,也便于在程序中利用并行计算进行加速。

对于标准的蚁群系统而言,这两种构建方式在算法性能和最终结果上是理论等价的;但在后续发展出的某些改进型蚁群算法(如蚁群系统改进型ACS、最大最小蚁群系统MMAS等)中,两者的使用方式可能会对算法收敛速度和解的质量产生不同程度的影响。因此,构建方式的选择在算法设计中是一个值得关注的因素。

应用示例

考虑四个城市A,B,C,DA,B,C,DA,B,C,D的TSP问题,距离矩阵如下:
W=dij=[∞3123∞5415∞2242∞] \begin{aligned} W = d_{ij} = \begin{bmatrix} \infty & 3 & 1 & 2 \\ 3 & \infty & 5 & 4 \\ 1 & 5 & \infty & 2 \\ 2 & 4 & 2 & \infty \end{bmatrix} \end{aligned} W=dij=312354152242
参数设置:蚁群规模m=3m=3m=3α=1\alpha=1α=1β=2\beta=2β=2ρ=0.5\rho=0.5ρ=0.5

具体的算法求解过程如下:

    1. 初始化:实现使用贪心算法(Greedy Algorithm)求解得到解:Rg=[A→C→D→B→A]R_{g}=[A\rightarrow C\rightarrow D\rightarrow B\rightarrow A]Rg=[ACDBA],则Cnn=f(Rg)=1+2+4+3=10C^{nn}=f(R_g)=1+2+4+3=10Cnn=f(Rg)=1+2+4+3=10。则τ0=mCnn=0.3\tau_0=\frac{m}{C^{nn}}=0.3τ0=Cnnm=0.3。令所有边上的信息素τij=τ0\tau_{ij}=\tau_0τij=τ0
    1. 为每只蚂蚁随机选择出发城市假设蚂蚁111选择城市AAA,蚂蚁222选择城市BBB,蚂蚁333选择城市DDD
    1. 为每只蚂蚁选择下一访问城市,这里仅以蚂蚁111为例,当前城市AAA,可访间城市集合J1(i)={B,C,D}J_1(i)=\{B,C,D \}J1(i)={B,C,D}。计算蚂蚁111选择下一访问城市的概率:
      A⇒{B:τABα×ηABβ=0.31×(1/3)2=0.033C:τACα×ηACβ=0.31×(1/1)2=0.3D:τADα×ηADβ=0.31×(1/2)2=0.075p(B)=0.0330.033+0.3+0.075=0.081p(C)=0.30.033+0.3+0.075=0.74p(D)=0.0750.033+0.3+0.075=0.18 \begin{aligned} &A \Rightarrow \begin{cases} B: \tau_{AB}^{\alpha} \times \eta_{AB}^{\beta} = 0.3^1 \times (1/3)^2 = 0.033 \\ C: \tau_{AC}^{\alpha} \times \eta_{AC}^{\beta} = 0.3^1 \times (1/1)^2 = 0.3 \\ D: \tau_{AD}^{\alpha} \times \eta_{AD}^{\beta} = 0.3^1 \times (1/2)^2 = 0.075 \end{cases} \\ & p(B) = \frac{0.033}{0.033 + 0.3 + 0.075} = 0.081 \\ & p(C) = \frac{0.3}{0.033 + 0.3 + 0.075} = 0.74 \\ & p(D) = \frac{0.075}{0.033 + 0.3 + 0.075} = 0.18 \end{aligned} AB:τABα×ηABβ=0.31×(1/3)2=0.033C:τACα×ηACβ=0.31×(1/1)2=0.3D:τADα×ηADβ=0.31×(1/2)2=0.075p(B)=0.033+0.3+0.0750.033=0.081p(C)=0.033+0.3+0.0750.3=0.74p(D)=0.033+0.3+0.0750.075=0.18
      用轮盘赌法则选择下一访问城市。假设产生的随机数q=random(0,1)=0.05q=random(0,1)=0.05q=random(0,1)=0.05,则蚂蚁111将会选择城市BBB。用同样的方法为蚂蚁222333选择下一访问城市,假设蚂蚁222选择城市DDD,蚂蚁333选择城市AAA
    1. 当前蚂蚁111所在城市i=Bi=Bi=B,路径记忆向量R1=(AB)R^1=(AB)R1=(AB),可访问城市集合J1(i)={C,D}J_1(i)=\{C,D\}J1(i)={C,D}。计算蚂蚁1选择C、D作为下一城市的概率,再通过轮盘赌选择下一个访问的城市。对于蚂蚁222333同样操作。
    1. 直到可访问城市集合J1(i)=∅J_1(i)=\emptyJ1(i)=,三只蚂蚁构建的路径为:
    • 蚂蚁111[A→B→D→C→A][A\rightarrow B\rightarrow D\rightarrow C\rightarrow A][ABDCA]
    • 蚂蚁222[B→D→C→A→B][B\rightarrow D\rightarrow C\rightarrow A\rightarrow B][BDCAB]
    • 蚂蚁333[D→A→C→B→D][D\rightarrow A\rightarrow C\rightarrow B\rightarrow D][DACBD]
    1. 信息素更新:计算每只蚂蚁构建路径的长度f(R1)=10,f(R2)=10,f(R3)=12f(R^1)=10,f(R^2)=10,f(R^3)=12f(R1)=10,f(R2)=10,f(R3)=12;更新每条边上的信息素
      τAB=(1−ρ)×τAB+∑k=13ΔτABk=0.5×0.3+(110+110)=0.35τAC=(1−ρ)×τAC+∑k=13ΔτACk=0.5×0.3+(112)=0.16...... \begin{aligned} &\tau_{AB} = (1 - \rho) \times \tau_{AB} + \sum_{k=1}^{3} \Delta \tau^k_{AB} = 0.5 \times 0.3 + \left( \frac{1}{10} + \frac{1}{10} \right) = 0.35 \\ &\tau_{AC} = (1 - \rho) \times \tau_{AC} + \sum_{k=1}^{3} \Delta \tau^k_{AC} = 0.5 \times 0.3 + \left( \frac{1}{12} \right) = 0.16 \\ &...... \end{aligned} τAB=(1ρ)×τAB+k=13ΔτABk=0.5×0.3+(101+101)=0.35τAC=(1ρ)×τAC+k=13ΔτACk=0.5×0.3+(121)=0.16......
    1. 如果满足结束条件,则输出结果并结束程序,否则,转向步骤2继续执行。

改进版本

精华蚂蚁系统(Elitist Ant System,EAS)

AS算法中,蚂蚁在路径上释放的信息素量与路径长度成反比,较优路径的边会积累更多信息素,从而在后续迭代中被优先选择。然而,面对大规模城市问题时,这种基础机制可能导致搜索效率不足,存在收敛速度瓶颈。
EAS算法在AS基础上引入了一种强化策略:除了常规的信息素更新外,每轮迭代结束后,搜索到当前最优路径(记为TbT_bTb)的蚂蚁会为该路径的边额外添加信息素。这种机制通过主动增强潜在最优路径的吸引力,加速搜索过程向高质量解收敛。EAS中边(i,j)(i,j)(i,j)的信息素量τ(i,j)\tau(i,j)τ(i,j)更新包含两部分:

  • 常规信息素更新:所有蚂蚁根据其构建路径的质量释放信息素。
  • 精华路径强化:当前最优路径T的边获得额外信息素增量,其强度通常与路径长度成反比。
    公式如下:
    τ(i,j)=(1−ρ)⋅τ(i,j)+∑k=1nΔτk(i,j)+eΔb(i,j)Δτk(i,j)={(Ck)−1,(i,j)∈Rk0,其他Δb(i,j)={(Cb)−1,(i,j) 在路径 Tb 上0,其他 \begin{aligned} &\tau(i,j) = (1 - \rho) \cdot \tau(i,j) + \sum_{k=1}^{n} \Delta \tau_k(i,j) + e \Delta_b(i,j) \\ &\Delta \tau_k(i,j) = \begin{cases} (C_k)^{-1}, & (i,j) \in R^k \\ 0, & \text{其他} \end{cases} \\ &\Delta_b(i,j) = \begin{cases} (C_b)^{-1}, & (i,j) \text{ 在路径 } T_b \text{ 上} \\ 0, & \text{其他} \end{cases} \end{aligned} τ(i,j)=(1ρ)τ(i,j)+k=1nΔτk(i,j)+eΔb(i,j)Δτk(i,j)={(Ck)1,0,(i,j)Rk其他Δb(i,j)={(Cb)1,0,(i,j) 在路径 Tb 其他
    这里新增了Δb(i,j)\Delta_b(i,j)Δb(i,j),并定义参数eee作为其权重。在每轮迭代中为属于最优路径TbT_bTb的弧增加了额外的eCb\frac{e}{C_b}Cbe的信息数量。该机制有效提升了算法对最优解的探索能力,尤其适用于复杂的大规模组合优化问题。

基于排列的蚂蚁系统(rank-based Ant System,ASrank\text{AS}_{\text{rank}}ASrank)

随着精华蚂蚁系统的提出,研究者开始探索更高效的信息素更新机制。这种机制需要强化T及各边信息素浓度,同时对其他边的信息素更新规则进行优化。基于排列的蚂蚁系统(rank-based Ant System, ASrank\text{AS}_{\text{rank}}ASrank)是其中的一种改进方案。
ASrank\text{AS}_{\text{rank}}ASrank在传统蚂蚁系统的基础上引入了权值机制。蚂蚁释放的信息素量与其路径质量直接相关,通过权值进一步放大信息素浓度的差异,从而更有效地引导搜索过程。每一轮迭代中,所有蚂蚁完成路径构建后,系统会根据路径长度对它们进行排名筛选。在每一轮所有蚂蚁构建完路径后,它们将按照所得路径的长短进行排名,只有生成了至今最优路径的蚂蚁和排名在前(ω−1)(\omega-1)(ω1)的蚂蚁才被允许释放信息素,蚂蚁在边(i,j)(i,j)(i,j)上释放的信息素 Δτk(i,j)\Delta \tau_k(i,j)Δτk(i,j)的权值由蚂蚁的排名决定。ASrank\text{AS}_{\text{rank}}ASrank中的信息素更新规则如下:
τ(i,j)=(1−ρ)⋅τ(i,j)+∑k=1ω−1(ω−k)Δτk(i,j)+ωΔb(i,j)Δτk(i,j)={(Ck)−1,(i,j)∈Rk0,其他Δτb(i,j)={(Cb)−1,(i,j) 在路径 Tb 上0,其他 \begin{aligned} &\tau(i,j) = (1 - \rho) \cdot \tau(i,j) + \sum_{k=1}^{\omega - 1} (\omega - k)\Delta \tau_k(i,j) + \omega \Delta_b(i,j) \\ &\Delta \tau_k(i,j) = \begin{cases} (C_k)^{-1}, & (i,j) \in R^k \\ 0, & \text{其他} \end{cases} \\ &\Delta \tau_b(i,j) = \begin{cases} (C_b)^{-1}, & (i,j) \text{ 在路径 } T_b \text{ 上} \\ 0, & \text{其他} \end{cases} \end{aligned} τ(i,j)=(1ρ)τ(i,j)+k=1ω1(ωk)Δτk(i,j)+ωΔb(i,j)Δτk(i,j)={(Ck)1,0,(i,j)Rk其他Δτb(i,j)={(Cb)1,0,(i,j) 在路径 Tb 其他
蚂蚁在构建当前最优路径T时,该路径可能不包含在当前迭代的路径中。蚁群算法假设蚂蚁具备记忆功能,能够始终保留历史最优路径的信息。最优路径T的边将增加信息素量,其权值大小为ω/C\omega/Cω/C,其中ω\omegaω通常设置为666。这一机制使得路径TbT_bTb获得最大的信息素增量。在每次迭代中,排名第k(k=1,2,⋯ ,ω−1)k(k=1,2,\cdots,\omega-1)k(k=1,2,,ω1)的蚂蚁释放的信息素量为(ω−k)/Ck(\omega-k)/C_k(ωk)/Ck。排名越高的蚂蚁释放的信息素量越多,权值(ω−k)(\omega-k)(ωk)的设计放大了不同路径之间的信息素浓度差异。这种机制增强了算法对蚂蚁搜索方向的引导能力。文献[4]表明与经典蚁群算法AS及精英蚂蚁系统EAS相比,该算法表现出更高的寻优效率和更快的收敛速度。

最大最小蚂蚁系统(MAX-MIN Ant System,MMAS)

为了避免探索过程中陷入局部最优和退化,MMAS在基本 AS 算法的基础上进行了下列四项改进:

  • (1)只允许迭代最优蚂蚁(在本次迭代构建出最短路径的蚂蚁),或者至今最优蚂蚁释放信息素。
  • (2)信息素量大小的取值范围被限制在一个区间内。
  • (3)信息素初始值为信息素取值区间的上限,并伴随一个较小的信息素蒸发速率。
  • 4)每当系统进入停滞状态,问题空间内所有边上的信息素量都会被重新初始化。

精华蚂蚁系统(EAS)仅允许历史最优解的蚂蚁释放信息素,而MMAS的更新机制更为灵活,允许历史最优解或当前迭代最优解的蚂蚁释放信息素。MMAS中这两种更新规则通常会交替使用。

仅采用历史最优解更新规则时,算法会表现出较强的导向性,快速收敛至历史最优解附近。仅采用迭代最优解更新规则时,算法的探索能力增强,但收敛速度会降低。针对不同规模的问题,这两种规则的适用性存在差异:小规模TSP问题仅需迭代最优更新,而大规模问题中历史最优更新规则的重要性会显著提升。实验表明,通过算法迭代过程动态调整更新策略效果更佳,具体表现为逐步提高历史最优更新规则的使用概率。这种动态调整策略能够平衡算法的探索与开发能力。

在MMAS算法中,为防止某些边上的信息素浓度增长过快导致早熟收敛(即蚂蚁集中搜索次优路径而非全局最优路径),采取了信息素浓度限制策略。将信息素量限定在固定区间[0<ρmin,ρmax≤1][0<\rho_{min},\rho_{max}\leq 1][0<ρmin,ρmax1]内,确保搜索多样性。且当且仅当蚂蚁只剩下一个可访问的城市时才有ρmin=ρmax=1\rho_{min}=\rho_{max}=1ρmin=ρmax=1

MMAS在初始化时将各边信息素τmax\tau_{max}τmax设置为统一估计值,并采用较低的信息素蒸发率(通常 (ρ=0.02\rho = 0.02ρ=0.02)。这种设计使得不同边的信息素差异缓慢累积,从而在初期阶段增强全局探索能力。相较于基础AS、EAS等算法,MMAS在初始阶段更倾向于广泛搜索,随后逐步收敛至全局最优路径。这种“先探索后聚焦”的策略提升了找到最优解的可能性。

蚁群系统(Ant Colony System,ACS)

1997年,蚁群算法的创始人 Dorigo在文献[5]中提出了一种具有全新机制的 ACO 算法——蚁群系统(Ant Colony System,ACS),进一步提高了ACO 算法的性能。ACS是蚁群算法发展史上的又一里程碑式的作品,在这一小节详细介绍蚁群系统的工作流程。

ACS与蚂蚁系统的不同主要体现在三个方面:

    1. 使用一种伪随机比例规则(pseudorandom proportional)选择下一城市节点,建立开发当前路径与探索新路径之间的平衡。
    1. 信息素全局更新规则只在属于至今最优路径的边上蒸发和释放信息素。
    1. 新增信息素局部更新规则,蚂蚁每次经过空间内的某条弧,它都会去除该弧上一定量的信息素,以增加后续蚂蚁探索其余路径的可能性。

一般的,ACS的算法求解过程如下:

  • 初始阶段,将mmm只蚂蚁随机或均匀分布在nnn个城市上。每只蚂蚁根据状态转移规则选择下一个访问的城市,优先选择信息素浓度较高且距离较短的路径。
  • 蚂蚁具有记忆能力,每只蚂蚁携带一个搜索禁忌表,确保在单次遍历中不会重复访问已走过的城市。蚂蚁在移动过程中会对经过的路径执行信息素局部更新
  • 当所有蚂蚁完成哈密顿回路的构建后,系统记录本轮最短路径,并依据信息素全局更新规则增强该路径上的信息素浓度。
  • 算法通过迭代上述过程直至满足终止条件。
    ACS求解TSP的流程如下:
    ACS求解TSP的流程图

状态转移规则

  • 定义:ACS 中的伪随机比例规则(pseudorandom proportional):对于每只蚂蚁kkk,路径记忆向量RkR^kRk按照访问顺序记录了所有kkk已经经过的城市序号。设蚂蚁kkk当前所在城市为iii,则下一个访问城市
    j={arg⁡max⁡j∈Jk(i){[τ(i,j)],[η(i,j)]β},q≤q0S,其他 \begin{aligned} j = \begin{cases} \arg \max_{j \in J_k(i)} \left\{ [\tau(i,j)] , [\eta(i,j)]^{\beta} \right\}, & q \leq q_0 \\ S, & \text{其他} \end{cases} \end{aligned} j={argmaxjJk(i){[τ(i,j)],[η(i,j)]β},S,qq0其他

其中,Jk(i)J_k(i)Jk(i)表示从城市iii可以直接到达的且又不在蚂蚁访问过的城市序列RkR^kRk中的城市集合。τ(i,j)\tau(i,j)τ(i,j)η(i,j)\eta(i,j)η(i,j)分别表示弧(i,j)(i,j)(i,j)上的信息素量和启发式信息。β\betaβ是描述信息素浓度和路径长度信息相对重要性的控制参数。随机参数0≤q0≤10\leq q_0\leq 10q01控制访问的过程:

  • q≤q0q\leq q_0qq0时,蚂蚁直接选择使启发式信息与信息素量的β\betaβ指数乘积最大的下一城市节点,通常称之为开发(exploitation)
  • 当产生的随机数q>q0q> q_0q>q0时,ACS 将和各种 AS 算法一样使用轮盘赌选择策略,此时算法执行方式称为偏向探索(biased exploration),根据下式计算访问概率:
    pk(i,j)={[τ(i,j)][η(i,j)]β∑u∈Jk(i)[τ(i,u)][η(i,u)]β,j∈Jk(i)0,其他 \begin{aligned} p_k(i,j) = \begin{cases} \frac{\left[ \tau(i,j) \right] \left[ \eta(i,j) \right]^\beta}{\sum_{u \in J_k(i)} \left[ \tau(i,u) \right] \left[ \eta(i,u) \right]^\beta}, & j \in J_k(i) \\ 0, & \text{其他} \end{cases} \end{aligned} pk(i,j)=uJk(i)[τ(i,u)][η(i,u)]β[τ(i,j)][η(i,j)]β,0,jJk(i)其他
    在ACS中,q0q_0q0是一个关键的控制变量,它直接影响算法的搜索行为。状态转移规则中,蚂蚁以概率q0q_0q0选择当前最优移动方向,而以概率1−q01-q_01q0进行偏向性路径探索。通过调节q0q_0q0的值,可以动态调整算法在“局部开发”与“全局探索”之间的权衡,从而影响对最优路径邻域的集中搜索或对其他区域的广泛探索。

信息素全局更新规则

在 ACS中,信息素的全局更新遵循一种更加严格的机制:仅允许当前为止构造出最优路径的蚂蚁(即自算法运行以来路径长度最短的个体)释放信息素。该策略与伪随机比例的状态转移规则相结合,显著增强了搜索过程的导向性和收敛速度。具体而言,在每轮迭代中,待所有蚂蚁均完成路径构建之后,才会执行信息素的全局更新操作,其更新过程可通过如下公式表达:
τ(i,j)=(1−ρ)⋅τ(i,j)+ρ⋅Δτb(i,j),∀(i,j)∈Tk \begin{aligned} \tau(i,j) = (1 - \rho) \cdot \tau(i,j) + \rho \cdot \Delta \tau_b(i,j), \quad \forall (i,j) \in T_k \end{aligned} τ(i,j)=(1ρ)τ(i,j)+ρΔτb(i,j),(i,j)Tk
其中Δτb(i,j)=1/Cb\Delta \tau_b(i,j)=1/C_bΔτb(i,j)=1/Cb。需要特别指出的是,无论是信息素的蒸发还是释放,在 ACS 中均仅发生于当前最优路径所包含的边上。这一机制与传统的 AS(Ant System)存在显著差异——在 AS 中,信息素的更新作用于图中所有边,使得信息素更新的计算复杂度为 O(n2)O(n^2)O(n2);而 ACS 仅对最优路径上的边进行信息素调整,从而将计算复杂度有效降低至 O(n)O(n)O(n)。其中,参数 ρ\rhoρ 表示信息素的蒸发速率。每条边 (i,j)(i,j)(i,j) 上新增的信息素量 Δτb(i,j)\Delta \tau_b(i,j)Δτb(i,j) 会被乘以系数 ρ\rhoρ,从而使更新后的信息素浓度介于原有信息素水平与新增释放量之间。这种方式在一定程度上隐式地起到了与 MMAS(Max-Min Ant System)算法中信息素取值范围限制类似的效果,但实现更为简洁高效。

信息素局部更新规则

在ACS中,在路径构建过程中,对每一只蚂蚁,每当其经过一条边(i,i)(i,i)(i,i)时,它将立刻对这条边进行信息素的更新,更新所使用的公式如下:
τ(i,j)=(1−ξ)⋅τ(i,j)+ξ⋅τ0 \begin{aligned} \tau(i,j) = (1 - \xi) \cdot \tau(i,j) + \xi \cdot \tau_0 \end{aligned} τ(i,j)=(1ξ)τ(i,j)+ξτ0
其中,0<ξ<10<\xi<10<ξ<1是信息素局部挥发速率,一般设置为0.10.10.1,信息素初始值τ0=1n⋅Cnn\tau_0=\frac{1}{n\cdot C^{nn}}τ0=nCnn1nnn为城市数目。
因为τ0=1n⋅Cnn≤τ(i,j)\tau_0=\frac{1}{n\cdot C^{nn}}\leq \tau(i,j)τ0=nCnn1τ(i,j),上式所计算出来的更更新后的信息素相比更新前减少了,这一调整使得当前边被后续蚂蚁选择的概率下降。通过降低已访问边的信息素强度,该机制促使蚂蚁探索未被频繁选择的路径。这种策略增强了算法的全局搜索能力,有效防止搜索过程过早收敛至局部最优解。

示例代码

定义算法(这部分代码为郭飞老师在git上的scikit-opt库(https://github.com/guofei9987/scikit-opt),大家可以去start一下。)

import numpy as np


class ACA_TSP:
    def __init__(self, func, n_dim,
                 size_pop=10, max_iter=20,
                 distance_matrix=None,
                 alpha=1, beta=2, rho=0.1,
                 ):
        self.func = func
        self.n_dim = n_dim  # 城市数量
        self.size_pop = size_pop  # 蚂蚁数量
        self.max_iter = max_iter  # 迭代次数
        self.alpha = alpha  # 信息素重要程度
        self.beta = beta  # 适应度的重要程度
        self.rho = rho  # 信息素挥发速度

        self.prob_matrix_distance = 1 / (distance_matrix + 1e-10 * np.eye(n_dim, n_dim))  # 避免除零错误

        self.Tau = np.ones((n_dim, n_dim))  # 信息素矩阵,每次迭代都会更新

        self.Table = np.zeros((size_pop, n_dim), dtype=int)  # 某一代每个蚂蚁的爬行路径

        self.y = None  # 某一代每个蚂蚁的爬行总距离
        self.generation_best_X, self.generation_best_Y = [], []  # 记录各代的最佳情况
        self.x_best_history, self.y_best_history = self.generation_best_X, self.generation_best_Y  # 历史原因,为了保持统一
        self.best_x, self.best_y = None, None

    def run(self, max_iter=None):
        self.max_iter = max_iter or self.max_iter
        for i in range(self.max_iter):  # 对每次迭代
            prob_matrix = (self.Tau ** self.alpha) * (self.prob_matrix_distance) ** self.beta  # 转移概率,无须归一化。
            for j in range(self.size_pop):  # 对每个蚂蚁
                self.Table[j, 0] = 0  # start point,其实可以随机,但没什么区别
                for k in range(self.n_dim - 1):  # 蚂蚁到达的每个节点
                    taboo_set = set(self.Table[j, :k + 1])  # 已经经过的点和当前点,不能再次经过
                    allow_list = list(set(range(self.n_dim)) - taboo_set)  # 在这些点中做选择
                    prob = prob_matrix[self.Table[j, k], allow_list]
                    prob = prob / prob.sum()  # 概率归一化
                    next_point = np.random.choice(allow_list, size=1, p=prob)[0]
                    self.Table[j, k + 1] = next_point

            # 计算距离
            y = np.array([self.func(i) for i in self.Table])

            # 顺便记录历史最好情况
            index_best = y.argmin()
            x_best, y_best = self.Table[index_best, :].copy(), y[index_best].copy()
            self.generation_best_X.append(x_best)
            self.generation_best_Y.append(y_best)

            # 计算需要新涂抹的信息素
            delta_tau = np.zeros((self.n_dim, self.n_dim))
            for j in range(self.size_pop):  # 每个蚂蚁
                for k in range(self.n_dim - 1):  # 每个节点
                    n1, n2 = self.Table[j, k], self.Table[j, k + 1]  # 蚂蚁从n1节点爬到n2节点
                    delta_tau[n1, n2] += 1 / y[j]  # 涂抹的信息素
                n1, n2 = self.Table[j, self.n_dim - 1], self.Table[j, 0]  # 蚂蚁从最后一个节点爬回到第一个节点
                delta_tau[n1, n2] += 1 / y[j]  # 涂抹信息素

            # 信息素飘散+信息素涂抹
            self.Tau = (1 - self.rho) * self.Tau + delta_tau

        best_generation = np.array(self.generation_best_Y).argmin()
        self.best_x = self.generation_best_X[best_generation]
        self.best_y = self.generation_best_Y[best_generation]
        return self.best_x, self.best_y

    fit = run

运行代码

import numpy as np
from scipy import spatial
import pandas as pd
import matplotlib.pyplot as plt

num_points = 25

points_coordinate = np.random.rand(num_points, 2)  # generate coordinate of points
distance_matrix = spatial.distance.cdist(points_coordinate, points_coordinate, metric='euclidean')


def cal_total_distance(routine):
    num_points, = routine.shape
    return sum([distance_matrix[routine[i % num_points], routine[(i + 1) % num_points]] for i in range(num_points)])


# %% Do ACA
# from sko.ACA import ACA_TSP

aca = ACA_TSP(func=cal_total_distance, n_dim=num_points,
              size_pop=50, max_iter=200,
              distance_matrix=distance_matrix)

best_x, best_y = aca.run()

# %% Plot
fig, ax = plt.subplots(1, 2)
best_points_ = np.concatenate([best_x, [best_x[0]]])
best_points_coordinate = points_coordinate[best_points_, :]
ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')
pd.DataFrame(aca.y_best_history).cummin().plot(ax=ax[1])
plt.show()

结果展示
代码运行结果

Refs

[1] 维基百科. 蚁群算法 [EB/OL]. https://zh.wikipedia.org/wiki/%E8%9A%81%E7%BE%A4%E7%AE%97%E6%B3%95
[2] Dorigo M, Maniezzo V, Colorni A. Ant system: optimization by a colony of cooperating agents[J]. IEEE transactions on systems, man, and cybernetics, part b (cybernetics), 1996, 26(1): 29-41.
[3] 《计算智能》张军 詹志辉等编著
[4] B Bullnheimer,R F Hartl,C Strauss. A new rank based version of the Ant System: acomputational study. Central European Journal for Operations Research and Fconomics, 1999, ?(1):25-38.
[5] Dorigo, Marco, and Luca Maria Gambardella. “Ant colony system: a cooperative learning approach to the traveling salesman problem.” IEEE Transactions on evolutionary computation 1.1 (1997): 53-66.
[6] @misc{scikit-opt,
author = {Guofei},
title = {scikit-opt},
year = {2021},
publisher = {GitHub},
howpublished = {\url{https://github.com/guofei9987/scikit-opt}},
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值