gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
factory_defs.hpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
24 
25 #ifndef __FACTORY_DEFS_HPP__
26 #define __FACTORY_DEFS_HPP__
27 
28 #include <string>
29 #include <typeinfo>
30 #ifdef __NO_PLUGIN_BOOST__
31  #include <memory>
32 #else
33  #include <boost/shared_ptr.hpp>
34  #include <boost/enable_shared_from_this.hpp>
35 #endif
36 
37 #ifdef WITH_MPI
38  #include <chrono>
40 #endif
41 
46 
47 namespace Gambit
48 {
49  namespace Scanner
50  {
51 #ifdef __NO_PLUGIN_BOOST__
52  using std::shared_ptr;
53  using std::enable_shared_from_this;
54 #else
55  using boost::shared_ptr;
56  using boost::enable_shared_from_this;
57 #endif
58 
60  template<typename T>
62 
64  template<typename T>
66 
68  template<typename T>
69  class scan_ptr;
70 
72  template<typename ret, typename... args>
73  class Function_Base <ret (args...)> : public enable_shared_from_this<Function_Base <ret (args...)>>
74  {
75  private:
76  friend class Function_Deleter<ret (args...)>;
77  friend class scan_ptr<ret (args...)>;
78 
81  std::string purpose;
82  int myRealRank; // the actual MPI rank of the process, use for process dependent setup etc. getRank() is for printing only.
83 
86 
89 
92 
93  virtual void deleter(Function_Base <ret (args...)> *in) const
94  {
95  delete in;
96  }
97 
98  virtual const std::type_info & type() const {return typeid(ret (args...));}
99 
100  public:
101  Function_Base(double offset = 0.) : myRealRank(0), purpose_offset(offset), use_alternate_min_LogL(false), _scanner_can_quit(false)
102  {
103  #ifdef WITH_MPI
104  GMPI::Comm world;
105  myRealRank = world.Get_rank();
106  #endif
107  // Check if we should be using the alternative min_LogL from the very beginning
108  // (for example if we are resuming from a run where we already switched to this)
109  if (Gambit::Scanner::Plugins::plugin_info.resume_mode())
110  {
112  }
113  else
114  {
115  // New scan; delete any old persistence file
116  // But only do this if we are process 0, otherwise I think race conditions can occur.
117  // (TODO do we need to ensure a sync here in case other processes than 0 get too far ahead?)
119  }
120  }
121 
122  virtual ret main(const args&...) = 0;
123  virtual ~Function_Base(){}
124 
125  ret operator () (const args&... params)
126  {
128  if(Gambit::Printers::auto_increment()) // This is slightly hacky, but I need to be able to disable the auto-incrementing in the post-processor scanner. Need to manually set the point ID.
129  {
131  }
132  ret ret_val = main(params...);
134 
135  return ret_val;
136  }
137 
138  void setPurpose(const std::string p) {purpose = p;}
139  void setPrinter(printer* p) {main_printer = p;}
140  void setPrior(Priors::BasePrior *p) {prior = p;}
141  printer &getPrinter() {return *main_printer;}
142  printer &getPrinter() const {return *main_printer;} // Need a const version as well.
143  Priors::BasePrior &getPrior() {return *prior;}
144  std::vector<std::string> getParameters() {return prior->getParameters();}
145  std::vector<std::string> getShownParameters() {return prior->getShownParameters();}
146  std::string getPurpose() const {return purpose;}
147  int getRank() const {return getPrinter().getRank();} // Printer controls the 'virtual' rank. Lets us re-print data from a point originally generated by another rank.
148  void setRank(int r) {getPrinter().setRank(r);} // Needed by postprocessor to adjust 'virtual' rank; generally should not use otherwise.
149  double getPurposeOffset() const { return purpose_offset; }
150  void setPurposeOffset(double os) { purpose_offset = os; }
151  unsigned long long int getPtID() const {return Gambit::Printers::get_point_id();}
152  void setPtID(unsigned long long int pID) {Gambit::Printers::get_point_id() = pID;} // Needed by postprocessor; should not use otherwise.
153  unsigned long long int getNextPtID() const {return getPtID()+1;} // Needed if PtID required by plugin *before* operator() is called. See e.g. GreAT plugin.
154 
157  {
159  }
160 
165  void disable_external_shutdown() { _scanner_can_quit = true; }
166 
168  bool scanner_can_quit() { return _scanner_can_quit; }
169 
173  {
174  use_alternate_min_LogL = true;
175  #ifdef WITH_MPI
176  GMPI::Comm& myComm(Gambit::Scanner::Plugins::plugin_info.scanComm());
177  static const int TAG = Gambit::Scanner::Plugins::plugin_info.MIN_LOGL_MSG;
178  MPI_Request req_null = MPI_REQUEST_NULL;
179  int nullmsg = 0; // Don't need message content, the message itself is the signal.
180  myComm.IsendToAll(&nullmsg, 1, TAG, &req_null);
181  #endif
182  Gambit::Scanner::Plugins::plugin_info.save_alt_min_LogL_state(); // Write a file to disk so that upon startup we can check if the alternate min LogL is supposed to be used.
183  }
184 
187  {
188  if(not use_alternate_min_LogL)
189  {
190  #ifdef WITH_MPI
191  GMPI::Comm& myComm(Gambit::Scanner::Plugins::plugin_info.scanComm());
192  static const int TAG = Gambit::Scanner::Plugins::plugin_info.MIN_LOGL_MSG;
193  if(myComm.Iprobe(MPI_ANY_SOURCE, TAG))
194  {
195  int nullmsg;
196  MPI_Status msg_status;
197  myComm.Recv(&nullmsg, 1, MPI_ANY_SOURCE, TAG, &msg_status); // Recv the message to delete it.
198  use_alternate_min_LogL = true;
199  }
200  #endif
201  }
202  // If we didn't decide to switch yet, check for the existence of
203  // the persistence file. This is not necessary for proper functioning
204  // of this system, but it allows users to manually create the persistence file
205  // as a 'hack' to force the likelihood to switch to the alternate min LogL
206  // value.
207  if(not use_alternate_min_LogL)
208  {
210  }
211  return use_alternate_min_LogL;
212  }
214 
215  };
216 
217  template<typename ret, typename... args>
218  class Function_Deleter<ret (args...)>
219  {
220  private:
221  Function_Base <ret (args...)> *obj;
222 
223  public:
224  Function_Deleter(void *in) : obj(static_cast< Function_Base<ret (args...)>* >(in)) {}
225 
226  Function_Deleter(const Function_Deleter<ret (args...)> &in) : obj(in.obj) {}
227 
228  void operator =(const Function_Deleter<ret (args...)> &in)
229  {
230  obj = in.obj;
231  }
232 
233  void operator()(Function_Base <ret (args...)> *in)
234  {
235  obj->deleter(in);
236  }
237  };
238 
240  template<typename ret, typename... args>
241  class scan_ptr<ret (args...)> : public shared_ptr< Function_Base< ret (args...)> >
242  {
243  private:
244  typedef shared_ptr< Function_Base< ret (args...) > > s_ptr;
245 
246  public:
248  scan_ptr(const scan_ptr &in) : s_ptr (in){}
249  scan_ptr(scan_ptr &&in) : s_ptr (std::move(in)) {}
250  scan_ptr(void *in) : s_ptr
251  (
252  static_cast< Function_Base<ret (args...)>* >(in),
253  Function_Deleter<ret (args...)>(in)
254  )
255  {
256  if (typeid(ret (args...)) != this->get()->type())
257  {
258  scan_err << "scan_ptr and the functor return by \"get functor\" do not have the same type." << scan_end;
259  }
260  }
261 
262  scan_ptr<ret (args...)> &operator=(void *in)
263  {
264  this->s_ptr::operator=
265  (
266  s_ptr
267  (
268  static_cast< Function_Base<ret (args...)>* >(in),
269  Function_Deleter<ret (args...)>(in)
270  )
271  );
272 
273  if (typeid(ret (args...)) != this->get()->type())
274  {
275  scan_err << "scan_ptr and the functor return by \"get functor\" do not have the same type." << scan_end;
276  }
277 
278  return *this;
279  }
280 
281  scan_ptr<ret (args...)> &operator=(const scan_ptr<ret (args...)> &in)
282  {
283  this->s_ptr::operator=(in);
284 
285  return *this;
286  }
287 
288  scan_ptr<ret (args...)> &operator=(s_ptr &&in)
289  {
290  this->s_ptr::operator=(std::move(in));
291 
292  return *this;
293  }
294 
295  ret operator()(const args&... params)
296  {
297  return (*this)->operator()(params...);
298  }
299  };
300 
301  // TODO (Ben): I am just flagging a possible issue here. In principle, can't
302  // two like_ptrs be active in the one scan? I.e. we could calculate two separate
303  // likelihood functions at the one point (no scanners currently allow this, but
304  // in-principle they could). If so, then there is a printer issue here to worry
305  // about, namely, an error will be thrown if we attempt to print MPIrank, pointID,
306  // and unitCubeParameters twice for the same point, which it seems is what would
307  // happen. So we need to change something here so that they only get printed once
308  // per point, no matter how many like_ptr's may be "active" at once.
309 
311  class like_ptr : public scan_ptr<double (std::unordered_map<std::string, double> &)>
312  {
313  private:
315  std::unordered_map<std::string, double> map;
316 
317  public:
319  like_ptr(const like_ptr &in) : s_ptr (in){}
320  //like_ptr(like_ptr &&in) : s_ptr (std::move(in)) {}
321  like_ptr(void *in) : s_ptr(in) {}
322 
323  std::unordered_map<std::string, double> transform(const std::vector<double> &vec)
324  {
325  (*this)->getPrior().transform(vec, map);
326  return map;
327  }
328 
329  std::vector<std::string> get_names() const
330  {
331  return (*this)->getPrior().getShownParameters();
332  }
333 
334  std::vector<double> inverse_transform(const std::unordered_map<std::string, double> &physical)
335  {
336  return (*this)->getPrior().inverse_transform(physical);
337  }
338 
339  double operator()(const std::vector<double> &vec)
340  {
341  int rank = (*this)->getRank();
342  (*this)->getPrior().transform(vec, map);
343  double ret_val = (*this)->operator()(map);
344  unsigned long long int id = Gambit::Printers::get_point_id();
345  (*this)->getPrinter().print(ret_val, (*this)->getPurpose(), rank, id);
346  if (vec.size() > 0 && (*this)->getPrinter().get_printUnitcube())
347  (*this)->getPrinter().print(vec, "unitCubeParameters", rank, id);
348  (*this)->getPrinter().print(id, "pointID", rank, id);
349  (*this)->getPrinter().print(rank, "MPIrank", rank, id);
350  (*this)->getPrinter().enable(); // Make sure printer is re-enabled (might have been disabled by invalid point error)
351 
352  return ret_val + (*this)->getPurposeOffset();
353  }
354 
355  double operator()(std::unordered_map<std::string, double> &map, const std::vector<double> &vec = std::vector<double>())
356  {
357  int rank = (*this)->getRank();
358  (*this)->getPrior().transform(vec, map);
359  double ret_val = (*this)->operator()(map);
360  unsigned long long int id = Gambit::Printers::get_point_id();
361  (*this)->getPrinter().print(ret_val, (*this)->getPurpose(), rank, id);
362  if (vec.size() > 0 && (*this)->getPrinter().get_printUnitcube())
363  (*this)->getPrinter().print(vec, "unitCubeParameters", rank, id);
364  (*this)->getPrinter().print(id, "pointID", rank, id);
365  (*this)->getPrinter().print(rank, "MPIrank", rank, id);
366  (*this)->getPrinter().enable(); // Make sure printer is re-enabled (might have been disabled by invalid point error)
367  // Return the value of the function, offset by any offset set
368  return ret_val + (*this)->getPurposeOffset();
369  }
370  };
371 
374  {
375  public:
376  virtual void * operator() (const std::string &purpose) const = 0;
377  virtual ~Factory_Base() {};
378  };
379  }
380 }
381 
382 #endif
like_ptr(const like_ptr &in)
std::vector< std::string > getParameters()
void tell_scanner_early_shutdown_in_progress()
Tell ScannerBit that we are aborting the scan and it should tell the scanner plugin to stop...
Abstract base class for priors.
Definition: base_prior.hpp:40
scan_ptr< ret(args...)> & operator=(s_ptr &&in)
void save_alt_min_LogL_state() const
Save persistence file to record that the alternative min_LogL value is in use for this scan...
bool check_for_switch_to_alternate_min_LogL()
Checks if some process has triggered the &#39;switch_to_alternate_min_LogL&#39; function. ...
declaration for scanner module
Functor that deletes a Function_Base functor.
STL namespace.
Pure Base class of a plugin Factory function.
Function_Deleter(const Function_Deleter< ret(args...)> &in)
std::vector< std::string > get_names() const
std::vector< std::string > getShownParameters()
EXPORT_SYMBOLS bool & auto_increment()
Global flag to indicate if auto-incrementing of the PointID by the likelihood container is allowed...
EXPORT_SYMBOLS unsigned long long int & get_point_id()
Returns unigue pointid;.
GAMBIT signal handling functions.
virtual void deleter(Function_Base< ret(args...)> *in) const
unsigned long long int getNextPtID() const
bool _scanner_can_quit
Variable to specify whether the scanner plugin should control the shutdown process.
ret operator()(const args &... params)
unsigned long long int getPtID() const
scan_ptr< ret(args...)> & operator=(const scan_ptr< ret(args...)> &in)
std::unordered_map< std::string, double > transform(const std::vector< double > &vec)
#define scan_err
Defined to macros to output errors in the form: scan_err << "error" << scan_end; scan_warn << "warnin...
bool scanner_can_quit()
Check whether likelihood container is supposed to control early shutdown of scan. ...
void disable_external_shutdown()
Tells log-likelihood function (defined by driver code) not to use its own shutdown system (e...
Utility Functions for the Gambit Scanner.
void operator()(Function_Base< ret(args...)> *in)
Generic function base used by the scanner. Can be Likelihood, observables, etc.
START_MODEL dNur_CMB r
Generic ptr that takes ownership of a Function_Base. This is how a plugin will call a function...
double operator()(const std::vector< double > &vec)
std::unordered_map< std::string, double > map
virtual std::vector< std::string > getShownParameters() const
Definition: base_prior.hpp:75
A simple C++ wrapper for the MPI C bindings.
#define scan_end
std::vector< std::string > getParameters() const
Definition: base_prior.hpp:83
bool use_alternate_min_LogL
Variable to store state of affairs regarding use of alternate min_LogL.
std::vector< double > inverse_transform(const std::unordered_map< std::string, double > &physical)
void clear_alt_min_LogL_state() const
Delete the persistence file if it exists (e.g. when starting a new run)
Loader singleton class for scanner plugins.
shared_ptr< Function_Base< ret(args...) > > s_ptr
std::vector< T > vec(std::vector< T > vector)
Definition: daFunk.hpp:142
scan_ptr< ret(args...)> & operator=(void *in)
void switch_to_alternate_min_LogL()
Tell log-likelihood function (defined by driver code) to switch to an alternate value for the minimum...
bool check_alt_min_LogL_state() const
Check persistence file to see if we should be using the alternative min_LogL value.
EXPORT_SYMBOLS pluginInfo plugin_info
Access Functor for plugin info.
TODO: see if we can use this one:
Definition: Analysis.hpp:33
likelihood container for scanner plugins.
double operator()(std::unordered_map< std::string, double > &map, const std::vector< double > &vec=std::vector< double >())
virtual const std::type_info & type() const
void setPtID(unsigned long long int pID)
double purpose_offset
Variable to store some offset to be removed when printing out the return value of the function...