#pragma warning(disable: 4786)
#include <iostream>
#include<fstream>
#include<set>
#include <string>
#include <list>
#include <vector>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <float.h>
using namespace std;
#define N 31 //城市数目
#define M 31 //蚂蚁数目
double inittao=1;
double tao[N][N];
double detatao[N][N];
double city_distance[N][N];
double yita[N][N];
int tabu[M][N]; //每一只蚂蚁一行
int route[M][N];
double solution[M];
int BestRoute[N];
double BestSolution= DBL_MAX; //赋值为double的最大值
double alfa,beta,rou,Q;
int iteration_times;
double EvalueSolution(int *a)
{
double dist=0;
for(int i=0;i<N-1;i++)dist+=city_distance[a[i]][a[i+1]];
dist+=city_distance[a[i]][a[0]];
return dist;
}
void InCityXY( double x[], double y[], char *infile )
{
fstream inxyfile(infile , ios::in );
if( !inxyfile )
{
cout<<"不能打开文件 <"<<infile<<"> file!\n";
exit(0);
}
int i=0;
while( !inxyfile.eof() )
{
inxyfile>>x[i]>>y[i];
if( ++i >= N ) break;
}
}
void initparameter(void)
{
alfa=1;
beta=5;
rou=0.9;
Q=100;
iteration_times=300;
double x[N];
double y[N];
InCityXY( x, y, "test.txt" );
for(int i=0;i<N;i++)
for(int j=i+1;j<N;j++)
{
city_distance[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
city_distance[i][j]=city_distance[j][i];
}
// 初始化启发式参数
for(i=0;i<N;i++)
for(int j=0;j<N;j++)
{
tao[i][j]=inittao;
if(j!=i)
yita[i][j]=100/city_distance[i][j]; //能见度为距离分之1
}
}
inline double RandFloat()
{
return (rand())/(RAND_MAX+1.0);
}
int roulette_wheel_selection(double A[],int n)
{
double t=RandFloat();
int i;
double d=0.0;
for(i=0;i<n;i++)
{
d+=A[i];
if(d>t)return i;
}
return rand()%n;//这里出现的概率几乎为0,只有在精度丢失时才发生
}
void initstate()
{
int i,k;
for( k=0;k<M;k++)
for(i=0;i<N;i++)
{
tabu[k][i]=0;
route[k][i]=-1;
}
for(k=0;k<M;k++)
{
int whichcity=k%N;
route[k][0]=whichcity; //把蚂蚁放在城市上
tabu[k][whichcity]=1;
}
}
void main(void)
{
srand(time(NULL));
initparameter();
int i,k;
int times;
for(times=0; times<iteration_times;times++)//迭代次数
{
initstate();
int s;
//每一只蚂蚁都去寻经
for(k=0;k<M;k++)
for(s=1;s<N;s++)//重复执行直到禁忌表满为止
{
double partsum=0;
for(int j=0;j<N;j++)
{
if(tabu[k][j]==0)partsum+=pow(tao[route[k][s-1]][j],alfa)*pow(yita[route[k][s-1]][j],beta);
}
double nextpie[N];
memset(nextpie,0,sizeof(double)*N);
for(j=0;j<N;j++)
{
if(tabu[k][j]==0)
nextpie[j]+=pow(tao[route[k][s-1]][j],alfa)*pow(yita[route[k][s-1]][j],beta)/partsum;
}
//赌盘轮循
int nextcity=roulette_wheel_selection(nextpie,N);
tabu[k][nextcity]=1;
route[k][s]=nextcity;
}
// 更新信息素
for(i=0;i<N;i++)
for(int j=0;j<N;j++)
detatao[i][j]=0;
for(k=0;k<M;k++) //每一只蚂蚁都有一个solution
{
solution[k]=EvalueSolution(route[k]);
if(solution[k]<BestSolution)
{
BestSolution=solution[k];
for(s=0;s<N;s++)
BestRoute[s]=route[k][s];
}
}
//更新detatao矩阵
for(k=0;k<M;k++)
{
for(s=0;s<N-1;s++)
{
detatao[route[k][s]][route[k][s+1]]+=Q/solution[k]; // s->s+1,s=[0,N-1]
}
detatao[route[k][N-1]][route[k][0]]+=Q/solution[k]; //N-1->0,此处完成一个循环
}
//更新tao矩阵
for(i=0;i<N;i++)
for(int j=0;j<N;j++)
{
tao[i][j]=rou*tao[i][j]+detatao[i][j];
}
}
//output the calculating results
cout<<"*-------------------------------------------------------------------------*"<<endl;
cout<<"ACA参数配置如下:";
cout<<"alfa="<<alfa<<", beta="<<beta<<", rou="<<rou<<", Q="<<Q<<endl;
cout<<"ACA最大迭代次数为:"<<iteration_times<<endl;
cout<<"最短路径为:"<<BestSolution<<endl;
cout<<"最优路由为:"<<endl;
for(i=0;i<N;i++)
cout<<BestRoute[i]<<" ";
cout<<endl;
cout<<"*-------------------------------------------------------------------------*"<<endl<<endl;
system("pause");
}
test.txt文件(答案:15601.9)
1304 2312
3639 1315
4177 2244
3712 1399
3488 1535
3326 1556
3238 1229
4196 1004
4312 790
4386 570
3007 1970
2562 1756
2788 1491
2381 1676
1332 695
3715 1678
3918 2179
4061 2370
3780 2212
3676 2578
4029 2838
4263 2931
3429 1908
3507 2367
3394 2643
3439 3201
2935 3240
3140 3550
2545 2357
2778 2826
2370 2975