最近任务需要,学习路径搜索,先是看了A*算法,然后自己又研究了下蚁群算法。
我是在三维网格地图中实现的路径搜索,用的点而不是边来标记信息素的,主要是觉得边要麻烦一些,感兴趣的可以自己实现边标记信息素。蚂蚁在三维地图中走,每次可以上下,左右,斜着走,且都算作等效的一步距离。
1.原理
用到的公式如下:
(1)
(2)
(3)
这两个是基础公式,表示信息素的更新过程,(1)分别更新,该蚂蚁走过的路径中的信息素,(2)信息素的改变值是用一个常数Q除以该蚂蚁路径的长度,然后再。未走过的点更新值为0。(3)在自然界中蚂蚁遗留下来的信息素经过一段时间后会挥发,我们在算法中也模拟上述过程
主要步骤:
1. 首先要初始化一群蚂蚁和信息素,初始值设为1。
2. 每一只蚂蚁的时候按照信息素的轮盘赌算法,或者锦标赛算子走下一步。
3. 每一轮所有蚂蚁走完路径后,更新所有路径上的信息素。
4. 同时环境以一定的速率让信息素消失(信息素的挥发)。
5. 这样循环往复,蚂蚁们就有可能走出一条最优路径。
在此基础上加入了精英蚂蚁策略,每轮路径最优的蚂蚁,获得额外的信息素更新。
(4)
2.规划每只蚂蚁的路径
首先初始化信息素。
//初始化信息素
for(int i=0;i<x_len;i++){
for(int j=0;j<y_len;j++){
for(int k=0;k<z_len;k++){
pheromones[i][j][k] = initalPher;
}
}
}
private static Ant planPath(Point start,Point end,double[][][]pheromones,int[][][] map){
int x_len = map.length;
int y_len = map[0].length;
int z_len = map[0][0].length;
//规划路径
int tmp_x = start.getX() ,tmp_y = start.getY(),tmp_z = start.getZ();
int[][][] mark = new int[x_len][y_len][z_len];//每只蚂蚁走过后重置
Ant ant = new Ant();
while(tmp_x!=end.getX() || tmp_y!= end.getY() || tmp_z!= end.getZ()){
mark[tmp_x][tmp_y][tmp_z] = -1;///表示此处已经计算过了
ArrayList<Point> availablePoint = new ArrayList<>();
//寻找可达的点
for(int h=-1;h<=1;h++){
for(int w=-1;w<=1;w++){
for(int t=-1;t<=1;t++){
int next_x = tmp_x + h; ///下一个将加入open 集的格子的i
int next_y = tmp_y + w;///下一个将加入open 集的格子的j
int next_z = tmp_z + t;///下一个将加入open 集的格子的k
if(next_x>=0 && next_x<=x_len-1 && next_y>=0 && next_y<=y_len-1 && next_z>=0 && next_z<=z_len-1){
数组不越界,则进行计算
if(map[next_x][next_y][next_z]== obstacle || mark[next_x][next_y][next_z]==-1 ||(h==0&&w==0&t==0)){
//如果该格子是障碍,或者格子本身,跳过
continue;
}
availablePoint.add(new Point(next_x,next_y,next_z));
// if(t!=0 && (h!=0 || w!=0)){
// continue;
// }
mark[next_x][next_y][next_z] = -1;///表示此处已经计算过了
}
}
}
}
// int m = roulette(availablePoint,pheromones);
int m = jingbiaosai(availablePoint,pheromones);
//如果无路可走,重新从起点开始规划,,标记清零,路径清零
if(m==-1){
tmp_x = start.getX();
tmp_y = start.getY();
tmp_z = start.getZ();
// for(Point p1:ant.getPath()){
// mark[p1.getX()][p1.getY()][p1.getZ()] = 0;
// }
mark = new int[x_len][y_len][z_len];//每只蚂蚁走过后重置
ant.setPath(new ArrayList<Point>());
}else{
// System.out.print("选择的点:"+m+" ");
//轮盘赌选择下一个点
Point nextPoint = availablePoint.get(m);
//更新当前位置
tmp_x = nextPoint.getX();
tmp_y = nextPoint.getY();
tmp_z = nextPoint.getZ();
// System.out.print("("+tmp_x+","+tmp_y+","+tmp_z+")");
ant.getPath().add(nextPoint);//添加路径
mark[tmp_x][tmp_y][tmp_z] = -1;//走过了,标记
}
}
// System.out.println();
return ant;
}
选择下一步使用锦标赛算子,如下
private static int jingbiaosai(ArrayList<Point> availablePoint,
double[][][] pheromones) {
int len = availablePoint.size();
if(len==0)
return -1;
int a = (int) (Math.random()*len);
int b = (int) (Math.random()*len);
Point A = availablePoint.get(a);
Point B = availablePoint.get(b);
if(pheromones[A.getX()][A.getY()][A.getZ()]> pheromones[B.getX()][B.getY()][B.getZ()])
return a;
else
return b;
}
经过多轮的迭代后,输出最后一轮中的最佳结果。
3.总结与感想
通过自己的练习,对蚁群算法有了较为深刻的理解,发现蚁群算法和遗传算法有着许多相似之处。现在的缺点是运行时间慢,需要优化代码的效率。感兴趣的可以下载代码,代码链接如下:
https://download.csdn.net/download/mtngt11/10423686
请大家多多支持哟