人工智能应用-实验4-蚁群算法求解 TSP

🧡🧡实验内容🧡🧡

编写基于蚁群算法求解 TSP 问题的程序,分别求出 20 个城市之间和 50 个城市之间的最短路径。


🧡🧡代码🧡🧡

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

%% 导入数据
citys_31 = [ % 内陆的31个主要省会城市,不含港澳台
    116.407395, 39.904211;
    117.200983, 39.084158;
    114.514862, 38.042307;
    118.180193, 39.630867;
    112.549248, 37.857014;
    111.670801, 40.818311;
    123.431475, 41.805698;
    125.323544, 43.817071;
    126.534967, 45.803775;
    121.473701, 31.230416;
    118.796877, 32.060255;
    120.153576, 30.287459;
    117.227239, 31.820587;
    119.296494, 26.074508;
    115.892151, 28.676493;
    117.120019, 36.651216;
    113.665412, 34.757975;
    114.298572, 30.584355;
    112.938814, 28.228209;
    113.264434, 23.129162;
    108.320004, 22.82402;
    110.33119, 20.031971;
    104.065735, 30.659462;
    106.713478, 26.578343;
    102.712251, 25.040609;
    108.948024, 34.263161;
    103.834303, 36.061089;
    101.778228, 36.617144;
    91.132212, 29.660361;
    106.278179, 38.46637;
    87.617733, 43.792818;
];
citys_50=[
    110.469286198181   50.4746691410186;
    92.5266910201309   42.7595185867962;
    85.8168137464198   33.3510745658952;
    103.005033088825   37.3718509138302;
    115.815409819431   32.4287938317344;
    125.720207837641   42.4575314260683;
    83.1496903823127   46.5890781381871;
    86.5692819178498   51.4168621571695;
    95.8073622632917   48.1280677266756;
    130.620267741678   45.2905464411555;
    82.7428601931531   35.0371447515392;
    124.230437470352   29.5943527737754;
    108.307261544677   43.8646083607653;
    105.837300942493   15.7127956890334;
    126.891027665425   44.3382449137088;
    109.501233625833   32.4217551748842;
    114.895073617088   40.9239984204817;
    115.95881   51.4517223372703;
    119.640883772243   22.7559646793684;
    101.482506618948   29.0125930804905;
    122.579272261262   44.4500855598353;
    128.423962506030   18.5572682527589;
    87.3523632932626   20.6025092238485;
    129.029503867517   33.8399355659161;
    109.540700690432   26.3141382912873;
    130.445329656714   23.6507514948169;
    84.9868745956852   39.5895240262594;
    103.812894324380   49.5222693078745;
    73.7535688054273   38.4530364608632;
    124.603837227041   37.1160006808058;
    74.9217946493522   35.8982407433328;
    89.2026003945863   36.0532693055382;
    107.891311021032   20.5177333856848;
    104.321662298107   47.3711070688777;
    80.5936363842351   52.6694785312550;
    133.111293665466   40.2547112805644;
    88.3720406809424   25.9026846100506;
    133.072259309913   25.7819126780322;
    120.466021232856   19.2388485754945;
    77.5238676167198   48.1650585535397;
    76.5154109411933   34.5941955801035;
    107.205075462786   30.6395114651284;
    95.2040830320626   23.4266972302777;
    81.3734952157783   26.2383951416844;
    80.4755943569925   22.1074033577527;
    78.2814334811311   24.0545780185756;
    83.0016130798109   37.5738520876487;
    113.203798272594   14.2722816613816;
    122.804520260080   46.8178856055774;
    116.735480758245   23.4382459106337;
];


%% 计算城市间相互距离
citys = citys_31;
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;
        end
    end    
end

%% 初始化参数
rng(66)                              % 随机因子,确保程序每次运行结果相同
m = 35;                              % 蚂蚁数量
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);      % 各代路径的平均长度  

