蚁群算法求解迷宫最优路径问题

来源:互联网 发布:商业分析师 知乎 编辑:程序博客网 时间:2024/04/29 07:08

本段程序的基本思想是利用蚁群算法中的蚁周模型,来对全局的迷宫图进行信息素的跟新

和为每一只蚂蚁选择下一个方格。 一共会进行RcMax = 2000轮模拟(理论上模拟的次数越多结果

会越接近真实值),而在每一轮中会排除 M = 10只蚂蚁进行探路。同时在算法的回溯思想上采用的

是栈的数据结构来实现的。当栈最终为空时则表示无解。但同时这段程序的一缺点就是:由于我没在

算法中对每一轮的每只探路蚂蚁采用多线程的模式,所以整体的运行效率还不是很高。如读者有好的

思想或建议,请留言。

#include<iostream>#include<stack>#include<bitset>using namespace std;//坐标类struct Point{int x;int y;};//地图类template<int A,int B>class Map{public:int (*p)[B];//1表示为障碍方格,0表示该方格可通bitset<4> (*around)[B];//记录每一个方格四周四个方法的可选标记int row;//行数int col;//列数Map(){p =new int[A][B];around = new bitset<4>[A][B];}Map(Map<A,B> & B1){ p =new int[A][B]; around = new bitset<4>[A][B]; row = B1.row; col = B1.col; for(int i = 0;i<row;i++) { for(int j = 0;j<col;j++) { p[i][j] = B1.p[i][j]; around[i][j] = B1.around[i][j]; } }}Map<A,B> & operator=(Map<A,B> & B1){ row = B1.row; col = B1.col; for(int i = 0;i<row;i++) { for(int j = 0;j<col;j++) { this->p[i][j] = B1.p[i][j]; around[i][j] = B1.around[i][j]; } } return *this;}};//start起始点, end终止点template<int A,int B>bool FindPath(Map<A,B> & map,Point & start,Point & end){const int N1 =  A;const int N2 =  B;const int M = 10;//每一轮中蚂蚁的个数const int RcMax = 2000;//迭代次数const int IN = 1;//信息素的初始量double add[N1][N2];//每一段的信息素增量数组double phe[N1][N2];//每一段路径上的信息素double MAX = 0x7fffffff;double alphe,betra,rout,Q;//alphe信息素的影响因子,betra路线距离的影响因子,rout信息素的保持度,Q用于计算每只蚂蚁在其路迹留下的信息素增量double bestSolution = MAX;//最短距离stack<Point> Beststackpath;//最优路线//初始化变量参数和信息数组alphe = betra = 2;rout = 0.7;Q = 10;//先给图的外围加上障碍for(int i = 0;i<map.col;i++){map.p[0][i] = map.p[map.row-1][i] = 1;}for(int i = 0;i<map.row;i++){map.p[i][0] = map.p[i][map.col-1] = 1;}//初始化图中每一个方格的四周访问表示位,0表示可访问//初始化信息素数组for(int i = 0;i<N1;i++ ){ for(int j = 0;j<N2;j++) {phe[i][j] = IN;map.around[i][j].reset();//4个方向全部设为可选 }}//用于方向选择的偏移量数组   按照顺时针的方向Point offset[4];offset[0].x = 0; offset[0].y = 1;//向右offset[1].x = 1; offset[1].y = 0;//向下offset[2].x = 0; offset[2].y = -1;//向左offset[3].x = -1; offset[3].y = 0;//向上//每轮M只蚂蚁,每一轮结束后才进行全局信息素更新stack<Point> stackpath[M];//拷贝障碍地图Map<A,B> Ini_map[M];//记录每一只蚂蚁的当前位置Point Allposition[M];int s = 0;while(s<RcMax)//一共RcMax轮{//先清空每一只蚂蚁的路线存储栈for(int i = 0;i<M;i++){while (!stackpath[i].empty()){stackpath[i].pop();}}for(int i = 0;i<M;i++){Ini_map[i] = map;//将起点初始化为障碍点    Ini_map[i].p[start.x][start.y] = 1;//起点入栈    stackpath[i].push(start);//初始化每一只蚂蚁的当前位置Allposition[i] = start;}//开启M只蚂蚁循环 for(int j = 0;j<M;j++) { while(((Allposition[j].x)!=(end.x)||(Allposition[j].y)!=(end.y))) {       //选择下一步   double psum = 0;   for(int op = 0;op<4;op++)  {//计算下一个可能的坐标int x =  Allposition[j].x + offset[op].x;int y =  Allposition[j].y + offset[op].y;  if((Ini_map[j].around[ Allposition[j].x][Allposition[j].y])[op]==0 && Ini_map[j].p[x][y] !=1)  {  psum += pow(phe[x][y],alphe) * pow((10.0/stackpath[j].size()),betra);  }  }  //判断是否有选择  //如找到了下一点  if(psum!=0)  {  double drand = (double)(rand())/(RAND_MAX+1);  double pro = 0;  int re;  int x,y;  for( re = 0;re<4;re++)  {    //计算下一个可能的坐标 x =  Allposition[j].x + offset[re].x; y =  Allposition[j].y + offset[re].y;     if((Ini_map[j].around[ Allposition[j].x][Allposition[j].y])[re]==0 &&Ini_map[j].p[x][y]!=1) {  pro += (pow(phe[x][y],alphe) * pow((10.0/stackpath[j].size()),betra))/psum;  if(pro>=drand)  {  break;  } }  }   //入栈   Allposition[j].x = x;   Allposition[j].y = y;   stackpath[j].push(Allposition[j]);   //设置障碍   Ini_map[j].p[Allposition[j].x][Allposition[j].y] = 1;  }  else//没找到了下一点  {     //向后退一步,出栈  stackpath[j].pop();  //消除入栈时设置的障碍  Ini_map[j].p[Allposition[j].x][Allposition[j].y] = 0;  if(stackpath[j].empty())  {  return false;  }  //设置回溯后的Allposition  if(Allposition[j].x == stackpath[j].top().x)  {  if((Allposition[j].y - stackpath[j].top().y)==1)//向右  {  (Ini_map[j].around[ stackpath[j].top().x][stackpath[j].top().y])[0] = 1;//标记该方向已访问  }  if((Allposition[j].y - stackpath[j].top().y)==-1)//向左  {  (Ini_map[j].around[ stackpath[j].top().x][stackpath[j].top().y])[2] = 1;//标记该方向已访问  }  }  if(Allposition[j].y == stackpath[j].top().y)  {    if((Allposition[j].x - stackpath[j].top().x)==1)//向下  {  (Ini_map[j].around[ stackpath[j].top().x][stackpath[j].top().y])[1] = 1;//标记该方向已访问  }   if((Allposition[j].x - stackpath[j].top().x)==-1)//向上  {  (Ini_map[j].around[ stackpath[j].top().x][stackpath[j].top().y])[3] = 1;//标记该方向已访问  }  }  Allposition[j].x = stackpath[j].top().x;  Allposition[j].y = stackpath[j].top().y;  } } }//保存最优路线double solution = 0;for(int i = 0;i<M;i++){solution = 0;solution = stackpath[i].size();if(solution<bestSolution){ Beststackpath = stackpath[i]; bestSolution = solution;}}//计算每一只蚂蚁在其每一段路径上留下的信息素增量//初始化信息素增量数组for(int i = 0;i<N1;i++){ for(int j = 0;j<N2;j++) {  add[i][j] = 0; }}for(int i = 0;i<M;i++){ //先算出每只蚂蚁的路线的总距离solu double solu = 0; solu = stackpath[i].size(); double d = Q/solu; while(!stackpath[i].empty()) { add[stackpath[i].top().x][stackpath[i].top().y] += d; stackpath[i].pop(); }}//更新信息素for(int i=0;i<N1;i++){ for(int j = 0;j<N2;j++) { phe[i][j] = phe[i][j]*rout + add[i][j]; //为信息素设置一个下限值和上限值if(phe[i][j]<0.0001){phe[i][j] = 0.0001;}if(phe[i][j]>20){phe[i][j] = 20;} }}s++;}//轮//找到路径,并输出stackpathcout<<"找到最优路径!"<<endl;cout<<"最短路线长度为: 共"<<Beststackpath.size()<<"个方格!"<<endl;while(!Beststackpath.empty()){cout<<"<"<<Beststackpath.top().x<<","<<Beststackpath.top().y<<">"<<endl;Beststackpath.pop();}return true;}int main(){//建立迷宫Map<10,10> map;map.col = map.row = 10;int p[10][10];for(int i =0;i<10;i++)//初始化迷宫{ for(int j=0;j<10;j++) { p[i][j] = 0; }}//为迷宫设置障碍p[1][3] = 1;p[1][7] = 1;p[2][3] = 1;p[2][7] = 1;p[3][5] = 1;p[3][6] = 0;p[4][2] = 1;p[4][3] = 1;p[4][4] = 1;p[5][4] = 1;p[6][2] = 1;p[6][6] = 1;p[7][2] = 1;p[7][3] = 1;p[7][4] = 1;p[7][6] = 1;p[8][1] = 1;map.p = p ;Point start,end;start.x = start.y = 1;end.x =8,end.y = 8;if(!FindPath<10,10>(map,start,end)){  cout<<"该迷宫无解!"<<endl;}}


6 1
原创粉丝点击