vSMC  v3.0.0
Scalable Monte Carlo
sampler.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/core/sampler.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, 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 VSMC_CORE_SAMPLER_HPP
33 #define VSMC_CORE_SAMPLER_HPP
34 
35 #include <vsmc/internal/common.hpp>
36 #include <vsmc/core/monitor.hpp>
37 #include <vsmc/core/particle.hpp>
38 
39 #define VSMC_RUNTIME_ASSERT_CORE_SAMPLER_MONITOR_NAME(iter, map, func) \
40  VSMC_RUNTIME_ASSERT( \
41  (iter != map.end()), "**Sampler::" #func "** INVALID MONITOR NAME")
42 
43 #define VSMC_RUNTIME_ASSERT_CORE_SAMPLER_FUNCTOR(func, caller, name) \
44  VSMC_RUNTIME_ASSERT( \
45  (func), "**Sampler::" #caller "** INVALID " #name " OBJECT")
46 
47 namespace vsmc
48 {
49 
53  SamplerInit = 1 << 0,
54  SamplerMove = 1 << 1,
55  SamplerMCMC = 1 << 2
56 }; // enum SamplerStage
57 
59 {
60  return static_cast<SamplerStage>(
61  static_cast<int>(s1) & static_cast<int>(s2));
62 }
63 
65 {
66  return static_cast<SamplerStage>(
67  static_cast<int>(s1) | static_cast<int>(s2));
68 }
69 
71 {
72  return static_cast<SamplerStage>(
73  static_cast<int>(s1) ^ static_cast<int>(s2));
74 }
75 
76 inline constexpr SamplerStage operator~(SamplerStage s)
77 {
78  return static_cast<SamplerStage>(~static_cast<int>(s));
79 }
80 
82 {
83  return s1 = s1 & s2;
84 }
85 
87 {
88  return s1 = s1 | s2;
89 }
90 
92 {
93  return s1 = s1 ^ s2;
94 }
95 
98 template <typename T>
99 class Sampler
100 {
101  public:
103  using eval_type = std::function<std::size_t(std::size_t, Particle<T> &)>;
104 
109  template <typename... Args>
110  explicit Sampler(Args &&... args)
111  : particle_(std::forward<Args>(args)...)
112  , iter_num_(0)
113  , resample_threshold_(resample_threshold_never())
114  {
115  }
116 
119  {
120  Sampler<T> sampler(*this);
121  sampler.particle().rng_set().seed();
122  Seed::instance()(sampler.particle().rng());
123 
124  return sampler;
125  }
126 
128  size_type size() const { return particle_.size(); }
129 
131  void reserve(std::size_t num)
132  {
133  num += iter_num_;
134  size_history_.reserve(num);
135  ess_history_.reserve(num);
136  resampled_history_.reserve(num);
137  status_history_.reserve(num);
138  for (auto &m : monitor_)
139  m.second.reserve(num);
140  }
141 
143  std::size_t iter_size() const { return size_history_.size(); }
144 
146  std::size_t iter_num() const { return iter_num_; }
147 
150  const eval_type &new_eval, SamplerStage stage, bool append = true)
151  {
152  if (!append)
153  eval_.clear();
154  eval_.push_back(std::make_pair(new_eval, stage));
155 
156  return *this;
157  }
158 
162  ResampleScheme scheme, double threshold = resample_threshold_always())
163  {
164  switch (scheme) {
165  case Multinomial:
166  resample_eval_ = ResampleEval<T>(ResampleMultinomial());
167  break;
168  case Residual:
169  resample_eval_ = ResampleEval<T>(ResampleResidual());
170  break;
171  case Stratified:
172  resample_eval_ = ResampleEval<T>(ResampleStratified());
173  break;
174  case Systematic:
175  resample_eval_ = ResampleEval<T>(ResampleSystematic());
176  break;
177  case ResidualStratified:
178  resample_eval_ = ResampleEval<T>(ResampleResidualStratified());
179  break;
180  case ResidualSystematic:
181  resample_eval_ = ResampleEval<T>(ResampleResidualSystematic());
182  break;
183  }
184  resample_threshold(threshold);
185 
186  return *this;
187  }
188 
191  double threshold = resample_threshold_always())
192  {
193  resample_eval_ = res_eval;
194  resample_threshold(threshold);
195 
196  return *this;
197  }
198 
200  double resample_threshold() const { return resample_threshold_; }
201 
203  Sampler<T> &resample_threshold(double threshold)
204  {
205  resample_threshold_ = threshold;
206  return *this;
207  }
208 
211  static double resample_threshold_never()
212  {
213  return -std::numeric_limits<double>::infinity();
214  }
215 
219  {
220  return std::numeric_limits<double>::infinity();
221  }
222 
227  Sampler<T> &monitor(const std::string &name, const Monitor<T> &mon)
228  {
229  monitor_.insert(std::make_pair(name, mon));
230 
231  return *this;
232  }
233 
235  Monitor<T> &monitor(const std::string &name)
236  {
237  typename monitor_map_type::iterator iter = monitor_.find(name);
238 
240 
241  return iter->second;
242  }
243 
245  const Monitor<T> &monitor(const std::string &name) const
246  {
247  typename monitor_map_type::const_iterator citer = monitor_.find(name);
248 
250  citer, monitor_, monitor);
251 
252  return citer->second;
253  }
254 
256  bool monitor_clear(const std::string &name)
257  {
258  return monitor_.erase(name) ==
259  static_cast<typename monitor_map_type::size_type>(1);
260  }
261 
264  {
265  monitor_.clear();
266 
267  return *this;
268  }
269 
272  {
273  do_initialize();
274 
275  return *this;
276  }
277 
279  Sampler<T> &iterate(std::size_t num = 1)
280  {
281  if (num > 1)
282  reserve(num);
283  for (std::size_t i = 0; i != num; ++i)
284  do_iterate();
285 
286  return *this;
287  }
288 
290  Particle<T> &particle() { return particle_; }
291 
293  const Particle<T> &particle() const { return particle_; }
294 
297  size_type size_history(std::size_t iter) const
298  {
299  return size_history_[iter];
300  }
301 
303  template <typename OutputIter>
304  OutputIter read_size_history(OutputIter first) const
305  {
306  return std::copy(size_history_.begin(), size_history_.end(), first);
307  }
308 
311  double ess_history(std::size_t iter) const { return ess_history_[iter]; }
312 
314  template <typename OutputIter>
315  OutputIter read_ess_history(OutputIter first) const
316  {
317  return std::copy(ess_history_.begin(), ess_history_.end(), first);
318  }
319 
321  bool resampled_history(std::size_t iter) const
322  {
323  return resampled_history_[iter];
324  }
325 
327  template <typename OutputIter>
328  OutputIter read_resampled_history(OutputIter first) const
329  {
330  return std::copy(
331  resampled_history_.begin(), resampled_history_.end(), first);
332  }
333 
335  std::size_t status_history(std::size_t iter, std::size_t id) const
336  {
337  return status_history_[iter][id];
338  }
339 
341  std::map<std::string, Vector<double>> summary() const
342  {
343  const double missing_data = std::numeric_limits<double>::quiet_NaN();
344 
345  std::map<std::string, Vector<double>> df;
346  Vector<double> data(iter_size());
347 
348  std::copy(size_history_.begin(), size_history_.end(), data.begin());
349  df["Size"] = data;
350 
351  std::copy(resampled_history_.begin(), resampled_history_.end(),
352  data.begin());
353  df["Resampled"] = data;
354 
355  df["ESS"] = ess_history_;
356 
357  std::size_t ssize = 0;
358  for (std::size_t i = 0; i != iter_size(); ++i)
359  if (ssize < status_history_[i].size())
360  ssize = status_history_[i].size();
361  for (std::size_t j = 0; j != ssize; ++j) {
362  for (std::size_t i = 0; i != iter_size(); ++i) {
363  data[i] = status_history_[i].size() > j ?
364  status_history_[i][j] :
365  missing_data;
366  }
367  df["Status." + std::to_string(j)] = data;
368  }
369 
370  for (const auto &m : monitor_) {
371  if (m.second.iter_size() > 0) {
372  for (std::size_t d = 0; d != m.second.dim(); ++d) {
373  std::size_t miter = 0;
374  for (std::size_t i = 0; i != iter_size(); ++i) {
375  if (miter != m.second.iter_size() &&
376  i == m.second.index(miter)) {
377  data[i] = m.second.record(d, miter++);
378  } else {
379  data[i] = missing_data;
380  }
381  }
382  if (m.second.name(d).empty())
383  df[m.first + "." + std::to_string(d)] = data;
384  else
385  df[m.second.name(d)] = data;
386  }
387  }
388  }
389 
390  return df;
391  }
392 
397  template <typename CharT, typename Traits>
398  std::basic_ostream<CharT, Traits> &print(
399  std::basic_ostream<CharT, Traits> &os, char sepchar = '\t') const
400  {
401  if (!os || iter_size() == 0)
402  return os;
403 
404  const std::map<std::string, Vector<double>> df = summary();
405 
406  for (const auto &v : df)
407  os << v.first << sepchar;
408  os << '\n';
409  for (std::size_t i = 0; i != iter_size(); ++i) {
410  for (const auto &v : df)
411  os << v.second[i] << sepchar;
412  os << '\n';
413  }
414 
415  return os;
416  }
417 
418  private:
419  using monitor_map_type = std::map<std::string, Monitor<T>>;
420 
421  Particle<T> particle_;
422  std::size_t iter_num_;
423 
425  eval_type resample_eval_;
426  double resample_threshold_;
427 
428  Vector<size_type> size_history_;
429  Vector<double> ess_history_;
430  Vector<bool> resampled_history_;
431  Vector<Vector<std::size_t>> status_history_;
432  Vector<std::size_t> status_;
433  monitor_map_type monitor_;
434 
435  void do_reset()
436  {
437  iter_num_ = 0;
438  particle_.weight().set_equal();
439  for (auto &m : monitor_)
440  m.second.clear();
441 
442  size_history_.clear();
443  ess_history_.clear();
444  resampled_history_.clear();
445  status_history_.clear();
446  status_.clear();
447  }
448 
449  void do_initialize()
450  {
451  do_reset();
452  status_.clear();
453  do_init();
454  do_common();
455  }
456 
457  void do_iterate()
458  {
459  ++iter_num_;
460  status_.clear();
461  do_move();
462  do_common();
463  }
464 
465  void do_common()
466  {
467  do_monitor(MonitorMove);
468  do_resample(resample_threshold_);
469  do_monitor(MonitorResample);
470  do_mcmc();
471  do_monitor(MonitorMCMC);
472  status_history_.push_back(std::move(status_));
473  }
474 
475  void do_init()
476  {
477  for (auto &e : eval_)
478  if ((e.second & SamplerInit) != 0)
479  status_.push_back(e.first(iter_num_, particle_));
480  }
481 
482  void do_move()
483  {
484  for (auto &e : eval_)
485  if ((e.second & SamplerMove) != 0)
486  status_.push_back(e.first(iter_num_, particle_));
487  }
488 
489  void do_mcmc()
490  {
491  for (auto &e : eval_)
492  if ((e.second & SamplerMCMC) != 0)
493  status_.push_back(e.first(iter_num_, particle_));
494  }
495 
496  void do_resample(double threshold)
497  {
498  size_history_.push_back(size());
499  ess_history_.push_back(particle_.weight().ess());
500 
501  if (ess_history_.back() < size() * threshold) {
502  resampled_history_.push_back(true);
503  resample_eval_(iter_num_, particle_);
504  } else {
505  resampled_history_.push_back(false);
506  }
507  }
508 
509  void do_monitor(MonitorStage stage)
510  {
511  for (auto &m : monitor_)
512  if (!m.second.empty())
513  m.second(iter_num_, particle_, stage);
514  }
515 }; // class Sampler
516 
517 template <typename CharT, typename Traits, typename T>
518 inline std::basic_ostream<CharT, Traits> &operator<<(
519  std::basic_ostream<CharT, Traits> &os, const Sampler<T> &sampler)
520 {
521  return sampler.print(os);
522 }
523 
524 } // namespace vsmc
525 
526 #endif // VSMC_CORE_SAMPLER_HPP
std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
ResampleAlgorithm< U01SequenceSorted, false > ResampleMultinomial
Multinomial resampling.
Definition: algorithm.hpp:161
OutputIter read_size_history(OutputIter first) const
Read sampler size history through an output iterator.
Definition: sampler.hpp:304
static SeedGenerator< ID, ResultType > & instance()
Definition: seed.hpp:82
Definition: monitor.hpp:48
SizeType< T > size_type
Definition: particle.hpp:86
Particle class representing the whole particle set.
Definition: particle.hpp:83
SamplerStage & operator&=(SamplerStage &s1, SamplerStage s2)
Definition: sampler.hpp:81
std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, char sepchar= '\t') const
Print the history of the Sampler.
Definition: sampler.hpp:398
double ess_history(std::size_t iter) const
Get ESS of a given iteration, (initialization count as iter zero)
Definition: sampler.hpp:311
size_type size() const
Number of particles.
Definition: sampler.hpp:128
MonitorStage
Monitor stage.
Definition: monitor.hpp:53
Sampler< T > clone() const
Clone the Sampler except the RNG engines.
Definition: sampler.hpp:118
const Particle< T > & particle() const
Read only access to the Particle<T> object.
Definition: sampler.hpp:293
Evaluation at iteration before resampling.
Definition: sampler.hpp:54
Sampler< T > & resample_method(const eval_type &res_eval, double threshold=resample_threshold_always())
Set resampling method by a eval_type object.
Definition: sampler.hpp:190
Sampler(Args &&...args)
Construct a Sampler.
Definition: sampler.hpp:110
ResampleScheme
Resampling schemes.
Definition: defines.hpp:59
weight_type & weight()
Read and write access to the weight collection object.
Definition: particle.hpp:174
Stratified resampling on residuals.
Definition: defines.hpp:64
STL namespace.
bool monitor_clear(const std::string &name)
Erase a named monitor.
Definition: sampler.hpp:256
OutputIter read_resampled_history(OutputIter first) const
Read resampling indicator history through an output iterator.
Definition: sampler.hpp:328
std::size_t iter_size() const
Number of iterations (including initialization)
Definition: sampler.hpp:143
ResampleAlgorithm< U01SequenceStratified, false > ResampleStratified
Stratified resampling.
Definition: algorithm.hpp:165
Multinomial resampling.
Definition: defines.hpp:60
Sampler< T > & monitor_clear()
Erase all monitors.
Definition: sampler.hpp:263
ResampleAlgorithm< U01SequenceSystematic, true > ResampleResidualSystematic
Residual systematic resampling.
Definition: algorithm.hpp:183
Monitor evaluated after moves.
Definition: monitor.hpp:54
Sampler< T > & eval(const eval_type &new_eval, SamplerStage stage, bool append=true)
Add a new evaluation object.
Definition: sampler.hpp:149
Sampler<T>::eval_type subtype.
Definition: algorithm.hpp:106
double resample_threshold() const
Get resampling threshold.
Definition: sampler.hpp:200
Stratified resampling.
Definition: defines.hpp:61
#define VSMC_RUNTIME_ASSERT_CORE_SAMPLER_MONITOR_NAME(iter, map, func)
Definition: sampler.hpp:39
Sampler< T > & iterate(std::size_t num=1)
Iteration.
Definition: sampler.hpp:279
static double resample_threshold_always()
Special value of resampling threshold that indicate no resampling will always be performed.
Definition: sampler.hpp:218
typename Particle< T >::size_type size_type
Definition: sampler.hpp:102
ResampleAlgorithm< U01SequenceStratified, true > ResampleResidualStratified
Residual stratified resampling.
Definition: algorithm.hpp:178
std::function< std::size_t(std::size_t, Particle< T > &)> eval_type
Definition: sampler.hpp:103
OutputIter read_ess_history(OutputIter first) const
Read ESS history through an output iterator.
Definition: sampler.hpp:315
void reserve(std::size_t num)
Reserve space for a specified number of iterations.
Definition: sampler.hpp:131
Residual resampling.
Definition: defines.hpp:63
size_type size_history(std::size_t iter) const
Get sampler size of a given iteration (initialization count as iteration zero)
Definition: sampler.hpp:297
Systematic resampling on residuals.
Definition: defines.hpp:65
constexpr SamplerStage operator~(SamplerStage s)
Definition: sampler.hpp:76
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const Sampler< T > &sampler)
Definition: sampler.hpp:518
constexpr SamplerStage operator&(SamplerStage s1, SamplerStage s2)
Definition: sampler.hpp:58
SamplerStage
Sampler evaluaiton stages.
Definition: sampler.hpp:52
SamplerStage & operator^=(SamplerStage &s1, SamplerStage s2)
Definition: sampler.hpp:91
std::size_t status_history(std::size_t iter, std::size_t id) const
Get the status of a given move id and the iteration.
Definition: sampler.hpp:335
constexpr SamplerStage operator^(SamplerStage s1, SamplerStage s2)
Definition: sampler.hpp:70
Sampler< T > & resample_method(ResampleScheme scheme, double threshold=resample_threshold_always())
Set resampling method by a built-in ResampleScheme scheme name.
Definition: sampler.hpp:161
std::map< std::string, Vector< double > > summary() const
Summary of sampler history.
Definition: sampler.hpp:341
Monitor evaluated after MCMC moves.
Definition: monitor.hpp:56
Monitor for Monte Carlo integration.
Definition: monitor.hpp:62
Evaluation at initialization before resampling.
Definition: sampler.hpp:53
std::size_t iter_num() const
Current iteration number (initialization count as zero)
Definition: sampler.hpp:146
Systematic resampling.
Definition: defines.hpp:62
Sampler< T > & resample_threshold(double threshold)
Set resampling threshold.
Definition: sampler.hpp:203
SamplerStage & operator|=(SamplerStage &s1, SamplerStage s2)
Definition: sampler.hpp:86
constexpr SamplerStage operator|(SamplerStage s1, SamplerStage s2)
Definition: sampler.hpp:64
static double resample_threshold_never()
Special value of resampling threshold that indicate no resampling will be ever performed.
Definition: sampler.hpp:211
Particle< T > & particle()
Read and write access to the Particle<T> object.
Definition: sampler.hpp:290
SMC Sampler.
Definition: sampler.hpp:99
ResampleAlgorithm< U01SequenceSorted, true > ResampleResidual
Residual resampling.
Definition: algorithm.hpp:173
Sampler< T > & initialize()
Initialization.
Definition: sampler.hpp:271
Monitor< T > & monitor(const std::string &name)
Read and write access to a named monitor.
Definition: sampler.hpp:235
Evaluation at after resampling.
Definition: sampler.hpp:55
bool resampled_history(std::size_t iter) const
Get resampling indicator of a given iteration.
Definition: sampler.hpp:321
const Monitor< T > & monitor(const std::string &name) const
Read only access to a named monitor.
Definition: sampler.hpp:245
Sampler< T > & monitor(const std::string &name, const Monitor< T > &mon)
Add a monitor.
Definition: sampler.hpp:227
Monitor evaluated after resampling.
Definition: monitor.hpp:55
ResampleAlgorithm< U01SequenceSystematic, false > ResampleSystematic
Systematic resampling.
Definition: algorithm.hpp:169