文章目录
- 🧡🧡实验内容🧡🧡
- 🧡🧡代码🧡🧡
- 🧡🧡分析结果🧡🧡
- 🧡🧡实验总结🧡🧡
🧡🧡实验内容🧡🧡
编写基于蚁群算法求解 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的搜索作用类似,记录哪些城市已经访问,哪些城市还没访问。实验中需要组合调试主要参数,而每次运行的收敛时间都相对来说比较长(也可能与我设置的迭代代数和城市规模过大有关),并且有时得出的解的质量其实并不能有太大差别,不敢保证搜到的就是全局最优,因此,对于城市规模较小的问题,可以先尝试使用其他算法求解理想最优值,以对实验结果进行更好的评估和判断。