12#include <QCoreApplication>
21 GA_params.maxpop = 100;
22 Ind.resize(GA_params.maxpop);
23 Ind_old.resize(GA_params.maxpop);
27 GA_params.cross_over_type = 1;
36 ifstream file(filename);
40 GA_params.RCGA =
false;
43 filenames.pathname = Model->OutputPath();
45 while (file.eof() ==
false)
47 s = aquiutils::getline(file);
49 {
if (s[0] ==
"maxpop") GA_params.maxpop = atoi(s[1].c_str());
50 if (s[0] ==
"ngen") GA_params.nGen = atoi(s[1].c_str());
51 if (s[0] ==
"pcross") GA_params.pcross = atof(s[1].c_str());
52 if (s[0] ==
"pmute") GA_params.pmute = atof(s[1].c_str());
53 if (s[0] ==
"shakescale") GA_params.shakescale = atof(s[1].c_str());
54 if (s[0] ==
"shakescalered") GA_params.shakescalered = atof(s[1].c_str());
55 if (s[0] ==
"outputfile") filenames.outputfilename = s[1];
56 if (s[0] ==
"getfromfilename") filenames.getfromfilename = s[1].c_str();
57 if (s[0] ==
"initial_population") filenames.initialpopfilemame = s[1];
58 if (s[0] ==
"numthreads") numberOfThreads = atoi(s[1].c_str());
63 for (
int i=0; i<Model->Parameters().size(); i++)
67 if (Model->Parameters()[i]->GetPriorDistribution() ==
"lognormal")
68 { minval.push_back(log10(Model->Parameters()[i]->GetRange(
_range::low)));
69 maxval.push_back(log10(Model->Parameters()[i]->GetRange(
_range::high)));
74 minval.push_back(Model->Parameters()[i]->GetRange(
_range::low));
75 maxval.push_back(Model->Parameters()[i]->GetRange(
_range::high));
77 apply_to_all.push_back(
false);
78 if (Model->Parameters()[i]->GetPriorDistribution() ==
"lognormal")
83 paramname.push_back(Model->Parameters().getKeyAtIndex(i));
88 Ind.resize(GA_params.maxpop);
89 Ind_old.resize(GA_params.maxpop);
92 GA_params.cross_over_type = 1;
94 for (
int i=0; i<GA_params.maxpop; i++)
97 Ind[i].fit_measures.resize(model->ObservationsCount()*3);
99 Ind_old[i].fit_measures.resize(model->ObservationsCount()*3);
102 for (
int i = 0; i<GA_params.nParam; i++)
103 Setminmax(i, minval[i], maxval[i],4);
112 GA_params.nParam = 0;
113 GA_params.pcross = 1;
115 GA_params.RCGA =
false;
116 numberOfThreads = 20;
118 filenames.pathname = Model->GetOutputPath();
119 GA_params.maxpop = max(1,GA_params.maxpop);
120 for (
unsigned int i=0; i<Model->Parameters().size(); i++)
125 { minval.push_back(log10(Model->parameter(i)->GetVal(
"low")));
126 maxval.push_back(log10(Model->parameter(i)->GetVal(
"high")));
131 minval.push_back(Model->parameter(i)->GetVal(
"low"));
132 maxval.push_back(Model->parameter(i)->GetVal(
"high"));
134 apply_to_all.push_back(
false);
140 paramname.push_back(Model->GetParameterName(i));
145 Ind.resize(GA_params.maxpop);
146 Ind_old.resize(GA_params.maxpop);
149 GA_params.cross_over_type = 1;
151 for (
int i=0; i<GA_params.maxpop; i++)
154 Ind[i].fit_measures.resize(model->ObservationsCount());
156 Ind_old[i].fit_measures.resize(model->ObservationsCount());
159 for (
int j = 0; j < GA_params.nParam; j++)
160 Setminmax(j, minval[j], maxval[j], 4);
168 GA_params.nParam = Model->Parameters().size();
170 for (
unsigned int i=0; i<Model->Parameters().size(); i++)
174 { minval.push_back(log10(Model->parameter(i)->GetVal(
"low")));
175 maxval.push_back(log10(Model->parameter(i)->GetVal(
"high")));
180 minval.push_back(Model->parameter(i)->GetVal(
"low"));
181 maxval.push_back(Model->parameter(i)->GetVal(
"high"));
183 apply_to_all.push_back(
false);
189 paramname.push_back(Model->GetParameterName(i));
194 Ind.resize(GA_params.maxpop);
195 Ind_old.resize(GA_params.maxpop);
198 GA_params.cross_over_type = 1;
200 for (
int i=0; i<GA_params.maxpop; i++)
203 Ind[i].fit_measures.resize(Model->ObservationsCount());
205 Ind_old[i].fit_measures.resize(Model->ObservationsCount());
208 for (
int j = 0; j < GA_params.nParam; j++)
209 Setminmax(j, minval[j], maxval[j], 4);
217 Ind.resize(GA_params.maxpop);
218 Ind_old.resize(GA_params.maxpop);
219 for (
int i=0; i<GA_params.maxpop; i++)
232 GA_params.maxpop = n;
236 Ind.resize(GA_params.maxpop);
237 Ind_old.resize(GA_params.maxpop);
238 for (
int i=0; i<n; i++)
242 for (
int j = 0; j<nParam; j++)
244 Ind[i].minrange[j] = TempInd.
minrange[j];
245 Ind[i].maxrange[j] = TempInd.
maxrange[j];
246 Ind[i].precision[j] = TempInd.
precision[j];
247 Ind_old[i].minrange[j] = TempInd.
minrange[j];
248 Ind_old[i].maxrange[j] = TempInd.
maxrange[j];
249 Ind_old[i].precision[j] = TempInd.
precision[j];
260 Ind.resize(GA_params.maxpop);
261 Ind_old.resize(GA_params.maxpop);
299 for (
int i=0; i<GA_params.maxpop; i++)
304 if (filenames.initialpopfilemame!=
"")
306 getinifromoutput(filenames.pathname+filenames.initialpopfilemame);
307 for (
int i=0; i<initial_pop.size(); i++)
308 for (
int j=0; j<max(
int(initial_pop[i].size()),GA_params.nParam); j++)
310 Ind[i].x[j] = log10(initial_pop[i][j]);
312 Ind[i].x[j] = initial_pop[i][j];
319 for (
int i=0; i<GA_params.maxpop; i++)
321 Ind[i].maxrange[a] = maxrange;
322 Ind[i].minrange[a] = minrange;
323 Ind[i].precision[a] = prec;
333 vector<vector<double>> inp;
335 inp.resize(GA_params.maxpop);
338 for (
int k=0; k<GA_params.maxpop; k++)
339 inp[k].resize(GA_params.nParam);
341 vector<double> time_(GA_params.maxpop);
342 vector<int> epochs(GA_params.maxpop);
346 for (
int k = 0; k < GA_params.maxpop; k++)
348 for (
int i = 0; i < GA_params.nParam; i++)
352 inp[k][i] = Ind[k].x[i];
356 inp[k][i] = pow(10, Ind[k].
x[i]);
360 Ind[k].actual_fitness = 0;
366 for (
int i = 0; i < GA_params.nParam; i++)
367 Models[k].SetParameterValue(i, inp[k][i]);
374 omp_set_num_threads(numberOfThreads);
377#pragma omp parallel for
378 for (
int k=0; k<GA_params.maxpop; k++)
381 if (GA_params.Steepest_Descent && k<min(GA_params.maxpop/10,1))
384 qDebug()<<
"Prior Likelihood: " <<Models[k].GetObjectiveFunctionValue();
385 CVector updated_params;
386 for (
int j=0; j<5; j++)
387 updated_params = Models[k].GradientUpdate();
388 for (
int i = 0; i < GA_params.nParam; i++)
392 inp[k][i] = updated_params[i];
393 Ind[k].x[i] = updated_params[i];
398 inp[k][i] = updated_params[i];
399 Ind[k].x[i] = log10(updated_params[i]);
404 qDebug()<<
"Posterior Likelihood: " <<Models[k].GetObjectiveFunctionValue();
411 FileOut = fopen((filenames.pathname+
"detail_GA.txt").c_str(),
"a");
412 fprintf(FileOut,
"%i, ", k);
413 for (
int l=0; l<Ind[0].nParams; l++)
415 fprintf(FileOut,
"%le, ", pow(10,Ind[k].
x[l]));
417 fprintf(FileOut,
"%le, ", Ind[k].
x[l]);
421 fprintf(FileOut,
"\n");
424 time_t t0 = time(
nullptr);
428 Ind[k].actual_fitness = Models[k].GetObjectiveFunctionValue();
433 time_[k] = time(
nullptr)-t0;
441 if (omp_get_thread_num() == 0)
458 Model_out = Models[maxfitness()];
467 assignfitness_rank(GA_params.N);
476 int a = maxfitness();
479 for (
int i=2; i<GA_params.maxpop; i+=2)
482 int j1 = fitdist.GetRand();
483 int j2 = fitdist.GetRand();
484 double x = fitdist.GetRndUniF(0,1);
485 if (
x<GA_params.pcross)
486 if (GA_params.cross_over_type == 1)
487 cross(Ind_old[j1], Ind_old[j2], Ind[i], Ind[min(i+1,GA_params.maxpop-1)]);
489 cross2p(Ind_old[j1], Ind_old[j2], Ind[i], Ind[min(i + 1, GA_params.maxpop - 1)]);
492 Ind[i] = Ind_old[j1];
493 Ind[i+1] = Ind_old[j2];
504 for (
int i=0; i<GA_params.maxpop; i++)
506 int a = maxfitness();
509 for (
int i=2; i<GA_params.maxpop; i+=2)
511 int j1 = fitdist.GetRand();
512 int j2 = fitdist.GetRand();
514 if (
x<GA_params.pcross)
515 cross_RC_L(Ind_old[j1], Ind_old[j2], Ind[i], Ind[i+1]);
518 Ind[i] = Ind_old[j1];
519 Ind[i+1] = Ind_old[j2];
527 if (aquiutils::tolower(varname) ==
"maxpop" || varname ==
"Population") {GA_params.maxpop = aquiutils::atoi(value); setnumpop(GA_params.maxpop);
return true;}
528 if (aquiutils::tolower(varname) ==
"ngen" || varname ==
"Number of Generations") {GA_params.nGen = aquiutils::atoi(value);
return true;}
529 if (aquiutils::tolower(varname) ==
"pcross" || varname ==
"Cross-over probability") {GA_params.pcross = aquiutils::atof(value);
return true;}
530 if (aquiutils::tolower(varname) ==
"pmute" || varname ==
"Mutation probability") {GA_params.pmute = aquiutils::atof(value);
return true;}
531 if (aquiutils::tolower(varname) ==
"shakescale" || varname ==
"Shake coefficient") {GA_params.shakescale = aquiutils::atof(value);
return true;}
532 if (aquiutils::tolower(varname) ==
"shakescalered" || varname ==
"Shake coefficient reduction factor") {GA_params.shakescalered = aquiutils::atof(value);
return true;}
533 if (aquiutils::tolower(varname) ==
"outputfile" || varname ==
"GA output file") {filenames.outputfilename = value;
return true;}
534 if (aquiutils::tolower(varname) ==
"getfromfilename") {filenames.getfromfilename = value.c_str();
return true;}
535 if (aquiutils::tolower(varname) ==
"initial_population") {filenames.initialpopfilemame = value;
return true;}
536 if (aquiutils::tolower(varname) ==
"numthreads" || varname ==
"Number of threads to be used") {numberOfThreads = aquiutils::atoi(value.c_str());
return true;}
537 if (aquiutils::tolower(varname) ==
"steepest descent") {
539 if (aquiutils::tolower(value) ==
"true")
540 GA_params.Steepest_Descent =
true;
542 GA_params.Steepest_Descent =
false;
545 last_error =
"Property '" + varname +
"' was not found!";
552 for (map<string,string>::const_iterator it=arguments.begin(); it!=arguments.end(); it++)
553 SetProperty(it->first, it->second);
561 for (
int i=0; i<GA_params.maxpop; i++)
562 sum += Ind[i].fitness;
563 return sum/GA_params.maxpop;
571 FileOut = fopen((filenames.pathname +
"detail_GA.txt").c_str(),
"a");
572 fprintf(FileOut,
"%s\n", s.c_str());
581 QCoreApplication::processEvents();
583 string RunFileName = filenames.pathname + filenames.outputfilename;
588 FileOut = fopen(RunFileName.c_str(),
"w");
590 FileOut1 = fopen((filenames.pathname +
"detail_GA.txt").c_str(),
"w");
593 double shakescaleini = GA_params.shakescale;
595 vector<double> X(Ind[0].nParams);
598 double ininumenhancements = GA_params.numenhancements;
599 GA_params.numenhancements = 0;
601 CMatrix Fitness(GA_params.nGen, 3);
604 Models.resize(GA_params.maxpop);
605 for (
int k=0; k<GA_params.maxpop; k++)
607 for (current_generation=0; current_generation<GA_params.nGen; current_generation++)
610 write_to_detailed_GA(
"Assigning fitnesses ...");
614 write_to_detailed_GA(
"Assigning fitnesses done!");
615 FileOut = fopen(RunFileName.c_str(),
"a");
616 printf(
"Generation: %i\n", current_generation);
617 fprintf(FileOut,
"Generation: %i\n", current_generation);
618 fprintf(FileOut,
"ID, ");
619 for (
int k=0; k<Ind[0].nParams; k++)
620 fprintf(FileOut,
"%s, ", paramname[k].c_str());
623 for (
unsigned int i=0; i<Model->ObservationsCount();i++)
625 fprintf(FileOut,
"%s, %s, %s", (Model->observation(i)->GetName()+
"_MSE").c_str(), (Model->observation(i)->GetName()+
"_R2").c_str(), (Model->observation(i)->GetName()+
"_NSE").c_str());
627 fprintf(FileOut,
"\n");
628 write_to_detailed_GA(
"Generation: " + aquiutils::numbertostring(current_generation));
629 for (
int j1=0; j1<GA_params.maxpop; j1++)
632 fprintf(FileOut,
"%i, ", j1);
634 for (
int k=0; k<Ind[0].nParams; k++)
636 fprintf(FileOut,
"%le, ", pow(10, Ind[j1].
x[k]));
638 fprintf(FileOut,
"%le, ", Ind[j1].
x[k]);
640 fprintf(FileOut,
"%le, %le, %i, ", Ind[j1].actual_fitness, Ind[j1].fitness, Ind[j1].rank);
641 for (
unsigned int i=0; i<Model->ObservationsCount();i++)
643 fprintf(FileOut,
",%le, %le, %le", Ind[j1].fit_measures[i]);
645 fprintf(FileOut,
"\n");
649 int j = maxfitness();
651 Fitness[current_generation][0] = Ind[j].actual_fitness;
655 {
if (current_generation==0)
657 rtw->SetYRange(0,Ind[j].actual_fitness*1.1);
658 rtw->SetXRange(0,GA_params.nGen);
660 rtw->SetProgress(
double(current_generation)/
double(GA_params.nGen));
661 rtw->AppendPoint(current_generation+1,Ind[j].actual_fitness);
663 QCoreApplication::processEvents();
666 if (current_generation>10)
668 if ((Fitness[current_generation][0] == Fitness[current_generation - 3][0]) && GA_params.shakescale>pow(10.0, -Ind[0].precision[0]))
669 GA_params.shakescale *= GA_params.shakescalered;
672 if ((Fitness[current_generation][0]>Fitness[current_generation - 1][0]) && (GA_params.shakescale<shakescaleini))
673 GA_params.shakescale /= GA_params.shakescalered;
674 GA_params.numenhancements = 0;
677 if (current_generation>50)
679 if (Fitness[current_generation][0] == Fitness[current_generation - 20][0])
681 GA_params.numenhancements *= 1.05;
682 if (GA_params.numenhancements == 0) GA_params.numenhancements = ininumenhancements;
685 if (Fitness[current_generation][0] == Fitness[current_generation - 50][0])
686 GA_params.numenhancements = ininumenhancements * 10;
689 Fitness[current_generation][1] = GA_params.shakescale;
690 Fitness[current_generation][2] = GA_params.pmute;
692 if (current_generation>20)
694 if (GA_params.shakescale == Fitness[current_generation - 20][1])
695 GA_params.shakescale = shakescaleini;
700 MaxFitness = Ind[j].actual_fitness;
702 Fitness[current_generation][0] = Ind[j].actual_fitness;
707 write_to_detailed_GA(
"Cross-over ...");
709 if (GA_params.RCGA ==
true)
714 write_to_detailed_GA(
"Cross-over done! ");
716 write_to_detailed_GA(
"Mutation ...");
718 mutate(GA_params.pmute);
719 write_to_detailed_GA(
"Mutation done!");
720 write_to_detailed_GA(
"Shake...!");
722 write_to_detailed_GA(
"Shake done!");
728 FileOut = fopen(RunFileName.c_str(),
"a");
729 fprintf(FileOut,
"Final Enhancements\n");
731 int j = maxfitness();
733 MaxFitness = Ind[j].actual_fitness;
734 final_params.resize(GA_params.nParam);
737 for (
int k = 0; k<Ind[0].nParams; k++)
739 if (loged[k] == 1) final_params[k] = pow(10, Ind[j].
x[k]);
else final_params[k] = Ind[j].x[k];
740 fprintf(FileOut,
"%s, ", paramname[k].c_str());
741 fprintf(FileOut,
"%le, ", final_params[k]);
742 fprintf(FileOut,
"%le, %le\n", Ind[j].actual_fitness, Ind[j].fitness);
744 for (
unsigned int i=0; i<Model->ObservationsCount();i++)
746 fprintf(FileOut,
",%le, %le, %le\n", Ind[j].fit_measures[i]);
750 assignfitnesses(final_params);
755 rtw->SetProgress(1.0);
756 QCoreApplication::processEvents();
769 double likelihood = 0;
773 for (
int i = 0; i < GA_params.nParam; i++)
774 Model1.SetParameterValue(i, inp[i]);
778 likelihood -= Model1.GetObjectiveFunctionValue();
823 ifstream file(filename);
825 final_params.resize(GA_params.nParam);
826 while (file.eof() ==
false)
828 s = aquiutils::getline(file);
831 if (s[0] ==
"Final Enhancements")
832 for (
int i = 0; i<GA_params.nParam; i++)
834 s = aquiutils::getline(file);
836 write_to_detailed_GA(
"The number of parameters in GA output file does not match the number of unknown parameters");
838 final_params[i] = atof(s[1].c_str());
842 double ret = assignfitnesses(final_params);
851 for (
int j = 0; j<i; j++)
852 if (apply_to_all[j]) l++;
else l += 1;
864 for (
int j = 0; j<GA_params.nParam; j++)
866 if (apply_to_all[j]) l += 1;
else l += 1;
869 if (apply_to_all[j]) l -= 1;
else l--;
879 for (
int i=1; i<GA_params.maxpop; i++)
880 Ind[i].shake(GA_params.shakescale);
887 for (
int i=2; i<GA_params.maxpop; i++)
895 double max_fitness = 1E+308 ;
897 for (
int i=0; i<GA_params.maxpop; i++)
898 if (max_fitness>Ind[i].actual_fitness)
900 max_fitness = Ind[i].actual_fitness;
911 double a = avgfitness();
912 for (
int i=0; i<GA_params.maxpop; i++)
913 sum += (a - Ind[i].fitness)*(a - Ind[i].fitness);
922 double a = avg_inv_actual_fitness();
923 for (
int i=0; i<GA_params.maxpop; i++)
924 sum += (a - 1/Ind[i].actual_fitness)*(a - 1/Ind[i].actual_fitness);
925 return sqrt(sum)/GA_params.maxpop/a;
933 for (
int i=0; i<GA_params.maxpop; i++)
934 sum += Ind[i].actual_fitness;
935 return sum/GA_params.maxpop;
943 for (
int i=0; i<GA_params.maxpop; i++)
944 sum += 1/Ind[i].actual_fitness;
945 return sum/GA_params.maxpop;
953 for (
int i=0; i<GA_params.maxpop; i++)
956 for (
int j=0; j<GA_params.maxpop; j++)
958 if (Ind[i].actual_fitness > Ind[j].actual_fitness) r++;
969 for (
int i=0; i<GA_params.maxpop; i++)
971 Ind[i].fitness = pow(1.0/
static_cast<double>(Ind[i].rank),GA_params.N);
980 for (
int i=0; i<GA_params.maxpop; i++)
986 fitdist.e[0] = Ind[0].fitness/sum;
987 for (
int i=1; i<GA_params.maxpop-1; i++)
989 fitdist.e[i] = fitdist.e[i-1] + Ind[i].fitness/sum;
990 fitdist.s[i] = fitdist.e[i-1];
992 fitdist.s[GA_params.maxpop-1] = fitdist.e[GA_params.maxpop-2];
993 fitdist.e[GA_params.maxpop-1] = 1;
1000 vector<double> v(1);
1003 int x_nParam = GA_params.nParam;
1004 vector<int> x_params = params;
1005 GA_params.nParam = 1;
1008 out[0] = assignfitnesses(v);
1010 out.writetofile(filenames.pathname +
"likelihood.txt");
1012 GA_params.nParam = x_nParam;
1019 ifstream file(filename);
1021 initial_pop.resize(1);
1022 initial_pop[0].resize(GA_params.nParam);
1023 while (file.eof() ==
false)
1025 s = aquiutils::getline(file);
1027 {
if (s[0] ==
"Final Enhancements")
1028 for (
int i=0; i<GA_params.nParam; i++)
1030 s = aquiutils::getline(file);
1032 initial_pop[0][i] = atof(s[1].c_str());
1034 initial_pop[0][i] = atof(s[1].c_str());
1045 ifstream file(filename);
1048 while (file.eof() ==
false)
1050 s = aquiutils::getline(file);
1055 for (
int j=0; j<s.size(); j++)
1056 initial_pop.push_back(aquiutils::ATOF(s));
void cross2p(CBinary &B1, CBinary &B2, int p1, int p2)
void cross(CBinary &B1, CBinary &B2, int p)
void cross_RC_L(const CIndividual &I1, const CIndividual &I2, CIndividual &IR1, CIndividual &IR2)
double GetRndUnif(double xmin, double xmax)
Genetic Algorithm optimizer for global parameter estimation.
double MaxFitness
Maximum fitness value in current population.
void fillfitdist()
Fill fitness distribution for roulette wheel selection.
bool SetProperty(const std::string &varname, const std::string &value)
Set GA property from string key-value pair.
std::vector< int > params
Parameter indices being optimized.
int maxfitness()
Find index of individual with maximum fitness.
void assignrank()
Assign ranks to individuals based on fitness.
int get_time_series(int i)
Get time series index for parameter.
double avg_actual_fitness()
Calculate average of actual (untransformed) fitness values.
bool SetProperties(const std::map< std::string, std::string > &arguments)
Set multiple GA properties from map.
GA_Tweaking_parameters GA_params
GA algorithm configuration parameters.
void shake()
Apply shake/perturbation to population.
virtual ~CGA()
Destructor.
std::vector< CIndividual > Ind
Current population of individuals.
GADistribution fitdist
Fitness distribution for parent selection.
CGA operator=(CGA &C)
Assignment operator.
void setnumpop(int n)
Set population size.
double evaluateforward()
Evaluate model forward (compute predictions)
std::vector< std::string > paramname
Names of parameters being optimized.
void Setminmax(int a, double minrange, double maxrange, int prec)
Set parameter bounds and precision.
double avg_inv_actual_fitness()
Calculate average of inverse actual fitness.
void crossoverRC()
Real-coded crossover operation.
CGA()
Default constructor.
void assignfitnesses()
Evaluate fitness for all individuals in population.
void setnparams(int n)
Set number of parameters.
int optimize()
Main optimization loop.
void getinifromoutput(std::string filename)
Initialize population from previous output file.
double stdfitness()
Calculate standard deviation of population fitness.
int getparamno(int i, int ts)
Get parameter index for variable and time series.
void mutate(double mu)
Apply mutation to population.
std::vector< CIndividual > Ind_old
Previous generation's population.
void initialize()
Initialize GA structures and allocate memory.
void crossover()
Perform crossover operation on population.
double variancefitness()
Calculate variance of population fitness.
std::vector< int > loged
Flags indicating if parameters are log-transformed.
double getfromoutput(std::string filename)
Read best solution from previous output file.
void write_to_detailed_GA(std::string s)
Write detailed GA information to file.
void InitiatePopulation()
Create initial population.
void assignfitness_rank(double N)
Assign fitness using rank-based scheme.
void getinitialpop(std::string filename)
Read initial population from file.
double avgfitness()
Calculate average fitness of population.
_filenames filenames
File paths for GA input/output.
std::vector< int > precision
std::vector< double > minrange
std::vector< double > maxrange
@ lognormal
Lognormal distribution: ln(x) ~ N(μ, σ²), for strictly positive variables.
@ low
Lower bound of the parameter range.
@ high
Upper bound of the parameter range.
int maxpop
Maximum population size (number of individuals)