蚁群算法原理及c++实现
⼀、原理
1. 蚂蚁觅⾷⾏为
蚁群在寻找⾷物时,总能找到⼀条蚁⽳到⾷物的最短路径,并且能随着环境的变化⽽更新最优路径。究其原因,是因为蚂蚁在运动过程中,会在所经过路径上留下⼀种称为信息素(pheromone)的物质,其他蚂蚁在运动中可以感知到这种物质,并以此来指导⾃⼰的运动⽅向。蚁群的这种⾏为表现出⼀种信息正反馈现象:某⼀路径上⾛过的蚂蚁越多,则后来者选择该路径的概率越⼤。
2.蚁群算法
⼜称蚂蚁算法,是⼀种基于群体智能的算法,⽤来在图中寻找优化路径的概率型。它由Marco Dorigo于1992年在他的博⼠论⽂中提出,其灵感来源于蚂蚁在寻找⾷物过程中发现路径的⾏为。在解决实际问题时,⼈⼯蚁群相较于⾃然蚁群有⼀定的记忆能⼒,可记住已访问过的节点,其次⼈⼯蚁群在选择路径时依照⼀定规律,并不是盲⽬的。蚁群算法常⽤来解决路径规划等离散优化问题,如旅⾏商问题(TSP)、指派问题、调度问题。
2,1 特点
1. 正反馈:可较快发现较优解。
2. 分布式:基于种群的进化算法,本质具有并⾏性,易于并⾏实现。
3. 启发式搜索:反映搜索中的的先验性和确定性因素(如距离)强度。
4. 鲁棒性强:不易受某个个体影响。梦见大雪
2.2 算法流程(以TSP问题为例)
TSP问题:⼀商⼈去n个城市销货,所有城市⾛⼀遍再回到起点,使所⾛路程最短。
1. 初始化相关参数:蚁群规模、信息素因⼦、启发函数因⼦、信息素挥发因⼦、信息素常数和最⼤迭代次数等。将城市信息读⼊程序并
进⾏预处理,即将城市间信息转化为矩阵。
2. 随机将蚂蚁放⼊不同出发点,计算每个蚂蚁的下⼀步要访问的城市,直到有蚂蚁访问完所有城市。
3. 计算每个蚂蚁经过的路径长度Lk,记录当前迭代次数下的最优解(访问完所有城市且路径长度最短),更新各条路径上的信息素浓
度。
4. 断是否达到最⼤迭代次数,若否则返回步骤2,若是则顺序执⾏。
5. 输出最优路径和相关指标,如运⾏时间和迭代次数。
2.3 相关公式
混声唱法怎么练
2.4 流程图
三、例⼦
试设计⼀个并⾏算法,求下图中⼀个源点到其他定点的最短路径。(VS2019+Eigen)
3.1 关键代码
数据结构:
将蚂蚁设置为⼀个结构体,包含所在位置、禁忌表、所⾛路径和是否到达终点标志四项内容。为了便于计算,将信息素、启发信息与距离信息分别在8*8的矩阵中存放,这样可以调⽤Eigen库直接进⾏矩阵计算,达到更新信息素的⽬的。
城市也设为⼀个结构体,包含城市编号和选择概率两项内容。这⾥将城市设置为结构体,主要是考虑到在选择下⼀步⾏进城市时,要先计算选择概率再通过轮盘赌来确定下⼀步城市,轮盘赌时需要将城市编号与其选择概率⼀⼀对应。
具体代码部分如下:
struct ant //蚂蚁结构体
{
int loc;//位置
int tabu[cityNum];//禁忌表
int antPath[pathNum];//⾛过的路
bool flag;//是否到达终点7
};
struct ant ants[antNum];//蚁群
typedef Matrix<double,8,8> Matrix8d;
Matrix8d dist;//距离矩阵
Matrix8d pher;//信息素矩阵
Matrix8d nextPher;//下⼀代信息素矩阵
Matrix8d insp;//启发信息矩阵
struct city //城市结构体
{
int num;//编号
double prob;//选择概率
};
struct city cityProb[cityNum];//可到达城市组
double lineCityProb[cityNum];//线性化可到达城市的选择概率
城市选择⽅式
当蚂蚁k选择下⼀步要去的城市时,有以下⼏个步骤:
1. 对照蚂蚁k的禁忌表,求出下⼀步所有可去的城市各⾃的选择概率(概率计算见公式(1));
2. 线性化所有可去城市的概率,⽣成介于0~1之间的随机数(线性化概率的⽬的是实现轮盘赌);
3. 使⽤轮盘赌⽅法选择下⼀步要去的城市。
我奉献我快乐作文概率计算与轮盘赌选择对应代码⽚如下:
//轮盘赌选择下⼀步⾏进城市
微生物与人类
int citySelect(int k,int f)
{
int c =0;//记录蚂蚁可⾏进的城市个数
/
/1、计算可⾏进的各城市选择概率
for(int m =0; m < cityNum; m++)
{
建行面试
//若城市(i,j)之间有路且j不在蚂蚁k的禁忌表中,则计算概率
if(dist(ants[k].loc, m)!=-1&&!ifCityInTabu(m, k))
{
cityProb[c].num = m;
cityProb[c].prob =citySelProb(k, m);
c++;
什么是html
}
}
/
/2、线性化选择概率
for(int m =0; m < c; m++)
{
for(int n = m; n >=0; n--)
{
面试复试lineCityProb[m]+= cityProb[n].prob;
}
}
//3、产⽣随机数选择城市
double r =rand()/double(RAND_MAX);
int j =0;//选取的⽬标城市
for(int m =0; m < cityNum; m++)
{
if(r <= lineCityProb[m])
{
j = cityProb[m].num;
updateAnt(k, j);
吃俺老孙一棒if(j == f)
ants[k].flag =1;//若蚂蚁k下⼀步城市为⽬的地城市,则修改标志
return j;
}
}
}
信息素更新
因为将信息素存⼊矩阵,所以在计算时较为简单,具体分为如下⼏步:
1. 计算信息素增量矩阵:
for k = 1 to m do (遍历蚁群)
for j = 1 to n do (遍历蚂蚁k的⾏⾛路径)
计算蚂蚁k在路径(i, j)对应的信息素增量(见公式(3));
更新路径(i, j)在上⼀轮的信息素增量;
end for
end for
2. 计算更新后的信息素矩阵:
信息素挥发系数*信息素矩阵+信息素增量矩阵(见公式(2))。
对应代码⽚如下: