旅行商问题--蚁群优化算法求解(matlab实现)

今天给大家分享一下matlab实现蚁群优化算法,解决旅行商问题。
在上一篇博客中对蚁群优化算法做了较为详细的介绍,有需要的小伙伴可以看一下
https://blog.csdn.net/HuangChen666/article/details/115827732

1. 初始化城市信息
     1.1 随机获取城市坐标
     1.2 求出城市之间距离
2. 初始化参数
3. 迭代寻找最佳路径
     3.1 随机产生蚂蚁起点城市
     3.2 迭代计算选择城市概率
     3.3 轮盘赌选出下一个城市
     3.4 更新最短路径
     3.5 更新信息素
4. 得出结果
5. 全部代码

1. 初始化城市信息

第一步初始化城市的信息,例如数量、坐标、距离等等。

1.1 随机获取城市坐标

首先随机产生n个城市的坐标,使用randperm(100,n)产生n个城市的横坐标和纵坐标,randperm(100,n)表示随机产生n个1~100(包含1和100)的整数,然后使用plot函数进行描点,例如:

在这里插入图片描述

1.2 求出城市之间距离

计算各个城市之间的距离,存放如一个n*n的矩阵中,由于距离在后面的公式要放在分母上,所以城市i到城市i的距离不能是0,这里设置成eps,即一个非常小的数。

在这里插入图片描述
对角线上是城市 i 到 i 的距离,用一个很小的数代替。

2. 初始化参数

迭代寻找最佳路径之前,对一些必要的参数进行初始化,比如信息素重要程度因子、启发函数重要程度因子、信息素挥发因子、启发函数等等。

在这里插入图片描述

3. 迭代寻找最佳路径

准备工作做好后,下面就是迭代寻找最佳路径,对m只蚂蚁和n个城市进行循环,核心是蚁群优化算法的两个公式,一个是计算选择城市概率的,另一个是更新信息素的。

3.1 随机产生蚂蚁起点城市

首选将蚂蚁随机放在n个城市上,当然这里并不是真的拿蚂蚁过来放,而是随机产生1~n的数字,即代表第 i 只蚂蚁的初始城市。

在这里插入图片描述

3.2 迭代计算选择城市概率

计算蚂蚁选择目前没有去过的城市的概率,需要事先去掉已经访问过的城市,计算选择城市概率公式如下:

在这里插入图片描述
在这里插入图片描述

3.3 轮盘赌选出下一个城市

求出蚂蚁选择其他未访问过的城市的选择概率后,并不能一味地就选择概率最大的那个,这样很容易陷入局部最优解,这样采用轮盘赌的方法进行选择,对轮盘赌不熟悉的同学可以借鉴下这个博客

https://blog.csdn.net/xuxinrk/article/details/80158786

3.4 更新最短路径

因为最终还是要求最短路径的嘛,到了这一步就是对上面选择完城市后的路径一一求和,得出每只蚂蚁在该次周游中的路径和(还要加上最后一个节点回到起点的距离)
***这里需要注意的是计算出本次的最短路径和上一次的最短路径相比不一定更小,结果得到的最短路径的收敛轨迹波动会特别大,比如下面这样

在这里插入图片描述

所以这里可以改进一下,基本思想是:如果本次周游中的最短路径大小比上一次的要大,则本次的最短路径大小改为和上一次一样,这样就不会出现后面迭代出比前面还要打的最短距离,这样处理会更符合人们的观念,更加合理,修改后如下所示

在这里插入图片描述

3.5 更新信息素

所有的蚂蚁周游后开始下一次周游,下一次周游前更新信息素,信息素=上一次的信息素*(1-挥发因子)+上一轮增加的信息素,路径上走的蚂蚁越多,信息素增加越多,相比信息素越浓。

在这里插入图片描述

4. 得出结果

根据上述步骤编写代码,以75只蚂蚁,30个城市为例,得到结果如下,最短路径路线图

在这里插入图片描述
下面是最短距离收敛曲线和平均距离收敛曲线

在这里插入图片描述
命令行输出结果

在这里插入图片描述

5. 全部代码

代码借鉴了两个视频,大家有兴趣有耐心可以看下,我觉得这两个讲的都不错,第二个视频有一个后记视频讲了关于调参的事情。

https://www.bilibili.com/video/BV1c4411W7zc
https://www.bilibili.com/video/BV1Z7411H78S?from=search&seid=14512389210209190890

clc;clear;
t0=clock;   %用于计时
%% 初始化城市信息
n=30;                    %定义城市个数
city=[(randperm(100,n))',(randperm(100,n))'];  %获取城市坐标
figure('name','蚁群优化算法');
plot(city(:,1),city(:,2),'o');  %描点
for i=1:n
    text(city(i,1)+0.5,city(i,2),num2str(i));       %标号
end
title('蚁群优化算法');
%设置横纵坐标范围
grid on     %网格线
hold on

