写了个求10个数的最大和,取值范围啥0-99,因为状态空间比较大,所以变异概率选的0.3,大一点,交叉概率0.8,种群大小100,遗传代数1000
效果的话,不是很理想,距离990的极限还有不小的差距
可以看到,只有8次在950以上,并且,在遗传代数增加到10000以后,效果并没有明显增加,挺失败的
#include<bits/stdc++.h> using namespace std; const double by=0.3;//变异概率 const double jh=0.8;//自由交换概率 const int max_size=100; const int max_d=100000; int sum; struct node{ int v[10]; int fitness; void col(){ fitness=0; for(int i=0;i<10;i++) fitness+=v[i]; } }now[105],Max,Min; //分别是种群,临时的,最大个体,最小个体 //生成初始种群 void init(){ for(int i=0;i<max_size;i++){ for(int j=0;j<10;j++) now[i].v[j]=rand()%100; } } void js(){ sum=0; Max.fitness=-1;Min.fitness=0x3f3f3f3f; for(int i=0;i<max_size;i++){ now[i].col(); if(now[i].fitness>Max.fitness)Max=now[i]; if(now[i].fitness<Min.fitness)Min=now[i]; sum+=now[i].fitness; } } //打印某个个体 void print_o(node a){ for(int i=0;i<10;i++) printf("%d ",a.v[i]); printf(" -> %d ",a.fitness); } //打印当前所有种群 void print(){ for(int i=0;i<max_size;i++) print_o(now[i]); } int rand_id(){ int d=rand()%(sum+1); int cnt=0; for(int i=0;i<max_size;i++){ cnt+=now[i].fitness; if(cnt>=d)return i; } return rand()%max_size; } double randd(){ double ans=rand()%1000; ans/=1000; return ans; } void tran(){ js(); //找到最优个体 int tmp=0,i,j,pos; for(int i=1;i<max_size;i++) if(now[i].fitness>now[tmp].fitness) tmp=i; for(int k=0;k<max_size;k+=2){ //选择交叉个体 i=rand_id(); j=rand_id(); //交叉位置 pos=rand()%10; //交换 if(randd()<jh){ swap(now[k].v[pos],now[j].v[pos]); swap(now[k].v[pos],now[i].v[pos]); } //变异 if(randd()<by){ pos=rand()%10; now[k].v[pos]=rand()%100; } } js(); int id=0; for(int i=1;i<max_size;i++) if(now[id].fitness>now[i].fitness) id=i; now[id]=Max; } void ga(){ int cnt=0; while(cnt<max_d){ tran();cnt++; // print(); // puts(" "); } int ans=now[0].fitness; for(int i=0;i<max_size;i++)ans=max(ans,now[i].fitness); printf("%d ",ans); } int main(){ srand((unsigned)time(NULL)); for(int i=1;i<=15;i++){ printf("Case %d: ",i); init(); ga(); } return 0; }