目录
例题:已知敌方 100 个目标的经度、纬度(旅行商问题TSP的变种)
2.create_distance_matrix.m文件:计算距离矩阵D
3.haversine_distance.m文件:计算飞机在圆圆的地球上的飞行距离的函数
蚁群算法
自然界蚂蚁觅食行为
- 蚂蚁的觅食路径:蚂蚁在寻找食物时,会随机选择路径。当蚂蚁找到食物后,会在返回巢穴的路上释放信息素。
- 信息素的作用:信息素是一种化学物质,能够吸引其他蚂蚁。信息素的浓度越高,蚂蚁越有可能选择这条路径。
- 信息素的挥发:信息素会随着时间的推移而挥发。较短路径上的信息素浓度会更快增加,因为这些路径被更多蚂蚁频繁使用。
蚁群算法原理
举个栗子!通俗理解~
假设有一群蚂蚁在一个迷宫中寻找最短路径到达食物源,它们的行为可以总结如下:
- 起点:蚂蚁从迷宫入口随机出发。
- 路径选择:蚂蚁在前进过程中会选择信息素浓度较高的路径,但也有一定概率选择其它路径,这保证了探索新路径的可能性(随机性)。
- 信息素沉积:找到食物的蚂蚁返回巢穴,在路上会释放信息素,标记这条路径。
- 路径优化:随着更多蚂蚁发现并使用较短路径,该路径上的信息素浓度增加,吸引更多蚂蚁选择这条路径,逐渐找到最短路径。
蚁群算法模拟了上述蚂蚁觅食的过程来解决优化问题。
- 初始化:在问题空间上初始化若干蚂蚁和信息素矩阵。
- 构建解:每只蚂蚁在搜索过程中根据概率规则(信息素和启发式信息)选择下一步路径,直到构建完整解。
- 更新信息素:根据蚂蚁构建的解和路径长度更新信息素矩阵,短路径会有更多的信息素沉积。
- 迭代:重复构建解和更新信息素的过程,逐步优化解决方案。
概率规则:
- 蚂蚁选择下一步走哪条路径通常是根据路径上的信息素浓度和路径的吸引力(通常与路径长度成反比)来决定的。
- 具体选择公式为:每条路径被选择的概率与信息素浓度和路径吸引力的乘积成正比。
蚁群算法步骤
- 1. 初始化:初始化信息素矩阵和其他参数。
- 2. 解构建:每只蚂蚁构建一个完整解。蚂蚁根据信息素和启发信息选择路径。
- 3. 更新信息素:根据蚂蚁构建解的质量更新信息素,较优解会留下更多信息素,同时所有路径上的信息素都会挥发。
- 4. 记录最优解:如果本次迭代中的解优于已知的最优解,则更新最优解。
- 5. 重复:重复上述步骤直到达到停止条件。
适用问题
- 特别适合路径优化问题,如旅行商问题(TSP)、车辆路径问题(VRP)等。
- 由于信息素的引导,适合处理具有多个局部最优解的复杂问题。
模型评价
模型优缺点
- 蚁群算法对初始路线的要求不高,即使初始解较差,也能通过算法的不断迭代和优化找到较好的解,不易受个体影响。
- 当问题规模较大时,计算每条路径的信息素更新和选择概率可能会变得非常复杂。
对于较小规模的问题,解空间较小,少量蚂蚁就能充分探索;对于较大规模的问题,设置蚂蚁数量为城市数量的2到10倍。适量的蚂蚁数量可以提高算法的收敛速度,但过多的蚂蚁可能会导致算法过早收敛到局部最优解,反而降低了结果质量。
TSP问题
假设有一个旅行商人要拜访n个城市,需选择一条路线,要求所有城市走一遍回到起点,同时使所走路程最短。
例题:已知敌方 100 个目标的经度、纬度(旅行商问题TSP的变种)
经度 | 纬度 | 经度 | 纬度 | 经度 | 纬度 | 经度 | 纬度 |
53.7121 | 15.3046 | 22.1075 | 18.5569 | 24.4509 | 6.5634 | 52.8423 | 27.288 |
51.1758 | 0.0322 | 0.1215 | 18.8726 | 26.7213 | 28.5667 | 39.9494 | 29.5114 |
46.3253 | 28.2753 | 48.2077 | 16.8889 | 37.5848 | 16.8474 | 47.5099 | 24.0664 |
30.3313 | 6.9348 | 31.9499 | 17.6309 | 35.6619 | 9.9333 | 10.1121 | 27.2662 |
56.5432 | 21.4188 | 0.7732 | 0.4656 | 24.4654 | 3.1644 | 28.7812 | 27.6659 |
10.8198 | 16.2529 | 47.4134 | 23.7783 | 0.7775 | 6.9576 | 8.0831 | 27.6705 |
22.7891 | 23.1045 | 41.8671 | 3.5667 | 14.4703 | 13.6368 | 9.1556 | 14.1304 |
10.1584 | 12.4819 | 43.5474 | 3.9061 | 19.866 | 15.1224 | 53.7989 | 0.2199 |
20.105 | 15.4562 | 53.3524 | 26.7256 | 3.1616 | 4.2428 | 33.649 | 0.398 |
1.9451 | 0.2057 | 30.8165 | 13.4595 | 18.5245 | 14.3598 | 1.3496 | 16.8359 |
26.4951 | 22.1221 | 27.7133 | 5.0706 | 58.6849 | 27.1485 | 49.9816 | 6.0828 |
31.4847 | 8.964 | 23.9222 | 7.6306 | 39.5168 | 16.9371 | 19.3635 | 17.6622 |
26.2418 | 18.176 | 51.9612 | 22.8511 | 56.5089 | 13.709 | 36.9545 | 23.0265 |
44.0356 | 13.5401 | 12.7938 | 15.7307 | 52.5211 | 15.7957 | 15.732 | 19.5697 |
28.9836 | 25.9879 | 4.9568 | 8.3669 | 38.43 | 8.4648 | 11.5118 | 17.3884 |
38.4722 | 20.1731 | 21.5051 | 24.0909 | 51.8181 | 23.0159 | 44.0398 | 16.2635 |
28.2694 | 29.0011 | 15.2548 | 27.2111 | 8.9983 | 23.644 | 39.7139 | 28.4203 |
32.191 | 5.8699 | 6.207 | 5.1442 | 50.1156 | 23.7816 | 6.9909 | 23.1804 |
36.4863 | 29.7284 | 49.243 | 16.7044 | 13.7909 | 1.951 | 38.3392 | 19.995 |
0.9718 | 28.1477 | 17.1168 | 20.0354 | 34.0574 | 23.396 | 24.6543 | 19.6057 |
8.9586 | 24.6635 | 34.1688 | 22.7571 | 23.0624 | 8.4319 | 36.998 | 24.3992 |
16.5618 | 23.6143 | 9.4402 | 3.92 | 19.9857 | 5.7902 | 4.1591 | 3.1853 |
10.5597 | 15.1178 | 11.5812 | 14.5677 | 40.8801 | 14.2978 | 40.14 | 20.303 |
50.2111 | 10.2944 | 52.1181 | 0.4088 | 58.8289 | 14.5229 | 23.9876 | 9.403 |
8.1519 | 9.5325 | 9.5559 | 11.4219 | 18.6635 | 6.7436 | 41.1084 | 27.7149 |
我方有一个基地,经度和纬度为(70,40)。假设我方飞机的速度为 1000 公里/小时。
我方派一架飞机从基地出发,侦察完敌方所有目标,再返回原来的基地。在敌方每一目
标点的侦察时间不计,求该架飞机所花费的时间(假设我方飞机巡航时间可以充分长)。
1.主程序文件:
clc;clear;
%% 第一步:变量初始化
m=500; % m 蚂蚁个数
Alpha=1; % Alpha表征信息素重要程度的参数
Beta=5; % Beta表征启发式因子重要程度的参数
Rho=0.1; % Rho信息素蒸发系数
max_iter=150; % 最大迭代次数
Q=100; % 信息素增加强度系数
speed=1000; % 飞机时速
data=[70 40; % 最终要回到起点,于是将出发点加入总的目标地点中
53.7121 15.3046;51.1758 0.0322;46.3253 28.2753;30.3313 6.9348 ;
56.5432 21.4188 ;10.8198 16.2529 ;22.7891 23.1045;10.1584 12.4819;
20.1050 15.4562 ;1.9451 0.2057;26.4951 22.1221;31.4847 8.9640 ;
26.2418 18.1760;44.0356 13.5401 ; 28.9836 25.9879 ;38.4722 20.1731;
28.2694 29.0011 ;32.1910 5.8699; 36.4863 29.7284; 0.9718 28.1477 ;
8.9586 24.6635 ;16.5618 23.6143 ;10.5597 15.1178; 50.2111 10.2944 ;
8.1519 9.5325 ;22.1075 18.5569 ; 0.1215 18.8726 ;48.2077 16.8889 ;
31.9499 17.6309; 0.7732 0.4656 ;47.4134 23.7783; 41.8671 3.5667 ;
43.5474 3.9061 ;53.3524 26.7256 ;30.8165 13.4595 ;27.7133 5.0706 ;
23.9222 7.6306 ;51.9612 22.8511 ;12.7938 15.7307; 4.9568 8.3669 ;
21.5051 24.0909 ;15.2548 27.2111 ; 6.2070 5.1442 ;49.2430 16.7044 ;
17.1168 20.0354; 34.1688 22.7571; 9.4402 3.9200 ;11.5812 14.5677 ;
52.1181 0.4088 ;9.5559 11.4219 ;24.4509 6.5634; 26.7213 28.5667 ;
37.5848 16.8474 ;35.6619 9.9333 ;24.4654 3.1644; 0.7775 6.9576 ;
14.4703 13.6368 ;19.8660 15.1224; 3.1616 4.2428 ;18.5245 14.3598;
58.6849 27.1485 ;39.5168 16.9371; 56.5089 13.7090; 52.5211 15.7957;
38.4300 8.4648 ;51.8181 23.0159 ;8.9983 23.6440 ;50.1156 23.7816 ;
13.7909 1.9510 ;34.0574 23.3960 ;23.0624 8.4319 ;19.9857 5.7902 ;
40.8801 14.2978 ;58.8289 14.5229 ;18.6635 6.7436; 52.8423 27.2880;
39.9494 29.5114 ;47.5099 24.0664; 10.1121 27.2662; 28.7812 27.6659;
8.0831 27.6705 ;9.1556 14.1304 ;53.7989 0.2199 ;33.6490 0.3980 ;
1.3496 16.8359 ;49.9816 6.0828 ;19.3635 17.6622 ;36.9545 23.0265;
15.7320 19.5697; 11.5118 17.3884; 44.0398 16.2635 ;39.7139 28.4203;
6.9909 23.1804 ;38.3392 19.9950 ; 24.6543 19.6057 ;36.9980 24.3992 ;
4.1591 3.1853 ;40.1400 20.3030 ; 23.9876 9.4030 ;41.1084 27.7149
]; % 100个经纬度坐标数据
% R_best 各代最佳路线
% L_best 各代最佳路线的长度
n=size(data,1); % n=101个目标地点
D=zeros(n,n); % D表示完全图的赋权邻接矩阵
D = create_distance_matrix(data);
% 此处调用了create_distance_matrix.m文件,计算距离矩阵D
%% 变量
Eta=1./D; % Eta为启发因子,设为距离的倒数
Tau=ones(n,n); % Tau为信息素矩阵
Tabu=zeros(m,n); % 存储并记录路径的生成
n_iter=1; % 迭代计数器,记录迭代次数
R_best=zeros(max_iter, n); % 各代最佳路线
L_best=inf .* ones(max_iter, 1); % 各代最佳路线的长度 % inf正无穷
L_ave=zeros(max_iter, 1); % 各代路线的平均长度
%% 进行蚁群算法 % 第二步:将m只蚂蚁放到n个目标地点上
while n_iter<=max_iter
Randpos=[]; %随即存取
for i=1:(ceil(m/n))
Randpos=[Randpos,randperm(n)]; %randperm(n)产生1-n的随机数
end
Tabu(:,1)=(Randpos(1,1:m))'; %将路径矩阵里面的第一列随机初始到一个地点
%% 第三步:m只蚂蚁按概率函数选择下一个目标地点,完成各自的周游
for j=2:n
for i=1:m
visited=Tabu(i,1:(j-1)); %记录已访问的地点,避免重复访问
J=zeros(1,(n-j+1)); %待访问的地点
P=J; %待访问地点的选择概率分布
Jc=1;
for k=1:n
if isempty(find(visited==k, 1)) %开始时置0
J(Jc)=k;
Jc=Jc+1; %访问的地点个数自加1
end
end
%下面计算待选地点的概率分布
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); %若计算的概率大于原来的就选择这条路线
to_visit=J(Select(1));
Tabu(i,j)=to_visit;
end
end
if n_iter>=2
Tabu(1,:)=R_best(n_iter-1,:);
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(n_iter)=min(L); % 最佳距离取最小
pos=find(L==L_best(n_iter));
R_best(n_iter,:)=Tabu(pos(1),:); % 此轮迭代后的最佳路线
L_ave(n_iter)=mean(L); % 此轮迭代后的平均距离
n_iter
L_best(n_iter)
n_iter=n_iter+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);
%此次循环在整个路径上的信息素增量
end
Tau=(1-Rho).*Tau+Delta_Tau; %考虑信息素挥发,更新后的信息素
%% 第六步:禁忌表清零(禁忌表:防止搜索过程中出现循环,避免局部最优)
Tabu=zeros(m,n); %直到最大迭代次数
end
%% 第七步:输出结果,可视化
Pos=find(L_best==min(L_best)); %找到最佳路径
Shortest_Route=R_best(Pos(1),:) %最大迭代次数后最佳路径
Shortest_Length=L_best(Pos(1)) %最大迭代次数后最短距离
figure(1)
plot(L_best)
xlabel('迭代次数')
ylabel('最短路径长度')
title('每代最短路径长度进化曲线')
figure(2)
%绘制第一个子图形,路线图
subplot(1,2,1)
N=length(Shortest_Route);
scatter(data(:,1),data(:,2)); %绘制闪点图
hold on
plot([data(Shortest_Route(1),1),data(Shortest_Route(N),1)],[data(Shortest_Route(1),2),data(Shortest_Route(N),2)],'g');
hold on
for ii=2:N
plot([data(Shortest_Route(ii-1),1),data(Shortest_Route(ii),1)],[data(Shortest_Route(ii-1),2),data(Shortest_Route(ii),2)],'g')
hold on
end
title('最短路线结果图 ')
%绘制第二个子图形
subplot(1,2,2)
plot(L_best)
hold on %保持图形
plot(L_ave,'r')
legend('最短距离','平均距离')
title('平均距离和最短距离')
% 总时长
totaltime=Shortest_Length/speed;
totaltime
2.create_distance_matrix.m文件:计算距离矩阵D
计算目标点与目标点之间的距离。
function D = create_distance_matrix(data)
% 目标点之间的距离
n=101;
for i = 1:n
for j = 1:n
D(i, j) = haversine_distance(data(i, 1), data(i, 2), data(j, 1), data(j, 2));
% 此处又调用了haversine_distance.m文件中的haversine_distance函数
% 由于地球是圆的,距离的计算并不能简单地用欧氏距离
D(j, i) = D(i, j); % 矩阵是对称的
end
end
end
3.haversine_distance.m文件:计算飞机在圆圆的地球上的飞行距离的函数
% 计算飞机在圆圆的地球上的飞行距离的函数
function dist = haversine_distance(lat1, lon1, lat2, lon2)
% 将十进制度数转化为弧度
R = 6371; % 地球平均半径,单位千米
dLat = deg2rad(lat2 - lat1);
dLon = deg2rad(lon2 - lon1);
lat1 = deg2rad(lat1);
lat2 = deg2rad(lat2);
% Haversine公式(不懂的可以上网查查科普)
a = sin(dLat/2).^2 + cos(lat1) .* cos(lat2) .* sin(dLon/2).^2;
c = 2 * atan2(sqrt(a), sqrt(1-a));
dist = R * c;
end
运行主程序文件即可得到结果:
巡航路径及路径长度为39433km,总时长为39.4331小时左右。