#include<iostream>#include<iomanip>#include<algorithm>#include<cmath>#include<ctime>usingnamespace std;//程序分配内存的数组大小 constint maxn =10000;//最大种群规模constint maxlen =1000;//最大的染色体长度//遗传算法的关键参数 constint n =200;//种群的个体数constint len =30;//每个个体染色体的长度,x和y各占据一半constint crossNum =4;//交叉操作时多点交叉的交叉点个数constint maxGeneration =2000;//最大进化代数constdouble probCross =0.85;//交叉概率constdouble proMutation =0.15;//编译概率 //个体的染色体类classChromosome{public:bool g[maxlen];//二进制的编码数组Chromosome(){//默认构造函数 for(int i =0; i < len ; i ++){
g[i]=rand()%2;}}Chromosome(const Chromosome& c){//拷贝构造函数,进行深复制 for(int i =0; i < len ; i ++){
g[i]= c.g[i];}}voidoperator=(const Chromosome& c){//重载=号,进行深复制 for(int i =0; i < len ; i ++){
g[i]= c.g[i];}}};double bestValue;//记录当前所得的最优值
Chromosome bestC;//记录当前最优值对应的个体染色体
Chromosome group[maxn], temGroup[maxn];//个体的种群,辅助数组//目标函数doublef(double x,double y){return x *sin(10* M_PI * x)+2.0;}//解码函数,从染色体得到x和y的值voiddecode(const Chromosome& c,double& x,double& y){double num =pow(2.0, len /2.0);int tem =0;for(int i = len-1,q =1; i >= len/2; i --){
tem += c.g[i]* q;
q *=2;}
y =1+(2-1)/ num * tem;
tem =0;for(int i = len/2-1, q =1; i >=0; i --){
tem += c.g[i]* q;
q *=2;}
x =1+(2-1)/ num * tem;}//适应度函数,为了避免负值,把目标函数添加一个正数 doublefitness(const Chromosome& c){double x, y;decode(c, x, y);returnf(x, y)+5;}//辅助函数,生成0-1之间的随机小数doubleinlinerandom_0_1(){returnrand()%10000/10000.0;}//选择操作voidselect(Chromosome group[maxn]){//计算每个个体的选择概率double fitnessValue[maxn];for(int i =0; i < n ; i ++){
fitnessValue[i]=fitness(group[i]);}double sum =0;for(int i =0; i < n ; i ++){
sum += fitnessValue[i];}double prob[maxn];for(int i =0; i < n ; i ++){
prob[i]+= fitnessValue[i];}//随机选择n个个体组成新种群int selectId[maxn];for(int i =0; i < n ; i ++){
prob[i]+= prob[i-1];}for(int i =0; i < n ; i ++){//使用轮盘算法选择个体double randNum =random_0_1();int j;for(j =0; j < n-1; j ++){if(randNum < prob[j]){
selectId[i]= j;break;}}if(j == n-1){
selectId[i]= j;}}//把种群更新为新选择的个体集合for(int i =0; i < n ; i ++){
temGroup[i]= group[i];}for(int i =0; i < n ; i ++){
group[i]= temGroup[selectId[i]];}}//交叉操作,使用多点交叉voidcrossOver(Chromosome& c1, Chromosome& c2){//生成交叉位置,并排序int crossPoint[maxn];for(int i =0; i < crossNum; i ++){
crossPoint[i]=rand()% len;}sort(crossPoint, crossPoint + crossNum);//进行交叉bool flag =0;for(int i =0, j =0; i < len ; i ++){if(!flag){swap(c1.g[i], c2.g[i]);}if(i == crossPoint[j]){//如果若干个交叉点重合,则效果叠加//偶数个交叉点效果相当于没有交叉点while(j < crossNum && i == crossPoint[j]){
j ++;
flag =!flag;}}}}//变异操作voidmutate(Chromosome& c){//随机选择一位进行翻转int i =rand()% len;
c.g[i]=!c.g[i];}//获取种群最优个体intgetOptimal(Chromosome group[maxn],double& x,double& y,double& value){//计算适应值,遍历得到最优值并进行解码double fitnessValue[maxn];int id =0;for(int i =0; i < n ; i ++){if(fitnessValue[i]> fitnessValue[id]){
id = i;}}decode(group[id], x, y);
value =f(x, y);return id;}//遗传算法总代码voidGA(double& x,double& y,double& value){//初始化种群for(int i =0; i < n ; i ++){
group[i]=Chromosome();}
bestC = group[getOptimal(group, x, y, bestValue)];//控制进化代数for(int g =0; g < maxGeneration ; g ++){//选择操作select(group);//根据交叉概率进行交叉for(int i =0,pre =-1; i < n ; i ++){if(random_0_1()< probCross){if(pre ==-1){
pre = i;}else{crossOver(group[pre], group[i]);
pre =-1;}}}//根据概率进行变异for(int i =0; i < n ; i ++){if(random_0_1()< proMutation){mutate(group[i]);}}//防止种群退化double temValue;int bestId =getOptimal(group, x, y, temValue);if(temValue < bestValue){//如果种群的最优值变差,把较优的个体替换进新种群
group[bestId]= bestC;}else{//如果种群的最优值变好,则更新最优值记录
bestC = group[bestId];
bestValue = temValue;}}//获取最优值getOptimal(group, x, y, value);}intmain(){srand(time(0));double x, y, maxValue;GA(x, y, maxValue);
cout<<"函数在点("<<fixed<<setprecision(15)<<x<<", "<<y<<")取得最大值:"<<maxValue<<endl;return0;}