tic; % 开始计时
%% 迭代寻找最佳路径
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);
%               Delta_Tau(Table(i,j),Table(i,j+1)) = Delta_Tau(Table(i,j),Table(i,j+1)) + Q/D(j,j+1);
%               Delta_Tau(Table(i,j),Table(i,j+1)) = Delta_Tau(Table(i,j),Table(i,j+1)) + Q;
          end
          Delta_Tau(Table(i,n),Table(i,1)) = Delta_Tau(Table(i,n),Table(i,1)) + Q/Length(i);
%           Delta_Tau(Table(i,n),Table(i,1)) = Delta_Tau(Table(i,n),Table(i,1)) + Q/D(n,1); 
%           Delta_Tau(Table(i,n),Table(i,1)) = Delta_Tau(Table(i,n),Table(i,1)) + Q; 
      end
      Tau = (1-rho) * Tau + Delta_Tau;
    % 迭代次数加1,清空路径记录表
    iter = iter + 1;
    Table = zeros(m,n);
end
elapsedTime = toc;% 结束计时

%% 结果显示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距离:' num2str(Shortest_Length)]);
disp(['最短路径:' num2str([Shortest_Route Shortest_Route(1)])]);
disp(['程序运行时间:', num2str(elapsedTime), '秒']);

%% 绘图
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),'       起点', 'Color', 'red');
text(citys(Shortest_Route(end),1),citys(Shortest_Route(end),2),'       终点', 'Color', 'red');
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('各代最短距离与平均距离对比')

🧡🧡分析结果🧡🧡

为贴合现实情况,并且有利于研究TSP,我采用中国内陆的31个省会城市作为数据1,对于50个城市,我选择随机生成经纬度在一定范围内的城市坐标,然后保持起来,作为数据。
在这里插入图片描述
设置参数如下:
在这里插入图片描述
31个城市的最短路径图和迭代最佳距离变化图如下
在这里插入图片描述
在这里插入图片描述
改变为50个城市时:
得到50个城市的最短路径图和迭代最佳距离变化图如下
在这里插入图片描述
在这里插入图片描述

分析蚁群算法和遗传算法的区别与联系以及蚁群算法的优缺点
区别:
蚁群算法主要是模拟蚂蚁在寻找食物时释放信息素的过程,通过信息素的积累来更新路径,实现优化。
遗传算法主要是利用生物进化的思想,通过种群的选择、交叉、变异等基本操作,不断优化进化得到更好的解。
联系:
蚁群算法和遗传算法都是基于集体智慧的思想,通过群体中个体之间的交互和信息共享来实现全局最优化。
蚁群算法的优缺点:

  • 优点:
    蚁群算法能够较好地保持全局探索能力,避免陷入局部最优解。
  • 缺点:
    蚁群算法对于问题的参数敏感,需要进行较多的参数设置和实验,才能得到较好的效果。并且算法的收敛速度相对较慢,可能需要较长的时间才能达到最优解(这次实验普遍运行3秒以上,而实验二中用遗传算法求解TSP普遍1秒之内)。

🧡🧡实验总结🧡🧡

理论理解方面
给我感觉是和粒子群类似,通过定义一些公式,来实现启发式搜索:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单来说就是对于所有蚂蚁,计算t时刻这只蚂蚁从城市i到城市j的概率,而这个概率与路径上信息素浓度相关,而信息浓度又与路径长度有关,因此让这只蚂蚁不断根据概率选择城市前往,在每一代从能得到这只蚂蚁的路径,也即一个解。对于信息素启发因子α,其值越大,表示信息素的浓度在转移中起的作用越大;β为启发函数重要程度因子,其值越大,表示启发函数在转移中的作用越大,即蚂蚁会以较大的概率转移到距离短的城市。当α=0时,算法就是传统的贪心算法,而当β=0时,就成了纯粹的正反馈的启发式算法。

