vSMC
vSMC: Scalable Monte Carlo
weight_set.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/core/weight_set.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, 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_WEIGHT_SET_HPP
33 #define VSMC_CORE_WEIGHT_SET_HPP
34 
35 #include <vsmc/internal/common.hpp>
38 
39 namespace vsmc {
40 
43 class WeightSet
44 {
45  public :
46 
47  typedef std::size_t size_type;
48 
49  explicit WeightSet (size_type N) :
50  size_(N), ess_(static_cast<double>(N)), weight_(N), log_weight_(N) {}
51 
52 #if VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
53  WeightSet (const WeightSet &) = default;
54  WeightSet &operator= (const WeightSet &) = default;
55 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
56  WeightSet (WeightSet &&) = default;
57  WeightSet &operator= (WeightSet &&) = default;
58 #endif
59 #else // VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
60  WeightSet (const WeightSet &other) :
61  size_(other.size_), ess_(other.ess_),
62  weight_(other.weight_), log_weight_(other.log_weight_) {}
63 
64  WeightSet &operator= (const WeightSet &other) {
65  if (this != &other) {
66  size_ = other.size_;
67  ess_ = other.ess_;
68  weight_ = other.weight_;
69  log_weight_ = other.log_weight_;
70  }
71 
72  return *this;
73  }
74 
75 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
76  WeightSet (WeightSet &&other) :
77  size_(other.size_), ess_(other.ess_),
78  weight_(cxx11::move(other.weight_)),
79  log_weight_(cxx11::move(other.log_weight_)) {}
80 
81  WeightSet &operator= (WeightSet &&other) {
82  if (this != &other) {
83  size_ = other.size_;
84  ess_ = other.ess_;
85  weight_ = cxx11::move(other.weight_);
86  log_weight_ = cxx11::move(other.log_weight_);
87  }
88 
89  return *this;
90  }
91 #endif
92 #endif // VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
93 
94  virtual ~WeightSet () {}
95 
96  size_type size () const {return size_;}
97 
99  double ess () const {return ess_;}
100 
102  template <typename InputIter>
103  double ess (InputIter first, bool use_log) const
104  {
105  std::vector<double, AlignedAllocator<double> > buffer(size_);
106  double *const bptr = &buffer[0];
107 #if VSMC_HAS_CXX11LIB_ALGORITHM
108  std::copy_n(first, size_, bptr);
109 #else
110  for (size_type i = 0; i != size_; ++i, ++first)
111  bptr[i] = *first;
112 #endif
113 
114  return compute_ess(bptr, use_log);
115  }
116 
118  template <typename RandomIter>
119  double ess (RandomIter first, int stride, bool use_log) const
120  {
121  std::vector<double, AlignedAllocator<double> > buffer(size_);
122  double *const bptr = &buffer[0];
123  for (size_type i = 0; i != size_; ++i, first += stride)
124  bptr[i] = *first;
125 
126  return compute_ess(bptr, use_log);
127  }
128 
130  template <typename InputIter>
131  double cess (InputIter first, bool use_log) const
132  {
133  std::vector<double, AlignedAllocator<double> > buffer(size_);
134  double *const bptr = &buffer[0];
135 #if VSMC_HAS_CXX11LIB_ALGORITHM
136  std::copy_n(first, size_, bptr);
137 #else
138  for (size_type i = 0; i != size_; ++i, ++first)
139  bptr[i] = *first;
140 #endif
141 
142  return compute_cess(bptr, use_log);
143  }
144 
146  template <typename RandomIter>
147  double cess (RandomIter first, int stride, bool use_log) const
148  {
149  std::vector<double, AlignedAllocator<double> > buffer(size_);
150  double *const bptr = &buffer[0];
151  for (size_type i = 0; i != size_; ++i, first += stride)
152  bptr[i] = *first;
153 
154  return compute_cess(bptr, use_log);
155  }
156 
158  virtual size_type resample_size () const {return size_;}
159 
162  virtual void read_resample_weight (double *first) const
163  {read_weight(first);}
164 
166  template <typename OutputIter>
167  void read_weight (OutputIter first) const
168  {std::copy(weight_.begin(), weight_.end(), first);}
169 
172  template <typename RandomIter>
173  void read_weight (RandomIter first, int stride) const
174  {
175  const double *const wptr = &weight_[0];
176  for (size_type i = 0; i != size_; ++i, first += stride)
177  *first = wptr[i];
178  }
179 
181  template <typename OutputIter>
182  void read_log_weight (OutputIter first) const
183  {std::copy(log_weight_.begin(), log_weight_.end(), first);}
184 
187  template <typename RandomIter>
188  void read_log_weight (RandomIter first, int stride) const
189  {
190  const double *const lwptr = &log_weight_[0];
191  for (size_type i = 0; i != size_; ++i, first += stride)
192  *first = lwptr[i];
193  }
194 
196  double weight (size_type id) const {return weight_[id];}
197 
199  double log_weight (size_type id) const {return log_weight_[id];}
200 
204  {
205  ess_ = static_cast<double>(resample_size());
206  std::fill_n(&weight_[0], size_, 1 / ess_);
207  std::memset(&log_weight_[0], 0, sizeof(double) * size_);
208  }
209 
213  template <typename InputIter>
214  void set_weight (InputIter first)
215  {
216  double *const wptr = &weight_[0];
217 #if VSMC_HAS_CXX11LIB_ALGORITHM
218  std::copy_n(first, size_, wptr);
219 #else
220  for (size_type i = 0; i != size_; ++i, ++first)
221  wptr[i] = *first;
222 #endif
223  post_set_weight();
224  }
225 
229  template <typename RandomIter>
230  void set_weight (RandomIter first, int stride)
231  {
232  double *const wptr = &weight_[0];
233  for (size_type i = 0; i != size_; ++i, first += stride)
234  wptr[i] = *first;
235  post_set_weight();
236  }
237 
241  template <typename InputIter>
242  void mul_weight (InputIter first)
243  {
244  double *const wptr = &weight_[0];
245  for (size_type i = 0; i != size_; ++i, ++first)
246  wptr[i] *= *first;
247  post_set_weight();
248  }
249 
254  template <typename RandomIter>
255  void mul_weight (RandomIter first, int stride)
256  {
257  double *const wptr = &weight_[0];
258  for (size_type i = 0; i != size_; ++i, first += stride)
259  wptr[i] *= *first;
260  post_set_weight();
261  }
262 
266  template <typename InputIter>
267  void set_log_weight (InputIter first)
268  {
269  double *const lwptr = &log_weight_[0];
270 #if VSMC_HAS_CXX11LIB_ALGORITHM
271  std::copy_n(first, size_, lwptr);
272 #else
273  for (size_type i = 0; i != size_; ++i, ++first)
274  lwptr[i] = *first;
275 #endif
276  post_set_log_weight();
277  }
278 
282  template <typename RandomIter>
283  void set_log_weight (RandomIter first, int stride)
284  {
285  double *const lwptr = &log_weight_[0];
286  for (size_type i = 0; i != size_; ++i, first += stride)
287  lwptr[i] = *first;
288  post_set_log_weight();
289  }
290 
294  template <typename InputIter>
295  void add_log_weight (InputIter first)
296  {
297  double *const lwptr = &log_weight_[0];
298  for (size_type i = 0; i != size_; ++i, ++first)
299  lwptr[i] += *first;
300  post_set_log_weight();
301  }
302 
307  template <typename RandomIter>
308  void add_log_weight (RandomIter first, int stride)
309  {
310  double *const lwptr = &log_weight_[0];
311  for (size_type i = 0; i != size_; ++i, first += stride)
312  lwptr[i] += *first;
313  post_set_log_weight();
314  }
315 
317  template <typename URNG>
318  size_type draw (URNG &eng) const
319  {return draw_(eng, weight_.begin(), weight_.end(), true);}
320 
322  virtual const double *resample_weight_data () const {return &weight_[0];}
323 
325  const double *weight_data () const {return &weight_[0];}
326 
328  const double *log_weight_data () const {return &log_weight_[0];}
329 
330  protected :
331 
332  void set_ess (double e) {ess_ = e;}
333 
334  double *mutable_weight_data () {return &weight_[0];}
335 
336  double *mutable_log_weight_data () {return &log_weight_[0];}
337 
339  virtual void log_weight2weight ()
340  {math::vExp(size_, &log_weight_[0], &weight_[0]);}
341 
343  virtual void weight2log_weight ()
344  {math::vLn(size_, &weight_[0], &log_weight_[0]);}
345 
347  virtual void normalize_log_weight ()
348  {
349  double *const lwptr = &log_weight_[0];
350  double dmax = lwptr[0];
351  for (size_type i = 0; i != size_; ++i)
352  if (dmax < lwptr[i])
353  dmax = lwptr[i];
354  dmax = -dmax;
355  for (size_type i = 0; i != size_; ++i)
356  lwptr[i] += dmax;
357  }
358 
360  virtual void normalize_weight ()
361  {
362  double *const wptr = &weight_[0];
363  double coeff = 1 / math::asum(size_, wptr);
364  math::scal(size_, coeff, wptr);
365  ess_ = 1 / math::dot(size_, wptr, wptr);
366  }
367 
369  virtual double compute_ess (const double *first, bool use_log) const
370  {
371  std::vector<double, AlignedAllocator<double> > buffer(size_);
372  double *const bptr = &buffer[0];
373 
374  if (use_log) {
375  math::vAdd(size_, &log_weight_[0], first, bptr);
376  double dmax = bptr[0];
377  for (size_type i = 0; i != size_; ++i)
378  if (dmax < bptr[i])
379  dmax = bptr[i];
380  dmax = -dmax;
381  for (size_type i = 0; i != size_; ++i)
382  bptr[i] += dmax;
383  math::vExp(size_, bptr, bptr);
384  } else {
385  math::vMul(size_, &weight_[0], first, bptr);
386  }
387 
388  double coeff = 1 / math::asum(size_, bptr);
389  math::scal(size_, coeff, bptr);
390 
391  return 1 / math::dot(size_, bptr, bptr);
392  }
393 
395  virtual double compute_cess (const double *first, bool use_log) const
396  {
397  const double *bptr = first;
398  const double *const wptr = &weight_[0];
399  std::vector<double, AlignedAllocator<double> > buffer;
400  if (use_log) {
401  buffer.resize(size_);
402  math::vExp(size_, first, &buffer[0]);
403  bptr = &buffer[0];
404  }
405 
406  double above = 0;
407  double below = 0;
408  for (size_type i = 0; i != size_; ++i) {
409  double wb = wptr[i] * bptr[i];
410  above += wb;
411  below += wb * bptr[i];
412  }
413 
414  return above * above / below;
415  }
416 
417  private :
418 
419  size_type size_;
420  double ess_;
421  std::vector<double, AlignedAllocator<double> > weight_;
422  std::vector<double, AlignedAllocator<double> > log_weight_;
424 
425  void post_set_log_weight ()
426  {
430  }
431 
432  void post_set_weight ()
433  {
437  }
438 }; // class WeightSet
439 
450 {
451  public :
452 
453  typedef std::size_t size_type;
454 
455  explicit WeightSetNull (size_type) {}
456 
457  size_type size () const {return 0;}
458 
459  double ess () const {return max_ess();}
460 
461  template <typename InputIter>
462  double ess (InputIter, bool) const {return max_ess();}
463 
464  template <typename RandomIter>
465  double ess (RandomIter, int, bool) const {return max_ess();}
466 
467  template <typename InputIter>
468  double cess (InputIter, bool) const {return max_ess();}
469 
470  template <typename RandomIter>
471  double cess (RandomIter, int, bool) const {return max_ess();}
472 
473  size_type resample_size () const {return 0;}
474 
475  void read_resample_weight (double *) const {}
476 
477  template <typename OutputIter>
478  void read_weight (OutputIter) const {}
479 
480  template <typename RandomIter>
481  void read_weight (RandomIter, int) const {}
482 
483  template <typename OutputIter>
484  void read_log_weight (OutputIter) const {}
485 
486  template <typename RandomIter>
487  void read_log_weight (RandomIter, int) const {}
488 
489  double weight (size_type) const {return 1;}
490 
491  double log_weight (size_type) const {return 0;}
492 
493  void set_equal_weight () {}
494 
495  template <typename InputIter>
496  void set_weight (InputIter) {}
497 
498  template <typename RandomIter>
499  void set_weight (RandomIter, int) {}
500 
501  template <typename InputIter>
502  void mul_weight (InputIter) {}
503 
504  template <typename RandomIter>
505  void mul_weight (RandomIter, int) {}
506 
507  template <typename InputIter>
508  void set_log_weight (InputIter) {}
509 
510  template <typename RandomIter>
511  void set_log_weight (RandomIter, int) {}
512 
513  template <typename InputIter>
514  void add_log_weight (InputIter) {}
515 
516  template <typename RandomIter>
517  void add_log_weight (RandomIter, int) {}
518 
519  template <typename URNG>
520  size_type draw (URNG &) const {return 0;}
521 
522  private :
523 
524  static double max_ess ()
525  {return std::numeric_limits<double>::max VSMC_MNE ();}
526 }; // class WeightSetEmtpy
527 
528 } // namespace vsmc
529 
530 #endif // VSMC_CORE_WEIGHT_SET_HPP
virtual void log_weight2weight()
Compute unormalized logarithm weights from normalized weights.
Definition: weight_set.hpp:339
Definition: adapter.hpp:37
void set_weight(RandomIter, int)
Definition: weight_set.hpp:499
void vAdd(std::size_t n, const T *a, const T *b, T *y)
For , compute .
Definition: vmath.hpp:319
double ess() const
ESS of the particle collection based on the current weights.
Definition: weight_set.hpp:99
double ess() const
Definition: weight_set.hpp:459
std::size_t size_type
Definition: weight_set.hpp:47
void set_log_weight(InputIter)
Definition: weight_set.hpp:508
double log_weight(size_type id) const
Get the unnormalized logarithm weight of the id'th particle.
Definition: weight_set.hpp:199
virtual void normalize_weight()
Normalize weights such that the summation is one.
Definition: weight_set.hpp:360
void read_weight(OutputIter first) const
Read normalized weights through an output iterator.
Definition: weight_set.hpp:167
void read_log_weight(RandomIter first, int stride) const
Read unnormalized logarithm weights through a random access iterator with (possible non-uniform strid...
Definition: weight_set.hpp:188
void set_weight(InputIter first)
Set normalized weight, unnormalized logarithm weight and ESS by changing the (possible unnormalized) ...
Definition: weight_set.hpp:214
void read_log_weight(OutputIter) const
Definition: weight_set.hpp:484
virtual size_type resample_size() const
Size of the weight set for the purpose of resampling.
Definition: weight_set.hpp:158
void set_weight(RandomIter first, int stride)
Set normalized weight, unnormalized logarithm weight and ESS by changing the (possible unnormalized) ...
Definition: weight_set.hpp:230
void read_log_weight(OutputIter first) const
Read unnormalized logarithm weights through an output iterator.
Definition: weight_set.hpp:182
double cess(RandomIter first, int stride, bool use_log) const
Compute CESS given (log) incremental weights.
Definition: weight_set.hpp:147
void add_log_weight(RandomIter first, int stride)
Set normalized weight, unnormalized logarithm weight and ESS by adding to the unnormalized logarithm ...
Definition: weight_set.hpp:308
void mul_weight(RandomIter first, int stride)
Set normalized weight, unnormalized logarithm weight and ESS by multiply the normalized weight with (...
Definition: weight_set.hpp:255
double log_weight(size_type) const
Definition: weight_set.hpp:491
size_type resample_size() const
Definition: weight_set.hpp:473
void read_weight(RandomIter, int) const
Definition: weight_set.hpp:481
void vMul(std::size_t n, const T *a, const T *b, T *y)
For , compute .
Definition: vmath.hpp:328
virtual ~WeightSet()
Definition: weight_set.hpp:94
void mul_weight(InputIter)
Definition: weight_set.hpp:502
void add_log_weight(InputIter)
Definition: weight_set.hpp:514
void * memset(void *dst, int ch, std::size_t n)
SIMD optimized memset with non-temporal store for large buffers.
Definition: cstring.hpp:906
virtual void normalize_log_weight()
Normalize logarithm weights such that the maximum is zero.
Definition: weight_set.hpp:347
void add_log_weight(InputIter first)
Set normalized weight, unnormalized logarithm weight and ESS by adding to the unnormalized logarithm ...
Definition: weight_set.hpp:295
double * mutable_weight_data()
Definition: weight_set.hpp:334
double ess(InputIter first, bool use_log) const
Compute ESS given (log) incremental weights.
Definition: weight_set.hpp:103
size_type draw(URNG &) const
Definition: weight_set.hpp:520
void add_log_weight(RandomIter, int)
Definition: weight_set.hpp:517
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
Definition: defines.hpp:38
double * mutable_log_weight_data()
Definition: weight_set.hpp:336
size_type size() const
Definition: weight_set.hpp:96
void set_log_weight(RandomIter first, int stride)
Set normalized weight, unnormalized logarithm weight and ESS by changing the (possible unnormalized) ...
Definition: weight_set.hpp:283
size_type size() const
Definition: weight_set.hpp:457
T dot(std::size_t n, const T *x, const T *y)
The dot product.
Definition: cblas.hpp:75
double weight(size_type id) const
Get the normalized weight of the id'th particle.
Definition: weight_set.hpp:196
void scal(std::size_t n, T a, T *x)
Scale a vector.
Definition: cblas.hpp:80
void vLn(std::size_t n, const T *a, T *y)
For , compute .
Definition: vmath.hpp:403
remove_reference< T >::type && move(T &&t) noexcept
void read_resample_weight(double *) const
Definition: weight_set.hpp:475
An empty weight set class.
Definition: weight_set.hpp:449
void mul_weight(RandomIter, int)
Definition: weight_set.hpp:505
double cess(InputIter, bool) const
Definition: weight_set.hpp:468
virtual void weight2log_weight()
Compute unormalized weights from normalized logarithm weights.
Definition: weight_set.hpp:343
double weight(size_type) const
Definition: weight_set.hpp:489
Weight set class.
Definition: weight_set.hpp:43
T asum(std::size_t n, const T *x)
Sum of vector magnitudes.
Definition: cblas.hpp:61
std::size_t size_type
Definition: weight_set.hpp:453
double cess(InputIter first, bool use_log) const
Compute CESS given (log) incremental weights.
Definition: weight_set.hpp:131
WeightSetNull(size_type)
Definition: weight_set.hpp:455
double cess(RandomIter, int, bool) const
Definition: weight_set.hpp:471
const double * weight_data() const
Read only access to the raw data of weight.
Definition: weight_set.hpp:325
void set_weight(InputIter)
Definition: weight_set.hpp:496
virtual double compute_cess(const double *first, bool use_log) const
Compute CESS given (logarithm) unormalized incremental weights.
Definition: weight_set.hpp:395
void set_ess(double e)
Definition: weight_set.hpp:332
void set_equal_weight()
Set normalized weight, unnormalized logarithm weight and ESS such that each particle has a equal weig...
Definition: weight_set.hpp:203
virtual double compute_ess(const double *first, bool use_log) const
Compute ESS given (logarithm) unormalzied incremental weights.
Definition: weight_set.hpp:369
double ess(RandomIter first, int stride, bool use_log) const
Compute ESS given (log) incremental weights.
Definition: weight_set.hpp:119
void read_log_weight(RandomIter, int) const
Definition: weight_set.hpp:487
void read_weight(RandomIter first, int stride) const
Read normalized weights through a random access iterator with (possible non-uniform stride) ...
Definition: weight_set.hpp:173
double ess(RandomIter, int, bool) const
Definition: weight_set.hpp:465
virtual void read_resample_weight(double *first) const
Read normalized weights through an output iterator for the purpose of resampling. ...
Definition: weight_set.hpp:162
size_type draw(URNG &eng) const
Draw a sample according to the weights.
Definition: weight_set.hpp:318
void vExp(std::size_t n, const T *a, T *y)
For , compute .
Definition: vmath.hpp:397
void mul_weight(InputIter first)
Set normalized weight, unnormalized logarithm weight and ESS by multiply the normalized weight with (...
Definition: weight_set.hpp:242
WeightSet & operator=(const WeightSet &)=default
WeightSet(size_type N)
Definition: weight_set.hpp:49
virtual const double * resample_weight_data() const
Read only access to the resampling weights.
Definition: weight_set.hpp:322
void set_log_weight(InputIter first)
Set normalized weight, unnormalized logarithm weight and ESS by changing the (possible unnormalized) ...
Definition: weight_set.hpp:267
void set_log_weight(RandomIter, int)
Definition: weight_set.hpp:511
double ess(InputIter, bool) const
Definition: weight_set.hpp:462
void read_weight(OutputIter) const
Definition: weight_set.hpp:478
const double * log_weight_data() const
Read only access to the raw data of logarithm weight.
Definition: weight_set.hpp:328