#include<iostream> #include<vector> #include<algorithm>//random_shuffle();sort();lower_bound(); #include<cmath> #include<ctime> using namespace std; typedef vector<int> VI; typedef vector<VI> VVI; #define PB push_back //在vector尾部加入一个数据 #define MP make_pair //1.将2个数据组合成一个数据//2.当一个函数需要返回2个数据的时候,可以选择pair //pair的实现是一个结构体,主要的两个成员变量是first、second //因为是使用struct不是class,所以可以直接使用pair的成员变量 int next_int(); double next_double(); void pmx(VI& a,VI& b,int pointcnt);//PMX交叉 double fitness(const VI& v,int pointcnt);//计算适应度 void change0(vector<int>& K,int N);//变异策略:两点互换 void mutate(VI& route,int mutate_type,int pointcnt); bool pair_dec(const pair<double,VI*>& a,const pair<double,VI*>& b); vector<double> x,y;//全局函数,记录城市坐标 class other_population { public: int popsize,pointcnt;//种群规模,染色体长度 double pc,pm;//交叉概率,变异概率 vector<pair<double,VI*> >pop;//种群 pair<double,VI*> bestofpop;//最好个体 int cross_type;//交叉类型 int mutate_type;//变异类型 int make_p;//个体概率分配策略类型 int select_type;//个体选择类型 int toursize;//竞赛规模 double bestp;//最好个体选择概率 other_population(int a,int b,int c,int f,int g,double d,double e,int h,double j,int m) { popsize=a,pointcnt=b,cross_type=c,mutate_type=f,make_p=g,pc=d,pm=e,toursize=h,bestp=j,select_type=m; for(int i=0;i<popsize;i++)//初始化种群 { VI* v=new VI(pointcnt); for(int j=0;j<pointcnt;j++) (*v)[j]=j; random_shuffle(v->begin(),v->end()); pop.PB(MP(fitness(*v,pointcnt),v)); } sort(pop.begin(),pop.end(),pair_dec); bestofpop.first=pop[0].first;//初始时最好个体的适应度 bestofpop.second=new VI(*pop[0].second);//初始时最好个体的染色体 } ~other_population() { for(int i=0;i<pop.size();i++) delete pop[i].second; delete bestofpop.second; } void next()//产生下一代种群 { vector<double> ps(popsize); if(make_p==0) //按适应度比例分配个体的选择概率 { double sum=0; for(int i=0;i<popsize;i++) sum+=pop[i].first; for(i=0;i<popsize;i++) ps[i]=pop[i].first/sum; } if(select_type==0)//轮盘赌选择个体 { vector<pair<double,VI*> > select_res; vector<double> addsum(popsize); for(int i=0;i<popsize-1;i++)//计算个体的累计概率 { if(i==0) addsum[i]=ps[0]; else addsum[i]=addsum[i-1]+ps[i]; } addsum[popsize-1]=1.5; for(i=0;i<popsize;i++) { double rd=next_double(); int r=lower_bound(addsum.begin(),addsum.end(),rd)-addsum.begin(); //lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value, //而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。 VI* v=new VI(*pop[r].second); select_res.PB(MP(fitness(*v,pointcnt),v)); } for(i=0;i<popsize;i++) delete pop[i].second; pop=select_res; //////////////////////////////// /*cout<<"选择后共"<<pop.size()<<"个子染色体\n"; for(i=0;i<pop.size();i++) { VI temp=*pop[i].second; for(int j=0;j<10;j++) cout<<temp[j]<<" "; cout<<"\n"; }*/ ////////////////////////////// } int Count_cross=0; for(int cc=0;cc<popsize/2;cc++)//随机选择两个个体,然后进行交叉 { int a=next_int()%popsize; int b=(a+1+(next_int()%(popsize-1)))%popsize; if(next_double()<pc)//随机数小于交叉概率,进行交叉 { if(cross_type==0)//pmx交叉 pmx(*pop[a].second,*pop[b].second,pointcnt); /////////////////////////////// /*Count_cross+=2; cout<<"交叉后第"<< a <<"条子染色体: "; VI temp=*pop[a].second; for(int j=0;j<10;j++) cout<<temp[j]<<" "; cout<<"\n"; ////////////////////////////// cout<<"交叉后第"<< b <<"条子染色体: "; temp=*pop[b].second; for(j=0;j<10;j++) cout<<temp[j]<<" "; cout<<"\n";*/ //////////////////////////////// pop[a].first=fitness(*pop[a].second,pointcnt);//计算交叉后个体a的适应度 if(bestofpop.first<pop[a].first)//更新最好个体 { bestofpop.first=pop[a].first; delete bestofpop.second; bestofpop.second=new VI(*pop[a].second); } pop[b].first=fitness(*pop[b].second,pointcnt);//计算交叉后个体b的适应度 if(bestofpop.first<pop[b].first)//更新最好个体 { bestofpop.first=pop[b].first; delete bestofpop.second; bestofpop.second=new VI(*pop[b].second); } } } ////////////////////////////////////// //cout<<"交叉"<<Count_cross<<"条染色体\n"; //cout<<"交叉后共"<<pop.size()<<"个子染色体\n"; ///////////////////////////////////// int Count_mutate=0;//变异染色体条数 for(int i=pop.size()-1;i>=0;i--)//进行变异 if(next_double()<pm)//随机数小于变异概率,进行变异 { mutate(*pop[i].second,mutate_type,pointcnt);//变异 pop[i].first=fitness(*pop[i].second,pointcnt);//计算变异后个体的适应度 /////////////////////////////// /*Count_mutate++; cout<<"变异后第"<< i <<"个子染色体: "; VI temp=*pop[i].second; for(int j=0;j<10;j++) cout<<temp[j]<<" "; cout<<"\n";*/ /////////////////////////////// } /////////////////////////////// //cout<<"变异"<<Count_mutate<<"条染色体\n"; //cout<<"变异后共"<<pop.size()<<"个子染色体\n\n\n"; /////////////////////////////// sort(pop.begin(),pop.end(),pair_dec);//从大到小排序 if(bestofpop.first<pop[0].first)//更新最好个体 { delete bestofpop.second; bestofpop.first=pop[0].first; bestofpop.second=new VI(*pop[0].second); } } }; int next_int() { return rand()*(RAND_MAX+1)+rand(); } double next_double() { return (double(rand()*(RAND_MAX+1)+rand()))/((RAND_MAX+1)*RAND_MAX+RAND_MAX); } double fitness(const VI& v,int pointcnt)//计算适应度 { double r=0; for(int i=0;i<pointcnt;i++) { double dx=x[v[i]]-x[v[(i+1)%pointcnt]]; double dy=y[v[i]]-y[v[(i+1)%pointcnt]]; r+=sqrt(dx*dx+dy*dy);//个体的适应度为相邻两城市之间的距离平方的平方根和 } return 1.0/r; } int flag=0; void pmx(VI& a,VI& b,int pointcnt)//PMX交叉 { int i; int sa=next_int()%pointcnt,sb=next_int()%pointcnt;//随机选择两交叉位 if (sa>sb) { swap(sa,sb); }//保证交叉位sa<=sb /*if(flag==0) { cout<<"互换前(互换位:"<<sa<<" "<<sb<<")\n"; for(i=0;i<10;i++) cout<<a[i]<<" "; cout<<"\n"; for(i=0;i<10;i++) cout<<b[i]<<" "; cout<<"\n"; }*/ VI m1(pointcnt,-1); VI m2(pointcnt,-1); for (i = sa; i <= sb; ++i) //互换交叉位之间的基因 { //相当于a中将城市a[i]删了,用城市b[i]取代,从而出现城市b[i](替换后的a'[i])重复 // b中将城市b[i]删了,用城市a[i]取代,从而出现城市a[i](替换后的b'[i])重复 swap(a[i], b[i]); m1[a[i]] = b[i];//记录a'[i]所取代的城市a[i],用于替换非交叉部分的a'[i]的元素重复 m2[b[i]] = a[i]; } /////////////////////// /*if(flag==0) { cout<<"互换后(未调整)\n"; for(i=0;i<10;i++) cout<<a[i]<<" "; cout<<"\n"; for(i=0;i<10;i++) cout<<b[i]<<" "; cout<<"\n"; for(i=0;i<10;i++) cout<<m1[i]<<" "; cout<<"\n"; for(i=0;i<10;i++) cout<<m2[i]<<" "; cout<<"\n"; }*/ /////////////////////// for (i = 0; i < pointcnt; ++i)//调整交叉位之前、之后的基因,防止和交叉位之间的基因重复 if (i < sa || i > sb) { if (m2[b[i]] != -1) { while (m2[b[i]] != -1) b[i] = m2[b[i]]; } if (m1[a[i]] != -1) { while (m1[a[i]] != -1) a[i] = m1[a[i]]; } } ///////////////////// /*if(flag==0) { cout<<"互换调整后\n"; for(i=0;i<10;i++) cout<<a[i]<<" "; cout<<"\n"; for(i=0;i<10;i++) cout<<b[i]<<" "; cout<<"\n"; } flag=1;*/ //////////////////// } void mutate(VI& route,int mutate_type,int pointcnt)//变异 { if(mutate_type==0)//两点互换 change0(route,pointcnt); } void change0(vector<int>& K,int N)//变异策略:两点互换 { int i=next_int()%N; int d=next_int()%(N-1); int j=(i+1+d)%N; swap(K[i],K[j]); } bool pair_dec(const pair<double,VI*>& a,const pair<double,VI*>& b)//比较因子,用于sort()函数 { return a>b; } int main() { srand((unsigned)time(NULL)); int CASNUM,POINTCNT,POPSIZE,GENERATIONS; //scanf("%d",&CASNUM); CASNUM=10;//实验次数 //scanf("%d%d%d",&POINTCNT,&POPSIZE,&GENERATIONS); POINTCNT=10, POPSIZE=100,GENERATIONS=100;//染色体长度(城市数),种群规模,最大迭代步数 cout<<"城市数="<<POINTCNT<<endl; x.resize(POINTCNT); y.resize(POINTCNT); x[0]=87, x[1]=91,x[2]=83,x[3]=71,x[4]=64,x[5]=68,x[6]=83,x[7]=87,x[8]=74,x[9]=71; y[0]=7, y[1]=38,y[2]=46,y[3]=44,y[4]=60,y[5]=58,y[6]=69,y[7]=76,y[8]=78,y[9]=71; cout<<"各城市坐标:"<<endl; for(int i=0;i<POINTCNT;i++) { //scanf("%lf%lf",&x[i],&y[i]);//输入各个城市的坐标 cout<<"["<<x[i]<<", "<<y[i]<<"]"<<endl;//输出各个城市的坐标 } int select_type,make_p_type,k,cross_type,mutate_type; double q,pc,pm; //scanf("%d%d%d",&select_type,&make_p_type,&k); //scanf("%lf%lf%lf",&q,&pc,&pm); //scanf("%d%d",&cross_type,&mutate_type); select_type=0,make_p_type=0,k=5;//个体选择方法类型,个体选择概率分配类型,竞赛规模 q=0.5,pc=0.85,pm=0.15;//最好个体选择概率,交叉概率,变异概率 cross_type=0,mutate_type=0;//交叉类型,变异类型 double best=1e9,worst=0,sum=0; VI res; for(int cas=0;cas<CASNUM;cas++)//进行10代的试验 { other_population gen(POPSIZE,POINTCNT,cross_type,mutate_type,make_p_type,pc,pm,k,q,select_type);//初始化 for(int g=0;g<GENERATIONS;g++)//每次试验进行迭代进化(100代进化) gen.next();//每代进化过程中都会记录最更好的染色体 if(best>1.0/gen.bestofpop.first)//更新历次最好适应度 { best=1.0/gen.bestofpop.first; res=*gen.bestofpop.second;//存放最好个体的染色体 } if(worst<1.0/gen.bestofpop.first)//更新历次最差适应度 worst=1.0/gen.bestofpop.first; sum+=1.0/gen.bestofpop.first;//计算各次最好个体的适应度之和 } sum/=CASNUM;//计算平均适应度 cout<<endl; cout<<"历次最好适应度:"<<best<<"\n"<<"历次最差适应度:"<<worst<<"\n"<<"平均适应度:"<<sum<<"\n"; cout<<"输出最好解:"; for(i=0;i<POINTCNT;i++)//输出解 { cout<<res[i];//输出各城市 if (i<POINTCNT-1) cout<<"-"; } cout<<endl; return 0; }