Genetic algorithm is an algorithm which imitate the law of natural selection.
The main step:
Step 1: Initialization (Set Max evolutionary algebra and Create new individuals randomly)
Step 2: Individual evaluation (Evaluate the fitness of each individuals using a fitness function)
Step 3: Selection (Pick the proper individuals according to fitness)
Step 4: Crossover (The most important part of GA)
Step 5: Mutation (Accelerating convergence of the optimal solution)
Worth mentioning, in most function, GA has to be stochastic realization. For example, in selection part, the larger an individual’s fitness is, the greater the chance of an individual to survive instead of individuals which has a larger survival rate survive certainly.
To realize the randomness, there lots of methods we can choose. A good way is roulette wheel selection. We can first figure out the survival rate of an individual like this:
And then, we produce a random number and find out which part of it. Implement code:
Genome GenAlg:: GetChromoRoulette() { //产生一个0到人口总适应性评分总和之间的随机数. //中m_dTotalFitness记录了整个种群的适应性分数总和) double Slice = (random()) * totalFitness; //这个基因将承载转盘所选出来的那个个体. Genome TheChosenOne; //累计适应性分数的和. double FitnessSoFar = 0; //遍历总人口里面的每一条染色体。 for (int i=0; i<popSize; ++i) { //累计适应性分数. FitnessSoFar += vecPop[i].fitness; //如果累计分数大于随机数,就选择此时的基因. if (FitnessSoFar >= Slice) { TheChosenOne = vecPop[i]; break; } } //返回转盘选出来的个体基因 return TheChosenOne; }
This weekend, I just learn a little of the GA, understanding the process of this algorithm. And take TSP problem as an example, simulating the process of GA roughly. Due to the lack of the main optimization algorithm, my GA code seem to be useless. My first GA code only reflect the idea of random, but not the idea of optimization and convergence. But my understanding of GA is deepen through this problem.
Here is my code:
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<fstream> #include<cmath> #include<ctime> using namespace std; typedef long long LL; /************************City Set************************/ string filename = "berlin52.txt"; #define runs 10 #define groupNum 10 #define cnt 52 //城市数量 const double pc = 0.65;//交配概率 const double mp = 0.35;//变异概率 /*********************************************************/ double edge[cnt][cnt]; double best_tsp = 1e7; int trace[cnt]; struct City{ double x, y; }city[cnt]; struct Group{ int cities[cnt]; double tsp; double fit; }group[groupNum], groupt[groupNum]; void init(){ int num = 0; ifstream fin(filename); while(fin>>num){ fin>>city[num-1].x>>city[num-1].y; //cout<<num-1<<" "<<city[num-1].x<<" "<<city[num-1].y<<endl; } //构造邻接矩阵 for(int i =0 ; i< cnt ; ++i){ edge[i][i] = 0; for(int j =i+1 ; j< cnt ; ++j){ edge[j][i] = edge[i][j] = sqrt((city[i].x-city[j].x)*(city[i].x-city[j].x) + (city[i].y-city[j].y)*(city[i].y-city[j].y)); } } /*cout<<"邻接矩阵为"<<endl; for(int i=0 ; i<cnt ; ++i){ for(int j =0 ; j<cnt ; ++j){ cout<<edge[i][j]<<" "; } cout<<endl; }*/ } void print(){ for(int i =0 ; i<groupNum ;++i){ cout<<"Group"<<i<<":"; for(int j= 0 ; j<cnt ; ++j) cout<<" "<<group[i].cities[j]; cout<<endl; } } void pre_value(){ srand(time(0)); /***********************给每个种群初始化**************************/ for(int i = 0 ; i<groupNum ; ++i){ int j = 0; for(int k = 0 ; k< cnt ; ++k){ group[i].cities[k] = -1; } while( j<cnt ){ int x = rand()%cnt ; if(group[i].cities[x] == -1){ group[i].cities[x] = j; ++j; } } } /********************打印种群*****************************/ cout<<"Initial Population:"<<endl; for(int i=0 ; i<groupNum ; ++i){ cout<<"Group"<<i<<":"; for(int j=0 ;j<cnt ; ++j){ cout<<group[i].cities[j]<<" "; } cout<<endl; } //system("pause"); } void fitness(){ /*************************计算种群总路径*****************************/ double sum_dis = 0; for(int i=0 ; i< groupNum ; ++i){ group[i].tsp = 0; group[i].fit = 0; } for(int i =0 ; i<groupNum ; ++i){ for(int j=0 ; j<cnt ; ++j){ if(j == cnt -1){ group[i].tsp += edge[group[i].cities[cnt-1]][group[i].cities[0]]; } else group[i].tsp += edge[group[i].cities[j]][group[i].cities[j+1]]; } sum_dis += group[i].tsp; } /*************************计算每个种群的存活几率***********************/ double sum_fit = 0; for(int i=0 ; i<groupNum ; ++i){ group[i].fit = 1 - group[i].tsp / sum_dis; sum_fit += group[i].fit; } for(int i=0 ; i<groupNum ;++i){ group[i].fit = group[i].fit/sum_fit; } int best = 0; for(int i= 0; i<groupNum ; ++i){ if( group[i].tsp < group[best].tsp ){ best = i; } } /************************************************************************/ /*cout<<"当前代最好的种群是种群"<<best<<‘:‘<<endl; for(int i=0; i<cnt ; ++i){ cout<<group[best].cities[i]<<" "; }*/ if( group[best].tsp < best_tsp){ best_tsp = group[best].tsp; for(int i=0 ; i< cnt ; ++i){ trace[i] = group[best].cities[i]; } } //cout<<"TSP = "<<group[best].tsp<<endl; //system("pause"); } void select(){ int chosen[groupNum]; /*********************轮盘法随机选择种群***************************/ for(int i =0 ; i<groupNum ; ++i){ double x = rand()%100; x /= 100; double fitSofar = 0; for(int j=0 ; j< groupNum ; ++j){ fitSofar += group[j].fit; if(fitSofar > x ){ chosen[i] = j; break; } } } /*************************复制产生新一代种群*************************/ for(int i=0 ; i<groupNum ; ++i){ groupt[i] = group[i]; } for(int i=0 ; i<groupNum ;++i){ group[i] = groupt[ chosen[i] ]; } /*********************************************************************/ //cout<<"The new generation:"<<endl; //print(); //system("pause"); } void cross(){ int t=0; int crossp[groupNum]; memset(crossp, 0, sizeof(crossp)); /*********************确定交配种群个数***********************/ for(int i=0 ; i< groupNum ; ++i){ double x = rand()%100; x /= 100; if( x<pc ){ crossp[t++] = i; } } //t = t/2*2; //保证t为偶数 /************************开始交配**************************/ for(int j=0 ; j+1<t ; j+=2){ int temp1 = j, temp2 = j+1; int map1[cnt], map2[cnt]; int point1, point2; point1 = rand()%cnt; point2 = rand()%cnt; if(point2<point1) swap(point1, point2); //两头直接交换 for(int i=0 ; i<point1; ++i){ swap(group[temp1].cities[i], group[temp2].cities[i]); } for(int i=point2+1 ; i<cnt; ++i){ swap(group[temp1].cities[i], group[temp2].cities[i]); } //中间产生映射, 处理冲突 memset(map1, 0, sizeof(map1)); memset(map2, 0, sizeof(map2)); for(int i=point1 ; i<=point2; ++i){ map1[group[temp1].cities[i]] = group[temp2].cities[i]; map2[group[temp2].cities[i]] = group[temp1].cities[i]; } //处理temp1的冲突 for(int k = 0 ; k < point1; ++k){ for(int kk = point1; kk<=point2; ++kk){ if(group[temp1].cities[k] == group[temp1].cities[kk]){ group[temp1].cities[k] = map1[group[temp1].cities[kk]]; kk=point1-1; //cout<<"kk = "<<kk<<" "; system("pause"); } } } for(int k = point2+1 ; k < cnt; ++k){ for(int kk = point1; kk<=point2; ++kk){ if(group[temp1].cities[k] == group[temp1].cities[kk]){ group[temp1].cities[k] = map1[group[temp1].cities[kk]]; kk=point1-1; } } } //处理temp2的冲突 for(int k = 0 ; k < point1; ++k){ for(int kk = point1; kk<=point2; ++kk){ if(group[temp2].cities[k] == group[temp2].cities[kk]){ group[temp2].cities[k] = map2[group[temp2].cities[kk]]; kk=point1-1; } } } for(int k = point2+1 ; k < cnt; ++k){ for(int kk = point1; kk<=point2; ++kk){ if(group[temp2].cities[k] == group[temp2].cities[kk]){ group[temp2].cities[k] = map2[group[temp2].cities[kk]]; kk=point1-1; } } } } //cout<<"After crossover:"<<endl; //print(); } void mutate(){ int mutatep[groupNum]; int t=0;//变异个数 srand(time(0)); memset(mutatep, 0, sizeof(mutatep)); for(int i=0 ; i<groupNum ; ++i){ double x = rand()%100; x /= 100; if( x< mp){ mutatep[t++] = i; } } //开始变异,即随机交换一对城市 for(int i =0 ; i<t; ++i){ int temp = mutatep[i]; int point1 = rand()%cnt; int point2 = rand()%cnt; swap(group[temp].cities[point1], group[temp].cities[point2]); } //cout<<"After mutation:"<<endl; //print(); } int main(){ init(); pre_value(); int counter = 0; while(counter++ < runs){ fitness(); select(); cross(); mutate(); } print(); cout<<"Best tsp = "<<best_tsp<<endl; cout<<"Trace:"<<endl; for(int i=0 ; i<cnt ; ++i){ cout<<trace[i]<<" "; } cout<<endl; system("pause"); return 0; }