#pragma warning(disable: 4786)
#include <iostream> 
#include<fstream>
#include<set>
#include <string>
#include <list>
#include <vector>

#include <math.h> 
#include <time.h>
#include <conio.h> 
#include <stdlib.h> 
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <float.h>

 
using namespace std;

#define POP_SIZE 40
#define CROSS_RATE 0.7
#define MUTATE_RATE 0.5
const int iteration_times=2000;


typedef struct
{
 double code;//染色体
 double degree;//适应度
}individual;

individual group[POP_SIZE];//种群规模为40

void max_evaluation(individual &x)
{
 //根据sin2 (5. 1πx + 0. 5)的最大值
 double tmp=sin(5.1*3.14*x.code+0.5)+sin(5.1*3.14*x.code+0.5)-sin(5.1*3.14*x.code+0.5);
 x.degree=(tmp*tmp);
}

int happened(double p)//发生一个p=0~1间概率的事件
{
 return rand()<(int)(p*RAND_MAX);
}

void cross(individual &x,individual &y)//交叉操作,产生一个子代取代父代中最次的一个
{
 individual z;
 z.code=(x.code+y.code)/2.0;
 max_evaluation(z);
 
 if(x.degree<y.degree)
 {
  if(z.degree<=x.degree)return;
  //如果新个体不如双亲,淘汰之
  x=z;
 }
 else
 {
  if(z.degree<=y.degree)return;
  y=z;
 }
}
void mutate(individual &x)
{
 x.code=x.code+rand();
 max_evaluation(x);
 
}
double randfloat()  
{
 return (rand())/(RAND_MAX+1.0);
}

int roulette_wheel_selection(double A[],int n)
{
 srand(time(0));
 double t=randfloat();
 int i;
 double d=0.0;
 for(i=0;i<n;i++)
 {
  d+=A[i];
  if(d>t)return i;
 }
 return rand()%n;//这里出现的概率几乎为0,只有在精度丢失时才发生
}

void main()
{
 srand(time(0));
 int i,j,best ;
 double sum;
 
 for(i=0;i<POP_SIZE;++i)//随机得到初始种群
 {
  group[i].code=1.0+(double)rand()/RAND_MAX;
  max_evaluation(group[i]);
 }
 
 ////////////////////////////////////////////////////////
 for(i=1;i<=iteration_times;++i)//固定进化10代
 {
  sum=0.0;
  best=0;
  for(j=0;j<POP_SIZE;++j)
  {
   sum+=group[j].degree;//求总的适应度sum
   if(group[j].degree>group[best].degree)
    best=j;//求当前最优个体
  }
  
  printf("第%2d代中 最优个体为 %10f\n",i,group[best].degree);
  ///////////////////////////////////
  double probability[POP_SIZE];
  memset(probability,0,sizeof(double)* POP_SIZE);
  
  for(j=0;j<POP_SIZE;++j)
  {
   probability[j]=group[j].degree/sum;
  }
  
  for(j=0;j<POP_SIZE;++j)
  {
   int sel1=roulette_wheel_selection(probability,POP_SIZE);
   int sel2=roulette_wheel_selection(probability,POP_SIZE);
   
   if(happened(CROSS_RATE)) cross (group[sel1],group[sel2]);//交叉
   if(happened(MUTATE_RATE)) mutate(group[sel1]);//变异  
   
  }
 
 }
 system("pause");
}