时间:2019.8.12
老师:祁永强
内容:蚁群算法基本原理
个性:“无中生有,自圆其说”,戴准帽子(套框架),优化算法必须能用matlab仿真,狠劲,炼狱式成长,书由厚到薄(按页)由薄到厚(),撕书式成长,佯装努力结果是没有差别的,为人师在于唤人醒,“日锯其半,万日不竭”,20页最佳
感想:从原理上了解了蚁群算法,所找的一份ACATSP代码成功复现,并理解了全过程。唯独在下一个访问地点的概率计算与选择上稍有存疑,写在了最后。欢迎交流探讨观点,e-mail:03170908@cumt.edu.cn
1.概述概念
起源:意大利M.Dorigo等,通过模拟自然界蚂蚁搜索路径的行为,提出的新型模拟进化算法。
原理:蚂蚁在运动过程中,能感知信息素,指导自己的运动方向(正反馈)。信息素越多越好,为什么,因为初始时,信息素越多说明往返越多(同样时间时),即路径最短。
核心:信息素+正反馈(所有群体算法的核心)
适用:求解TSP问题、分配问题、job-shop调度问题
优势:求解复杂优化问题(特别是离散优化问题)
比较优势:与大多数基于梯度的优化算法想比
1.无集中控制约束,不会因个别的故障影响整个问题的求解,保证鲁棒性
2.非直接信息交换,确保系统的扩展性
3.并行分布式
4.对问题定义的连续性无特殊要求
5.算法实现简单
2.蚁群算法基本思想
信息素要按一定比率挥发(避免局部最优)
每只蚂蚁的一部转移概率由图中的每条边上的两类参数决定:
1.信息素值也称信息素痕迹
2.可见度,即先验值
信息素的更新方式:
1 挥发 :所有路径上的信息素以一定比率进行减少
2 增强 :给蚂蚁评价,好蚂蚁加强
基于图的蚁群算法(GBAS)
3.基本蚁群算法
表示时刻蚂蚁从城市i到城市的转移概率,计算公式如下:
:信息素
: 信息素增强(启发式的体现,和距离负相关)
: 推荐1,5
信息素挥发系数:推荐0.5
信息素增强=,Q推荐1,L表示距离长度
规模和终止条件:
1 给定终止轮数
2 最优解了连续次相同
3 给定目标值
4.【进阶】收敛
马于尔科夫收敛定义,依概率收敛于1
证明收敛,才能说算法是可以实现的
蚁群算法分支:MAX-MIN蚂蚁,精英蚂蚁,蚁周算法,蚁密算法,蚁量算法
5.代码实例
蚁群算法针对TSP应用(超详细分析)
ant-colony-algorithm-for-TSP(MATLAB可直接运行代码)
原始出处:解放军信息工程大学老师
下面代码注释为本人针对上面的资料进行学习之后添加,欢迎交流。转移矩阵部分务必参考上面的公式
function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ACATSP(C,NC_max,m,Alpha,Beta,Rho,Q)
%%-------------------------------------------------------------------------
%% 主要符号说明
%% C n个城市的坐标,n×2的矩阵
%% NC_max 最大迭代次数
%% m 蚂蚁个数
%% Alpha 表征信息素重要程度的参数 1
%% Beta 表征启发式因子重要程度的参数 5
%% Rho 信息素蒸发系数 0.5
%% Q 信息素增加强度系数 1
%% R_best 各代最佳路线
%% L_best 各代最佳路线的长度
%%=========================================================================
%%第一步:变量初始化
n=size(C,1);%n表示问题的规模(城市个数)
D=zeros(n,n);%D表示完全图的赋权邻接矩阵
for i=1:n
for j=1:n
if i~=j
D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
else
D(i,j)=eps; %i=j时不计算,应该为0,但后面的启发因子要取倒数,用eps(浮点相对精度)表示
end
D(j,i)=D(i,j); %对称矩阵
end
end
Eta=1./D; %Eta为启发因子,这里设为距离的倒数
Tau=ones(n,n); %Tau为信息素矩阵
Tabu=zeros(m,n); %存储并记录路径的生成
NC=1; %迭代计数器,记录迭代次数
R_best=zeros(NC_max,n); %各代最佳路线
L_best=inf.*ones(NC_max,1); %各代最佳路线的长度,先赋值inf无穷大,后面更新
L_ave=zeros(NC_max,1); %各代路线的平均长度
while NC<=NC_max %停止条件之一:达到最大迭代次数,停止
%%第二步:将m只蚂蚁放到n个城市上,全放完需要[m/n]轮
Randpos=[]; %#随机存取,此处初始起点,可以固定设置
for i=1:(ceil(m/n))
Randpos=[Randpos,randperm(n)];%randperm产生1到n的随机序列
end %使用这种随机分配方法可以保证初始去往各个城市的蚂蚁数量均匀,比全部随机要更好
Tabu(:,1)=(Randpos(1,1:m))'; %取出前m个,赋给Tabu路径矩阵,即给出了m只蚂蚁的初始去往地点
%%第三步:m只蚂蚁按概率函数选择下一座城市,对应公式中的转移矩阵
for j=2:n %所在城市不计算,j表示即将访问的下一座城市
for i=1:m
visited=Tabu(i,1:(j-1)); %记录已访问的城市,避免重复访问
J=zeros(1,(n-j+1)); %待访问的城市,总数n-j+1
P=J; %待访问城市的选择概率分布
Jc=1; %待访问的城市个数,初始为1(用于修改矩阵J时做下标)
for k=1:n
if isempty(find(visited==k, 1))%这里改善了寻找的性能,只要能找到一个等于K就非空
J(Jc)=k;
Jc=Jc+1; %待访问的城市个数自加1
end
end %循环完成后将更新完待访问矩阵J
%下面计算从当前城市visted(end)转移到待选城市k的概率分布,参照公式的分子
%信息素的作用也仅体现在这里,计算转移矩阵概率
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); %若计算的概率大于rand的就可以选择这条路线
to_visit=J(Select(1)); %选择可选城市列表Select中的第一个作为将访问的下一个
Tabu(i,j)=to_visit;
end
end
if NC>=2
Tabu(1,:)=R_best(NC-1,:);
%NC=2开始,第一只蚂蚁路径使用上一轮的最佳路线,参与下面的信息素更新
%#所以其实上面i=1那只蚂蚁的路径推演是没必要的,可以用if去优化掉
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(NC)=min(L); %最佳距离取最小
pos=find(L==L_best(NC));
R_best(NC,:)=Tabu(pos(1),:); %此轮迭代后的最佳路线
L_ave(NC)=mean(L); %此轮迭代后的平均距离
NC=NC+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);
%#此次循环在从n会到起点上的信息素增量,对应要求,单程可删去
end
Tau=(1-Rho).*Tau+Delta_Tau; %考虑信息素挥发掉Rho,更新后的信息素,加上Delta
%%第六步:路径表清零
Tabu=zeros(m,n); %%直到最大迭代次数
end
%%第七步:输出结果
Pos=find(L_best==min(L_best)); %找到最佳路径(非0为真)
Shortest_Route=R_best(Pos(1),:) %最大迭代次数后最佳路径
Shortest_Length=L_best(Pos(1)) %最大迭代次数后最短距离
subplot(1,2,1) %绘制第一个子图形
DrawRoute(C,Shortest_Route) %画路线图的子函数
subplot(1,2,2) %绘制第二个子图形
plot(L_best)
hold on %保持图形
plot(L_ave,'r')
title('平均距离和最短距离') %标题
function DrawRoute(C,R)
%%=========================================================================
%% DrawRoute.m
%% 画路线图的子函数
%% C Coordinate 节点坐标,由一个N×2的矩阵存储
%% R Route 路线
%%=========================================================================
N=length(R);
scatter(C(:,1),C(:,2));
hold on
plot([C(R(1),1),C(R(N),1)],[C(R(1),2),C(R(N),2)],'g')%#这里绘制了起点到终点的直连线,非循环路径可删去
hold on
for i=2:N
plot([C(R(i-1),1),C(R(i),1)],[C(R(i-1),2),C(R(i),2)],'g')
hold on
end
title('旅行商问题优化结果 ')
关于代码的一点说明,结合蚁群算法的原理和主要的转移概率公式,理解代码不难。上面的代码是针对完全图的回路所计算的,其中有多处可以加以改动,在注释号之后加上了#号,体现我的一点个人见解。
此外,一个困惑:上面在计算待访问城市之后,关于下一个城市的选择,使用的是向前累加,取判断大于某个随机值rand,这样体现的是轮盘赌算法吗?