蚁群算法代码超通俗解释(MATALB)

TSP问题

clc;clear;
m=50;%蚂蚁个数,即自变量个数50组(一组解集),最好是城市数量的1.5倍
Alpha=1;%信息素重要程度参数,一般取值范围[1,4]
%启发式因子值越大,蚂蚁在选择以前走过的路径可能性越大搜索随机性减弱
%越小,容易过早陷入局部最优解
Beta=5;%启发式因子重要程度参数,5最好
Rho=0.1;%信息素蒸发系数
%过小时,则表示以前搜索过的路径被再次选择的可能性过大,影响随机性与全局搜索能力
%过大时,路径上信息素去除的越多,但降低了收敛速度
G=200;%最大迭代次数
Q=100;%信息素增加强度系数
%Q对ant-cycl模型蚁群算法的性能没有明显的影响,不必特殊考虑,可以任取
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=dist(C,C');%D表示两个城市距离间隔矩阵
%dist计算欧氏距离,尽可能的减少for循环,提高运行效率
for i =1:n
    for j=1:n
        if i==j
            D(i,j)=eps;
            %为保证启发函数的分母不为0,设定的对角矩阵修正值为一个较小正值
        end
    end
end
Eta=1./D;%Eta为启发因子,这里设为距离的倒数(启发函数)
mess=ones(n,n);%信息素矩阵
road=zeros(m,n);%存储并记录路径的生成(路径记录表)
%一行代表一只蚂蚁,每列代表一个城市序号,一行的数为城市序号即记录每一只蚂蚁的路线
%城市共31个,序号按1~31编码
NC=1;%迭代计数器
R_best=zeros(G,n);%每次迭代中的最佳路线
%一行代表一次迭代,每列代表一个城市
L_best=inf.*ones(G,1);%每次迭代中的最佳路线长度,G次迭代共G行
%乘inf因为防止认为没迭代的那个值是最佳的,因为最佳路线长度是求最短
figure(1);%优化解
while NC<=G

    %将m只蚂蚁放到n个城市上
    Randpos=[];%清除前一次迭代的所有数据
    for i=1:(ceil(m/n)) %ceil向正无穷舍入,如ceil(10.1)为11
        %i=1:ceil(m/n),目的就是尽量不重复的分配城市,且每个蚂蚁都分配到
        %假如有35个蚂蚁,30个城市,如果只循环一次那只产生了30 个城市,但还有5只蚂蚁没有分配到
        %且不能直接randperm(35)因为城市序号范围就1~30,所以用ceil向正无穷取整,多循环一次
        Randpos=[Randpos,randperm(n)];
        %randperm(n)随机生成1~n不重复的整数共n个(行向量)
        %因为有50只蚂蚁,若直接把31个城市分配给蚂蚁,导致有19个蚂蚁没有城市
    end
    road(:,1)=(Randpos(1,1:m));
    %road的第一列为这m只蚂蚁第一次在的城市即初始位置,就取Randpos前m个
    
    %m只蚂蚁按概率函数选择下一座城市,完成各自周游
    for i=1:m   %大循环,目的是一只一只蚂蚁的来(逐个蚂蚁路径选择
        for j=2:n  %因为都是m行n列,初始城市有了,所以j从第二个开始(逐个城市路径选择)
            visited=road(i,1:(j-1));%已访问城市(禁忌表)
            J=zeros(1,(n-j+1));%待访问城市(空集),目的是统计还没有访问的城市数量
            P=J;%待访问的城市选择概率分布
            Jc=1;%后面计数用的
            for k=1:n  %n个城市序号
                if isempty(find(visited==k,1))
                    %find查找visited里面有没有序号k的城市,没找到即为空集,执行if
                    %即序号为k的城市没有在已访问的城市里面
                    J(Jc)=k;%将没有访问的城市的序号储存起来
                    Jc=Jc+1;%计数,让J(jc)一行一行储存
                end
            end

            %计算待选城市的概率分布
            for k=1:length(J)  %因为没有访问的城市序号是升序排列的
                P(k)=(mess(visited(end),J(k))^Alpha)*(Eta(visited(end),J(k))^Beta);
                %visited(end)表示蚂蚁当前在的城市,J(k)表示将要去的城市,
                %mess(visited(end),J(k))为提取到下一个城市的信息素
                %Eta(visited(end),J(k))为提取到下一个城市的启发因子
                %蚁群算法的核心,选择下一个城市受多方面影响概率
            end
            P=P/(sum(P));%计算待选城市的每个概率
            
            %按概率原则选取下一个城市
            Pcum=cumsum(P);%累计和,
            %cumsum函数用于求变量中累加元素的和,如A=[1,2,3,4,5],那么cumsum(A)=[1,3,6,10,15]
            Select=find(Pcum>=rand);%这是轮盘赌算法知识
            to_visit=J(Select(1));%被选中的城市序号
            road(i,j)=to_visit;%第i个蚂蚁,在j次时去序号to_visit的城市
        end
    end
    if NC>=2 %因为第一轮迭代还没有产生出最佳路线
        road(1,:)=R_best(NC-1,:);
        %将上一次迭代时,里面的最佳路线给road(1,:),即给第一只蚂蚁
    end
        
    %记录本次迭代最佳路线
    L=zeros(m,1);%清除上一次迭代的距离,记录m只蚂蚁各自总距离
    for i=1:m
         R=road(i,:);%提取第i只蚂蚁的路线
         for j=1:n-1
             L(i)=L(i)+D(R(j),R(j+1));
             %利用距离矩阵D累计求和
         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,:)=road(pos(1),:);%存储每次迭代中的最佳路线
    
    %更新信息素
    d_mess=zeros(n,n);%内存预分配
    for i=1:m %逐个蚂蚁计算
        for j =1:n-1  %逐个城市计算
            d_mess(road(i,j),road(i,j+1))=d_mess(road(i,j),road(i,j+1))+Q/L(i);
            %记录第i只蚂蚁的信息素信息,
            %当前城市序号(d_mess的行)与下一个城市序号(d_mess的列)之间的信息素为Q/L(i)
            %所以同一只蚂蚁在路线是留下的信息素值相同
        end
        d_mess(road(i,n),road(i,1))=d_mess(road(i,n),road(i,1))+Q/L(i);
        %循环无法把首尾算入,所以单独加上
    end
    mess=(1-Rho).*mess+d_mess;
    %将原来的信息素蒸发,用Rho控制蒸发的量,然后加上这次新增加的信息素;
    %信息素值是影响下一次迭代按概率选取下一个城市
    road=zeros(m,n);%禁忌表清零即本次迭代这些蚂蚁的路线清除
    
    %到这里蚁群算法结束,下面的为可视化结果

    %历代最优路线,目的是可视化体现出寻找最优路线的过程
    for i=1:n-1
        plot([C(R_best(NC,i),1),C(R_best(NC,i+1),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-"); 
    %把首尾也连接起来,并且直线用另一个颜色(ro-)标注  
    title(["优化最短距离:",num2str(L_best(NC))]);
    hold off
    pause(0.005);%控制图变化速度
    NC=NC+1;%最后增加迭代次数
end

%通过图与文字输出结果
[short_len,index]=min(L_best);%short_len最短距离,index对应最佳的那次迭代索引
short_road=R_best(index,:);%最短距离对应的最短的路线
% figure(2)
% plot(L_best);%查看最短距离变化情况
xlabel("迭代次数");
ylabel("路线距离");
title("每次迭代最短路线变化情况")
disp(['最短距离:' num2str(short_len)]);
disp(['最短路径:' num2str( [short_road short_road(1)] )]);

%画最终结果图
set(gca,'LineWidth',1.5); %边框加粗,美观
figure
plot([C(short_road,1);C(short_road(1),1) ], [ C(short_road,2);C(short_road(1),2) ], 'k.-','Markersize',20);
set(gca,'LineWidth',1.5); %边框加粗,美观
grid on;
for i = 1:size(C,1)
    text(C(i,1),C(i,2),['  ' num2str(i)]);
end
text(C(short_road(1),1),C(short_road(1),2),'    起点');
text(C(short_road(end),1),C(short_road(end),2),'    终点')
xlabel('城市位置横坐标');
ylabel('城市位置纵坐标');
title(['ACA最优化路径(最短距离:' num2str(short_len) ')']);
figure;
plot(1:G,L_best,'b');
set(gca,'LineWidth',1.5); %边框加粗,美观
legend('最短距离');
xlabel('迭代次数');
ylabel('距离');
title('算法收敛轨迹');
set(gca,'LineWidth',1.5);  %边框加粗,美观

运行结果:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

PlatinumA

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

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

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

打赏作者

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

抵扣说明:

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

余额充值