代码实操方面
有用到禁忌close表和open表,与BFS、DFS的搜索作用类似,记录哪些城市已经访问,哪些城市还没访问。实验中需要组合调试主要参数,而每次运行的收敛时间都相对来说比较长(也可能与我设置的迭代代数和城市规模过大有关),并且有时得出的解的质量其实并不能有太大差别,不敢保证搜到的就是全局最优,因此,对于城市规模较小的问题,可以先尝试使用其他算法求解理想最优值,以对实验结果进行更好的评估和判断。

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为AI助手,我很乐意帮助你开始编写蚁群算法求解TSP问题的Python程序。以下是一个基本的程序框架,你可以在此基础上进行扩展。程序将随机生成城市坐标,并使用蚁群算法求解TSP问题。 ```python import random import math # 常量定义 NUM_CITIES = 50 # 城市数量 NUM_ANTS = 50 # 蚂蚁数量 ALPHA = 1.0 # 信息素重要程度因子 BETA = 5.0 # 启发函数重要程度因子 RHO = 0.5 # 信息素挥发因子 Q = 100 # 信息素增加强度因子 MAX_ITER = 500 # 最大迭代次数 # 随机生成城市坐标 cities = [] for i in range(NUM_CITIES): x = random.uniform(0, 1) y = random.uniform(0, 1) cities.append((x, y)) # 计算城市之间的距离 distances = [[0] * NUM_CITIES for i in range(NUM_CITIES)] for i in range(NUM_CITIES): for j in range(NUM_CITIES): if i == j: distances[i][j] = 0 else: dx = cities[i][0] - cities[j][0] dy = cities[i][1] - cities[j][1] distances[i][j] = math.sqrt(dx*dx + dy*dy) # 初始化信息素矩阵 pheromone = [[1.0] * NUM_CITIES for i in range(NUM_CITIES)] # 开始迭代 best_path = None best_len = float('inf') for iter in range(MAX_ITER): # 初始化蚂蚁位置 ant_pos = [random.randint(0, NUM_CITIES-1) for i in range(NUM_ANTS)] # 蚂蚁移动 for k in range(NUM_CITIES-1): for i in range(NUM_ANTS): # 计算每个蚂蚁的下一步移动 probs = [0] * NUM_CITIES for j in range(NUM_CITIES): if j not in ant_pos: probs[j] = pheromone[ant_pos[i]][j] ** ALPHA * (1.0 / distances[ant_pos[i]][j]) ** BETA total_prob = sum(probs) if total_prob == 0: # 如果所有的概率都是0,则随机选择一个城市 next_city = random.choice([j for j in range(NUM_CITIES) if j != ant_pos[i]]) else: # 根据概率选择下一个城市 r = random.uniform(0, total_prob) next_city = 0 while r > 0: r -= probs[next_city] next_city += 1 next_city -= 1 ant_pos[i] = next_city # 更新信息素 delta_pheromone = [[0.0] * NUM_CITIES for i in range(NUM_CITIES)] for i in range(NUM_ANTS): for j in range(NUM_CITIES-1): delta_pheromone[ant_pos[i]][ant_pos[i+1]] += Q / distances[ant_pos[i]][ant_pos[i+1]] delta_pheromone[ant_pos[i+1]][ant_pos[i]] += Q / distances[ant_pos[i]][ant_pos[i+1]] for i in range(NUM_CITIES): for j in range(NUM_CITIES): pheromone[i][j] = pheromone[i][j] * (1 - RHO) + delta_pheromone[i][j] # 计算本次迭代的最短路径 path_len = 0 for i in range(NUM_ANTS): tmp_len = 0 for j in range(NUM_CITIES-1): tmp_len += distances[ant_pos[i]][ant_pos[i+1]] path_len += tmp_len if path_len < best_len: best_len = path_len best_path = ant_pos # 输出结果 print("最短路径长度:", best_len) print("最短路径:", best_path) ``` 希望这个程序框架对你有所帮助,祝你编写成功!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值