Tomographer  v5.2
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 
45 #include <tomographer/tools/fmt.h>
47 #include <tomographer/mhrw.h>
49 #include <tomographer/multiproc.h> // StatusReport Base
50 
51 
52 namespace Tomographer {
53 namespace MHRWTasks {
54 
55 
56 namespace tomo_internal {
57 // template<typename UIntType>
58 // struct bits_interleaved {
59 // // interleaves the first (lowest weight) HalfNBits of x and of y to yield a
60 // // (2*HalfNBits)-bit number
61 // template<int HalfNBits, int I = 0,
62 // TOMOGRAPHER_ENABLED_IF_TMPL(I < HalfNBits)>
63 // static inline constexpr UIntType interleave(const UIntType x, const UIntType y) {
64 // return ((x>>I)&0x1) | (((y>>I)&0x1)<<1) | interleave<HalfNBits, I+1>(x, y) << 2;
65 // }
66 // template<int HalfNBits, int I = 0,
67 // TOMOGRAPHER_ENABLED_IF_TMPL(I == HalfNBits)>
68 // static inline constexpr UIntType interleave(const UIntType , const UIntType ) {
69 // return 0;
70 // }
71 // };
72 // // generate a permutation of the bits of UIntType which maps integers 0...k to slightly
73 // // better seeds for each task's rng (spanning more of the seed bits)
74 // //
75 // // Despite the name, the permutation is always the same.
76 // template<typename UIntType, int NBits = sizeof(UIntType)*CHAR_BIT, typename = void>
77 // struct kinda_random_bits_perm {
78 // TOMO_STATIC_ASSERT_EXPR(!std::is_signed<UIntType>::value) ;
79 // // take the NBits least significant digits and apply the permutation to them
80 // static inline constexpr UIntType apply(UIntType x);
81 // };
82 // // implementation for NBits=4
83 // template<typename UIntType>
84 // struct kinda_random_bits_perm<UIntType,4,void> {
85 // TOMO_STATIC_ASSERT_EXPR(!std::is_signed<UIntType>::value) ;
86 // static inline constexpr UIntType apply(UIntType x)
87 // {
88 // // take the NBits least significant digits and apply the permutation to them
89 // return ( (x&0x1)<<2 | ((x>>1)&0x1)<<0 | ((x>>2)&0x1)<<3 | ((x>>3)&0x1)<<1 ) ;
90 // }
91 // };
92 // // implementation for NBits divisible by 8: apply the permutation to each halves of the
93 // // number and interleave them
94 // template<typename UIntType, int NBits>
95 // struct kinda_random_bits_perm<UIntType, NBits, // NBits can be divided by 8:
96 // typename std::enable_if<(NBits&(0x7))==0, void>::type>
97 // {
98 // TOMO_STATIC_ASSERT_EXPR(!std::is_signed<UIntType>::value) ;
99 // // take the NBits least significant digits and apply the permutation to them
100 // static inline constexpr UIntType apply(UIntType x)
101 // {
102 // // // left block of bits of the number is given by x>>(NBits/2) with NBits/2==NBits>>1
103 // // // right block of bits fo the number is given by x & MASK with MASK = ((1<<HalfNBits)-1)
104 // // constexpr int HalfNBits = (NBits>>1);
105 // // constexpr UIntType x1 = kinda_random_bits_perm<UIntType,HalfNBits>::apply(x >> HalfNBits) ;
106 // // constexpr UIntType x2 = kinda_random_bits_perm<UIntType,HalfNBits>::apply(x & ((1<<HalfNBits)-1)) ;
107 // // // now, interleave the HalfNBits of x1 and of x2
108 // // return bits_interleaved<UIntType>::interleave<HalfNBits>(x1,x2);
109 // return bits_interleaved<UIntType>::template interleave<(NBits>>1)>(
110 // kinda_random_bits_perm<UIntType,(NBits>>1)>::apply(x >> (NBits>>1)) ,
111 // kinda_random_bits_perm<UIntType,(NBits>>1)>::apply(x & ((UIntType(1)<<(NBits>>1))-1))
112 // );
113 // }
114 // };
115 
116 } // namespace tomo_internal
117 
118 
119 
120 
121 
131 template<typename MHWalkerParams_, typename IterCountIntType_ = int,
132  typename RngSeedType_ = std::mt19937::result_type>
133 struct TOMOGRAPHER_EXPORT CDataBase
134 {
136  typedef IterCountIntType_ IterCountIntType;
138  typedef MHWalkerParams_ MHWalkerParams;
139 
144  typedef RngSeedType_ RngSeedType;
145 
152 
153 
160  template<typename MHRWParamsType>
161  CDataBase(MHRWParamsType&& p, RngSeedType base_seed_)
162  : mhrw_params(std::forward<MHRWParamsType>(p)),
163  base_seed(base_seed_)
164  {
165  }
166 
174  const MHRWParamsType mhrw_params;
175 
190  const RngSeedType base_seed;
191 
201  template<typename TaskNoCountIntType>
202  inline RngSeedType getTaskInput(TaskNoCountIntType k) const
203  {
204  // empirically it's noticeably better to feed the RNG sequential numbers rather than
205  // try to shuffle bits around (!!)
206  return (RngSeedType)k;
207  }
208 
209 
213  inline void printBasicCDataMHRWInfo(std::ostream & str) const
214  {
215  str << "\tstep : " << std::setprecision(4) << mhrw_params.mhwalker_params << "\n"
216  << "\t# iter. / sweep = " << mhrw_params.n_sweep << "\n"
217  << "\t# therm. sweeps = " << mhrw_params.n_therm << "\n"
218  << "\t# run sweeps = " << mhrw_params.n_run << "\n";
219  }
220 
225  {
227  printBasicCDataMHRWInfo(ss);
228  return ss.str();
229  }
230 };
231 
232 
233 
234 
235 
236 
237 
238 
256 template<typename MHRWStatsResultsType_, typename IterCountIntType, typename MHWalkerParams>
257 struct TOMOGRAPHER_EXPORT MHRandomWalkTaskResult
258  : public virtual Tools::NeedOwnOperatorNew<MHRWStatsResultsType_>::ProviderType
259 {
264  typedef MHRWStatsResultsType_ MHRWStatsResultsType;
265 
269 
270  // /** \brief Construct an empty task result
271  // *
272  // */
273  // MHRandomWalkTaskResult()
274  // : stats_results(), mhrw_params(),
275  // acceptance_ratio(std::numeric_limits<double>::quiet_NaN())
276  // {
277  // }
278 
286  template<typename MHRWStatsResultsTypeInit,
287  typename MHRWParamsTypeInit>
288  MHRandomWalkTaskResult(MHRWStatsResultsTypeInit && stats_results_,
289  MHRWParamsTypeInit && mhrw_params_,
290  double acceptance_ratio_)
291  : stats_results(std::forward<MHRWStatsResultsTypeInit>(stats_results_)),
292  mhrw_params(std::forward<MHRWParamsTypeInit>(mhrw_params_)),
293  acceptance_ratio(acceptance_ratio_)
294  {
295  }
296 
304  template<typename MHRWStatsResultsTypeInit, typename MHRandomWalkType>
305  MHRandomWalkTaskResult(MHRWStatsResultsTypeInit && stats_results_,
306  const MHRandomWalkType & mhrandomwalk)
307  : stats_results(std::forward<MHRWStatsResultsTypeInit>(stats_results_)),
308  mhrw_params(mhrandomwalk.mhrwParams()),
309  acceptance_ratio(mhrandomwalk.hasAcceptanceRatio() ?
310  mhrandomwalk.acceptanceRatio() :
311  std::numeric_limits<double>::quiet_NaN())
312  {
313  }
314 
318  MHRWStatsResultsType stats_results;
319 
321  MHRWParamsType mhrw_params;
322 
325 
326 
329 };
330 
331 
332 
333 
343 template<typename MHRandomWalkTaskCData,
344  typename Rng = std::mt19937>
345 struct TOMOGRAPHER_EXPORT MHRandomWalkTask
346 {
348  typedef typename MHRandomWalkTaskCData::IterCountIntType IterCountIntType;
350  typedef typename MHRandomWalkTaskCData::MHWalkerParams MHWalkerParams;
351 
354 
359  typedef MHRandomWalkTaskResult<typename MHRandomWalkTaskCData::MHRWStatsResultsType,
360  IterCountIntType, MHWalkerParams> ResultType;
361 
366 
367 private:
369  typename Rng::result_type _seed;
370 
378  ResultType * result;
379 
380 
381 public:
382 
388  template<typename LoggerType>
389  MHRandomWalkTask(typename Rng::result_type inputseed, const MHRandomWalkTaskCData * /*pcdata*/,
390  LoggerType & logger)
391  : _seed(inputseed), result(NULL)
392  {
393  logger.longdebug("MHRandomWalkTask", [&](std::ostream & stream) { stream << "() inputseed=" << inputseed; });
394  }
395 
397  {
398  if (result != NULL) {
399  delete result;
400  }
401  }
402 
403 private:
404 
405  template<typename LoggerType, typename TaskMgrIface>
406  struct RunInnerCallable
407  {
408  const MHRandomWalkTaskCData * pcdata;
409  Rng & rng;
410  LoggerType & baselogger;
411  TaskMgrIface * tmgriface;
412 
413  ResultType ** ppresult;
414 
415  RunInnerCallable(const MHRandomWalkTaskCData * pcdata_, Rng & rng_, LoggerType & logger_,
416  TaskMgrIface * tmgriface_, ResultType ** ppresult_)
417  : pcdata(pcdata_), rng(rng_), baselogger(logger_), tmgriface(tmgriface_), ppresult(ppresult_)
418  {
419  }
420  ~RunInnerCallable() {
421  }
422 
423  template<typename MHWalkerType, typename MHRWStatsCollectorType, typename MHRWControllerType>
424  inline void operator()(MHWalkerType & mhwalker, MHRWStatsCollectorType & stats,
425  MHRWControllerType & controller)
426  {
427  // here we actually run the stuff
428 
429  auto logger = Logger::makeLocalLogger("Tomographer::MHRWTasks::MHRandomWalkTask::run()/run", baselogger);
430 
431  // our own "stats collector" which checks if we need to send a status report back
432  typedef PredStatusReportMHRWStatsCollector<MHRWParamsType> OurStatusReportCheck;
433  OurStatusReportCheck statreportcheck(
434  // predicate
435  [&]() { return this->tmgriface->statusReportRequested(); },
436  // send-status-function
437  [&](StatusReportType report) { this->tmgriface->submitStatusReport(std::move(report)); }
438  );
439 
441  OurStatsCollectors;
442  OurStatsCollectors ourstatscollectors(stats, statreportcheck);
443 
444  logger.longdebug("About to creat MHRandomWalk instance");
445 
447  MHRandomWalkType;
448 
449  MHRandomWalkType rwalk(
450  // MH random walk parameters
451  pcdata->mhrw_params,
452  // the MHWalker
453  mhwalker,
454  // our stats collectors
455  ourstatscollectors,
456  // the random walk controller
457  controller,
458  // a random number generator
459  rng,
460  // and a logger
461  baselogger
462  );
463 
464  logger.longdebug("MHRandomWalk object created, running...");
465 
466  rwalk.run();
467 
468  logger.longdebug("MHRandomWalk run finished.");
469 
470  *ppresult = new ResultType(stats.stealResult(), rwalk);
471  }
472 
473  template<typename MHWalkerType, typename MHRWStatsCollectorType>
474  inline void operator()(MHWalkerType & mhwalker, MHRWStatsCollectorType & stats)
475  {
476  MHRWNoController ctrl;
477  operator()<MHWalkerType, MHRWStatsCollectorType, MHRWNoController>(mhwalker, stats, ctrl) ;
478  }
479  };
480 
481 
482 public:
492  template<typename LoggerType, typename TaskManagerIface>
493  inline void run(const MHRandomWalkTaskCData * pcdata, LoggerType & baselogger, TaskManagerIface * tmgriface)
494  {
495  auto logger = Logger::makeLocalLogger("Tomographer::MHRWTasks::MHRandomWalkTask::run()", baselogger) ;
496 
497  Rng rng(_seed); // seeded random number generator
498 
499  RunInnerCallable<LoggerType, TaskManagerIface> run_object(pcdata, rng, baselogger, tmgriface, &result);
500 
501  pcdata->setupRandomWalkAndRun(rng, baselogger, run_object);
502  }
503 
504  inline ResultType getResult() const
505  {
506  return *result;
507  }
508 
509  inline ResultType stealResult()
510  {
511  return std::move(*result);
512  }
513 };
514 
515 
516 
517 } // namespace MHRWTasks
518 
519 
520 
521 } // namespace Tomographer
522 
523 
524 
525 #endif
A Metropolis-Hastings Random Walk.
Definition: mhrw.h:602
Utilities for formatting strings.
MHRWParams< MHWalkerParams, IterCountIntType > MHRWParamsType
Type to stores the parameters of the random walk.
Definition: mhrwtasks.h:353
MHRWStatsResultsType_ MHRWStatsResultsType
The type which stores the results from the statistics carried out during the random walk...
Definition: mhrwtasks.h:264
MHRandomWalkTaskCData::MHWalkerParams MHWalkerParams
The type used to describe a step size (see MHRWParams)
Definition: mhrwtasks.h:350
Base namespace for the Tomographer project.
Definition: densellh.h:45
CDataBase(MHRWParamsType &&p, RngSeedType base_seed_)
Constructor.
Definition: mhrwtasks.h:161
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:158
RngSeedType getTaskInput(TaskNoCountIntType k) const
Returns a random seed to seed the random number generator with for run number k.
Definition: mhrwtasks.h:202
STL namespace.
void run(const MHRandomWalkTaskCData *pcdata, LoggerType &baselogger, TaskManagerIface *tmgriface)
Run this task.
Definition: mhrwtasks.h:493
MHRWStatsResultsType stats_results
The result(s) coming from stats collecting (may be processed, see MHRandomWalkTaskCData Interface) ...
Definition: mhrwtasks.h:318
CountIntType n_therm
Number of thermalization sweeps.
Definition: mhrw.h:154
double acceptance_ratio
The acceptance ratio of the Metropolis-Hastings random walk.
Definition: mhrwtasks.h:324
A "stats collector" which produces status reports whenever a predicate evaluates to true...
Random Walk task, collecting statistics.
Definition: mhrwtasks.h:345
void printBasicCDataMHRWInfo(std::ostream &str) const
Get some human-readable info about the random walk as a string.
Definition: mhrwtasks.h:213
STL class.
Data needed to be accessible to the working code.
Definition: mhrwtasks.h:133
MHRWParamsType mhrw_params
The parameters of the random walk (see MHRWParams<MHWalkerParams,IterCountIntType>) ...
Definition: mhrwtasks.h:321
CountIntType n_sweep
The number of individual updates to collect together in a "sweep".
Definition: mhrw.h:150
MHRandomWalkTask(typename Rng::result_type inputseed, const MHRandomWalkTaskCData *, LoggerType &logger)
Constructs the MHRandomWalkTask.
Definition: mhrwtasks.h:389
RngSeedType_ RngSeedType
Type used to specify the seed of the random number generator.
Definition: mhrwtasks.h:144
LocalLogger< BaseLoggerType > makeLocalLogger(std::string origin_fn_name, BaseLoggerType &baselogger)
Create a local logger.
Definition: loggers.h:1960
A MHRWController Interface which combines several independent random walk controllers.
Definition: mhrw.h:357
T str(T... args)
const RngSeedType base_seed
A base random seed from which each run seed will be derived.
Definition: mhrwtasks.h:190
MHRWParams< MHWalkerParams, IterCountIntType > MHRWParamsType
The type to use to store the parameters of the random walk.
Definition: mhrwtasks.h:268
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:151
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
Status Report structure representing the status of a MHRandomWalk.
Definition: mhrw.h:1099
std::string getBasicCDataMHRWInfo() const
Get some human-readable info about the random walk as a string, see printBasicCDataMHRWInfo() ...
Definition: mhrwtasks.h:224
Some common definitions for multiprocessing interfaces.
MHRandomWalkTaskResult(MHRWStatsResultsTypeInit &&stats_results_, MHRWParamsTypeInit &&mhrw_params_, double acceptance_ratio_)
Construct an empty task result.
Definition: mhrwtasks.h:288
MHRandomWalkTaskResult(MHRWStatsResultsTypeInit &&stats_results_, const MHRandomWalkType &mhrandomwalk)
Constructor with mhrw_params initialized from a random walk instance.
Definition: mhrwtasks.h:305
Definitions for MHRWStatsCollector Interface&#39;s.
IterCountIntType_ IterCountIntType
Type used to count the number of iterations.
Definition: mhrwtasks.h:136
Routines for performing a Metropolis-Hastings random walk.
const MHRWParamsType mhrw_params
Parameters of the random walk.
Definition: mhrwtasks.h:174
T setprecision(T... args)
MHRandomWalkTaskCData::IterCountIntType IterCountIntType
The type used to count iterations (see MHRWParams)
Definition: mhrwtasks.h:348
MHWalkerParams_ MHWalkerParams
Type used to specify the step size.
Definition: mhrwtasks.h:138
STL class.
MHWalkerParams mhwalker_params
The parameters of the mh-walker, typically just the step size of the random walk. ...
Definition: mhrw.h:146
MHRWStatusReport< MHRWParamsType > StatusReportType
Typedef for MHRWStatusReport. This is needed by, e.g. MultiProc::OMP::TaskDispatcher.
Definition: mhrwtasks.h:365
MHRandomWalkTaskResult< typename MHRandomWalkTaskCData::MHRWStatsResultsType, IterCountIntType, MHWalkerParams > ResultType
Result type of a single task run.
Definition: mhrwtasks.h:360
A simple MHRWStatsCollector interface which combines several stats collectors.