Tomographer  v5.4
Tomographer C++ Framework Documentation
mhrwtasks.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHER_MHWALKER_TASKS_H
29 #define TOMOGRAPHER_MHWALKER_TASKS_H
30 
38 #include <climits>
39 
40 #include <string>
41 #include <limits>
42 #include <random>
43 #include <sstream>
44 #include <stdexcept>
45 
46 #include <boost/serialization/serialization.hpp>
47 #include <boost/serialization/vector.hpp>
48 
49 #include <tomographer/tools/fmt.h>
51 #include <tomographer/mhrw.h>
53 #include <tomographer/multiproc.h> // StatusReport Base
54 
55 
56 namespace Tomographer {
57 namespace MHRWTasks {
58 
59 
60 
61 
79 template<typename MHWalkerParams_, typename IterCountIntType_ = int,
80  typename RngSeedType_ = std::mt19937::result_type>
81 struct TOMOGRAPHER_EXPORT CDataBase
82 {
84  typedef IterCountIntType_ IterCountIntType;
86  typedef MHWalkerParams_ MHWalkerParams;
87 
92  typedef RngSeedType_ RngSeedType;
93 
100 
101 
108  template<typename MHRWParamsType>
109  CDataBase(MHRWParamsType&& p, RngSeedType base_seed_)
110  : mhrw_params(std::forward<MHRWParamsType>(p)),
111  base_seed(base_seed_),
112  task_seeds()
113  {
114  }
115 
123  template<typename MHRWParamsType>
124  CDataBase(MHRWParamsType&& p, std::vector<RngSeedType> task_seeds_)
125  : mhrw_params(std::forward<MHRWParamsType>(p)),
126  base_seed(0),
127  task_seeds(std::move(task_seeds_))
128  {
129  }
130 
132  CDataBase() : mhrw_params(), base_seed(), task_seeds() { }
133 
134 
146  MHRWParamsType mhrw_params;
147 
166  RngSeedType base_seed;
167 
176 
177 
193  template<typename TaskNoCountIntType>
194  inline RngSeedType getTaskInput(TaskNoCountIntType k) const
195  {
196  if (task_seeds.size() > 0) {
197  // specific task seeds given (e.g. from random device)
198  if (k < 0 || (std::size_t)k >= task_seeds.size()) {
199  throw std::out_of_range(streamstr("getTaskInput(): k="<<k<<" out of range; seed list size is = "
200  << task_seeds.size()));
201  }
202  return task_seeds[(std::size_t)k];
203  } else {
204  // derive seed from base seed
205 
206  // empirically it's noticeably better to feed the RNG sequential numbers rather than
207  // try to shuffle bits around (!!)
208  return base_seed + (RngSeedType)k;
209  }
210  }
211 
212 
216  inline void printBasicCDataMHRWInfo(std::ostream & str) const
217  {
218  str << "\tstep : " << std::setprecision(4) << mhrw_params.mhwalker_params << "\n"
219  << "\t# iter. / sweep = " << mhrw_params.n_sweep << "\n"
220  << "\t# therm. sweeps = " << mhrw_params.n_therm << "\n"
221  << "\t# run sweeps = " << mhrw_params.n_run << "\n";
222  }
223 
228  {
230  printBasicCDataMHRWInfo(ss);
231  return ss.str();
232  }
233 
234 private:
235  friend boost::serialization::access;
236  template<typename Archive>
237  void serialize(Archive & a, unsigned int /* version */)
238  {
239  a & mhrw_params;
240  a & base_seed;
241  a & task_seeds;
242  }
243 };
244 
245 
246 
247 
248 
249 
250 
271 template<typename MHRWStatsResultsType_, typename IterCountIntType, typename MHWalkerParams>
272 struct TOMOGRAPHER_EXPORT MHRandomWalkTaskResult
273  : public virtual Tools::NeedOwnOperatorNew<MHRWStatsResultsType_>::ProviderType
274 {
279  typedef MHRWStatsResultsType_ MHRWStatsResultsType;
280 
284 
292  template<typename MHRWStatsResultsTypeInit,
293  typename MHRWParamsTypeInit>
294  MHRandomWalkTaskResult(MHRWStatsResultsTypeInit && stats_results_,
295  MHRWParamsTypeInit && mhrw_params_,
296  double acceptance_ratio_)
297  : stats_results(std::forward<MHRWStatsResultsTypeInit>(stats_results_)),
298  mhrw_params(std::forward<MHRWParamsTypeInit>(mhrw_params_)),
299  acceptance_ratio(acceptance_ratio_)
300  {
301  }
302 
310  template<typename MHRWStatsResultsTypeInit, typename MHRandomWalkType>
311  MHRandomWalkTaskResult(MHRWStatsResultsTypeInit && stats_results_,
312  const MHRandomWalkType & mhrandomwalk)
313  : stats_results(std::forward<MHRWStatsResultsTypeInit>(stats_results_)),
314  mhrw_params(mhrandomwalk.mhrwParams()),
315  acceptance_ratio(mhrandomwalk.hasAcceptanceRatio() ?
316  mhrandomwalk.acceptanceRatio() :
317  std::numeric_limits<double>::quiet_NaN())
318  {
319  }
320 
321 
324  MHRandomWalkTaskResult() : stats_results(), mhrw_params(), acceptance_ratio() { }
325 
326 
331 
334 
337 
338 
341 
342 private:
343  friend boost::serialization::access;
344  template<typename Archive,
345  typename MHRWStatsResultsType2 = MHRWStatsResultsType>
346  void serialize(Archive & a, unsigned int /* version */)
347  {
348  MHRWStatsResultsType2 & stats_results_ref = stats_results;
349  a & stats_results_ref;
350  a & mhrw_params;
351  a & acceptance_ratio;
352  }
353 };
354 
355 
356 
357 
367 template<typename MHRandomWalkTaskCData,
368  typename Rng = std::mt19937>
369 struct TOMOGRAPHER_EXPORT MHRandomWalkTask
370 {
372  typedef typename MHRandomWalkTaskCData::IterCountIntType IterCountIntType;
374  typedef typename MHRandomWalkTaskCData::MHWalkerParams MHWalkerParams;
375 
378 
383  typedef MHRandomWalkTaskResult<typename MHRandomWalkTaskCData::MHRWStatsResultsType,
384  IterCountIntType, MHWalkerParams> ResultType;
385 
390 
391 private:
393  typename Rng::result_type _seed;
394 
402  ResultType * result;
403 
404 
405 public:
406 
412  template<typename LoggerType>
413  MHRandomWalkTask(typename Rng::result_type inputseed, const MHRandomWalkTaskCData * /*pcdata*/,
414  LoggerType & logger)
415  : _seed(inputseed), result(NULL)
416  {
417  logger.longdebug("MHRandomWalkTask", [&](std::ostream & stream) {
418  stream << "inputseed=" << inputseed;
419  });
420  }
421 
423  {
424  if (result != NULL) {
425  delete result;
426  }
427  }
428 
429 private:
430 
431  template<typename LoggerType, typename TaskMgrIface>
432  struct RunInnerCallable
433  {
434  const MHRandomWalkTaskCData * pcdata;
435  Rng & rng;
436  LoggerType & baselogger;
437  TaskMgrIface * tmgriface;
438 
439  ResultType ** ppresult;
440 
441  RunInnerCallable(const MHRandomWalkTaskCData * pcdata_, Rng & rng_, LoggerType & logger_,
442  TaskMgrIface * tmgriface_, ResultType ** ppresult_)
443  : pcdata(pcdata_), rng(rng_), baselogger(logger_), tmgriface(tmgriface_), ppresult(ppresult_)
444  {
445  }
446  ~RunInnerCallable() {
447  }
448 
449  template<typename MHWalkerType, typename MHRWStatsCollectorType, typename MHRWControllerType>
450  inline void operator()(MHWalkerType & mhwalker, MHRWStatsCollectorType & stats,
451  MHRWControllerType & controller)
452  {
453  // here we actually run the stuff
454 
455  auto logger = Logger::makeLocalLogger("Tomographer::MHRWTasks::MHRandomWalkTask::run()/run", baselogger);
456 
457  // our own "stats collector" which checks if we need to send a status report back
458  typedef PredStatusReportMHRWStatsCollector<MHRWParamsType> OurStatusReportCheck;
459  OurStatusReportCheck statreportcheck(
460  // predicate
461  [&]() { return this->tmgriface->statusReportRequested(); },
462  // send-status-function
463  [&](StatusReportType report) { this->tmgriface->submitStatusReport(std::move(report)); }
464  );
465 
467  OurStatsCollectors;
468  OurStatsCollectors ourstatscollectors(stats, statreportcheck);
469 
470  logger.longdebug("About to creat MHRandomWalk instance");
471 
473  MHRandomWalkType;
474 
475  MHRandomWalkType rwalk(
476  // MH random walk parameters
477  pcdata->mhrw_params,
478  // the MHWalker
479  mhwalker,
480  // our stats collectors
481  ourstatscollectors,
482  // the random walk controller
483  controller,
484  // a random number generator
485  rng,
486  // and a logger
487  baselogger
488  );
489 
490  logger.longdebug("MHRandomWalk object created, running...");
491 
492  rwalk.run();
493 
494  logger.longdebug("MHRandomWalk run finished.");
495 
496  *ppresult = new ResultType(stats.stealResult(), rwalk);
497  }
498 
499  template<typename MHWalkerType, typename MHRWStatsCollectorType>
500  inline void operator()(MHWalkerType & mhwalker, MHRWStatsCollectorType & stats)
501  {
502  MHRWNoController ctrl;
503  operator()<MHWalkerType, MHRWStatsCollectorType, MHRWNoController>(mhwalker, stats, ctrl) ;
504  }
505  };
506 
507 
508 public:
518  template<typename LoggerType, typename TaskManagerIface>
519  inline void run(const MHRandomWalkTaskCData * pcdata, LoggerType & baselogger, TaskManagerIface * tmgriface)
520  {
521  auto logger = Logger::makeLocalLogger("Tomographer::MHRWTasks::MHRandomWalkTask::run()", baselogger) ;
522 
523  logger.debug([&](std::ostream & stream) {
524  stream << "Starting random walk, using rng seed = " << _seed;
525  });
526 
527  Rng rng(_seed); // seeded random number generator
528 
529  RunInnerCallable<LoggerType, TaskManagerIface> run_object(pcdata, rng, baselogger, tmgriface, &result);
530 
531  pcdata->setupRandomWalkAndRun(rng, baselogger, run_object);
532  }
533 
534  inline ResultType getResult() const
535  {
536  return *result;
537  }
538 
539  inline ResultType stealResult()
540  {
541  return std::move(*result);
542  }
543 };
544 
545 
546 
547 } // namespace MHRWTasks
548 
549 
550 
551 } // namespace Tomographer
552 
553 
554 
555 #endif
A Metropolis-Hastings Random Walk.
Definition: mhrw.h:643
Utilities for formatting strings.
MHRWParams< MHWalkerParams, IterCountIntType > MHRWParamsType
Type to stores the parameters of the random walk.
Definition: mhrwtasks.h:377
MHRWParamsType mhrw_params
Parameters of the random walk.
Definition: mhrwtasks.h:146
MHRWStatsResultsType_ MHRWStatsResultsType
The type which stores the results from the statistics carried out during the random walk...
Definition: mhrwtasks.h:279
MHRandomWalkTaskCData::MHWalkerParams MHWalkerParams
The type used to describe a step size (see MHRWParams)
Definition: mhrwtasks.h:374
Base namespace for the Tomographer project.
Definition: densellh.h:45
CDataBase(MHRWParamsType &&p, RngSeedType base_seed_)
Constructor.
Definition: mhrwtasks.h:109
Provide appropriate operator new() definitions for a structure which has a member of the given stored...
CountIntType n_run
Number of live sweeps.
Definition: mhrw.h:184
RngSeedType getTaskInput(TaskNoCountIntType k) const
Returns a random seed to seed the random number generator with for run number k.
Definition: mhrwtasks.h:194
STL namespace.
std::vector< RngSeedType > task_seeds
A list of random seeds to use for each task.
Definition: mhrwtasks.h:175
void run(const MHRandomWalkTaskCData *pcdata, LoggerType &baselogger, TaskManagerIface *tmgriface)
Run this task.
Definition: mhrwtasks.h:519
CDataBase()
Construct an invalid object – ONLY for use with Boost.serialization.
Definition: mhrwtasks.h:132
MHRWStatsResultsType stats_results
The result(s) coming from stats collecting (may be processed, see MHRandomWalkTaskCData Interface) ...
Definition: mhrwtasks.h:330
CountIntType n_therm
Number of thermalization sweeps.
Definition: mhrw.h:180
double acceptance_ratio
The acceptance ratio of the Metropolis-Hastings random walk.
Definition: mhrwtasks.h:336
RngSeedType base_seed
A base random seed from which each run seed will be derived.
Definition: mhrwtasks.h:166
A "stats collector" which produces status reports whenever a predicate evaluates to true...
Random Walk task, collecting statistics.
Definition: mhrwtasks.h:369
void printBasicCDataMHRWInfo(std::ostream &str) const
Get some human-readable info about the random walk as a string.
Definition: mhrwtasks.h:216
STL class.
CDataBase(MHRWParamsType &&p, std::vector< RngSeedType > task_seeds_)
Constructor.
Definition: mhrwtasks.h:124
Data needed to be accessible to the working code.
Definition: mhrwtasks.h:81
MHRWParamsType mhrw_params
The parameters of the random walk (see MHRWParams<MHWalkerParams,IterCountIntType>) ...
Definition: mhrwtasks.h:333
CountIntType n_sweep
The number of individual updates to collect together in a "sweep".
Definition: mhrw.h:176
MHRandomWalkTask(typename Rng::result_type inputseed, const MHRandomWalkTaskCData *, LoggerType &logger)
Constructs the MHRandomWalkTask.
Definition: mhrwtasks.h:413
RngSeedType_ RngSeedType
Type used to specify the seed of the random number generator.
Definition: mhrwtasks.h:92
LocalLogger< BaseLoggerType > makeLocalLogger(std::string origin_fn_name, BaseLoggerType &baselogger)
Create a local logger.
Definition: loggers.h:2040
A MHRWController Interface which combines several independent random walk controllers.
Definition: mhrw.h:398
T str(T... args)
MHRWParams< MHWalkerParams, IterCountIntType > MHRWParamsType
The type to use to store the parameters of the random walk.
Definition: mhrwtasks.h:283
T move(T... args)
MHRWParams< MHWalkerParams, IterCountIntType > MHRWParamsType
Type to store the parameters of the Metropolis-Hastings random walk (number of runs, sweep size, etc.)
Definition: mhrwtasks.h:99
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
T size(T... args)
Status Report structure representing the status of a MHRandomWalk.
Definition: mhrw.h:1142
std::string getBasicCDataMHRWInfo() const
Get some human-readable info about the random walk as a string, see printBasicCDataMHRWInfo() ...
Definition: mhrwtasks.h:227
Some common definitions for multiprocessing interfaces.
MHRandomWalkTaskResult(MHRWStatsResultsTypeInit &&stats_results_, MHRWParamsTypeInit &&mhrw_params_, double acceptance_ratio_)
Constructor, initializes fields to the given values.
Definition: mhrwtasks.h:294
MHRandomWalkTaskResult(MHRWStatsResultsTypeInit &&stats_results_, const MHRandomWalkType &mhrandomwalk)
Constructor with mhrw_params initialized from a random walk instance.
Definition: mhrwtasks.h:311
Definitions for MHRWStatsCollector Interface&#39;s.
IterCountIntType_ IterCountIntType
Type used to count the number of iterations.
Definition: mhrwtasks.h:84
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:149
Routines for performing a Metropolis-Hastings random walk.
T setprecision(T... args)
MHRandomWalkTaskCData::IterCountIntType IterCountIntType
The type used to count iterations (see MHRWParams)
Definition: mhrwtasks.h:372
MHWalkerParams_ MHWalkerParams
Type used to specify the step size.
Definition: mhrwtasks.h:86
STL class.
MHWalkerParams mhwalker_params
The parameters of the mh-walker, typically just the step size of the random walk. ...
Definition: mhrw.h:172
MHRWStatusReport< MHRWParamsType > StatusReportType
Typedef for MHRWStatusReport. This is needed by, e.g. MultiProc::OMP::TaskDispatcher.
Definition: mhrwtasks.h:389
MHRandomWalkTaskResult< typename MHRandomWalkTaskCData::MHRWStatsResultsType, IterCountIntType, MHWalkerParams > ResultType
Result type of a single task run.
Definition: mhrwtasks.h:384
A simple MHRWStatsCollector interface which combines several stats collectors.