Tomographer  v5.3
Tomographer C++ Framework Documentation
mhrwacceptratiowalkerparamscontroller.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_MHRWACCEPTRATIOWALKERPARAMSCONTROLLER_H
29 #define _TOMOGRAPHER_MHRWACCEPTRATIOWALKERPARAMSCONTROLLER_H
30 
31 #include <cstddef>
32 #include <cmath>
33 #include <cstdlib>
34 
35 #include <algorithm> // std::max
36 #include <limits>
37 #include <random>
38 #include <iomanip>
39 
41 #include <tomographer/tools/fmt.h>
44 #include <tomographer/mhrw.h>
46 
47 
48 
56 namespace Tomographer {
57 
58 
61 namespace MHRWAcceptRatioWalkerParamsControllerDefaults {
62 
63 static constexpr double AcceptableAcceptanceRatioMin =
65 static constexpr double AcceptableAcceptanceRatioMax =
67 static constexpr double DesiredAcceptanceRatioMin =
68  (0.9 * AcceptableAcceptanceRatioMin + 0.1 * AcceptableAcceptanceRatioMax);
69 static constexpr double DesiredAcceptanceRatioMax =
70  (0.35 * AcceptableAcceptanceRatioMin + 0.65 * AcceptableAcceptanceRatioMax);
71 static constexpr double EnsureNThermFixedParamsFraction = 0.5;
72 
73 } // MHRWAcceptRatioWalkerParamsControllerDefaults
74 
75 
76 
85 template<typename MHRWAcceptanceRatioBasedParamsAdjusterType_,
86  typename MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
87  typename BaseLoggerType_ = Logger::VacuumLogger,
88  typename IterCountIntType_ = int>
89 class TOMOGRAPHER_EXPORT MHRWAcceptRatioWalkerParamsController
90 {
91 public:
92  enum { AdjustmentStrategy = MHRWControllerAdjustEveryIterationWhileThermalizing };
93 
94  typedef MHRWAcceptanceRatioBasedParamsAdjusterType_ MHRWAcceptanceRatioBasedParamsAdjusterType;
95  typedef MHRWMovingAverageAcceptanceRatioStatsCollectorType_
96  MHRWMovingAverageAcceptanceRatioStatsCollectorType;
97  typedef BaseLoggerType_ BaseLoggerType;
98  typedef IterCountIntType_ IterCountIntType;
99 
100 private:
101  const MHRWMovingAverageAcceptanceRatioStatsCollectorType & accept_ratio_stats_collector;
102 
103  MHRWAcceptanceRatioBasedParamsAdjusterType & params_adjuster;
104 
105  const double desired_accept_ratio_min;
106  const double desired_accept_ratio_max;
107  const double acceptable_accept_ratio_min;
108  const double acceptable_accept_ratio_max;
109 
110  IterCountIntType orig_n_therm;
111  IterCountIntType last_corrected_unacceptable_iter_k;
112 
117  const double ensure_n_therm_fixed_params_fraction;
118 
120 
121 public:
123  const MHRWMovingAverageAcceptanceRatioStatsCollectorType & accept_ratio_stats_collector_,
124  BaseLoggerType & baselogger_,
125  MHRWAcceptanceRatioBasedParamsAdjusterType & params_adjuster_,
126  double desired_accept_ratio_min_ =
127  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMin,
128  double desired_accept_ratio_max_ =
129  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMax,
130  double acceptable_accept_ratio_min_ =
131  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMin,
132  double acceptable_accept_ratio_max_ =
133  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMax,
134  double ensure_n_therm_fixed_params_fraction_ =
135  MHRWAcceptRatioWalkerParamsControllerDefaults::EnsureNThermFixedParamsFraction
136  )
137  : accept_ratio_stats_collector(accept_ratio_stats_collector_),
138  params_adjuster(params_adjuster_),
139  desired_accept_ratio_min(desired_accept_ratio_min_),
140  desired_accept_ratio_max(desired_accept_ratio_max_),
141  acceptable_accept_ratio_min(acceptable_accept_ratio_min_),
142  acceptable_accept_ratio_max(acceptable_accept_ratio_max_),
143  orig_n_therm(0),
144  last_corrected_unacceptable_iter_k(0),
145  ensure_n_therm_fixed_params_fraction(ensure_n_therm_fixed_params_fraction_),
146  llogger("Tomographer::MHRWAcceptRatioWalkerParamsController", baselogger_)
147  {
148  }
149 
150 
151  inline double desiredAcceptRatioMin() const { return desired_accept_ratio_min; }
152  inline double desiredAcceptRatioMax() const { return desired_accept_ratio_max; }
153  inline double acceptableAcceptRatioMin() const { return acceptable_accept_ratio_min; }
154  inline double acceptableAcceptRatioMax() const { return acceptable_accept_ratio_max; }
155 
156  inline double ensureNThermFixedParamsFraction() const { return ensure_n_therm_fixed_params_fraction; }
157 
158  inline IterCountIntType originalNTherm() const { return orig_n_therm; }
159 
160 
161  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
162  inline void init(MHRWParamsType & params, const MHWalker & mhwalker, const MHRandomWalkType & mhrw)
163  {
164  auto logger = llogger.subLogger(TOMO_ORIGIN) ;
165 
166  orig_n_therm = params.n_therm;
167 
168  params_adjuster.initParams(params, mhwalker, mhrw) ;
169  }
170 
171  template<bool IsThermalizing, bool IsAfterSample,
172  typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType,
173  TOMOGRAPHER_ENABLED_IF_TMPL(IsThermalizing)> // Only while thermalizing
174  inline void adjustParams(MHRWParamsType & params, const MHWalker & mhwalker,
175  IterCountIntType iter_k, const MHRandomWalkType & mhrw)
176  {
177  auto logger = llogger.subLogger(TOMO_ORIGIN) ;
178 
179  logger.longdebug([&](std::ostream & stream) {
180  stream << "cur params = " << params << " and accept_ratio = "
181  << accept_ratio_stats_collector.movingAverageAcceptanceRatio();
182  });
183 
184  // only adjust every moving-avg-accept-ratio-buffer-size
185  if ( ! accept_ratio_stats_collector.hasMovingAverageAcceptanceRatio() ||
186  (iter_k % (IterCountIntType)accept_ratio_stats_collector.bufferSize()) != 0 ) {
187  return;
188  }
189 
190  logger.longdebug([&](std::ostream & stream) {
191  stream << "will consider correction. iter_k = " << iter_k
192  << ", last_corrected_unacceptable_iter_k = " << last_corrected_unacceptable_iter_k;
193  });
194 
195  const double accept_ratio = accept_ratio_stats_collector.movingAverageAcceptanceRatio();
196 
197  if (!std::isfinite(accept_ratio) || // no statistics gathered yet -- just continue at this pace
198  (accept_ratio >= desired_accept_ratio_min && // or accept_ratio already in the desired interval
199  accept_ratio <= desired_accept_ratio_max)) {
200  return;
201  }
202 
203  logger.longdebug([&](std::ostream & stream) {
204  stream << "will adjust.";
205  });
206 
207 
208  if (accept_ratio < acceptable_accept_ratio_min || accept_ratio > acceptable_accept_ratio_max) {
209  last_corrected_unacceptable_iter_k = iter_k;
210  }
211 
212  params_adjuster.adjustParamsForAcceptRatio( params, accept_ratio, *this, mhwalker, iter_k, mhrw ) ;
213  }
214 
215  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
216  bool allowDoneThermalization(const MHRWParamsType & params, const MHWalker & /*mhwalker*/,
217  IterCountIntType iter_k, const MHRandomWalkType & /*mhrw*/)
218  {
219  auto logger = llogger.subLogger(TOMO_ORIGIN);
220 
221  const double accept_ratio = accept_ratio_stats_collector.movingAverageAcceptanceRatio();
222  logger.longdebug([&](std::ostream & stream) {
223  stream << "iter_k=" << iter_k << ", accept_ratio=" << accept_ratio;
224  });
225  if (!std::isfinite(accept_ratio) ||
226  accept_ratio < desired_accept_ratio_min || accept_ratio > desired_accept_ratio_max) {
227  logger.longdebug("not allowing, based on accept_ratio=%.4g", accept_ratio);
228  return false;
229  }
230 
231  if ((iter_k - last_corrected_unacceptable_iter_k)
232  < params.n_sweep*(ensure_n_therm_fixed_params_fraction*orig_n_therm)) {
233  logger.longdebug([&](std::ostream & stream) {
234  stream << "not allowing, based on iter_k=" << iter_k
235  << " & last_corrected_unacceptable_iter_k=" << last_corrected_unacceptable_iter_k;
236  }) ;
237  return false; // not passed enough thermalizing iterations since last correction
238  }
239 
240  logger.longdebug("all fine, can return");
241  return true;
242  }
243 
244  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
245  bool allowDoneRuns(const MHRWParamsType & /*params*/, const MHWalker & /*mhwalker*/,
246  IterCountIntType /*iter_k*/, const MHRandomWalkType & /*mhrw*/)
247  {
248  return true; // do whatever you like
249  }
250 
251  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
252  inline void thermalizingDone(MHRWParamsType & /*params*/, const MHWalker & /*mhwalker*/,
253  const MHRandomWalkType & /*mhrw*/) const
254  {
255  }
256 
257  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
258  inline void done(MHRWParamsType & /*params*/, const MHWalker & /*mhwalker*/,
259  const MHRandomWalkType & /*mhrw*/) const
260  {
261  }
262 };
263 
264 
265 
266 
267 
268 } // namespace Tomographer
269 
270 
271 
272 #endif
Utilities for formatting strings.
Basic functionality for a MHRWController Interface to adjust MHWalkerParams based on keeping the acce...
Base namespace for the Tomographer project.
Definition: densellh.h:45
Logger that discards all messages.
Definition: loggers.h:1149
constexpr const double MHRWAcceptanceRatioRecommendedMax
Maximal recommended acceptance ratio.
Definition: mhrw.h:87
constexpr const double MHRWAcceptanceRatioRecommendedMin
Minimal recommended acceptance ratio.
Definition: mhrw.h:85
#define TOMO_ORIGIN
Use this as argument for a Tomographer::Logger::LocalLogger constructor .
Definition: loggers.h:1608
LocalLogger< LocalLogger< BaseLoggerType > > subLogger(std::string new_prefix)
Create a sub-logger.
Definition: loggers.h:1846
Adjustemnts should be performed only while thermalizing, after each individual iteration.
Definition: mhrw.h:258
T isfinite(T... args)
Some C++ utilities, with a tad of C++11 tricks.
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
Definitions for MHRWStatsCollector Interface&#39;s.
Routines for performing a Metropolis-Hastings random walk.
STL class.
Utilities for logging messages.