MCKL
Monte Carlo Kernel Library
mcmc.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/algorithm/mcmc.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_ALGORITHM_MCMC_HPP
33 #define MCKL_ALGORITHM_MCMC_HPP
34 
35 #include <mckl/internal/common.hpp>
36 #include <mckl/core/estimator.hpp>
37 #include <mckl/core/sampler.hpp>
38 #include <mckl/random/rng.hpp>
39 
40 namespace mckl {
41 
44 template <typename T, typename U = double>
45 class MCMCEstimator : public Estimator<U, std::size_t, std::size_t, T &, U *>
46 {
47  public:
50 
51  void estimate(std::size_t iter, T &state)
52  {
53  this->eval(iter, this->dim(), state, this->insert_estimate());
54  }
55 }; // class MCMCEstimator
56 
57 template <typename, typename = double>
59 
60 template <typename T, typename U>
62 {
63  public:
64  using eval_type = std::function<std::size_t(std::size_t, T &)>;
66 }; // class SamplerTrait
67 
70 template <typename T, typename U>
71 class MCMCSampler : public Sampler<MCMCSampler<T, U>>
72 {
73  public:
74  using state_type = T;
77 
78  template <typename... Args>
79  explicit MCMCSampler(Args &&... args)
80  : Sampler<MCMCSampler<T, U>>(1)
81  , state_(std::forward<Args>(args)...)
82  , iter_(0)
83  {
84  }
85 
87  std::size_t num_iter() const
88  {
89  return accept_history_.size() == 0 ? 0 :
90  accept_history_.front().size();
91  }
92 
94  void reserve(std::size_t n)
95  {
97  for (auto &a : accept_history_) {
98  a.reserve(num_iter() + n);
99  }
100  }
101 
104  void reset()
105  {
106  Sampler<MCMCSampler<T, U>>::reset();
107  clear();
108  }
109 
111  void clear()
112  {
114  iter_ = 0;
115  accept_history_.clear();
116  }
117 
119  template <typename Eval>
120  std::size_t mutation(Eval &&eval,
121  std::enable_if_t<!std::is_integral<Eval>::value> * = nullptr)
122  {
123  return this->eval(0, std::forward<Eval>(eval));
124  }
125 
126  eval_type &mutation(std::size_t k) { return this->eval(0, k); }
127 
128  const eval_type &mutation(std::size_t k) const { return this->eval(0, k); }
129 
130  template <typename Estimator>
131  std::size_t estimator(Estimator &&estimator)
132  {
133  return Sampler<MCMCSampler<T, U>>::estimator(
134  0, std::forward<Estimator>(estimator));
135  }
136 
137  estimator_type &estimator(std::size_t k)
138  {
139  return Sampler<MCMCSampler<T, U>>::estimator(0, k);
140  }
141 
142  const estimator_type &estimator(std::size_t k) const
143  {
144  return Sampler<MCMCSampler<T, U>>::estimator(0, k);
145  }
146 
148  void iterate(std::size_t n = 1)
149  {
150  if (n > 1) {
151  reserve(n);
152  }
153  for (std::size_t i = 0; i != n; ++i) {
154  do_iterate();
155  }
156  }
157 
159  state_type &state() { return state_; }
160 
162  const state_type &state() const { return state_; }
163 
165  template <typename OutputIter>
166  OutputIter read_accept_history(std::size_t i, OutputIter first) const
167  {
168  runtime_assert(i < accept_history_.size(),
169  "**MCMCSampler::read_accept_history** index out of range");
170 
171  return std::copy(
172  accept_history_[i].begin(), accept_history_[i].end(), first);
173  }
174 
176  template <typename OutputIter>
177  OutputIter read_accept_history(MatrixLayout layout, OutputIter first) const
178  {
179  if (layout == RowMajor) {
180  if (accept_history_.size() > 0) {
181  const std::size_t n = accept_history_.front().size();
182  const std::size_t d = accept_history_.size();
183  for (std::size_t i = 0; i != n; ++i) {
184  for (std::size_t j = 0; j != d; ++j) {
185  *first++ = accept_history_[j][i];
186  }
187  }
188  }
189  } else {
190  for (std::size_t i = 0; i != accept_history_.size(); ++i) {
191  first = read_accept_history(i, first);
192  }
193  }
194 
195  return first;
196  }
197 
198  private:
199  state_type state_;
200  std::size_t iter_;
201  Vector<Vector<std::size_t>> accept_history_;
202 
203  void do_iterate()
204  {
205  accept_history_.resize(this->eval(0).size());
206  for (std::size_t i = 0; i != this->eval(0).size(); ++i) {
207  accept_history_[i].push_back(this->eval(0)[i](iter_, state_));
208  }
209 
210  for (auto &e : Sampler<MCMCSampler<T, U>>::estimator(0)) {
211  e.estimate(iter_, state_);
212  }
213 
214  ++iter_;
215  }
216 }; // class MCMCSampler
217 
218 } // namespace mckl
219 
220 #endif // MCKL_ALGORITHM_MCMC_HPP
std::size_t num_iter() const noexcept
The number of iterations stored in the estimate matrix.
void clear()
Clear all history.
Definition: mcmc.hpp:111
std::function< std::size_t(std::size_t, T &)> eval_type
Definition: mcmc.hpp:64
void reserve(std::size_t n)
Reserve space for additional iterations.
void clear()
Clear the estimate matrix but preserve the dimension.
MCMCSampler(Args &&... args)
Definition: mcmc.hpp:79
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
Definition: memory.hpp:435
Sampler for iterative Monte Carlo algorithms.
Definition: sampler.hpp:46
STL namespace.
const estimator_type & estimator(std::size_t k) const
Definition: mcmc.hpp:142
const eval_type & mutation(std::size_t k) const
Definition: mcmc.hpp:128
typename Sampler< MCMCSampler< T, U > >::eval_type eval_type
Definition: mcmc.hpp:75
estimator_type & estimator(std::size_t k)
Definition: mcmc.hpp:137
iterator end()
Iterator to one pass the lower right corner of the matrix.
Definition: matrix.hpp:178
static constexpr MatrixLayout layout()
The layout of the matrix.
Definition: matrix.hpp:479
state_type & state()
Read and write access to the state object.
Definition: mcmc.hpp:159
MCMC estimator.
Definition: mcmc.hpp:45
size_type size() const
The total number of elements.
Definition: matrix.hpp:494
iterator begin()
Iterator to the upper left corner of the matrix.
Definition: matrix.hpp:169
typename Sampler< MCMCSampler< T, U > >::estimator_type estimator_type
Definition: mcmc.hpp:76
OutputIter read_accept_history(std::size_t i, OutputIter first) const
Read accept count history given mutation step index.
Definition: mcmc.hpp:166
std::size_t num_iter() const
The number of iterations already performed.
Definition: mcmc.hpp:87
U * insert_estimate()
Add space for a new estimate, return a pointer to the new row.
const state_type & state() const
Read only access to the state object.
Definition: mcmc.hpp:162
Definition: mcmc.hpp:40
void reserve(std::size_t n)
Reserve space for a specified number of iterations.
Definition: mcmc.hpp:94
void estimate(std::size_t iter, T &state)
Definition: mcmc.hpp:51
std::size_t mutation(Eval &&eval, std::enable_if_t<!std::is_integral< Eval >::value > *=nullptr)
Add a new evaluation object for the mutation step.
Definition: mcmc.hpp:120
MCMC sampler.
Definition: mcmc.hpp:58
eval_type & mutation(std::size_t k)
Definition: mcmc.hpp:126
Estimator for iterative Monte Carlo algorithms.
Definition: estimator.hpp:45
void reset()
Reset the sampler by clear all history, evaluation objects, and estimators.
Definition: mcmc.hpp:104
std::size_t dim() const noexcept
The dimension of the estimator.
void iterate(std::size_t n=1)
Iterate the sampler.
Definition: mcmc.hpp:148
std::size_t estimator(Estimator &&estimator)
Definition: mcmc.hpp:131
OutputIter read_accept_history(MatrixLayout layout, OutputIter first) const
Read all accept count history into a matrix.
Definition: mcmc.hpp:177
void runtime_assert(bool cond, const char *msg, bool soft=false)
Definition: assert.hpp:65
MatrixLayout
Matrix layout.
Definition: defines.hpp:46