美文网首页【散人】数学建模
【国赛培训】蚁群算法

【国赛培训】蚁群算法

作者: 地球上的新新人 | 来源:发表于2019-08-12 16:40 被阅读4次

    时间:2019.8.12
    老师:祁永强
    内容:蚁群算法基本原理
    个性:“无中生有,自圆其说”,戴准帽子(套框架),优化算法必须能用matlab仿真,狠劲,炼狱式成长,书由厚到薄(按页)由薄到厚(),撕书式成长,佯装努力结果是没有差别的,为人师在于唤人醒,“日锯其半,万日不竭”,20页最佳

    感想:从原理上了解了蚁群算法,所找的一份ACATSP代码成功复现,并理解了全过程。唯独在下一个访问地点的概率计算与选择上稍有存疑,写在了最后。欢迎交流探讨观点,e-mail:03170908@cumt.edu.cn

    1.概述概念

    起源:意大利M.Dorigo等,通过模拟自然界蚂蚁搜索路径的行为,提出的新型模拟进化算法。
    原理:蚂蚁在运动过程中,能感知信息素,指导自己的运动方向(正反馈)。信息素越多越好,为什么,因为初始时,信息素越多说明往返越多(同样时间时),即路径最短。
    核心:信息素+正反馈(所有群体算法的核心)
    适用:求解TSP问题、分配问题、job-shop调度问题
    优势:求解复杂优化问题(特别是离散优化问题)
    比较优势:与大多数基于梯度的优化算法想比
    1.无集中控制约束,不会因个别的故障影响整个问题的求解,保证鲁棒性
    2.非直接信息交换,确保系统的扩展性
    3.并行分布式
    4.对问题定义的连续性无特殊要求
    5.算法实现简单

    2.蚁群算法基本思想

    信息素要按一定比率挥发(避免局部最优)

    每只蚂蚁的一部转移概率由图中的每条边上的两类参数决定:
    1.信息素值也称信息素痕迹
    2.可见度,即先验值

    信息素的更新方式:
    1 挥发 :所有路径上的信息素以一定比率进行减少
    2 增强 :给蚂蚁评价,好蚂蚁加强

    基于图的蚁群算法(GBAS)

    3.基本蚁群算法

    P_{ij}^k(t)表示t时刻蚂蚁k从城市i到城市j的转移概率,计算公式如下:

    P^k(i,j)=\left\{ \begin{aligned} &\frac {\tau[(i,j)]^\alpha{\cdot}{\eta}[(i,j)]^\beta}{\sum \limits_{s\in{J}_k({i})}\tau[(i,s)]^\alpha{\cdot}{\eta}[(i,s)]^\beta} & if\ j\in{J}_k(i) \\ &0& {otherwise} \end{aligned}\tag{1} \right.

    {\tau[(i,j)]^\alpha} :信息素
    {{\eta}[(i,j)]^\beta} : 信息素增强(启发式的体现,和距离负相关)
    \alpha\beta : 推荐1,5
    信息素挥发系数\rho:推荐0.5
    信息素增强\delta=Q/L,Q推荐1,L表示距离长度

    规模和终止条件:
    1 给定终止轮数
    2 最优解了连续次相同
    3 给定目标值

    4.【进阶】收敛

    马于尔科夫收敛定义,依概率收敛于1
    证明收敛,才能说算法是可以实现的
    蚁群算法分支:MAX-MIN蚂蚁,精英蚂蚁,蚁周算法,蚁密算法,蚁量算法

    5.代码实例

    蚁群算法针对TSP应用(超详细分析)
    ant-colony-algorithm-for-TSP(MATLAB可直接运行代码)
    原始出处:解放军信息工程大学老师
    下面代码注释为本人针对上面的资料进行学习之后添加,欢迎交流。转移矩阵部分务必参考上面的公式

    function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ACATSP(C,NC_max,m,Alpha,Beta,Rho,Q)
    %%-------------------------------------------------------------------------
    %% 主要符号说明
    %% C n个城市的坐标,n×2的矩阵
    %% NC_max 最大迭代次数
    %% m 蚂蚁个数
    %% Alpha 表征信息素重要程度的参数     1
    %% Beta 表征启发式因子重要程度的参数  5
    %% Rho 信息素蒸发系数                0.5
    %% Q 信息素增加强度系数               1
    %% R_best 各代最佳路线
    %% L_best 各代最佳路线的长度
    %%=========================================================================
     
    %%第一步:变量初始化
    n=size(C,1);%n表示问题的规模(城市个数)
    D=zeros(n,n);%D表示完全图的赋权邻接矩阵
    for i=1:n
        for j=1: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;      %i=j时不计算,应该为0,但后面的启发因子要取倒数,用eps(浮点相对精度)表示
            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(NC_max,n);       %各代最佳路线
    L_best=inf.*ones(NC_max,1);   %各代最佳路线的长度,先赋值inf无穷大,后面更新
    L_ave=zeros(NC_max,1);        %各代路线的平均长度
     
    while NC<=NC_max        %停止条件之一:达到最大迭代次数,停止
        %%第二步:将m只蚂蚁放到n个城市上,全放完需要[m/n]轮
            Randpos=[];   %#随机存取,此处初始起点,可以固定设置
        for i=1:(ceil(m/n))
            Randpos=[Randpos,randperm(n)];%randperm产生1到n的随机序列
        end %使用这种随机分配方法可以保证初始去往各个城市的蚂蚁数量均匀,比全部随机要更好
        Tabu(:,1)=(Randpos(1,1:m))';    %取出前m个,赋给Tabu路径矩阵,即给出了m只蚂蚁的初始去往地点
    
        %%第三步:m只蚂蚁按概率函数选择下一座城市,对应公式中的转移矩阵
        for j=2:n     %所在城市不计算,j表示即将访问的下一座城市
            for i=1:m    
                visited=Tabu(i,1:(j-1)); %记录已访问的城市,避免重复访问
                J=zeros(1,(n-j+1));       %待访问的城市,总数n-j+1
                P=J;                      %待访问城市的选择概率分布
                Jc=1;                     %待访问的城市个数,初始为1(用于修改矩阵J时做下标)
                for k=1:n
                    if isempty(find(visited==k, 1))%这里改善了寻找的性能,只要能找到一个等于K就非空
                        J(Jc)=k;
                        Jc=Jc+1;           %待访问的城市个数自加1
                    end
                end                         %循环完成后将更新完待访问矩阵J
                %下面计算从当前城市visted(end)转移到待选城市k的概率分布,参照公式的分子
                %信息素的作用也仅体现在这里,计算转移矩阵概率
                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);     %cumsum,元素向上(或向前)累加求和
                Select=find(Pcum>=rand); %若计算的概率大于rand的就可以选择这条路线
                to_visit=J(Select(1));   %选择可选城市列表Select中的第一个作为将访问的下一个
                Tabu(i,j)=to_visit;
            end
        end
    
        if NC>=2
            Tabu(1,:)=R_best(NC-1,:);  
            %NC=2开始,第一只蚂蚁路径使用上一轮的最佳路线,参与下面的信息素更新
            %#所以其实上面i=1那只蚂蚁的路径推演是没必要的,可以用if去优化掉
        end
    
        %%第四步:记录本次迭代最佳路线
        L=zeros(m,1);     %开始距离为0,m*1的列向量
        for i=1:m
            R=Tabu(i,:);
            for j=1:(n-1)
                L(i)=L(i)+D(R(j),R(j+1));    %原距离加上第j个城市到第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),:); %此轮迭代后的最佳路线
        L_ave(NC)=mean(L);           %此轮迭代后的平均距离
        NC=NC+1;                      %迭代继续
    
    
        %%第五步:更新信息素
        Delta_Tau=zeros(n,n);        %开始时信息素增量为n*n的0矩阵
        for i=1:m
            for j=1:(n-1)
                Delta_Tau(Tabu(i,j),Tabu(i,j+1))=Delta_Tau(Tabu(i,j),Tabu(i,j+1))+Q/L(i);          
            %此次循环在路径(i,j)上的信息素增量
            end
                Delta_Tau(Tabu(i,n),Tabu(i,1))=Delta_Tau(Tabu(i,n),Tabu(i,1))+Q/L(i);
            %#此次循环在从n会到起点上的信息素增量,对应要求,单程可删去
        end
        Tau=(1-Rho).*Tau+Delta_Tau; %考虑信息素挥发掉Rho,更新后的信息素,加上Delta
        %%第六步:路径表清零
        Tabu=zeros(m,n);             %%直到最大迭代次数
    end
    
    
    %%第七步:输出结果
    Pos=find(L_best==min(L_best));  %找到最佳路径(非0为真)
    Shortest_Route=R_best(Pos(1),:) %最大迭代次数后最佳路径
    Shortest_Length=L_best(Pos(1))  %最大迭代次数后最短距离
    
    subplot(1,2,1)                  %绘制第一个子图形
    DrawRoute(C,Shortest_Route)     %画路线图的子函数
    subplot(1,2,2)                  %绘制第二个子图形
    plot(L_best)
    hold on                         %保持图形
    plot(L_ave,'r')
    title('平均距离和最短距离')     %标题
    
    function DrawRoute(C,R)
    %%=========================================================================
    %% DrawRoute.m
    %% 画路线图的子函数
    %% C Coordinate 节点坐标,由一个N×2的矩阵存储
    %% R Route 路线
    %%=========================================================================
    N=length(R);
    scatter(C(:,1),C(:,2));
    hold on
    plot([C(R(1),1),C(R(N),1)],[C(R(1),2),C(R(N),2)],'g')%#这里绘制了起点到终点的直连线,非循环路径可删去
    hold on
    
    for i=2:N
        plot([C(R(i-1),1),C(R(i),1)],[C(R(i-1),2),C(R(i),2)],'g')
        hold on
    end
    title('旅行商问题优化结果 ')
    
    

    关于代码的一点说明,结合蚁群算法的原理和主要的转移概率公式,理解代码不难。上面的代码是针对完全图的回路所计算的,其中有多处可以加以改动,在注释号之后加上了#号,体现我的一点个人见解。

    此外,一个困惑:上面在计算待访问城市之后,关于下一个城市的选择,使用的是向前累加,取判断大于某个随机值rand,这样体现的是轮盘赌算法吗?

    相关文章

      网友评论

        本文标题:【国赛培训】蚁群算法

        本文链接:https://www.haomeiwen.com/subject/bgqyjctx.html