Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

last_generation is sometimes empty when stopped using user_request_stop #18

Open
rtfcv opened this issue Jun 22, 2022 · 0 comments
Open

Comments

@rtfcv
Copy link

rtfcv commented Jun 22, 2022

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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant