#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<fstream>
using namespace std;
struct fun_value{
int key;
double value;
};
bool cmp(fun_value a,fun_value b){
return a.value>b.value;
}
ofstream outfile("result.txt",ios::in);
class GA{
public:
int pc,pm;
int n,m;
double max,mean;
vector<vector<int> >s;
vector<fun_value>f;
GA(int n,int m,int pc,int pm){
this->n=n;
this->m=m;
this->pc=pc;
this->pm=pm;
srand(unsigned(time(0)));
int i,j;
vector<int>s1(m);
for(i=0;i<n;i++){
for(j=0;j<m;j++)
s1.push_back(rand()%2);
s.push_back(s1);
s1.clear();
}
}
void select();
void cross();
double n2to10(int two[]);
double fun(vector<int>all_two);
};
void GA::select(){
int size=s.size();
int i;
double value=0;
vector<vector<int> >s2;
vector<fun_value>::iterator it;
f.resize(size);
for(i=0;i<size;i++){
f[i].key=i;
f[i].value=fun(s[i]);
}
sort(f.begin(),f.end(),cmp);
max=f[0].value;
for(it=f.begin();it!=f.end();it++)
value+=(*it).value;
mean=mean/size;
outfile<<f[0].value<<endl;
for(i=0;i<n;i++)
s2.push_back(s[f[i].key]);
s.clear();
s.assign(s2.begin(),s2.end());
}
void GA::cross(){
srand(unsigned(time(0)));
vector<int>sc;
vector<vector<int> >scross;
double maxoftwo;
int i,j,num1,num2,pos;
if(f[num1].value>f[num2].value) maxoftwo=f[num1].value;
else maxoftwo=f[num2].value;
for(i=0;i<n/2;i++){
num1=rand()%n;
num2=rand()%n;
pos=rand()%m;
if(maxoftwo>=mean) pc=0.9-0.3*(maxoftwo-mean)/(max-mean);
else pc=0.9;
if(((float)rand()/RAND_MAX)<pc){
sc.insert(sc.end(),s[num1].begin(),s[num1].begin()+pos);
sc.insert(sc.end(),s[num2].begin()+pos,s[num2].end());
scross.push_back(sc);
}
else{
scross.push_back(s[num1]);
}
sc.clear();
if(((float)rand()/RAND_MAX)<pc){
sc.insert(sc.end(),s[num2].begin(),s[num2].begin()+pos);
sc.insert(sc.end(),s[num1].begin()+pos,s[num1].end());
scross.push_back(sc);
}
else {
scross.push_back(s[num2]);
}
sc.clear();
if(f[num1].value>=mean) pm=0.1-0.099*(max-f[num1].value)/(max-mean);
else pm=0.1;
if(((float)rand()/RAND_MAX)<pm){
pos=rand()%m;
scross[i][pos]=abs(scross[i][pos]-1);
}
if(f[num2].value>=mean) pm=0.1-0.099*(max-f[num2].value)/(max-mean);
else pm=0.1;
if(((float)rand()/RAND_MAX)<pm){
pos=rand()%m;
scross[i+1][pos]=abs(scross[i+1][pos]-1);
}
}
s.insert(s.end(),scross.begin(),scross.end());
}
double GA::n2to10(int two[]){
double ten_value=0;
int i;
for(i=0;i<20;i++)
ten_value=ten_value*2+two[19-i];
ten_value=-32.0+ten_value*64.0/(pow(2,20)-1);
return ten_value;
}
double GA::fun(vector<int>all_two){
double part1,part2,ten_value,eval;
int i,j,k;
int two[20];
for(i=0;i<50;i++){
part1=part2=0.0;
k=i*20;
for(j=0;j<20;j++)
two[j]=all_two[k++];
ten_value=n2to10(two);
part1+=ten_value*ten_value;
part2+=cos(2*3.14*ten_value);
}
eval=20*exp(-0.2*sqrt(part1/50))+exp(part2/50);
return eval;
}
int main(){
GA ga(1500,1000,0.75,0.02);
int gnmax=2500;
int i;
for(i=0;i<gnmax;i++){
ga.select();
ga.cross();
}
cout<<ga.f[0].value;
}