Tomographer  v5.4
Tomographer C++ Framework Documentation
mhrwstepsizecontroller.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_MHRWSTEPSIZECONTROLLER_H
29 #define _TOMOGRAPHER_MHRWSTEPSIZECONTROLLER_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>
47 
48 
56 namespace Tomographer {
57 
58 
59 
68 template<typename MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
69  typename BaseLoggerType_ = Logger::VacuumLogger,
70  typename StepRealType_ = double,
71  typename IterCountIntType_ = int>
72 class TOMOGRAPHER_EXPORT MHRWStepSizeController
74  // we will be our own MHRWAcceptanceRatioBasedParamsAdjusterType
75  MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
76  BaseLoggerType_, StepRealType_, IterCountIntType_>,
77  // other params
78  MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
79  BaseLoggerType_,
80  IterCountIntType_
81  >
82 {
83 public:
85  // we will be our own MHRWAcceptanceRatioBasedParamsAdjusterType
86  MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
87  BaseLoggerType_, StepRealType_, IterCountIntType_>,
88  // other params
89  MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
90  BaseLoggerType_,
91  IterCountIntType_
92  > Base;
93 
94  using Base::AdjustmentStrategy;
95 
96  typedef MHRWMovingAverageAcceptanceRatioStatsCollectorType_
97  MHRWMovingAverageAcceptanceRatioStatsCollectorType;
98  typedef BaseLoggerType_ BaseLoggerType;
99  typedef StepRealType_ StepRealType;
100  typedef IterCountIntType_ IterCountIntType;
101 
102 private:
103 
104  StepRealType last_set_step_size;
105 
106  StepRealType orig_step_times_sweep;
107 
109 
110 public:
112  const MHRWMovingAverageAcceptanceRatioStatsCollectorType & accept_ratio_stats_collector_,
113  BaseLoggerType & baselogger_,
114  double desired_accept_ratio_min_ =
115  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMin,
116  double desired_accept_ratio_max_ =
117  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMax,
118  double acceptable_accept_ratio_min_ =
119  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMin,
120  double acceptable_accept_ratio_max_ =
121  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMax,
122  double ensure_n_therm_fixed_params_fraction_ =
123  MHRWAcceptRatioWalkerParamsControllerDefaults::EnsureNThermFixedParamsFraction
124  )
125  : Base(accept_ratio_stats_collector_,
126  baselogger_,
127  *this,
128  desired_accept_ratio_min_,
129  desired_accept_ratio_max_,
130  acceptable_accept_ratio_min_,
131  acceptable_accept_ratio_max_,
132  ensure_n_therm_fixed_params_fraction_),
133  last_set_step_size(std::numeric_limits<StepRealType>::quiet_NaN()),
134  orig_step_times_sweep(0),
135  llogger("Tomographer::MHRWStepSizeController", baselogger_)
136  {
137  }
138 
139 
140  // callbacks for MHRWAcceptanceRatioBasedParamsAdjusterType:
141 
142  template<typename MHRWParamsType, typename MHWalker, typename MHRandomWalkType>
143  inline void initParams(MHRWParamsType & params, const MHWalker & , const MHRandomWalkType & )
144  {
145  auto logger = llogger.subLogger(TOMO_ORIGIN) ;
146 
147  if (std::isfinite(params.mhwalker_params.step_size) &&
148  params.mhwalker_params.step_size > 0) {
149  // valid step size
150  orig_step_times_sweep = params.n_sweep * params.mhwalker_params.step_size;
151  } else {
152  // invalid step size
153  const StepRealType default_start_step_size = StepRealType(0.01);
154  logger.debug([&](std::ostream & stream) {
155  stream << "Invalid step_size = " << params.mhwalker_params.step_size
156  << ", set default of = " << default_start_step_size;
157  });
158  params.mhwalker_params.step_size = default_start_step_size;
159  params.n_sweep = (typename MHRWParamsType::CountIntType)(StepRealType(1)/default_start_step_size) + 1;
160  orig_step_times_sweep = 1;
161  }
162  }
163 
164  template<typename MHRWParamsType, typename MeType, typename MHWalker, typename MHRandomWalkType>
165  inline void adjustParamsForAcceptRatio(MHRWParamsType & params, double accept_ratio, const MeType & /* self */,
166  const MHWalker & /*mhwalker*/, IterCountIntType iter_k,
167  const MHRandomWalkType & /*mhrw*/)
168  {
169  auto logger = llogger.subLogger(TOMO_ORIGIN) ;
170 
171  // new step size -- guess a slight increase or decrease depending on too high or too low
172 
173  StepRealType new_step_size = params.mhwalker_params.step_size;
174 
175  const auto desired_accept_ratio_min = Base::desiredAcceptRatioMin();
176  const auto desired_accept_ratio_max = Base::desiredAcceptRatioMax();
177  //const auto acceptable_accept_ratio_min = Base::acceptableAcceptRatioMin();
178  //const auto acceptable_accept_ratio_max = Base::acceptableAcceptRatioMax();
179 
180  // accept ratio too high -- increase step size
181  if (accept_ratio >= 2*desired_accept_ratio_max) {
182  new_step_size *= StepRealType(1.5);
183  } else if (accept_ratio >= StepRealType(1.3)*desired_accept_ratio_max) {
184  new_step_size *= StepRealType(1.2);
185  } else if (accept_ratio >= desired_accept_ratio_max) {
186  new_step_size *= StepRealType(1.05);
187  } else if (accept_ratio <= StepRealType(0.5)*desired_accept_ratio_min) {
188  new_step_size *= StepRealType(0.5);
189  } else if (accept_ratio <= StepRealType(0.75)*desired_accept_ratio_min) {
190  new_step_size *= StepRealType(0.8);
191  } else {// if (accept_ratio <= desired_accept_ratio_min
192  new_step_size *= StepRealType(0.95);
193  }
194 
195  logger.longdebug([&](std::ostream & stream) {
196  stream << "Corrected step_size to " << new_step_size;
197  });
198 
199  // only allow the new step size to be within a certain range of the previous one
200  const auto cur_step_size = params.mhwalker_params.step_size;
201  if (new_step_size < StepRealType(0.7)*cur_step_size) {
202  new_step_size = StepRealType(0.7)*cur_step_size;
203  }
204  if (new_step_size > StepRealType(1.5)*cur_step_size) {
205  new_step_size = StepRealType(1.5)*cur_step_size;
206  }
207 
208  params.mhwalker_params.step_size = new_step_size;
209 
210  // store last set step size
211  last_set_step_size = new_step_size;
212 
213  // adapt sweep size
214  params.n_sweep = (typename MHRWParamsType::CountIntType)(orig_step_times_sweep / new_step_size + 1);
215 
216  // ensure there are enough n_therm sweeps left
217  const typename MHRWParamsType::CountIntType n_therm_min =
218  (typename MHRWParamsType::CountIntType)(
219  (iter_k/params.n_sweep) + 1 + (Base::ensureNThermFixedParamsFraction() * Base::originalNTherm())
220  );
221  if (params.n_therm < n_therm_min) {
222  logger.longdebug([&](std::ostream & stream) {
223  stream << "There aren't enough thermalization sweeps. I'm setting n_therm = " << n_therm_min;
224  });
225  params.n_therm = n_therm_min;
226  }
227 
228  logger.longdebug([&](std::ostream & stream) {
229  stream << "New params = " << params;
230  });
231  }
232 
233  inline StepRealType getLastSetStepSize() const { return last_set_step_size; }
234 
235 };
236 
237 
238 template<typename MHRWParamsType,
239  typename MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
240  typename BaseLoggerType_
241  >
242 inline
243 MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
244  BaseLoggerType_,
245  typename MHRWParamsType::MHWalkerParams::StepRealType,
246  typename MHRWParamsType::CountIntType>
247 mkMHRWStepSizeController(
248  const MHRWMovingAverageAcceptanceRatioStatsCollectorType_ & accept_ratio_stats_collector_,
249  BaseLoggerType_ & baselogger_,
250  double desired_accept_ratio_min_ =
251  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMin,
252  double desired_accept_ratio_max_ =
253  MHRWAcceptRatioWalkerParamsControllerDefaults::DesiredAcceptanceRatioMax,
254  double acceptable_accept_ratio_min_ =
255  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMin,
256  double acceptable_accept_ratio_max_ =
257  MHRWAcceptRatioWalkerParamsControllerDefaults::AcceptableAcceptanceRatioMax,
258  double ensure_n_therm_fixed_params_fraction_ =
259  MHRWAcceptRatioWalkerParamsControllerDefaults::EnsureNThermFixedParamsFraction
260  )
261 {
262  return MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType_,
263  BaseLoggerType_,
264  typename MHRWParamsType::MHWalkerParams::StepRealType,
265  typename MHRWParamsType::CountIntType>(
266  accept_ratio_stats_collector_,
267  baselogger_,
268  desired_accept_ratio_min_,
269  desired_accept_ratio_max_,
270  acceptable_accept_ratio_min_,
271  acceptable_accept_ratio_max_,
272  ensure_n_therm_fixed_params_fraction_
273  );
274 }
275 
276 
277 
278 
279 
280 
281 namespace Tools {
282 
283 template<typename MHRWMovingAverageAcceptanceRatioStatsCollectorType,
284  typename BaseLoggerType,
285  typename StepRealType,
286  typename IterCountIntType>
287 struct TOMOGRAPHER_EXPORT
288 StatusProvider<MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType,
289  BaseLoggerType, StepRealType, IterCountIntType> >
290 {
291  typedef MHRWStepSizeController<MHRWMovingAverageAcceptanceRatioStatsCollectorType,
292  BaseLoggerType, StepRealType, IterCountIntType> StatusableObject;
293 
294  static constexpr bool CanProvideStatusLine = true;
295 
296  static inline std::string getStatusLine(const StatusableObject * obj) {
297  double last_step = (double)obj->getLastSetStepSize();
298  if (std::isfinite(last_step)) {
299  return Tomographer::Tools::fmts("step size = %.3g", last_step);
300  } else {
301  return std::string();
302  }
303  }
304 };
305 
306 }
307 
308 
309 
310 } // namespace Tomographer
311 
312 
313 
314 #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
A MHRWController Interface dynamically adjusting the step size to keep a good acceptance ratio...
#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
STL class.
Tools for automatically and dynamically adjusting the step size of the random walk.
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) ...
std::string fmts(const char *fmt,...)
printf- format to a std::string
Definition: fmt.h:128
Template, specializable class to provide status reports for different objects.
Definitions for MHRWStatsCollector Interface&#39;s.
Routines for performing a Metropolis-Hastings random walk.
STL class.
Utilities for logging messages.