先来说一下整个蚁群算法的思想:模拟蚂蚁寻找食物的过程。每只蚂蚁觅食时在走过的路线上会留下一种称为信息素的物质,蚂蚁之间靠感知这种物质的浓度进行信息传递。蚂蚁在选择路径时总是倾向于朝信息索浓度高的方向移动,而距离短的路径上走过的蚂蚁多,留下的信息素也多,后续蚂蚁选择它的概率也会越大;其他路径上的信息素会随着时间的推移不断挥发,这样就形成了一种正反馈机制,最后整个蚁群聚集到最短路径上。
我个人感觉这个算法比较重要的两个点:(1)如何选择先一步要走的城市。这个选择里面有两个值起作用,一个是当前位置到下一个城市的距离,另一个是这条路上的信息素的浓度。有两个值ALPHA和BETA分别调节他们的权重,(怎么设置好像得靠经验了)。
2)就是信息素的更新方式。代码里采用蚁量算法更新信息素即:
就是释放的信息素除ij的距离。(为什么这么设置原因很简单,路径越长信息素就越少)。
最后就是通过新信息素=信息素残留系数*原来的信息素+增加的信息素的方式完成更新。其他的都是比较简单的了。
具体看代码吧!
#include <bits/stdc++.h> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<iostream> //#define NULL -1 typedef long long ll; using namespace std; double INF = 10e9; const int num_ant=30;//蚂蚁的数量 const int num_city=30;//城市数量 const int MAX_GEN=1000;//最大迭代次数 int ALPHA = 1;//信息素的权重 int BETA = 4;//启发式因子重要程度权重 int remain = 100;//信息素残留参数 //double beat_path;//最优路径长度 double dis[num_city+50][num_city+50];//各个城市的距离 int city[num_city][2]={{87,7},{91,38},{83,46},{71,44},{64,60},{68,58},{83,69},{87,76},{74,78},{71,71},{58,69},{54,62},{51,67},{37,84},{41,94},{2,99},{7,64},{22,60},{25,62},{18,54},{4,50},{13,40},{18,40},{24,42},{25,38},{41,26},{45,21},{44,35},{58,35},{62,32}}; //各个城市的位置 int vis[num_city][num_city];//禁忌表 double info[num_city][num_city];//信息素矩阵 //double active[num_city][num_city];//启发因子矩阵 const int Q = 100;//信息素残留系数 double ROU = 0.5;//信息素残留度 unsigned seed=(unsigned)time(0); int random (int l,int h) { return l+(h-l)*rand()/(RAND_MAX+1); } double random(double l,double h) { return l+(h-l)*rand()/(RAND_MAX+1.0); } double Random (double ans) { return (double)((int)(ans+0.5)); } double power(double x, int y)//快速幂 { double ans = 1; while(y) { if(y&1)ans*=x; x*=x; y>>=1; } return ans; } struct Ant { int Path[num_city]; double length;//当前已走的长度; int vis[num_city];//已走的城市 int cur_city;//现在所在的城市 int num_move;//已经走的城市数 void Init() { memset(vis,0,sizeof(vis)); length=0.0; cur_city=random(0,num_city); Path[0]=cur_city; vis[cur_city]=1; num_move=1; } int choose() { int select_city=-1;//选择的城市 double sum=0.0; double possible_city[num_city];//各个城市被选中的概率 for(int i=0;i<num_city;i++) { if(!vis[i]) { possible_city[i]=power(info[cur_city][i],ALPHA)*power(1.0/dis[cur_city][i],BETA); sum+=possible_city[i];//计算概率 } else { possible_city[i]=0; } } //轮盘赌选择 double possible_du=0.0; //double sum_tmp=0.0; if(sum>0.0) { possible_du=random(0.0,sum); for(int i=0;i<num_city;i++) { if(!vis[i]) { possible_du-=possible_city[i]; if(possible_du<0.0) { select_city=i; break; } } } } if(select_city==-1) { for(int i=0;i<num_city;i++) { if(!vis[i]) { select_city=i; break; } } } return select_city; } void move_ant() { //if(num_move>=30)printf("KKKKKKK"); int next_city=choose();//选择的城市 Path[num_move]=next_city; vis[next_city]=1; cur_city=next_city;//更新当前位置 length+=dis[Path[num_move-1]][Path[num_move]]; num_move++; //if(num_move>=30)printf("KKKKKKK"); } void find_() { Init(); while(num_move<num_city) { move_ant(); //printf("%d ",num_move); //printf("?????"); } //printf("???"); length+=dis[Path[num_city-1]][Path[0]];//更新长度 //printf("??"); } }; struct TSP { Ant ants[num_ant]; Ant ant_best; void Init() { ant_best.length=double(INF);//初始化最优的蚂蚁,设为最大 printf("Begin to count\n"); for(int i=0;i<num_city;i++) { for(int j=0;j<num_city;j++) { double tmp1=city[j][0]-city[i][0]; double tmp2=city[j][1]-city[i][1]; dis[i][j]=sqrt(tmp1*tmp1+tmp2*tmp2);//计算每个城市间的距离 //printf("%d %d %lf\n",i,j,dis[i][j]); } } printf("Init Information\n"); for(int i=0;i<num_city;i++) { for(int j=0;j<num_city;j++) { info[i][j]=1.0;//初始化信息素 } } } void Update() { double tmpinfo[num_city][num_city];//临时矩阵储存新增的信息素 memset(tmpinfo,0,sizeof(tmpinfo)); int n=0; int m=0; //蚁量算法更新信息素 for(int i=0;i<num_ant;i++) { for(int j=1;j<num_city;j++) { n=ants[i].Path[j-1]; m=ants[i].Path[j]; tmpinfo[n][m]+=Q/ants[i].length; tmpinfo[m][n]=tmpinfo[n][m]; } n=ants[i].Path[0]; tmpinfo[n][m]+=Q/ants[i].length; tmpinfo[m][n]=tmpinfo[n][m]; } //更新环境的信息素 for(int i=0;i<num_city;i++) { for(int j=0;j<num_city;j++) { //新环境的信息素=残留的+新留下的 info[i][j]=info[i][j]*ROU+tmpinfo[i][j];//感觉ROU有待商榷 } } } void find_() { for(int i=0;i<MAX_GEN;i++) { printf("current generation is %d\n",i); for(int j=0;j<num_ant;j++) { ants[j].find_(); //printf("****"); } for(int j=0;j<num_ant;j++) { if(ant_best.length>ants[j].length) { ant_best=ants[j];//更新每一代的最优解 } } Update(); printf("current best length is %lf\n",ant_best.length); } } }; int main() { srand(seed);//随机函数初始化 TSP tsp; // printf("Please enter 30 cities position\n"); // for(int i=0;i<30;i++) // { // scanf("%d%d",&city[i][0],&city[i][1]);//可以自己手动输入城市位置 // } tsp.Init(); tsp.find_(); printf("The minimum path is \n"); for(int i=0;i<num_city;i++) { printf("%d ",tsp.ant_best.Path[i]);//打印出路径 } return 0; }