OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
Sampler.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <string>
3 #include <limits>
4 
5 #include "Sample/Sampler.h"
6 
7 #include "OPALconfig.h"
8 #include "Utilities/Util.h"
9 
10 #include "Util/OptPilotException.h"
11 #include "Util/MPIHelper.h"
12 
13 #include <boost/property_tree/json_parser.hpp>
14 
15 #include <boost/filesystem.hpp>
16 
18  Expressions::Named_t constraints,
19  DVarContainer_t dvars,
20  size_t dim, Comm::Bundle_t comms,
21  CmdArguments_t args,
22  std::vector<double> hypervolRef,
23  int nrWorkerGroups)
24  : Optimizer(comms.opt)
25 {
26  throw OptPilotException("Sampler::Sampler",
27  "We shouldn't get here!");
28 }
29 
30 
31 Sampler::Sampler(const std::map<std::string,
32  std::shared_ptr<SamplingMethod>
33  >& sampleMethods,
34  Expressions::Named_t objectives,
35  DVarContainer_t dvars,
36  Comm::Bundle_t comms,
37  CmdArguments_t args)
38  : Optimizer(comms.opt)
39  , sampleMethods_m(sampleMethods)
40  , comms_(comms)
41  , dvars_m(dvars)
42  , objectives_m(objectives)
43  , args_(args)
44 {
45  my_local_pid_ = 0;
46  MPI_Comm_rank(comms_.opt, &my_local_pid_);
47 
48  std::string resultFile = args->getArg<std::string>("outfile", "output", false);
49  std::string resultDir = args->getArg<std::string>("outdir", "samples", false);
50  jsonDumpFreq_m = args->getArg<std::size_t>("jsonDumpFreq", true);
51 
52  std::ostringstream filename;
53  filename << resultDir << "/" << resultFile
54  << "_samples_" << comms_.island_id << ".json";
55  jsonFname_m = filename.str();
56 
57  if ( !boost::filesystem::exists(resultDir) ) {
58  boost::filesystem::create_directory(resultDir);
59  }
60 
62  for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
63  dVarBounds_m.push_back(
64  std::pair<double, double>
65  (boost::get<LOWER_BOUND>(itr->second),
66  boost::get<UPPER_BOUND>(itr->second)));
67  }
68 
70 }
71 
72 
74 
75  nSamples_m = args_->getArg<int>("nsamples", true);
76  act_sample_m = 0;
77  done_sample_m = 0;
79 
80  int nMasters = args_->getArg<int>("num-masters", true);
81 
82  if ( nMasters > nSamples_m )
83  throw OptPilotException("Sampler::initialize",
84  "More masters than samples.");
85 
86  // unique job id
87  int nLocSamples = nSamples_m / nMasters;
88  int rest = nSamples_m - nMasters * nLocSamples;
89 
90  if ( comms_.island_id < rest )
91  nLocSamples++;
92 
93  if ( rest == 0 )
94  gid = nLocSamples * comms_.island_id;
95  else {
96  if ( comms_.island_id < rest ) {
97  gid = nLocSamples * comms_.island_id;
98  } else {
99  gid = (nLocSamples + 1) * rest + (comms_.island_id - rest) * nLocSamples;
100  }
101  }
102 
103  nSamples_m = nLocSamples;
104 
105  // start poll loop
106  run();
107 }
108 
109 
110 bool Sampler::onMessage(MPI_Status status, size_t length) {
111  MPITag_t tag = MPITag_t(status.MPI_TAG);
112  switch(tag) {
113  case REQUEST_FINISHED: {
114  unsigned int jid = static_cast<unsigned int>(length);
115  typename std::map<size_t, boost::shared_ptr<Individual_t> >::iterator it;
116  it = jobmapping_m.find(jid);
117 
118  if(it == jobmapping_m.end()) {
119  std::cout << "NON-EXISTING JOB with ID = " << jid << std::endl;
120  throw OptPilotException("Sampler::onMessage",
121  "non-existing job");
122  }
123 
124 
125  boost::shared_ptr<Individual_t> ind = it->second;
126 
127  reqVarContainer_t res;
128  MPI_Recv_reqvars(res, status.MPI_SOURCE, comms_.opt);
129 
130  ind->objectives.clear();
131 
132  reqVarContainer_t::iterator itr = res.begin();
133  for(; itr != res.end(); ++itr) {
134  // mark invalid if expression could not be evaluated or constraint does not hold
135  if(!itr->second.is_valid || (itr->second.value.size() > 1 && !itr->second.value[0])) {
136  ind->objectives.push_back(std::numeric_limits<double>::infinity());
137  } else {
138  // update objective value for valid objective
139  if(itr->second.value.size() == 1)
140  ind->objectives.push_back(itr->second.value[0]);
141  }
142  }
143 
144  addIndividualToJSON(ind);
145 
146  jobmapping_m.erase(it);
147 
148  done_sample_m++;
149 
150  return true;
151  }
152  default: {
153  std::cout << "(Sampler) Error: unexpected MPI_TAG: "
154  << status.MPI_TAG << std::endl;
155  return false;
156  }
157  }
158 }
159 
160 
162 
163  if ( act_sample_m < nSamples_m ) {
164  this->createNewIndividual();
165  }
166 
167  runStateMachine();
168 }
169 
170 
172 
173  std::vector<std::string> dNames;
174 
176  for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
177  std::string dName = boost::get<VAR_NAME>(itr->second);
178  dNames.push_back(dName);
179  }
180 
181  boost::shared_ptr<Individual_t> ind = boost::shared_ptr<Individual_t>( new Individual_t(dNames));
182 
183  ind->id = gid++;
184 
185  for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
186  std::string dName = boost::get<VAR_NAME>(itr->second);
187  int i = ind->getIndex(dName);
188  sampleMethods_m[dName]->create(ind, i);
189  }
190 
191 
192  individuals_m.push(ind);
193 }
194 
195 
197  namespace pt = boost::property_tree;
198 
199  pt::ptree tree;
200 
201  tree.put("name", "sampler");
202  tree.put(OPAL_PROJECT_NAME " version", OPAL_PROJECT_VERSION);
203  tree.put("git revision", Util::getGitRevision());
204 
205  std::stringstream bounds;
206  DVarContainer_t::iterator itr = dvars_m.begin();
207  for (bounds_t::iterator it = dVarBounds_m.begin();
208  it != dVarBounds_m.end(); ++it, ++itr)
209  {
210  std::string dvar = boost::get<VAR_NAME>(itr->second);
211  bounds << "[ " << it->first << ", " << it->second << " ]";
212  tree.put("dvar-bounds." + dvar, bounds.str());
213  bounds.str("");
214  }
215 
216  pt::write_json(jsonFname_m, tree);
217 }
218 
219 
221 
222  if (individualsToDump_m.empty()) {
223  return;
224  }
225 
226  namespace pt = boost::property_tree;
227 
228  pt::ptree tree;
229  pt::read_json(jsonFname_m, tree);
230 
231  pt::ptree samples;
232 
233  if ( tree.get_optional<std::string>("samples") ) {
234  /* we already have individuals in the JSON
235  * file
236  */
237  samples = tree.get_child("samples");
238  tree.erase("samples");
239  }
240 
241  while (!individualsToDump_m.empty()) {
242  Individual_t ind = individualsToDump_m.front();
243  individualsToDump_m.pop_front();
244 
245  std::string id = std::to_string(ind.id);
246 
248  for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
249  std::string name = boost::get<VAR_NAME>(itr->second);
250  int i = ind.getIndex(name);
251  samples.put(id + ".dvar." + name, ind.genes[i]);
252  }
253 
255  expr_it = objectives_m.begin();
256 
257  for(size_t i=0; i < ind.objectives.size(); i++, expr_it++) {
258  std::string name = expr_it->first;
259 
260  // skip dummy objective (in constructor of SamplePilot.h)
261  if ( name == "dummy" )
262  continue;
263 
264  samples.put(id + ".obj." + name, ind.objectives[i]);
265  }
266  }
267 
268  tree.add_child("samples", samples);
269  boost::property_tree::write_json(jsonFname_m, tree);
270 }
271 
272 
273 void Sampler::addIndividualToJSON(const boost::shared_ptr<Individual_t>& ind) {
274  individualsToDump_m.push_back(*ind);
275 
276  if (jsonDumpFreq_m <= individualsToDump_m.size()) {
278  }
279 }
280 
281 
283 
284  switch(curState_m) {
285 
286  case SUBMIT: {
287  if ( done_sample_m == nSamples_m) {
288  curState_m = STOP;
289  } else {
290  if ( act_sample_m != nSamples_m ) {
292  }
293  }
294  break;
295  }
296  case STOP: {
297 
299 
301 
302  // notify pilot that we have converged
303  int dummy = 0;
304  MPI_Request req;
305  MPI_Isend(&dummy, 1, MPI_INT, comms_.master_local_pid,
307 
308  break;
309  }
310 
311  case TERMINATE: {
312  break;
313  }
314  }
315 }
316 
317 
319 
320  while ( !individuals_m.empty() ) {
321  boost::shared_ptr<Individual_t> ind = individuals_m.front();
322 
323  individuals_m.pop();
324 
325  Param_t params;
327 
328  for(itr = dvars_m.begin(); itr != dvars_m.end(); itr++) {
329  std::string dName = boost::get<VAR_NAME>(itr->second);
330  int i = ind->getIndex(dName);
331  params.insert(
332  std::pair<std::string, double>
333  (dName, ind->genes[i]));
334  }
335 
336  size_t jid = static_cast<size_t>(ind->id);
337  int pilot_rank = comms_.master_local_pid;
338 
339 
340  act_sample_m++;
341 
342  // now send the request to the pilot
343  MPI_Send(&jid, 1, MPI_UNSIGNED_LONG, pilot_rank, OPT_NEW_JOB_TAG, comms_.opt);
344 
345  MPI_Send_params(params, pilot_rank, comms_.opt);
346 
347  jobmapping_m.insert(
348  std::pair<size_t, boost::shared_ptr<Individual_t> >(jid, ind));
349  }
350 }
std::map< std::string, reqVarInfo_t > reqVarContainer_t
Definition: Types.h:64
SampleIndividual Individual_t
Definition: Sampler.h:107
DVarContainer_t dvars_m
design variables
Definition: Sampler.h:121
int island_id
Definition: types.h:15
int done_sample_m
Definition: Sampler.h:135
virtual void initialize()
Initialization and start algorithm.
Definition: Sampler.cpp:73
void dumpIndividualsToJSON()
Definition: Sampler.cpp:220
void dispatch_forward_solves()
Definition: Sampler.cpp:318
unsigned int id
id
CmdArguments_t args_
command line arguments specified by the user
Definition: Sampler.h:130
boost::shared_ptr< CmdArguments > CmdArguments_t
Definition: CmdArguments.h:169
std::map< std::string, std::shared_ptr< SamplingMethod > > sampleMethods_m
Definition: Sampler.h:100
std::map< size_t, boost::shared_ptr< Individual_t > > jobmapping_m
mapping from unique job ID to individual
Definition: Sampler.h:113
#define MPI_OPT_CONVERGED_TAG
optimizer notifies pilot that optimization has converged (EXIT)
Definition: MPIHelper.h:28
void postPoll()
executed after handling (if any) new request
Definition: Sampler.cpp:161
Expressions::Named_t objectives_m
objectives
Definition: Sampler.h:124
void bounds(const PETE_Expr< T1 > &expr, Vektor< T2, D > &minval, Vektor< T2, D > &maxval)
#define OPAL_PROJECT_NAME
Definition: OPALconfig.h:2
std::list< Individual_t > individualsToDump_m
Definition: Sampler.h:149
namedVariableCollection_t Param_t
Definition: Types.h:33
bool onMessage(MPI_Status status, size_t length)
Definition: Sampler.cpp:110
Sampler(Expressions::Named_t objectives, Expressions::Named_t constraints, DVarContainer_t dvars, size_t dim, Comm::Bundle_t comms, CmdArguments_t args, std::vector< double > hypervolRef, int nrWorkerGroups)
Definition: Sampler.cpp:17
An abstract class defining the interface for all optimizer components.
Definition: Optimizer.h:14
virtual void run()
Definition: Poller.h:62
int gid
Definition: Sampler.h:103
int getIndex(std::string name)
int act_sample_m
current generation
Definition: Sampler.h:133
#define OPAL_PROJECT_VERSION
Definition: OPALconfig.h:5
genes_t genes
genes of an individual
int my_local_pid_
Definition: Sampler.h:105
std::map< std::string, DVar_t > DVarContainer_t
Definition: Types.h:77
void MPI_Send_params(Param_t params, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:66
std::map< std::string, Expressions::Expr_t * > Named_t
type of an expressions with a name
Definition: Expression.h:45
std::string jsonFname_m
Definition: Sampler.h:147
void createNewIndividual()
Definition: Sampler.cpp:171
objectives_t objectives
values of objectives of an individual
const std::string name
void MPI_Recv_reqvars(reqVarContainer_t &reqvars, size_t pid, MPI_Comm comm)
Definition: MPIHelper.cpp:144
int master_local_pid
Definition: types.h:18
void writeJsonHeader()
Definition: Sampler.cpp:196
std::string getGitRevision()
Definition: Util.cpp:15
MPITag_t
Definition: MPIHelper.h:51
MPI_Comm opt
Definition: types.h:20
std::queue< boost::shared_ptr< Individual_t > > individuals_m
Definition: Sampler.h:115
std::string::iterator iterator
Definition: MSLang.h:16
bundles all communicators for a specific role/pid
Definition: types.h:14
int nSamples_m
Definition: Sampler.h:126
void addIndividualToJSON(const boost::shared_ptr< Individual_t > &ind)
Definition: Sampler.cpp:273
bounds_t dVarBounds_m
bounds on each specified gene
Definition: Sampler.h:118
Comm::Bundle_t comms_
communicator bundle for the optimizer
Definition: Sampler.h:110
std::size_t jsonDumpFreq_m
Dumps id, design variables and bound.
Definition: Sampler.h:146
void runStateMachine()
Definition: Sampler.cpp:282
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
State curState_m
Definition: Sampler.h:143