MCKL
Monte Carlo Kernel Library
smc.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/algorithm/smc.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_SMC_HPP
33 #define MCKL_ALGORITHM_SMC_HPP
34 
35 #include <mckl/internal/common.hpp>
37 #include <mckl/core/estimator.hpp>
38 #include <mckl/core/particle.hpp>
39 #include <mckl/core/sampler.hpp>
41 
42 MCKL_PUSH_CLANG_WARNING("-Wpadded")
43 
44 namespace mckl {
45 
48 template <typename T, typename U = double>
50  : public Estimator<U, std::size_t, std::size_t, Particle<T> &, U *>
51 {
52  static_assert(std::is_convertible<U, double>::value,
53  "**SMCEsimator** used with estimate type U not convertible to double");
54 
55  public:
56  SMCEstimator() : layout_(RowMajor), record_only_(false) {}
57 
58  SMCEstimator(std::size_t dim)
59  : Estimator<U, std::size_t, std::size_t, Particle<T> &, U *>(dim)
60  {
61  }
62 
63  template <typename Eval>
64  SMCEstimator(std::size_t dim, Eval &&eval, MatrixLayout layout = RowMajor,
65  bool record_only = false)
66  : Estimator<U, std::size_t, std::size_t, Particle<T> &, U *>(
67  dim, std::forward<Eval>(eval))
68  , layout_(layout)
69  , record_only_(record_only)
70  {
71  }
72 
74  bool record_only() const { return record_only_; }
75 
77  template <typename Eval>
78  void estimate(
79  Eval &&eval, MatrixLayout layout = RowMajor, bool record_only = false)
80  {
82  std::forward<Eval>(eval));
83  layout_ = layout;
84  record_only_ = record_only;
85  }
86 
89  void estimate(std::size_t iter, Particle<T> &particle)
90  {
91  result_.resize(this->dim());
92  if (record_only_) {
93  this->eval(iter, this->dim(), particle, this->insert_estimate());
94  return;
95  }
96 
97  const std::size_t n = static_cast<std::size_t>(particle.size());
98  const std::size_t d = this->dim();
99  u_.resize(n * d);
100  this->eval(iter, d, particle, u_.data());
101 
102  const double *w = particle.weight().data();
103  double *r = rptr(std::is_same<U, double>());
104  internal::size_check<MCKL_BLAS_INT>(n, "SMCEstimator::estimate");
105  internal::size_check<MCKL_BLAS_INT>(d, "SMCEstimator::estimate");
106  if (layout_ == RowMajor) {
107  internal::cblas_dgemv(internal::CblasColMajor,
108  internal::CblasNoTrans, static_cast<MCKL_BLAS_INT>(d),
109  static_cast<MCKL_BLAS_INT>(n), 1.0, r,
110  static_cast<MCKL_BLAS_INT>(d), w, 1, 0.0, result_.data(), 1);
111  } else {
112  internal::cblas_dgemv(internal::CblasColMajor,
113  internal::CblasTrans, static_cast<MCKL_BLAS_INT>(n),
114  static_cast<MCKL_BLAS_INT>(d), 1.0, r,
115  static_cast<MCKL_BLAS_INT>(n), w, 1, 0.0, result_.data(), 1);
116  }
117  this->insert_estimate(result_.data());
118  }
119 
120  private:
121  Vector<U> u_;
122  Vector<double> r_;
123  Vector<double> result_;
124  MatrixLayout layout_;
125  bool record_only_;
126 
127  double *rptr(std::true_type) { return u_.data(); }
128 
129  double *rptr(std::false_type)
130  {
131  r_.resize(u_.size());
132  std::copy(u_.begin(), u_.end(), r_.begin());
133 
134  return r_.data();
135  }
136 }; // class SMCEstimator
137 
138 template <typename, typename = double>
140 
141 template <typename T, typename U>
143 {
144  public:
145  using eval_type = std::function<void(std::size_t, Particle<T> &)>;
147 }; // class SamplerTrait
148 
151 template <typename T, typename U>
152 class SMCSampler : public Sampler<SMCSampler<T, U>>
153 {
154  public:
155  using state_type = T;
159 
160  SMCSampler() : iter_(0), resample_threshold_(resample_threshold_never()) {}
161 
166  template <typename... Args>
167  explicit SMCSampler(size_type N, Args &&... args)
168  : Sampler<SMCSampler<T, U>>(3)
169  , particle_(N, std::forward<Args>(args)...)
170  , iter_(0)
171  , resample_threshold_(resample_threshold_never())
172  {
173  }
174 
177  {
178  SMCSampler<T, U> sampler(*this);
179  sampler.particle().rng_set().reset();
180  sampler.particle().rng().seed(
181  Seed<typename Particle<T>::rng_type>::instance().get());
182 
183  return sampler;
184  }
185 
187  size_type size() const { return particle_.size(); }
188 
190  std::size_t num_iter() const { return size_history_.size(); }
191 
193  void reserve(std::size_t n)
194  {
195  Sampler<SMCSampler<T, U>>::reserve(n);
196  n += num_iter();
197  size_history_.reserve(n);
198  ess_history_.reserve(n);
199  }
200 
203  void reset()
204  {
205  Sampler<SMCSampler<T, U>>::reset();
206  clear();
207  }
208 
210  void clear()
211  {
212  Sampler<SMCSampler<T, U>>::clear();
213  iter_ = 0;
214  size_history_.clear();
215  ess_history_.clear();
216  }
217 
219  double resample_threshold() const { return resample_threshold_; }
220 
222  void resample_threshold(double threshold)
223  {
224  resample_threshold_ = threshold;
225  }
226 
229  static double resample_threshold_never() { return -const_inf<double>(); }
230 
233  static double resample_threshold_always() { return const_inf<double>(); }
234 
236  template <typename Eval>
237  std::size_t selection(Eval &&eval,
238  std::enable_if_t<!std::is_integral<Eval>::value> * = nullptr)
239  {
240  return this->eval(0, std::forward<Eval>(eval));
241  }
242 
243  eval_type &selection(std::size_t k) { return this->eval(0, k); }
244 
245  const eval_type &selection(std::size_t k) const
246  {
247  return this->eval(0, k);
248  }
249 
251  template <typename Eval>
252  std::size_t resample(Eval &&eval,
253  std::enable_if_t<!std::is_integral<Eval>::value> * = nullptr)
254  {
255  return this->eval(1, std::forward<Eval>(eval));
256  }
257 
260  std::size_t resample(ResampleScheme scheme)
261  {
262  switch (scheme) {
263  case Multinomial:
264  return resample(ResampleEval<T>(ResampleMultinomial()));
265  case Residual:
266  return resample(ResampleEval<T>(ResampleResidual()));
267  case Stratified:
268  return resample(ResampleEval<T>(ResampleStratified()));
269  case Systematic:
270  return resample(ResampleEval<T>(ResampleSystematic()));
271  case ResidualStratified:
272  return resample(ResampleEval<T>(ResampleResidualStratified()));
273  case ResidualSystematic:
274  return resample(ResampleEval<T>(ResampleResidualSystematic()));
275  }
276 
277  runtime_assert(false,
278  "**SMCSampler::resample** used with unknown resample "
279  "scheme");
280 
281  return resample(ResampleEval<T>(ResampleMultinomial()));
282  }
283 
284  eval_type &resample(std::size_t k) { return this->eval(1, k); }
285 
286  const eval_type &resample(std::size_t k) const { return this->eval(1, k); }
287 
289  template <typename Eval>
290  std::size_t mutation(Eval &&eval,
291  std::enable_if_t<!std::is_integral<Eval>::value> * = nullptr)
292  {
293  return this->eval(2, std::forward<Eval>(eval));
294  }
295 
296  eval_type &mutation(std::size_t k) { return this->eval(2, k); }
297 
298  const eval_type &mutation(std::size_t k) const { return this->eval(2, k); }
299 
300  template <typename Estimator>
301  std::size_t selection_estimator(Estimator &&estimator,
302  std::enable_if_t<!std::is_integral<Estimator>::value> * = nullptr)
303  {
304  return this->estimator(0, std::forward<Estimator>(estimator));
305  }
306 
308  {
309  return this->estimator(0, k);
310  }
311 
312  const estimator_type &selection_estimator(std::size_t k) const
313  {
314  return this->estimator(0, k);
315  }
316 
317  template <typename Estimator>
318  std::size_t resample_estimator(Estimator &&estimator,
319  std::enable_if_t<!std::is_integral<Estimator>::value> * = nullptr)
320  {
321  return this->estimator(1, std::forward<Estimator>(estimator));
322  }
323 
325  {
326  return this->estimator(1, k);
327  }
328 
329  const estimator_type &resample_estimator(std::size_t k) const
330  {
331  return this->estimator(1, k);
332  }
333 
334  template <typename Estimator>
335  std::size_t mutation_estimator(Estimator &&estimator,
336  std::enable_if_t<!std::is_integral<Estimator>::value> * = nullptr)
337  {
338  return this->estimator(2, std::forward<Estimator>(estimator));
339  }
340 
342  {
343  return this->estimator(2, k);
344  }
345 
346  const estimator_type &mutation_estimator(std::size_t k) const
347  {
348  return this->estimator(2, k);
349  }
350 
352  void iterate(std::size_t n = 1)
353  {
354  if (n > 1) {
355  reserve(n);
356  }
357  for (std::size_t i = 0; i != n; ++i) {
358  do_iterate();
359  }
360  }
361 
363  Particle<T> &particle() { return particle_; }
364 
366  const Particle<T> &particle() const { return particle_; }
367 
369  template <typename OutputIter>
370  OutputIter read_size_history(OutputIter first) const
371  {
372  return std::copy(size_history_.begin(), size_history_.end(), first);
373  }
374 
376  template <typename OutputIter>
377  OutputIter read_ess_history(OutputIter first) const
378  {
379  return std::copy(ess_history_.begin(), ess_history_.end(), first);
380  }
381 
382  private:
383  Particle<T> particle_;
384  std::size_t iter_;
385  double resample_threshold_;
386  Vector<size_type> size_history_;
387  Vector<double> ess_history_;
388 
389  void do_iterate()
390  {
391  do_eval(0);
392  do_estimate(0);
393 
394  size_history_.push_back(size());
395  ess_history_.push_back(particle_.weight().ess());
396 
397  if (ess_history_.back() < size() * resample_threshold_) {
398  do_eval(1);
399  }
400  do_estimate(1);
401 
402  do_eval(2);
403  do_estimate(2);
404 
405  ++iter_;
406  }
407 
408  void do_eval(std::size_t step)
409  {
410  for (auto &eval : this->eval(step)) {
411  eval(iter_, particle_);
412  }
413  }
414 
415  void do_estimate(std::size_t step)
416  {
417  for (auto &est : this->estimator(step)) {
418  est.estimate(iter_, particle_);
419  }
420  }
421 }; // class SMCSampler
422 
423 } // namespace mckl
424 
426 
427 #endif // MCKL_ALGORITHM_SMC_HPP
ResampleAlgorithm< U01SequenceSystematic, true > ResampleResidualSystematic
Residual systematic resampling.
Definition: resample.hpp:593
std::size_t num_iter() const
The number of iterations already performed.
Definition: smc.hpp:190
double resample_threshold() const
Get resampling threshold.
Definition: smc.hpp:219
constexpr ResampleScheme ResidualStratified
Definition: resample.hpp:56
std::size_t selection_estimator(Estimator &&estimator, std::enable_if_t<!std::is_integral< Estimator >::value > *=nullptr)
Definition: smc.hpp:301
std::size_t resample(ResampleScheme scheme)
Add a new evaluation object for the resample step by a built-in resample scheme.
Definition: smc.hpp:260
void iterate(std::size_t n=1)
Iterate the sampler.
Definition: smc.hpp:352
const estimator_type & selection_estimator(std::size_t k) const
Definition: smc.hpp:312
constexpr ResampleScheme Residual
Definition: resample.hpp:55
Particle< T > & particle()
Read and write access to the Particle<T> object.
Definition: smc.hpp:363
const eval_type & mutation(std::size_t k) const
Definition: smc.hpp:298
ResampleAlgorithm< U01SequenceSorted, false > ResampleMultinomial
Multinomial resampling.
Definition: resample.hpp:571
#define MCKL_PUSH_CLANG_WARNING(warning)
Definition: compiler.h:63
size_type size() const
this->particle().size()
Definition: smc.hpp:187
SMCEstimator(std::size_t dim)
Definition: smc.hpp:58
ResampleAlgorithm< U01SequenceSorted, true > ResampleResidual
Residual resampling.
Definition: resample.hpp:583
ResampleScheme
Resampling schemes.
Definition: resample.hpp:43
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.
bool record_only() const
If this is a record only estimator.
Definition: smc.hpp:74
ResampleAlgorithm< U01SequenceStratified, false > ResampleStratified
Stratified resampling.
Definition: resample.hpp:575
eval_type & selection(std::size_t k)
Definition: smc.hpp:243
std::function< void(std::size_t, Particle< T > &)> eval_type
Definition: smc.hpp:145
constexpr ResampleScheme Systematic
Definition: resample.hpp:54
void estimate(std::size_t iter, Particle< T > &particle)
Perform the evaluation given the iteration number and the particle system.
Definition: smc.hpp:89
estimator_type & mutation_estimator(std::size_t k)
Definition: smc.hpp:341
estimator_type & selection_estimator(std::size_t k)
Definition: smc.hpp:307
std::size_t selection(Eval &&eval, std::enable_if_t<!std::is_integral< Eval >::value > *=nullptr)
Add a new evaluation object for the selection step.
Definition: smc.hpp:237
weight_type & weight()
Read and write access to the weight collection object.
Definition: particle.hpp:340
typename rng_set_type::rng_type rng_type
Definition: particle.hpp:286
ResampleAlgorithm< U01SequenceStratified, true > ResampleResidualStratified
Residual stratified resampling.
Definition: resample.hpp:588
const eval_type & selection(std::size_t k) const
Definition: smc.hpp:245
OutputIter read_ess_history(OutputIter first) const
Read the history of the values of ESS.
Definition: smc.hpp:377
void reserve(std::size_t n)
Reserve space for a specified number of iterations.
Definition: smc.hpp:193
typename Sampler< SMCSampler< T, U > >::estimator_type estimator_type
Definition: smc.hpp:158
const estimator_type & resample_estimator(std::size_t k) const
Definition: smc.hpp:329
constexpr ResampleScheme ResidualSystematic
Definition: resample.hpp:58
SMCSampler<T>::eval_type subtype.
Definition: resample.hpp:471
const estimator_type & mutation_estimator(std::size_t k) const
Definition: smc.hpp:346
constexpr ResampleScheme Stratified
Definition: resample.hpp:53
const Particle< T > & particle() const
Read only access to the Particle<T> object.
Definition: smc.hpp:366
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: smc.hpp:290
SMCSampler(size_type N, Args &&... args)
Construct a SMC sampler.
Definition: smc.hpp:167
const eval_type & resample(std::size_t k) const
Definition: smc.hpp:286
SMCSampler< T, U > clone() const
Clone the SMC sampler except the RNG engines.
Definition: smc.hpp:176
eval_type & mutation(std::size_t k)
Definition: smc.hpp:296
size_type size() const
The number of particles.
Definition: particle.hpp:318
SizeType< T > size_type
Definition: particle.hpp:282
Definition: mcmc.hpp:40
void reset()
Reset the sampler by clear all history, evaluation objects, and estimators.
Definition: smc.hpp:203
#define MCKL_POP_CLANG_WARNING
Definition: compiler.h:66
eval_type & resample(std::size_t k)
Definition: smc.hpp:284
std::size_t resample(Eval &&eval, std::enable_if_t<!std::is_integral< Eval >::value > *=nullptr)
Add a new evaluation object for the selection step.
Definition: smc.hpp:252
typename Sampler< SMCSampler< T, U > >::eval_type eval_type
Definition: smc.hpp:157
void estimate(Eval &&eval, MatrixLayout layout=RowMajor, bool record_only=false)
Set a new evaluation object.
Definition: smc.hpp:78
typename Particle< T >::size_type size_type
Definition: smc.hpp:156
constexpr MatrixLayout RowMajor
Definition: defines.hpp:47
SMC estimator.
Definition: smc.hpp:49
ResampleAlgorithm< U01SequenceSystematic, false > ResampleSystematic
Systematic resampling.
Definition: resample.hpp:579
Estimator for iterative Monte Carlo algorithms.
Definition: estimator.hpp:45
estimator_type & resample_estimator(std::size_t k)
Definition: smc.hpp:324
Particle system.
Definition: particle.hpp:45
OutputIter read_size_history(OutputIter first) const
Read history the sampler sizes.
Definition: smc.hpp:370
std::size_t resample_estimator(Estimator &&estimator, std::enable_if_t<!std::is_integral< Estimator >::value > *=nullptr)
Definition: smc.hpp:318
SMC sampler.
Definition: smc.hpp:139
SMCEstimator(std::size_t dim, Eval &&eval, MatrixLayout layout=RowMajor, bool record_only=false)
Definition: smc.hpp:64
static double resample_threshold_never()
Special value of resampling threshold that indicates no resampling will be ever performed.
Definition: smc.hpp:229
RNG default seed generator.
Definition: seed.hpp:339
void clear()
Clear all history.
Definition: smc.hpp:210
void runtime_assert(bool cond, const char *msg, bool soft=false)
Definition: assert.hpp:65
MatrixLayout
Matrix layout.
Definition: defines.hpp:46
void resample_threshold(double threshold)
Set resampling threshold.
Definition: smc.hpp:222
constexpr ResampleScheme Multinomial
Definition: resample.hpp:52
std::size_t mutation_estimator(Estimator &&estimator, std::enable_if_t<!std::is_integral< Estimator >::value > *=nullptr)
Definition: smc.hpp:335
static double resample_threshold_always()
Special value of resampling threshold that indicates resampling will always be performed.
Definition: smc.hpp:233