完整下载
/*基本遗传算法求解TSP * *选择操作使用转赌轮算法 *变异算子采用逆转变异算法 *交叉时先使用顺序编码,单点交叉,然后解码 *运行效果并不理想 * *本程序写作过程中主要参考了 合肥工业大学 蒋荣2009年的硕士学位论文《遗传算法在TSP上的应用》 * * @author :[email protected] */ #include <iostream> #include <fstream> #include <vector> #include <algorithm> #include <math.h> #include <stdlib.h> #include <time.h> #include <assert.h> using namespace std; //roulette selection int roulette_select(double* arr,int num) { //srand((unsigned)time(NULL)); int i; double* stage=new double[num]; stage[0]=arr[0]; for (i=1;i<num;i++){ stage[i]=stage[i-1]+arr[i]; } double d=(double)rand()/RAND_MAX*stage[num-1]; i=0; while(d>stage[i]){ i++; } delete[] stage; assert(i<num||i>=0); return i; } //generate a integer sequence from 0 to n-1 at random void rand_int_order(vector<int>& randorder,const int n) { assert(n>1); randorder.clear(); randorder.resize(n); vector<int> recoder; for (int i=0;i<n;i++){ recoder.push_back(i); } for(int i=0;i<n;i++){ int sel=rand()%recoder.size(); randorder[i]=recoder[sel]; recoder.erase(recoder.begin()+sel); } //assertion assert(randorder.size()==n); } //sequence based sequence_encode void sequence_encode(vector<int>& chromosome) { vector<int>standard; for (int i=0;i<chromosome.size();i++){ standard.push_back(i); } vector<int>::iterator ite; for (int i=0;i<chromosome.size();i++){ ite=find(standard.begin(),standard.end(),chromosome[i]); assert(ite!=standard.end()); chromosome[i]=ite-standard.begin(); standard.erase(ite); } } //sequence_decode void sequence_decode(vector<int>& chromosome) { vector<int>standard; for (int i=0;i<chromosome.size();i++){ standard.push_back(i); } for (int i=0;i<chromosome.size();i++){ int t=chromosome[i]; chromosome[i]=standard[t]; standard.erase(standard.begin()+t); } } /* //function test int main() { //srand((unsigned)time(NULL)); //double a[10]; //int result[10]; //for (int i=0;i<10;i++){ // a[i]=10; // result[i]=0; //} // //for (int i=0;i<100;i++){ // int d=roulette_select((double*)a,10); // cout<<d<<" "; // result[d]++; // //cout<<rand()%10<<endl; //} //cout<<endl; //for(int i=0;i<10;i++){ // cout<<result[i]<<endl; //} /*vector<int> v; rand_int_order(v,5); for (int i=0;i<5;i++){ cout<<v[i]<<" "; } cout<<endl; sequence_encode(v); for (int i=0;i<5;i++){ cout<<v[i]<<" "; } cout<<endl; sequence_decode(v); for (int i=0;i<5;i++){ cout<<v[i]<<" "; } cout<<endl; } */ int main() { srand((unsigned)time(NULL)); //read data from file fstream filein("data/berlin52.tsp.processed",ios::in); fstream fileout("data/result.txt",ios::out); if (filein==NULL){ cout<<"cannot open data file"<<endl; return 1; } if (fileout==NULL){ cout<<"cannot open a file to write data"<<endl; return 1; } //number of cities unsigned int cityNum; //standard path int* standardPath; //distance between cities double** distance; //read data from filein filein>>cityNum; cout<<cityNum<<endl; standardPath=new int[cityNum]; for (int i=0;i<cityNum;i++){ filein>>standardPath[i]; } distance=new double* [cityNum]; for (int i=0;i<cityNum;i++){ distance[i]=new double[cityNum]; for (int j=0;j<cityNum;j++){ filein>>distance[i][j]; } } ////////////////////////////////////////////////////////////////////////// //parameters //number of generations unsigned int generation = 1000; //size of the population,i.e. number of chromosomes unsigned int populationSize = 70; //number of genes in a individual,i.e. length of chromosome unsigned int chromLen = cityNum; //mutate rate ,generally it is between 0.05 and 0.3 double mutationRate = 0.7; //crossover rate ,generally it is about 0.7 double crossoverRate = 0.9; // define the population vector<vector<int> > population; //initialize population at random for (int i=0;i<populationSize;i++){ vector<int> chromo; rand_int_order(chromo,chromLen); population.push_back(chromo); } //length of best path found double best_path_len=1<<(8*sizeof(int)-2); //index of best individual int bestIndex=0; //evolution for (int g=0;g<generation;g++){ //fitness value,i.e. length of the path double* fitness=new double[populationSize]; //calculate fitness of every individual for(int i=0;i<populationSize;i++){ fitness[i]=0; } //update population vector<vector<int> > parentGeneration=population; population.clear(); for (int s=0;s<populationSize;s++){ for (int l=0;l<chromLen-1;l++){ fitness[s]+=distance[parentGeneration[s][l]][parentGeneration[s][l+1]]; } fitness[s]+=distance[parentGeneration[s][chromLen-1]][parentGeneration[s][0]]; if (fitness[s]<best_path_len){ best_path_len=fitness[s]; bestIndex=s; } } //epoch while(population.size()<populationSize){ //roulette selection //children vector<int> baby1,baby2; int rs=roulette_select(fitness,populationSize); baby1=parentGeneration[rs]; rs=roulette_select(fitness,populationSize); baby2=parentGeneration[rs]; //crossover if(baby1!=baby2){ if (rand()/RAND_MAX<crossoverRate){ //sequence based sequence_encode sequence_encode(baby1); sequence_encode(baby2); //single point crossover int index=rand()%chromLen; int tmp=baby1[index]; baby1[index]=baby2[index]; baby2[index]=tmp; //sequence_decode sequence_decode(baby1); sequence_decode(baby2); } } //reverse mutate int point1=rand()%chromLen; int point2=point1; while(point1==point2){ point2=rand()%chromLen; } if (point1>point2){ int tmp=point1; point1=point2; point2=tmp; } //reverse reverse(baby1.begin()+point1,baby1.begin()+point2); reverse(baby2.begin()+point1,baby2.begin()+point2); //update population population.push_back(baby1); population.push_back(baby2); } //if populationSize is odd,after the epoch,size of population will be populationSize+1 if (population.size()>populationSize){ population.pop_back(); } fileout<<"generation :"<<g<<endl <<"best distance found for the moment: " <<best_path_len<<endl <<"best distance found in this epoch: " <<fitness[bestIndex]<<endl <<"best path found for the moment:"<<endl; for (int i=0;i<cityNum;i++){ fileout<<population[bestIndex][i]<<" "; } fileout<<endl; //to console cout<<"generation :"<<g<<endl <<"best distance found for the moment: " <<best_path_len<<endl <<"best distance found in this epoch: " <<fitness[bestIndex]<<endl <<"best path found for the moment:"<<endl; for (int i=0;i<cityNum;i++){ cout<<population[bestIndex][i]<<" "; } cout<<endl; delete[] fitness; } //show standard path and distance fileout<<"standard path:"<<endl; double standardbestlen=0; for (int i=0;i<cityNum;i++){ fileout<<standardPath[i]<<" "; } for (int i=0;i<cityNum-1;i++){ standardbestlen+=distance[standardPath[i]][standardPath[i+1]]; } standardbestlen+=distance[standardPath[cityNum-1]][standardPath[0]]; fileout<<endl<<"length of standard path: "<<endl<<" "<<standardbestlen<<endl; //append the best result found in this test to a file named "best.txt" fstream bestout("data/best.txt",ios::app); if (bestout==NULL){ cout<<"cannot open a file to write data"<<endl; return 1; } bestout<<best_path_len<<endl; for (int i=0;i<cityNum;i++){ bestout<<population[bestIndex][i]<<" "; } bestout<<endl; //free memory///////////////////////////////////////////////////////////// filein.close(); fileout.close(); bestout.close(); delete[] standardPath; for (int i=0;i<cityNum;i++){ delete[] distance[i]; } delete[] distance; return 0; }