Commit 42e6658e authored by snuverink_j's avatar snuverink_j
Browse files

fix 236: add option to add reference point for hypervolume calculation

parent dec39823
...@@ -61,11 +61,13 @@ public: ...@@ -61,11 +61,13 @@ public:
* @param[in] dim number of objectives * @param[in] dim number of objectives
* @param[in] comms available to the optimizer * @param[in] comms available to the optimizer
* @param[in] args the user passed on the command line * @param[in] args the user passed on the command line
* @param[in] hypervolRef hypervolume reference point
*/ */
FixedPisaNsga2(Expressions::Named_t objectives, FixedPisaNsga2(Expressions::Named_t objectives,
Expressions::Named_t constraints, Expressions::Named_t constraints,
DVarContainer_t dvars, size_t dim, Comm::Bundle_t comms, DVarContainer_t dvars, size_t dim, Comm::Bundle_t comms,
CmdArguments_t args); CmdArguments_t args,
std::vector<double> hypervolRef);
~FixedPisaNsga2(); ~FixedPisaNsga2();
...@@ -175,7 +177,7 @@ private: ...@@ -175,7 +177,7 @@ private:
DVarContainer_t dvars_m; DVarContainer_t dvars_m;
/// command line arguments specified by the user /// command line arguments specified by the user
CmdArguments_t args_; CmdArguments_t args_m;
/// size of initial population /// size of initial population
size_t alpha_m; size_t alpha_m;
...@@ -205,6 +207,9 @@ private: ...@@ -205,6 +207,9 @@ private:
double conv_hvol_progress_; double conv_hvol_progress_;
double hvol_progress_; double hvol_progress_;
/// hypervolume reference point
std::vector<double> hvol_ref_m;
/// file header for result files contains this parameter description /// file header for result files contains this parameter description
std::string file_param_descr_; std::string file_param_descr_;
......
...@@ -32,15 +32,17 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2( ...@@ -32,15 +32,17 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2(
Expressions::Named_t constraints, Expressions::Named_t constraints,
DVarContainer_t dvars, DVarContainer_t dvars,
size_t dim, Comm::Bundle_t comms, size_t dim, Comm::Bundle_t comms,
CmdArguments_t args) CmdArguments_t args,
std::vector<double> hypervolRef)
: Optimizer(comms.opt) : Optimizer(comms.opt)
, statistics_(new Statistics<size_t>("individuals")) , statistics_(new Statistics<size_t>("individuals"))
, comms_(comms) , comms_(comms)
, objectives_m(objectives) , objectives_m(objectives)
, constraints_m(constraints) , constraints_m(constraints)
, dvars_m(dvars) , dvars_m(dvars)
, args_(args) , args_m(args)
, dim_m(dim) , dim_m(dim)
, hvol_ref_m(hypervolRef)
{ {
my_local_pid_ = 0; my_local_pid_ = 0;
MPI_Comm_rank(comms_.opt, &my_local_pid_); MPI_Comm_rank(comms_.opt, &my_local_pid_);
...@@ -48,10 +50,10 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2( ...@@ -48,10 +50,10 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2(
//FIXME: proper rand gen initialization (use boost?!) //FIXME: proper rand gen initialization (use boost?!)
srand(time(NULL) + comms_.island_id); srand(time(NULL) + comms_.island_id);
dump_freq_ = args->getArg<int>("dump-freq", 1, false); dump_freq_ = args->getArg<int>("dump-freq", 1, false);
maxGenerations_m = args->getArg<int>("maxGenerations", true); maxGenerations_m = args->getArg<int>("maxGenerations", true);
resultFile_m = args->getArg<std::string>("outfile", "-th_generation.dat", false); resultFile_m = args->getArg<std::string>("outfile", "-th_generation.dat", false);
resultDir_m = args->getArg<std::string>("outdir", "generations", false); resultDir_m = args->getArg<std::string>("outdir", "generations", false);
// create output directory if it does not exists // create output directory if it does not exists
struct stat dirInfo; struct stat dirInfo;
...@@ -86,7 +88,7 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2( ...@@ -86,7 +88,7 @@ FixedPisaNsga2<CO, MO>::FixedPisaNsga2(
DVarContainer_t::iterator itr; DVarContainer_t::iterator itr;
std::vector<std::string> dNames; std::vector<std::string> dNames;
for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) { for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
std::string dName = boost::get<VAR_NAME>(itr->second); std::string dName = boost::get<VAR_NAME>(itr->second);
file_param_descr_ += '%' + dName + ','; file_param_descr_ += '%' + dName + ',';
...@@ -144,13 +146,13 @@ void FixedPisaNsga2<CO, MO>::initialize() { ...@@ -144,13 +146,13 @@ void FixedPisaNsga2<CO, MO>::initialize() {
// start poll loop // start poll loop
run_clock_start_ = boost::chrono::system_clock::now(); run_clock_start_ = boost::chrono::system_clock::now();
last_clock_ = boost::chrono::system_clock::now(); last_clock_ = boost::chrono::system_clock::now();
run(); run();
bool compHyvol = (objectives_m.size() > (hyper_opt / 2 + 1)); bool compHyvol = (objectives_m.size() > (hyper_opt / 2 + 1));
if (compHyvol) if (compHyvol)
current_hvol_ = current_hvol_ =
variator_m->population()->computeHypervolume(comms_.island_id); variator_m->population()->computeHypervolume(comms_.island_id, hvol_ref_m);
boost::chrono::duration<double> total = boost::chrono::duration<double> total =
boost::chrono::system_clock::now() - run_clock_start_; boost::chrono::system_clock::now() - run_clock_start_;
...@@ -262,9 +264,8 @@ bool FixedPisaNsga2<CO, MO>::onMessage(MPI_Status status, size_t length) { ...@@ -262,9 +264,8 @@ bool FixedPisaNsga2<CO, MO>::onMessage(MPI_Status status, size_t length) {
ind->objectives.clear(); ind->objectives.clear();
//XXX: check order of genes //XXX: check order of genes
reqVarContainer_t::iterator itr; reqVarContainer_t::iterator itr = res.begin();
std::map<std::string, double> vars; for(; itr != res.end(); ++itr) {
for(itr = res.begin(); itr != res.end(); itr++) {
// mark invalid if expression could not be evaluated or constraint does not hold // mark invalid if expression could not be evaluated or constraint does not hold
if(!itr->second.is_valid || (itr->second.value.size() > 1 && !itr->second.value[0])) { if(!itr->second.is_valid || (itr->second.value.size() > 1 && !itr->second.value[0])) {
std::ostringstream dump; std::ostringstream dump;
...@@ -321,7 +322,7 @@ void FixedPisaNsga2<CO, MO>::postPoll() { ...@@ -321,7 +322,7 @@ void FixedPisaNsga2<CO, MO>::postPoll() {
bool compHyvol = (objectives_m.size() > (hyper_opt / 2 + 1)); bool compHyvol = (objectives_m.size() > (hyper_opt / 2 + 1));
if (compHyvol) { if (compHyvol) {
double hvol = double hvol =
variator_m->population()->computeHypervolume(comms_.island_id); variator_m->population()->computeHypervolume(comms_.island_id, hvol_ref_m);
hvol_progress_ = fabs(current_hvol_ - hvol) / current_hvol_; hvol_progress_ = fabs(current_hvol_ - hvol) / current_hvol_;
current_hvol_ = hvol; current_hvol_ = hvol;
} }
...@@ -337,7 +338,7 @@ void FixedPisaNsga2<CO, MO>::postPoll() { ...@@ -337,7 +338,7 @@ void FixedPisaNsga2<CO, MO>::postPoll() {
stats << "dt = " << dt.count() << "s, total = " << total.count() stats << "dt = " << dt.count() << "s, total = " << total.count()
<< "s" << std::endl; << "s" << std::endl;
if (compHyvol) if (compHyvol)
stats << "Hypervolume = " << current_hvol_ << std::endl; stats << "Hypervolume = " << current_hvol_ << std::endl;
stats << "__________________________________________" << std::endl; stats << "__________________________________________" << std::endl;
progress_->log(stats); progress_->log(stats);
...@@ -370,7 +371,7 @@ void FixedPisaNsga2<CO, MO>::exchangeSolutionStates() { ...@@ -370,7 +371,7 @@ void FixedPisaNsga2<CO, MO>::exchangeSolutionStates() {
typedef typename FixedPisaNsga2::Individual_t individual; typedef typename FixedPisaNsga2::Individual_t individual;
size_t num_masters = args_->getArg<size_t>("num-masters", 1, false); size_t num_masters = args_m->getArg<size_t>("num-masters", 1, false);
if(num_masters <= 1 || if(num_masters <= 1 ||
exchangeSolStateFreq_m == 0 || exchangeSolStateFreq_m == 0 ||
...@@ -660,7 +661,7 @@ template< template <class> class CO, template <class> class MO > ...@@ -660,7 +661,7 @@ template< template <class> class CO, template <class> class MO >
void FixedPisaNsga2<CO, MO>::dumpPopulationToFile() { void FixedPisaNsga2<CO, MO>::dumpPopulationToFile() {
// only dump old data format if the user requests it // only dump old data format if the user requests it
if(! args_->getArg<bool>("dump-dat", false, false)) return; if(! args_m->getArg<bool>("dump-dat", false, false)) return;
typedef typename FixedPisaNsga2::Individual_t individual; typedef typename FixedPisaNsga2::Individual_t individual;
boost::shared_ptr<individual> temp; boost::shared_ptr<individual> temp;
......
...@@ -162,7 +162,9 @@ public: ...@@ -162,7 +162,9 @@ public:
} }
double computeHypervolume(size_t island_id) { double computeHypervolume(size_t island_id, const std::vector<double>& referencePoint) {
// protection check
if (individuals.empty() == true) return -1;
std::ofstream file; std::ofstream file;
std::ostringstream filename; std::ostringstream filename;
...@@ -186,7 +188,7 @@ public: ...@@ -186,7 +188,7 @@ public:
file.flush(); file.flush();
file.close(); file.close();
hypervolume_ = Hypervolume::FromFile(filename.str()); hypervolume_ = Hypervolume::FromFile(filename.str(), referencePoint);
return hypervolume_; return hypervolume_;
} }
......
...@@ -113,13 +113,15 @@ public: ...@@ -113,13 +113,15 @@ public:
functionDictionary_t known_expr_funcs, functionDictionary_t known_expr_funcs,
const DVarContainer_t &dvar, const DVarContainer_t &dvar,
const Expressions::Named_t &obj, const Expressions::Named_t &obj,
const Expressions::Named_t &cons) const Expressions::Named_t &cons,
std::vector<double> hypervolRef = {})
: Poller(comm->mpiComm()) : Poller(comm->mpiComm())
, comm_(comm) , comm_(comm)
, cmd_args_(args) , cmd_args_(args)
, objectives_(obj) , objectives_(obj)
, constraints_(cons) , constraints_(cons)
, dvars_(dvar) , dvars_(dvar)
, hypervolRef_(hypervolRef)
{ {
setup(known_expr_funcs); setup(known_expr_funcs);
} }
...@@ -157,9 +159,11 @@ protected: ...@@ -157,9 +159,11 @@ protected:
bool has_opt_converged_; bool has_opt_converged_;
bool continue_polling_; bool continue_polling_;
Expressions::Named_t objectives_; Expressions::Named_t objectives_; ///< objectives
Expressions::Named_t constraints_; Expressions::Named_t constraints_; ///< constraints
DVarContainer_t dvars_; DVarContainer_t dvars_; ///< design variables
std::vector<double> hypervolRef_; ///< hypervolume reference point
// keep track of state of all workers // keep track of state of all workers
std::vector<bool> is_worker_idle_; std::vector<bool> is_worker_idle_;
...@@ -248,7 +252,7 @@ protected: ...@@ -248,7 +252,7 @@ protected:
boost::scoped_ptr<Opt_t> opt( boost::scoped_ptr<Opt_t> opt(
new Opt_t(objectives_, constraints_, dvars_, objectives_.size(), new Opt_t(objectives_, constraints_, dvars_, objectives_.size(),
comm_->getBundle(), cmd_args_)); comm_->getBundle(), cmd_args_, hypervolRef_));
opt->initialize(); opt->initialize();
std::cout << "Stop Opt.." << std::endl; std::cout << "Stop Opt.." << std::endl;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
/** /**
* \class CmdArguments * \class CmdArguments
* \brief Parsing commando line arguments * \brief Parsing command line arguments
* *
* In order to have a flexible framework, each component implementation gets * In order to have a flexible framework, each component implementation gets
* access to all command line arguments. * access to all command line arguments.
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
*/ */
#include <string>
#include <vector>
// To do: // To do:
// - can we sort less often or reduce/optimise dominance checks? // - can we sort less often or reduce/optimise dominance checks?
// - should we use FPL's data structure? // - should we use FPL's data structure?
...@@ -36,7 +39,7 @@ ...@@ -36,7 +39,7 @@
namespace Hypervolume { namespace Hypervolume {
double FromFile(std::string file); double FromFile(std::string file, const std::vector<double>& referencePoint);
//Room for more functions to compute volumes //Room for more functions to compute volumes
//without accessing external files //without accessing external files
} }
...@@ -64,6 +64,7 @@ namespace { ...@@ -64,6 +64,7 @@ namespace {
MAXGENERATIONS, MAXGENERATIONS,
EPSILON, EPSILON,
EXPECTEDHYPERVOL, EXPECTEDHYPERVOL,
HYPERVOLREFERENCE,
CONVHVOLPROG, CONVHVOLPROG,
ONEPILOTCONVERGE, ONEPILOTCONVERGE,
SOLSYNCH, SOLSYNCH,
...@@ -114,6 +115,8 @@ OptimizeCmd::OptimizeCmd(): ...@@ -114,6 +115,8 @@ OptimizeCmd::OptimizeCmd():
("EPSILON", "Tolerance of hypervolume criteria, default 0.001"); ("EPSILON", "Tolerance of hypervolume criteria, default 0.001");
itsAttr[EXPECTEDHYPERVOL] = Attributes::makeReal itsAttr[EXPECTEDHYPERVOL] = Attributes::makeReal
("EXPECTED_HYPERVOL", "The reference hypervolume, default 0"); ("EXPECTED_HYPERVOL", "The reference hypervolume, default 0");
itsAttr[HYPERVOLREFERENCE] = Attributes::makeRealArray
("HYPERVOLREFERENCE", "The reference point (real array) for the hypervolume, default empty (origin)");
itsAttr[CONVHVOLPROG] = Attributes::makeReal itsAttr[CONVHVOLPROG] = Attributes::makeReal
("CONV_HVOL_PROG", "converge if change in hypervolume is smaller, default 0"); ("CONV_HVOL_PROG", "converge if change in hypervolume is smaller, default 0");
itsAttr[ONEPILOTCONVERGE] = Attributes::makeBool itsAttr[ONEPILOTCONVERGE] = Attributes::makeBool
...@@ -123,7 +126,7 @@ OptimizeCmd::OptimizeCmd(): ...@@ -123,7 +126,7 @@ OptimizeCmd::OptimizeCmd():
itsAttr[GENEMUTATIONPROBABILITY] = Attributes::makeReal itsAttr[GENEMUTATIONPROBABILITY] = Attributes::makeReal
("GENE_MUTATION_PROBABILITY", "Mutation probability of individual gene, default: 0.5"); ("GENE_MUTATION_PROBABILITY", "Mutation probability of individual gene, default: 0.5");
itsAttr[MUTATIONPROBABILITY] = Attributes::makeReal itsAttr[MUTATIONPROBABILITY] = Attributes::makeReal
("MUTATION_PROBABILITY", "Mutation probability of genom, default: 0.5"); ("MUTATION_PROBABILITY", "Mutation probability of genome, default: 0.5");
itsAttr[RECOMBINATIONPROBABILITY] = Attributes::makeReal itsAttr[RECOMBINATIONPROBABILITY] = Attributes::makeReal
("RECOMBINATION_PROBABILITY", "Probability for genes to recombine, default: 0.5"); ("RECOMBINATION_PROBABILITY", "Probability for genes to recombine, default: 0.5");
itsAttr[SIMBINCROSSOVERNU] = Attributes::makeReal itsAttr[SIMBINCROSSOVERNU] = Attributes::makeReal
...@@ -269,6 +272,7 @@ void OptimizeCmd::execute() { ...@@ -269,6 +272,7 @@ void OptimizeCmd::execute() {
} }
} }
} }
// sanity checks
if (Attributes::getString(itsAttr[INPUT]) == "") { if (Attributes::getString(itsAttr[INPUT]) == "") {
throw OpalException("OptimizeCmd::execute", throw OpalException("OptimizeCmd::execute",
"The argument INPUT has to be provided"); "The argument INPUT has to be provided");
...@@ -281,6 +285,11 @@ void OptimizeCmd::execute() { ...@@ -281,6 +285,11 @@ void OptimizeCmd::execute() {
throw OpalException("OptimizeCmd::execute", throw OpalException("OptimizeCmd::execute",
"The argument MAXGENERATIONS has to be provided"); "The argument MAXGENERATIONS has to be provided");
} }
if (Attributes::getRealArray(itsAttr[HYPERVOLREFERENCE]).empty() == false &&
Attributes::getRealArray(itsAttr[HYPERVOLREFERENCE]).size() != objectivesstr.size()) {
throw OpalException("OptimizeCmd::execute",
"The hypervolume reference point should have the same dimension as the objectives");
}
if (Attributes::getString(itsAttr[SIMTMPDIR]) != "") { if (Attributes::getString(itsAttr[SIMTMPDIR]) != "") {
fs::path dir(Attributes::getString(itsAttr[SIMTMPDIR])); fs::path dir(Attributes::getString(itsAttr[SIMTMPDIR]));
...@@ -405,7 +414,7 @@ void OptimizeCmd::execute() { ...@@ -405,7 +414,7 @@ void OptimizeCmd::execute() {
CmdArguments_t args(new CmdArguments(argv.size(), &argv[0])); CmdArguments_t args(new CmdArguments(argv.size(), &argv[0]));
boost::shared_ptr<Comm_t> comm(new Comm_t(args, MPI_COMM_WORLD)); boost::shared_ptr<Comm_t> comm(new Comm_t(args, MPI_COMM_WORLD));
boost::scoped_ptr<pilot_t> pi(new pilot_t(args, comm, funcs, dvars, objectives, constraints)); boost::scoped_ptr<pilot_t> pi(new pilot_t(args, comm, funcs, dvars, objectives, constraints, Attributes::getRealArray(itsAttr[HYPERVOLREFERENCE])));
} catch (OptPilotException &e) { } catch (OptPilotException &e) {
std::cout << "Exception caught: " << e.what() << std::endl; std::cout << "Exception caught: " << e.what() << std::endl;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment