#include <stdio.h>
#include <cmath>
#include <iostream>
#include <fstream>
#include <time.h>
using namespace std;
const int iAntCount=34;//蚂蚁数量
const int iCityCount=51;//城市数量
const int iItCount=2000;//最大跌代次数
const double Q=100;
const double alpha=0;
const double beta=5;
const double rou=0.5;
int besttour[iCityCount];//最短路径列表
double rnd(int low,double uper){ //获得随机数
double p=(rand()/(double)RAND_MAX)*((uper)-(low))+(low);
return (p);
};
int rnd(int uper) {
return (rand()%uper);
};
class GInfo { //tsp地图信息,包含了信息素,城市距离,和信息素变化矩阵
public:
double m_dDeltTrial[iCityCount][iCityCount];
double m_dTrial[iCityCount][iCityCount];
double distance[iCityCount][iCityCount];
};
GInfo Map;
class ant {
private:
int ChooseNextCity();//选择城市
double prob[iCityCount]; // probability of choosing next city for each ant
int m_iCityCount; // recode the # of city in tabu
int AllowedCity[iCityCount];// city haven' been visited yet; allowed if arr[i]=1, not allow if arr[i]=0
public:
int tabu[iCityCount]; // index from 0 to m_iCityCount; value == city having been visited
double m_dLength;
ant();
void addcity(int city);
void Clear();
void CalcDistance(); // ## it's better to be name as CalcLengthTour()
void move();
void move2last();
};
void ant::move2last() { // TODO: WHAT IS THIS FOR?
int i;
for(i=0;i<iCityCount;i++)
if (AllowedCity[i]==1) {
addcity(i);
break;
}
} // ##: N ITERATION, CYCLE, EACH ANT COMPLETES A TOUR, TRAIL INTENSITY SHOULD BE UPDATED
void ant::Clear() {
for(int p = 0; p < iCityCount; ++p) {
for(int q = 0; q < iCityCount; ++q) {
Map.m_dDeltTrial[p][q] = 0;
}
} // set m_dDeltTrail[i][j] = 0 for next generation
for(int p = 0; p < iCityCount; ++p)
AllowedCity[p] = 1; // set all cities to be allowed for now
m_iCityCount = 0; //clear tabu list for next iteration; m_iCityCount should be executed before addcity(i); //it matters a lot for the performance of this progm
int i = tabu[iCityCount-1]; // THIS IS DEFAULT
prob[i] = 0;
addcity(i); // AllowedCity[i] = 0; is within addcity(i)
m_dLength = 0; // set m_dLength to be 0 for next generation
}
ant::ant() {
m_dLength = 0;
m_iCityCount = 0;
int i;
for(i=0;i<iCityCount;i++) {
AllowedCity[i]=1;
prob[i]=0;
}
}
void ant::addcity(int city) {
//add city to tabu;
tabu[m_iCityCount]=city;
m_iCityCount++;
AllowedCity[city]=0;
}
int ant::ChooseNextCity() {
//Update the probability of path selection
//select a path from tabu[m_iCityCount-1] to next
int i;
int j=10000;
double temp = 0; // store: denominator
int curCity=tabu[m_iCityCount-1];
for (i=0;i<iCityCount;i++) {
if(AllowedCity[i]==1) {
temp+=pow((1.0/Map.distance[curCity][i]),beta) * pow((Map.m_dTrial[curCity][i]),alpha);
} // fenmu -- denominator
}
double sel=0; // TODO: what is this for?
for (i=0;i<iCityCount;i++) {
if(AllowedCity[i]==1) {
//prob[i] = pow((1.0/Map.distance[curCity][i]),(int)beta) * pow((Map.m_dTrial[curCity][i]),(int)alpha)/temp;
prob[i] = (pow((1.0/Map.distance[curCity][i]),beta) * pow((Map.m_dTrial[curCity][i]), alpha))/temp;
sel+=prob[i]; // TODO: what is this for? // sel may stand for selection
}
else
prob[i]=0;
} // at this point sel should be almost equal to 1;
/* // Customized Probability code is MUCH less effecient
temp = prob[0];
int mmsel = 0;
for(int k = 1; k < iCityCount; ++k)
if(temp < prob[k]) {
temp = prob[k];
mmsel = k;
}
return mmsel;
*/
// TODO: DEL
double mRate=rnd(0,sel); //TODO: what is this for?
double mSelect=0; // TODO: what is this for?
for ( i = 0; i < iCityCount; i++ ) {// TODO: what is this for?
if(AllowedCity[i]==1)
mSelect+=prob[i] ;
if (mSelect>=mRate) { j=i; break; }
} // ##: IT IS PROBABLY FOR AVOID STAGNATION, PASS FOR THE MOMENT
if (j==10000) { // TODO: what is this for?
temp = -1;
for (i = 0; i < iCityCount; ++i) {
if(prob[i] > temp) {
j = i;
temp = prob[i];
}
}
// DEFAULT CODE
temp=-1;
for (i=0;i<iCityCount;i++) {
if(AllowedCity[i]==1)
if (temp) {
temp=pow((1.0/Map.distance[curCity][i]),beta)*pow((double)(Map.m_dTrial[curCity][i]),alpha);
j=i;
}
}
}
return j; // just return max(prob[i]);
}
void ant::CalcDistance() {
// Update the length of tour of each ant
int i;
for(i=0;i<iCityCount-1;i++)
m_dLength+=Map.distance[tabu[i]][tabu[i+1]];
m_dLength+=Map.distance[tabu[iCityCount-1]][tabu[0]];
}
void ant::move() {
//the ant move to next town and add town ID to tabu.
int j;
j=ChooseNextCity();
addcity(j);
}
class project {
public:
double m_dLengthVar;
ant ants[iAntCount];
project();
void UpdateTrial();
void initmap();
void GetAnt();
void StartSearch();
};
void project::initmap() {
int i;
int j;
for(i=0;i<iCityCount;i++)
for (j=0;j<iCityCount;j++) {
Map.m_dTrial[i][j]=1; // assign trail for each edge with a small value
Map.m_dDeltTrial[i][j]=0; // increment of trail is 0 at the beginning
}
}
project::project() {
//initial map,read map infomation from file . et.
initmap();
m_dLengthVar = 10e9; //TODO: what is this variable for?
ifstream in("eil51.tsp");
struct city {
int num; // # of the city
int x; // x-coordinate
int y; // y-coordinate
}cc[iCityCount];
for (int i=0;i<iCityCount;i++) {
in>>cc[i].num>>cc[i].x>>cc[i].y;
besttour[i]=0;
} // read file
int j;
for(int i=0;i<iCityCount;i++)
for (j=0;j<iCityCount;j++) {
Map.distance[i][j]=sqrt(pow((double)(cc[i].x-cc[j].x),2)+pow((double)(cc[i].y-cc[j].y),2));
} // compute distance of every two city; TODO: can be optimized
}
void project::UpdateTrial() {
//calculate the changes of trial information
int i;
int j;
for(i=0;i<iAntCount;i++) {
for (j=0;j<iCityCount-1;j++) {
Map.m_dDeltTrial[ants[i].tabu[j]][ants[i].tabu[j+1]]+=Q/ants[i].m_dLength ;
Map.m_dDeltTrial[ants[i].tabu[j+1]][ants[i].tabu[j]]+=Q/ants[i].m_dLength; // G[i][j] = G[j][i]
}
Map.m_dDeltTrial[ants[i].tabu[iCityCount-1]][ants[i].tabu[0]]+=Q/ants[i].m_dLength;
Map.m_dDeltTrial[ants[i].tabu[0]][ants[i].tabu[iCityCount-1]]+=Q/ants[i].m_dLength;
}
for (i=0;i<iCityCount;i++) {
for (j=0;j<iCityCount;j++)
{
Map.m_dTrial[i][j]=(rou*Map.m_dTrial[i][j]+Map.m_dDeltTrial[i][j] );
Map.m_dDeltTrial[i][j]=0;
}
}
}
void project::GetAnt() { // uniformly-distributed place m ants to n towns
//randomly put ant into map
int i=0;
int city;
srand( (unsigned)time( NULL ) +rand());
for (i=0;i<iAntCount;i++) {
city = rnd(iCityCount);
ants[i].addcity(city);
}
}
void project::StartSearch() {
//begin to find best solution
int max=0; // times of iteration
int i;
int j;
double temp; // store shortest distance among those m ants in each iteration
int temptour[iCityCount]; // temporary the tour with the shortest distance in the current iteration
while (max<iItCount) {
for (j=0;j<iAntCount;j++) {
for (i=0;i<iCityCount-1;i++)
ants[j].move();
} // in each iteration, every ant makes iCityCount moves, completing a cycle and then updating trail intensity
for(j=0;j<iAntCount;j++) {
// ants[j].move2last();
ants[j].CalcDistance(); // CalcLengthTour of each ant, preparing for updating delta trail
}
//find out the best solution of the step and put it into temp
int t;
temp = ants[0].m_dLength;
for (t=0;t<iCityCount;t++)
temptour[t]=ants[0].tabu[t];
for(j=1; j<iAntCount; j++) {
if (temp > ants[j].m_dLength) { // update shortest distance and its tour when possible
temp = ants[j].m_dLength;
for ( t = 0; t < iCityCount; t++ )
temptour[t]=ants[j].tabu[t];
}
}
if(temp < m_dLengthVar) { // m_dLengthVar is a member variable of Object of Class project
m_dLengthVar = temp;
for ( t=0;t<iCityCount;t++)
besttour[t] = temptour[t];
}
printf("%4d : %f\n", max, m_dLengthVar); // # of iteration and its shortest distance found
UpdateTrial();
for(j=0;j<iAntCount;j++)
ants[j].Clear();
max++;
}
printf("The shortest route is : %f\n",m_dLengthVar); // print out the shortest path of N nodes
for ( int t=0;t<iCityCount;t++)
printf(" %d ",besttour[t]);
printf("\n");
}
int main() {
project TSP;
TSP.GetAnt();
TSP.StartSearch();
return 0;
}
Reference:
http://www.oschina.net/code/snippet_33669_9138