#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<assert.h>
#include<time.h>
#include<fstream>
#define NUMBER_OF_INTERSECTIONS 8
#define MAX_DISTANCE 100
#define MIN_LOAD 0
#define SIGNAL_TIME 2
#define MAX_TOUR (NUMBER_OF_INTERSECTIONS * MAX_DISTANCE)
#define MAX_ANTS 8
using namespace std;
//Initial Definiton of the problem
struct antType{
int curNode, nextNode, pathIndex;
int tabu[NUMBER_OF_INTERSECTIONS];
int path[NUMBER_OF_INTERSECTIONS];
double tourLength;
};
struct antTime{
int curNode2,nextNode2,pathIndex2;
int tabu2[NUMBER_OF_INTERSECTIONS];
int path2[NUMBER_OF_INTERSECTIONS];
double tourTime;
};
#define ALPHA 1.0
#define BETA 5.0 //This parameter raises the weight of distance over pheromone
#define RHO 0.5 //Evapouration rate
#define QVAL 100
#define MAX_TOURS 20
#define MAX_TIME (MAX_TOURS * NUMBER_OF_INTERSECTIONS)
#define INIT_PHER (1.0/NUMBER_OF_INTERSECTIONS)
//cityType cities[NUMBER_OF_INTERSECTIONS];
antType ants[MAX_ANTS];
antTime ants2[MAX_ANTS];
antType antBest;
antTime antTBest;
double dist[NUMBER_OF_INTERSECTIONS][NUMBER_OF_INTERSECTIONS];
double load[NUMBER_OF_INTERSECTIONS][NUMBER_OF_INTERSECTIONS];
double phero[NUMBER_OF_INTERSECTIONS][NUMBER_OF_INTERSECTIONS];
double phero2[NUMBER_OF_INTERSECTIONS];
double best=(double)MAX_TOUR;
double bestTime=(double)(NUMBER_OF_INTERSECTIONS*SIGNAL_TIME);
int bestIndex;
int bestTIndex;
void init()
{
int from,to,ant;
//creating cities
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
//randomly place cities
// cities[from].x = (1 + (rand() % (int)(50 - 1+ 1)));
// cities[from].y = (1 + (rand() % (int)(50 - 1 + 1)));
//printf("\n %d %d",cities[from].x, cities[from].y);
for(to=0;to<NUMBER_OF_INTERSECTIONS;to++)
{
dist[from][to] = 0.0;
phero[from][to] = INIT_PHER;
}
}
//computing distance
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
for( to =0; to < NUMBER_OF_INTERSECTIONS; to++)
{
if(to!=from && dist[from][to]==0.0)
{
// int xd = pow( abs(cities[from].x - cities[to].x), 2);
// int yd = pow( abs(cities[from].y - cities[to].y), 2);
dist[from][to] = (1 + (rand() % (int)(100 - 1+ 1)));
dist[to][from] = dist[from][to];
}
}
}
//initializing the ANTs
to = 0;
for( ant = 0; ant < MAX_ANTS; ant++)
{
if(to == NUMBER_OF_INTERSECTIONS)
to=0;
ants[ant].curNode = to++;
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
ants[ant].tabu[from] = 0;
ants[ant].path[from] = -1;
}
ants[ant].pathIndex = 1;
ants[ant].path[0] = ants[ant].curNode;
ants[ant].nextNode = -1;
ants[ant].tourLength = 0;
//loading first city into tabu list
ants[ant].tabu[ants[ant].curNode] =1;
}
}
void init_Ants()
{
int from,to,ant;
//creating cities
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
phero2[from]= INIT_PHER;
}
cout<<"\nENTER THE LOAD MATRIX\n";
//computing distance
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
for( to =0; to < NUMBER_OF_INTERSECTIONS; to++)
{
cin>>load[from][to];
}
}
//initializing the ANTs
to = 0;
for( ant = 0; ant < MAX_ANTS; ant++)
{
if(to == NUMBER_OF_INTERSECTIONS)
to=0;
ants2[ant].curNode2 =antBest.path[ant] ;
for(from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
ants2[ant].tabu2[from] = 0;
ants2[ant].path2[from] = -1;
}
ants2[ant].pathIndex2 = 1;
ants2[ant].path2[0] = ants2[ant].curNode2;
ants2[ant].nextNode2 = -1;
ants2[ant].tourTime = 0;
//loading first city into tabu list
ants2[ant].tabu2[ants2[ant].curNode2] =1;
}
}
void restartTime_Ants()
{
int ant,i,to=0;
for(ant = 0; ant<MAX_ANTS; ant++)
{
if(ants2[ant].tourTime < bestTime)
{
bestTime = ants[ant].tourLength;
bestIndex = ant;
}
ants2[ant].nextNode2 = -1;
ants2[ant].tourTime = 0.0;
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
ants2[ant].tabu2[i] = 0;
ants2[ant].path2[i] = -1;
}
if(to == NUMBER_OF_INTERSECTIONS)
to=0;
ants2[ant].curNode2 = antBest.path[to++];
ants2[ant].pathIndex2 = 1;
ants2[ant].path2[0] = ants2[ant].curNode2;
ants2[ant].tabu2[ants2[ant].curNode2] = 1;
}
}
//reinitialize all ants and redistribute them
void restartAnts()
{
int ant,i,to=0;
for(ant = 0; ant<MAX_ANTS; ant++)
{
if(ants[ant].tourLength < best)
{
best = ants[ant].tourLength;
bestIndex = ant;
}
ants[ant].nextNode = -1;
ants[ant].tourLength = 0.0;
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
ants[ant].tabu[i] = 0;
ants[ant].path[i] = -1;
}
if(to == NUMBER_OF_INTERSECTIONS)
to=0;
ants[ant].curNode = to++;
ants[ant].pathIndex = 1;
ants[ant].path[0] = ants[ant].curNode;
ants[ant].tabu[ants[ant].curNode] = 1;
}
}
double antProduct(int from, int to)
{
return(( pow( phero[from][to], ALPHA) * pow( (1.0/ dist[from][to]), BETA)));
}
int selectnextTimeNode(int ant)
{
int from, to;
double denom = 0.0;
from=ants2[ant].curNode2;
for(to=0;to<NUMBER_OF_INTERSECTIONS;to++)
{
if(ants2[ant].tabu2[to] == 0)
{
denom += antProduct( from, to );
}
}
assert(denom != 0.0);
do
{
double p;
to++;
if(to >= NUMBER_OF_INTERSECTIONS)
to=0;
if(ants2[ant].tabu2[to] == 0)
{
p = antProduct(from,to)/denom;
//printf("\n%lf %lf", (double)rand()/RAND_MAX,p);
double x = ((double)rand()/RAND_MAX);
if(x < p)
{
//printf("%lf %lf Yo!",p,x);
break;
}
}
}while(1);
return to;
}
int selectnextNode( int ant )
{
int from, to;
double denom = 0.0;
from=ants[ant].curNode;
for(to=0;to<NUMBER_OF_INTERSECTIONS;to++)
{
if(ants[ant].tabu[to] == 0)
{
denom += antProduct( from, to );
}
}
assert(denom != 0.0);
do
{
double p;
to++;
if(to >= NUMBER_OF_INTERSECTIONS)
to=0;
if(ants[ant].tabu[to] == 0)
{
p = antProduct(from,to)/denom;
//printf("\n%lf %lf", (double)rand()/RAND_MAX,p);
double x = ((double)rand()/RAND_MAX);
if(x < p)
{
//printf("%lf %lf Yo!",p,x);
break;
}
}
}while(1);
return to;
}
int simulateTime()
{
int k;
int moving = 0;
for(k=0; k<MAX_ANTS; k++)
{
//checking if there are any more cities to visit
if( ants2[k].pathIndex2 < NUMBER_OF_INTERSECTIONS )
{
ants2[k].nextNode2 = selectnextTimeNode(k);
ants2[k].tabu2[ants2[k].nextNode2] = 1;
ants2[k].path2[ants2[k].pathIndex2++] = ants2[k].nextNode2;
ants2[k].tourTime += ((load[ants2[k].curNode2][ants2[k].nextNode2])/(dist[ants[k].curNode][ants[k].nextNode])*2); //handle last case->last city to first
if(ants2[k].pathIndex2 == NUMBER_OF_INTERSECTIONS)
{
ants2[k].tourTime += ((load[ants2[k].path2[NUMBER_OF_INTERSECTIONS -1]][ants2[k].path2[0]])/(dist[ants2[k].path2[NUMBER_OF_INTERSECTIONS -1]][ants2[k].path2[0]])*2);
}
ants2[k].curNode2 = ants2[k].nextNode2;
moving++;
}
}
return moving;
}
int simulateAnts()
{
int k;
int moving = 0;
for(k=0; k<MAX_ANTS; k++)
{
//checking if there are any more cities to visit
if( ants[k].pathIndex < NUMBER_OF_INTERSECTIONS )
{
ants[k].nextNode = selectnextNode(k);
ants[k].tabu[ants[k].nextNode] = 1;
ants[k].path[ants[k].pathIndex++] = ants[k].nextNode;
ants[k].tourLength += dist[ants[k].curNode][ants[k].nextNode]; //handle last case->last city to first
if(ants[k].pathIndex == NUMBER_OF_INTERSECTIONS)
{
ants[k].tourLength += dist[ants[k].path[NUMBER_OF_INTERSECTIONS -1]][ants[k].path[0]];
}
ants[k].curNode = ants[k].nextNode;
moving++;
}
}
return moving;
}
//Updating trails
void updateTime()
{
int from,to,i,ant;
//Pheromone Evaporation
for(from=0; from<NUMBER_OF_INTERSECTIONS;from++)
{
phero2[from] *=( 1.0 - RHO);
if(phero2[from]<0.0)
{
phero2[from] = INIT_PHER;
}
}
//Add new pheromone to the trails
for(ant=0;ant<MAX_ANTS;ant++)
{
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
from = ants2[ant].path2[i];
phero2[from] += (QVAL/ ants2[ant].tourTime);
}
}
for (from=0; from < NUMBER_OF_INTERSECTIONS;from++)
{
phero2[from] *= RHO;
}
}
void updateTrails()
{
int from,to,i,ant;
//Pheromone Evaporation
for(from=0; from<NUMBER_OF_INTERSECTIONS;from++)
{
for(to=0;to<NUMBER_OF_INTERSECTIONS;to++)
{
if(from!=to)
{
phero[from][to] *=( 1.0 - RHO);
if(phero[from][to]<0.0)
{
phero[from][to] = INIT_PHER;
}
}
}
}
//Add new pheromone to the trails
for(ant=0;ant<MAX_ANTS;ant++)
{
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
if( i < NUMBER_OF_INTERSECTIONS-1 )
{
from = ants[ant].path[i];
to = ants[ant].path[i+1];
}
else
{
from = ants[ant].path[i];
to = ants[ant].path[0];
}
phero[from][to] += (QVAL/ ants[ant].tourLength);
phero[to][from] = phero[from][to];
}
}
for (from=0; from < NUMBER_OF_INTERSECTIONS;from++)
{
for( to=0; to<NUMBER_OF_INTERSECTIONS; to++)
{
phero[from][to] *= RHO;
}
}
}
void emitDataTime(int bestTIndex)
{
std::ofstream f1;
f1.open("DataTime.txt");
antTBest = ants2[bestTIndex];
f1<<antTBest.curNode2<<" "<<antTBest.tourTime<<"\n";
int i;
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
f1<<antTBest.path2[i]<<" ";
}
f1.close();
}
void emitDataFile(int bestIndex)
{
std::ofstream f1;
f1.open("Data.txt");
antBest = ants[bestIndex];
f1<<antBest.curNode<<" "<<antBest.tourLength<<"\n";
int i;
for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
{
f1<<antBest.path[i]<<" ";
}
f1.close();
f1.open("city_data.txt");
for(int from = 0; from < NUMBER_OF_INTERSECTIONS; from++)
{
for( int to =0; to < NUMBER_OF_INTERSECTIONS; to++)
{
f1<<dist[from][to]<<" ";
//dist[to][from] = dist[from][to];
//}
}f1<<"\n";
}
// for(i=0;i<NUMBER_OF_INTERSECTIONS;i++)
// {
// f1<<cities[i].x<<" "<<cities[i].y<<"\n";
// }
f1.close();
}
int main()
{
int curTime = 0;
cout<<"MaxTime="<<MAX_TIME;
srand(time(NULL));
init();
while( curTime++ < MAX_TIME)
{
if( simulateAnts() == 0)
{
updateTrails();
if(curTime != MAX_TIME)
restartAnts();
cout<<"\nTime is "<<curTime<<"("<<best<<")";
}
}
cout<<"\nBest tour = "<<best<<endl;
emitDataFile(bestIndex);
init_Ants();
while(curTime++ < MAX_TIME)
{
if(simulateTime()==0)
{
updateTime();
if(curTime!=MAX_TIME)
restartTime_Ants();
cout<<"\nFINAL WAITING MINIMUM TIME "<<curTime<<"("<<bestTime<<")";
}
}
cout<<"\nBEST TIME="<<bestTime<<endl;
emitDataTime(bestTIndex);
return 0;
}