蚁群算法简要介绍及算法实现解决TSP问题

蚁群算法简介和算法实现

  1. 蚁群算法背景及实现方法简要介绍

    1. 背景

      ​ 单只蚂蚁的行为及其简单,行为数量在10种以内,但成千上万只蚂蚁组成的蚁群却能拥有巨大的智慧,这离不开它们信息传递的方式——信息素。
      ​ 蚂蚁在行走过程中会释放一种称为“信息素”的物质,用来标识自己的行走路径。在寻找食物的过程中,根据信息素的浓度选择行走的方向,并最终到达食物所在的地方。
      信息素会随着时间的推移而逐渐挥发。
      ​ 在一开始的时候,由于地面上没有信息素,因此蚂蚁们的行走路径是随机的。蚂蚁们在行走的过程中会不断释放信息素,标识自己的行走路径。随着时间的推移,有若干只蚂蚁找到了食物,此时便存在若干条从洞穴到食物的路径。由于蚂蚁的行为轨迹是随机分布的,因此在单位时间内,短路径上的蚂蚁数量比长路径上的蚂蚁数量要多,从而蚂蚁留下的信息素浓度也就越高。这为后面的蚂蚁们提供了强有力的方向指引,越来越多的蚂蚁聚集到最短的路径上去。
      ​ (1)高度结构化的组织——虽然蚂蚁的个体行为极其简单,但由个体组成的蚁群却构成高度结构化的社会组织,蚂蚁社会的成员有分工,有相互的通信和信息传递。
      ​ (2)自然优化——蚁群在觅食过程中,在没有任何提示下总能找到从蚁巢到食物源之间的最短路径;当经过的路线上出现障碍物时,还能迅速找到新的最优路径。
      ​ (3)信息正反馈——蚂蚁在寻找食物时,在其经过的路径上释放信息素(外激素)。蚂蚁基本没有视觉,但能在小范围内察觉同类散发的信息素的轨迹,由此来决定何去何从,并倾向于朝着信息素强度高的方向移动。
      ​ (4)自催化行为——某条路径上走过的蚂蚁越多,留下的信息素也越多(随时间蒸发一部分),后来蚂蚁选择该路径的概率也越高。

    2. 实现方法

      (1)根据具体问题设置多只蚂蚁,分头并行搜索。
      (2)每只蚂蚁完成一次周游后,在行进的路上释放信息素,信息素量与解的质量成正比。
      (3)蚂蚁路径的选择根据信息素强度大小(初始信息素量设为相等),同时考虑两点之间的距离,采用随机的局部搜索策略。这使得距离较短的边,其上的信息素量较大,后来的蚂蚁选择该边的概率也较大。
      (4)每只蚂蚁只能走合法路线(经过每个城市1次且仅1次),为此设置禁忌表来控制。
      (5)所有蚂蚁都搜索完一次就是迭代一次,每迭代一次就对所有的边做一次信息素更新,原来的蚂蚁死掉,新的蚂蚁进行新一轮搜索。
      (6)更新信息素包括原有信息素的蒸发和经过的路径上信息素的增加。
      (7)达到预定的迭代步数,或出现停滞现象(所有蚂蚁都选择同样的路径,解不再变化),则算法结束,以当前最优解作为问题的最优解。

  2. 用途

    主要用来解决路径优化问题!!!

  3. 参数

    • m:蚂蚁数量;

    • k:蚂蚁编号;

    • t:时刻;

    • n:城市数;

    • d i,j d_\text{i,j} di,j:城市(i,j)之间的距离;

    • η i,j \eta_\text{i,j} ηi,j:启发式因子(能见度)反应蚂蚁由城市i转移到城市j的启发程度;
      η i,j = 1 d i,j \displaystyle\eta_\text{i,j}=\frac{1}{d_\text{i,j}} ηi,j=di,j1

    • τ i,j \tau_\text{i,j} τi,j:边(i,j)上的信息素;
      τ i,j ( t + n ) = ( 1 − ρ ) ⋅ τ i,j ( t ) + Δ τ i,j τ i,j ( 0 ) = C \tau_\text{i,j}(t+n)=(1-\rho)\cdot\tau_\text{i,j}(t)+\Delta\tau_\text{i,j}\\ \tau_\text{i,j}(0)=C τi,j(t+n)=(1ρ)τi,j(t)+Δτi,jτi,j(0)=C

    • Δ τ i,j \Delta\tau_\text{i,j} Δτi,j:本次迭代边(i,j)上的信息素增量;
      Δ τ i,j = ∑ k = 1 m Δ τ i,j k Δ τ i,j ( 0 ) = 0 \Delta\tau_\text{i,j}=\sum_{k=1}^m\Delta\tau_\text{i,j}^k\\ \Delta\tau_\text{i,j}(0)=0 Δτi,j=k=1mΔτi,jkΔτi,j(0)=0

    • Δ τ i,j k \Delta\tau_\text{i,j}^k Δτi,jk:第k只蚂蚁在本次迭代中留在边(i,j)上的信息素量;
      Δ τ i,j k = { Q L k   ,   若 蚂 蚁 在 本 次 周 游 中 经 过 变 ( i , j ) 0   ,   其 他 \Delta\tau_\text{i,j}^k= \left\{ \begin{array}{l} \displaystyle\frac{Q}{L_k}\ ,\ 若蚂蚁在本次周游中经过变(i,j)\\ 0\ ,\ 其他 \end{array} \right. Δτi,jk=LkQ , (i,j)0 , 

      Q — — 正 常 数 ; L k — — 蚂 蚁 k 在 本 次 周 游 中 所 走 的 路 径 的 长 度 。 \begin{array}{l} Q——正常数;\\ L_k——蚂蚁k在本次周游中所走的路径的长度。 \end{array} QLkk

    • ρ \rho ρ:信息素蒸发(或挥发)系数;

    • 1 − ρ 1-\rho 1ρ:持久性(或残留)系数,0< ρ \rho ρ<1;

    • P i,j k ( t ) P_\text{i,j}^k(t) Pi,jk(t):时刻t蚂蚁k由城市i转移到城市j的概率(转移概率);
      P i,j k ( t ) = { [ τ i,j ( t ) ] α ⋅ [ η i,j ( t ) ] β ∑ s ∈ J k ( i ) [ τ i,s ( t ) ] α ⋅ [ η i,s ( t ) ] β P_\text{i,j}^k(t)= \left\{ \begin{array}{l} \displaystyle\frac{[\tau_\text{i,j}(t)]^{\alpha}\cdot[\eta_\text{i,j}(t)]^\beta}{\displaystyle\sum_{s\in J_k(i)}[\tau_\text{i,s}(t)]^{\alpha}\cdot[\eta_\text{i,s}(t)]^\beta} \end{array} \right. Pi,jk(t)=sJk(i)[τi,s(t)]α[ηi,s(t)]β[τi,j(t)]α[ηi,j(t)]β

      α — — 信 息 素 的 相 对 重 要 程 度 ; β — — 启 发 式 因 子 的 相 对 重 要 程 度 ; J k ( i ) — — 蚂 蚁 k 下 一 步 允 许 选 择 的 城 市 合 集 \begin{array}{l} \alpha——信息素的相对重要程度;\\ \beta——启发式因子的相对重要程度;\\ J_k(i)——蚂蚁k下一步允许选择的城市合集 \end{array} αβJk(i)k

    • t a b o o k taboo_k tabook:蚂蚁k的禁忌表

  4. 算法流程

    1. 所有参数的初始化(包括城市距离表、各种系数等)

    2. 寻找每次迭代下的最佳路径

      1. 确定每只蚂蚁的初始位置和终点位置

      2. 计算每只蚂蚁该次迭代下的路径

        1. 确定在该城市下的禁忌表 ⟹ \Longrightarrow 进而确定下一步可以选择的城市
        2. 计算可选城市中每一座的转移概率
        3. 依据转移概率,按照轮盘赌法确认下一座城市
        4. 通过一次重复上述过程,确认一只蚂蚁的运动路径
      3. 计算每只蚂蚁走过的路程

      4. 按照当前计算出的路径更新各城市间道路的信息素

      5. 计算出该次迭代下所走路程最小的蚂蚁及其走过的路径和路程

    3. 在计算出的所有迭代次数中的最优路径寻找长度最小的一条

    4. 将结果进行打印展示

  5. 流程总结
    蚁群算法简要介绍及算法实现解决TSP问题_第1张图片
    6.示例代码(解决TSP问题)

%% I. 清空环境变量
clear
clc
close all

%% II. 导入数据
x = [2, 4, 7, 13, 18, 18, 22, 24, 25, 25, 37, 41, 41, 44, 45, 54, 54, 58, 58, 62, 64, 68, 71, 71, 74, 82, 83, 83, 87, 91];
y = [99, 50, 64, 40, 40, 54, 60, 42, 38, 62, 84, 26, 94, 35, 21, 62, 67, 35, 69, 32, 60, 58, 44, 71, 78, 7, 46, 69, 76, 38];

citys = [];

for i = 1:length(x)
    citys = [citys; [x(i), y(i)]];
end

%% III. 获得城市距离地图表

n = length(citys); % 城市个数
CitysDistanceTable = zeros(n, n); % 各城市之间距离矩阵
CitysNameList = 1:n; % 城市名称索引(主要给下面禁忌表构建使用)
% 计算个城市之间距离,构建距离矩阵表
for i = 1:n

    for j = 1:n

        if i ~= j
            CitysDistanceTable(i, j) = sqrt(sum((citys(i, :) - citys(j, :)).^2));
        else
            CitysDistanceTable(i, j) = 0;
        end

    end

end

%% IV. 初始化参数

m = 200; % 蚁群数量
eta = 1 ./ CitysDistanceTable; % 可见度
tau = ones(n, n); % 信息素浓度矩阵
rho = 0.1; % 信息素挥发系数
Q = 1; % 一常数,与信息素浓度有关(个人感觉取任何数都可以)
alpha = 1; % 信息素相对重要程度
beta = 5; % 能见度相对重要程度
iter_Max = 200; % 最大迭代次数
Thre = 0.1; % 当所求最优解不变次数超过iter_Max*Thre时,终止迭代
waitbarjiange = iter_Max / 100; % 和进度条有关的一个数据
RouteBest = zeros(iter_Max, n + 1); % 每次迭代最优路径合集
LengthBest = zeros(iter_Max, 1); % 每次迭代路径最小值合集

%% V. 迭代寻找最佳路径
tic
% 添加进度条
h = waitbar(0, ['已完成:0%   搜索中...   已用时:', num2str(toc)]);

i = 1; % 迭代次数初始化
ConstantNumberOfTimes = 0; % 最优解不变次数计数初始化
% 开始迭代,迭代有两个限制条件
% 1. 迭代次数达到iter_Max
% 2. 连续iter_Max*Thre次最优解不出现变化
while (i <= iter_Max) && (ConstantNumberOfTimes < iter_Max * Thre)
    RouteTable = zeros(m, n + 1); % 当前迭代次数下路径存放表初始化
    RouteStart = zeros(m, 1); % 蚁群初始位置
    % 初始化蚁群初始位置
    for j = 1:m
        temp = randperm(n);
        RouteStart(j) = temp(1);
    end

    % 确认蚁群初始位置和最终位置
    RouteTable(:, 1) = RouteStart;
    RouteTable(:, end) = RouteStart;

    % 计算该次迭代下,每只蚂蚁的路径
    for j = 1:m
        % 第j只蚂蚁的情况
        for k = 2:n
            % 计算第j只蚂蚁经过的第k的城市
            % 计算的依据转移概率
            TabooList = RouteTable(j, 1:k - 1); % 第j只蚂蚁经过了k-1座城市后的禁忌表
            % 计算第j只蚂蚁第k个城市的可选项
            RouteAllow_temp = ~ismember(CitysNameList, TabooList);
            RouteAllow = CitysNameList(RouteAllow_temp);
            % 计算第j只蚂蚁每个可选城市的转移概率
            P = zeros(1, length(RouteAllow));

            for l = 1:length(P)
                P(l) = (tau(TabooList(end), RouteAllow(l)))^alpha * (eta(TabooList(end), RouteAllow(l)))^beta;
            end

            P = P ./ sum(P);
            % 依据轮盘赌法确定第j只蚂蚁的下一个城市
            % 为什么用轮盘赌法不清楚,但是实际证明,该方法效果明显优于寻找最大转移概率
            P = cumsum(P);
            target_index = find(P >= rand);
            NextTarget = RouteAllow(target_index(1));
            RouteTable(j, k) = NextTarget;
        end

    end

    % 计算每只蚂蚁走过的路程
    Length = zeros(m, 1);

    for j = 1:m

        for k = 1:n
            Length(j) = Length(j) + CitysDistanceTable(RouteTable(j, k), RouteTable(j, k + 1));
        end

    end

    % 寻找该迭代次数下,蚁群中所走过的最短路径
    if i == 1
        [MinLength, MinLengthRouteIndex] = min(Length);
        RouteBest(i, :) = RouteTable(MinLengthRouteIndex, :);
        LengthBest(i) = MinLength;
    else
        [MinLength, MinLengthRouteIndex] = min(Length);
        % 该处判断的目的:让第二个迭代限制条件能够生效;同时使得画出的图像更加美观
        if LengthBest(i - 1) < MinLength
            RouteBest(i, :) = RouteBest(i - 1, :);
            LengthBest(i) = LengthBest(i - 1);
            ConstantNumberOfTimes = ConstantNumberOfTimes + 1;
        else
            RouteBest(i, :) = RouteTable(MinLengthRouteIndex, :);
            LengthBest(i) = MinLength;
            ConstantNumberOfTimes = 0;
        end

    end

    % 更新信息素
    Delta_Tau = zeros(n, n);

    for j = 1:m

        for k = 1:n
            Delta_Tau(RouteTable(j, k), RouteTable(j, k + 1)) = ...
                Delta_Tau(RouteTable(j, k), RouteTable(j, k + 1)) + ...
                Q / Length(j);
        end

    end

    tau = (1 - rho) * tau + Delta_Tau;
    % 生成进度条
    if mod(i, waitbarjiange) == 0
        waitbar(i / iter_Max, h, ['已完成:', num2str(i / iter_Max * 100), '%   搜索中...   已用时:', num2str(toc)]);
    end

    i = i + 1;
end

close(h)
%% VI. 绘图与打印结果

% 打印最短路径和最短距离
Shortest_Length = LengthBest(i - 1);
Shortest_Route = RouteBest(i - 1, :);
disp(['最短距离', num2str(Shortest_Length)]);
disp(['最短路径', num2str(Shortest_Route)]);
% 绘制路径最优解
figure(1)
plot(citys(Shortest_Route, 1), citys(Shortest_Route, 2), 'o-');

for i = 1:n
    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), 1), citys(Shortest_Route(end - 1), 2), '       终点');
xlabel('城市位置横坐标')
ylabel('城市位置纵坐标')
title(['蚁群算法优化路径(最短距离:' num2str(Shortest_Length) ')'])

% 绘制最短路径长度变化曲线
figure(2)
plot(1:i - 1, LengthBest(1:i - 1), 'b')
legend('最短距离')
xlabel('迭代次数')
ylabel('距离')
title('各代最短距离')

你可能感兴趣的:(算法,图论,机器学习)