%% 求出各个城市之间的距离
D=zeros(n,n);      %新建一个n*n的矩阵存放距离
for i=1:n
   for j=1:n
       if i~=j
           D(i,j)=sqrt(sum((city(i,:)-city(j,:)).^2));
       else
           D(i,j)=eps;     %设置成一个很小的数,但不能为0,因为后面分母中会用到
       end
   end
end

%% 初始化参数
m=75;                   %蚂蚁数量
alpha = 1;              %信息素重要程度因子
beta = 5;               %启发函数重要程度因子
rho = 0.2;              %信息素挥发因子
Q=10;                   %常系数
Eta = 1./D;             %启发函数(距离的倒数)
Tau = ones(n,n);        %信息素矩阵(初始时每条路上的信息素都设为1)
Table = zeros(m,n);     %路径记录表,记录m个蚂蚁走过的路径
iter = 1;               %迭代次数初值
iter_max = 100;         %最大迭代次数
Route_best = zeros(iter_max,n);     %各代最佳路径
Length_best = zeros(iter_max,1);    %各代最佳路径的长度
Length_ave = zeros(iter_max,1);     %各代路径的平均长度

%% 迭代寻找最佳路径
for iter=1:iter_max
    %随机产生蚂蚁的起点城市
    for i=1:m
       Table(i,1)=randperm(n,1);
    end
    citys_index=1:n;        %定义全部城市索引
    for i=1:m               %遍历所有蚂蚁
       for j=2:n            %遍历其他所有城市
           tabu=Table(i,1:(j-1));      %已访问城市(禁止访问表)
           allow=citys_index(~ismember(citys_index,tabu)); %除去已访问城市(待访问城市)
           P=allow;         %存放概率,定义成什么都可以,只要和allow长度一样
           %计算城市间的选择概率
           for k=1:length(allow)
               %tabu(end)代表该蚂蚁此刻所在城市,allow(k)代表该蚂蚁即将去向的城市
               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;               %确定第i只蚂蚁去往的第j-1个城市 
       end
    end
    %每只蚂蚁周游一遍后计算每只蚂蚁的路径长度
    Length=zeros(m,1);
    for i=1:m
        for j=1:(n-1)
            Length(i)=Length(i)+D(Table(i,j),Table(i,j+1));
        end
        %最后加上最后一个点回到起点的距离
        Length(i)=Length(i)+D(Table(i,n),Table(i,1));
    end
    %% 计算最短路径距离及平均距离
    [min_length,min_index]=min(Length);     %取出最短路径及其下标
    if iter==1
        Length_best(iter)=min_length;           %保存此次最短路径距离
    else
        Length_best(iter)=min(Length_best(iter-1),min_length);  %选择本次和上次中最短路径较小的
    end
    Route_best(iter,:)=Table(min_index,:);  %保存此次最短路线路径
    Length_ave(iter)=mean(Length);          %保存此次路线距离平均值
    
    %% 更新信息素
    Tau_Ant=Q./Length;          %每条蚂蚁在路径上留下的信息素浓度
    Tau_Temp=zeros(n,n);
    for i=1:m
        for j=1:n-1
            %更新信息素
            Tau_Temp(Table(i,j),Table(i,j+1))=Tau_Temp(Table(i,j),Table(i,j+1))+Tau_Ant(i);
        end
        %最后更新最后一个节点到起点的信息素
        Tau_Temp(Table(i,n),Table(i,1))=Tau_Temp(Table(i,n),Table(i,1))+Tau_Ant(i);
    end
    Tau=(1-rho)*Tau+Tau_Temp;   %信息素挥发后再加上新增的信息素
    Table = zeros(m,n);     %清空路线,进行下一轮周游
end

%% 命令行窗口显示结果
[min_length,min_index]=min(Length_best);         %取出最短路径及其下标
Finnly_Route=Route_best(min_index,:);
last_time=etime(clock,t0);
disp(['最短距离为:' num2str(min_length)]);
disp(['最短路径为:' num2str(Finnly_Route)]);
disp(['运行时间:' num2str(last_time) '秒']);

%% 绘图
plot([city(Finnly_Route,1);city(Finnly_Route,1)],...
     [city(Finnly_Route,2);city(Finnly_Route,2)],'bo-');  %描点
text(city(Finnly_Route(1),1),city(Finnly_Route(1),2),'    起点');
text(city(Finnly_Route(end),1),city(Finnly_Route(end),2),'    终点');

figure(2);
subplot(1,2,1);     %显示在一行两列图像中的第一列
plot(Length_best);
xlabel('迭代次数');
ylabel('最短距离');
title('最短距离收敛曲线');

subplot(1,2,2);     %显示在一行两列图像中的第二列
plot(Length_ave);
xlabel('迭代次数');
ylabel('平均距离');
title('平均距离收敛曲线');

猜你喜欢

转载自blog.csdn.net/HuangChen666/article/details/115913181