openGA
openGA copied to clipboard
last_generation is sometimes empty when stopped using user_request_stop
The title says it all. The problem can be easily reproduced in the rather sloppy code below. I think the problem is simple, as I also wrote in pull request #17 . I believe updating of the last_generation deserves the same handling as the report_generation(new_generation); Which would coincidentally stop last_generation from being overwritten by empty new_generation, which should only be empty when user_request_stop is set.
// This library is free and distributed under
// Mozilla Public License Version 2.0.
#include <string>
#include <iostream>
#include <fstream>
#include <csignal>
#include "openGA.hpp"
struct MySolution
{
double x1;
double x2;
std::string to_string() const
{
return
"{x1:"+std::to_string(x1)+
", x2:"+std::to_string(x2)+
"}";
}
};
struct MyMiddleCost
{
// This is where the results of simulation
// is stored but not yet finalized.
double cost_f1;
double cost_f2;
};
typedef EA::Genetic<MySolution,MyMiddleCost> GA_Type;
typedef EA::GenerationType<MySolution,MyMiddleCost> Generation_Type;
GA_Type ga_obj;
int i = 0;
void init_genes(MySolution& p,const std::function<double(void)> &rnd01)
{
p.x1=1.0*rnd01();
p.x2=1.0*rnd01();
}
bool eval_solution(
const MySolution& p,
MyMiddleCost &c)
{
if(++i >= 400)
ga_obj.user_request_stop = true;
double x1=p.x1;
double x2=p.x2;
// the middle comupations of cost:
double g=(x1-0.5)*(x1-0.5)+(x2-0.5)*(x2-0.5);
constexpr double pi=3.14159265359;
c.cost_f1=(1+g)*cos(x1*pi/2);
c.cost_f2=(1+g)*sin(x1*pi/2);
return true; // genes are accepted
}
MySolution mutate(
const MySolution& X_base,
const std::function<double(void)> &rnd01,
double shrink_scale)
{
MySolution X_new;
bool in_range_x1,in_range_x2;
const double mu=0.2*shrink_scale; // mutation radius
do{
X_new=X_base;
X_new.x1+=mu*(rnd01()-rnd01());
X_new.x2+=mu*(rnd01()-rnd01());
in_range_x1= (X_new.x1>=0.0 && X_new.x1<1.0);
in_range_x2= (X_new.x2>=0.0 && X_new.x2<1.0);
} while(!in_range_x1 || !in_range_x2);
return X_new;
}
MySolution crossover(
const MySolution& X1,
const MySolution& X2,
const std::function<double(void)> &rnd01)
{
MySolution X_new;
double r;
r=rnd01();
X_new.x1=r*X1.x1+(1.0-r)*X2.x1;
r=rnd01();
X_new.x2=r*X1.x2+(1.0-r)*X2.x2;
return X_new;
}
std::vector<double> calculate_MO_objectives(const GA_Type::thisChromosomeType &X)
{
return {
X.middle_costs.cost_f1,
X.middle_costs.cost_f2
};
}
void MO_report_generation(
int generation_number,
const EA::GenerationType<MySolution,MyMiddleCost> &last_generation,
const std::vector<unsigned int>& pareto_front)
{
(void) last_generation;
std::cout<<"Generation ["<<generation_number<<"], ";
std::cout<<"Pareto-Front {";
for(unsigned int i=0;i<pareto_front.size();i++)
{
std::cout<<(i>0?",":"");
std::cout<<pareto_front[i];
}
std::cout<<"}"<<std::endl;
}
void save_results(const GA_Type &ga_obj)
{
std::ofstream output_file;
output_file.open("./bin/result_mo2.txt");
output_file<<"N"<<"\t"<<"x"<<"\t"<<"y"<<"\t"<<"cost1"<<"\t"<<"cost2"<<"\n";
std::cout << "ga_obj.last_generation.fronts.size() = " << ga_obj.last_generation.fronts.size() << std::endl;;
if(ga_obj.last_generation.fronts.size()==0)
exit(0);
std::vector<unsigned int> paretofront_indices=ga_obj.last_generation.fronts[0];
for(unsigned int i:paretofront_indices)
{
const auto &X=ga_obj.last_generation.chromosomes[i];
output_file
<<i<<"\t"
<<X.genes.x1<<"\t"
<<X.genes.x2<<"\t"
<<X.middle_costs.cost_f1<<"\t"
<<X.middle_costs.cost_f2<<"\n";
}
output_file.close();
}
int main()
{
EA::Chronometer timer;
timer.tic();
ga_obj.problem_mode= EA::GA_MODE::NSGA_III;
ga_obj.dynamic_threading=false;
ga_obj.multi_threading=true;
ga_obj.idle_delay_us=1; // switch between threads quickly
ga_obj.verbose=false;
ga_obj.population=40;
ga_obj.generation_max=100;
ga_obj.calculate_MO_objectives= calculate_MO_objectives;
ga_obj.init_genes=init_genes;
ga_obj.eval_solution=eval_solution;
ga_obj.mutate=mutate;
ga_obj.crossover=crossover;
ga_obj.MO_report_generation=MO_report_generation;
ga_obj.crossover_fraction=0.7;
ga_obj.mutation_rate=0.4;
ga_obj.solve();
std::cout<<"The problem is optimized in "<<timer.toc()<<" seconds."<<std::endl;
save_results(ga_obj);
return 0;
}