蚁群算法

算法介绍

蚁群算法(ant colony optimization, ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型算法。其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。

蚁群算法应用广泛,如旅行商问题(traveling salesman problem,简称TSP)、指派问题、Job-shop调度问题、车辆路径问题(vehicle routing problem)、图着色问题(graph coloring problem)和网络路由问题(network routing problem)等。本文以TSP问题为例进行介绍。

蚁群算法这种算法具有分布计算、信息正反馈和启发式搜索的特征,本质上是进化算法中的一种启发式全局优化算法。

TSP问题

旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。

假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。

启发式算法

启发式算法是一类用于寻找复杂优化问题近似解的方法,特别适用于在计算资源有限的情况下求解大型问题。与精确算法不同,启发式算法不保证找到全局最优解,但能在可接受的时间内提供一个质量较高的解。

经典的启发式算法包括模拟退火、遗传算法、蚁群算法、神经网络等。

算法思想

蚂蚁在行走过程中会释放一种称为“信息素”的物质,用来标识自己的行走路径。在寻找食物的过程中,根据信息素的浓度选择行走的方向,并最终到达食物所在的地方。信息素会随着时间的推移而逐渐挥发。

路径较短的蚂蚁释放的信息素量较多,随着时间的推进,较短的路径上累积的信息素浓度逐渐增高,选择该路径的蚂蚁个数也愈来愈多。最终,整个蚂蚁会在正反馈的作用下集中到最佳的路径上, 此时对应的便是待优化问题的最优解。

算法原理

算法流程

  1. 初始化: 在计算之初需要对相关的参数进行初始化,如蚂蚁数量m、信息素因子α、启发函数因子β、信息素挥发因子ρ、信息素常数Q、最大迭代次数t 等。

  2. 构建解空间:将各个蚂蚁随机地放置于不同的出发点,对每个蚂蚁k(k=1,2,……,m),计算其下一个待访问的城市,直到所有蚂蚁访问完所有的城市。

  3. 更新信息素:计算各个蚂蚁经过的路径长度L,记录当前迭代次数中的最优解(最短路径)。同时,对各个城市连接路径上的信息素浓度进行更新。

  4. 判断是否终止:若迭代次数小于最大迭代次数则迭代次数加一,清空蚂蚁经过路径的记录表,并返回步骤二;否则终止计算,输出最优解。

原理解析

设整个蚂蚁群体中蚂蚁的数量为m,城市的数量为n。

城市i与城市j之间的相互距离为 $$d_{ij}(i,j=1,2,...,n)$$

t时刻城市i与城市j连接路径上的信息素浓度为 $$\tau _{ij}(t)$$ ,初始时刻各个城市连接路径上的信息素浓度相同,设为 $$\tau _{ij}(0)=\tau_0$$

t时刻蚂蚁k从城市i转移到城市j的概率为 $$P_{ij}^{k}(t)$$

蚂蚁从i到j的期望程度(启发函数)为 $$\eta_{ij}(t)=\frac{1}{d_{ij}}$$

蚁群算法的数学表示为

$$ P_{ij}^{k}(t)=\left\{ \begin{array}{rcl} \frac{[\tau _{ij}(t)]^{\alpha }[\eta_{ij}(t)]^{\beta }}{\sum_{s\in allow_k} [\tau_{is}(t)]^\alpha [\eta_{is}(t)]^\beta } & ,s\in allow_k \\ 0 & ,s\notin allow_k \end{array} \right. $$

$\alpha$ 为信息素重要程度因子 $\beta$ 为启发函数重要程度因子 $allow_k$ 表示蚂蚁待访问城市k

三种模型

  1. 第一种模型假设信息素总量一定。信息素浓度Q和经过路径的长度$L_k$成反比。
$$ \bigtriangleup \tau_{ij}^{k}=\left\{\begin{matrix} \frac{Q}{L_k} \\ 0 \end{matrix}\right. $$
  1. 第二种模型中不使用经过的总路径,而仅仅使用相邻城市的路径长度。
$$ \bigtriangleup \tau_{ij}^{k}=\left\{\begin{matrix} \frac{Q}{d_{ij} } \\ 0 \end{matrix}\right. $$
  1. 第三种模型不管距离长短,释放的信息素都一样。
$$ \bigtriangleup \tau_{ij}^{k}=\left\{\begin{matrix} Q \\ 0 \end{matrix}\right. $$

求解TSP问题

参数说明

蚂蚁数量:一般设置为目标数的1.5倍。当蚂蚁数量较多时,所有蚂蚁不容易收敛于一个解,而数量较少时,解的效果可能不会让人满意。

信息素重要程度因子:一般设置为[0,5]之间。蚂蚁移动过程中产生的信息素对蚂蚁的影响程度。参数越大,蚂蚁选择以前走过路径的可能性越大,会使蚁群更容易的收敛,导致搜索的随机性减弱不利于寻找全局最优解,过小就没有了信息素的意义。

启发函数重要程度因子:一般设置为[0,5]之间。反映了启发式信息在指导蚁群在路径搜索中的相对重要程度,其大小反映的是蚁群寻优过程种先验性、确定性因素作用的强度。越大越容易导致收敛过快。

信息素挥发因子:一般设置为[0.2,0.5]之间。指信息素的消失水平。它的大小直接关系到算法的全局搜索能力和收敛速度,过大导致信息素挥发过快,一些较好的路径会被排除,过小导致路径残留信息素较多,影响算法效率。

信息素常量:一般设置在[10,1000]。指蚂蚁在将路径走完时总共释放的信息素数量,往往和启发函数一起作用,问题规模越大信息素越高较好。

迭代次数:一般设置为[100,500]之间。指整个蚁群累积搜索了多少次,注意蚁群算法在搜索过程种是整个蚁群同时开始搜索,然后此蚁群循环迭代,迭代次数设置的过高对算法没有实质意义,一般使其能够收敛即可。

Python

Matlab

%% I. 清空环境变量
clear all
clc
%% II. 导入数据
% load citys_data.mat
 citys = [16.4700   96.1000
     16.4700   94.4400
     20.0900   92.5400
     22.3900   93.3700
     25.2300   97.2400
     22.0000   96.0500
     20.4700   97.0200
     17.2000   96.2900
     16.3000   97.3800
     14.0500   98.1200
     16.5300   97.3800
     21.5200   95.5900
     19.4100   97.1300
     20.0900   92.5500];
%% III. 计算城市间相互距离
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;  %如果是0会导致矩阵对角线都是0 导致启发函数无穷大 因此取个很小的值    
        end
    end    
end
 
%% IV. 初始化参数
m = 50;                              % 蚂蚁数量
alpha = 1;                           % 信息素重要程度因子
beta = 5;                            % 启发函数重要程度因子
rho = 0.1;                           % 信息素挥发因子
Q = 1;                               % 常系数
Eta = 1./D;                          % 启发函数
Tau = ones(n,n);                     % 信息素矩阵
Table = zeros(m,n);                  % 路径记录表,每一行代表一个蚂蚁走过的路径
iter = 1;                            % 迭代次数初值
iter_max = 200;                      % 最大迭代次数 
Route_best = zeros(iter_max,n);      % 各代最佳路径       
Length_best = zeros(iter_max,1);     % 各代最佳路径的长度  
Length_ave = zeros(iter_max,1);      % 各代路径的平均长度  
 
%% V. 迭代寻找最佳路径
while iter <= iter_max
     % 随机产生各个蚂蚁的起点城市
      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,清空路径记录表
    iter = iter + 1;
    Table = zeros(m,n);
end
 
%% VI. 结果显示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距离:' num2str(Shortest_Length)]);
disp(['最短路径:' num2str([Shortest_Route Shortest_Route(1)])]);
%% VII. 绘图
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('各代最短距离与平均距离对比')

参考

数学建模——蚁群算法(Ant Colony Algorithm, ACA)-CSDN博客

算法设计与分析-TSP六种方法-贪心算法(最近邻点、最短链接)、蛮力法、动态规划法、回溯法、分支限界法、模拟退火_tsp算法-CSDN博客

蚁群算法(实例帮助理解)-CSDN博客

智能优化算法之蚁群算法_蚁群算法公式-CSDN博客

蚁群算法 - BC_CJ - 博客园

发表评论