vSMC  v3.0.0
Scalable Monte Carlo
weight.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/core/weight.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_WEIGHT_HPP
33 #define VSMC_CORE_WEIGHT_HPP
34 
35 #include <vsmc/internal/common.hpp>
37 
38 namespace vsmc
39 {
40 
43 class Weight
44 {
45  public:
46  using size_type = std::size_t;
47 
48  explicit Weight(size_type N = 0) : ess_(0), data_(N) { set_equal(); }
49 
51  size_type size() const { return data_.size(); }
52 
57  void resize(size_type N)
58  {
59  if (N == size())
60  return;
61 
62  data_.resize(N);
63  set_equal();
64  }
65 
67  void reserve(size_type N) { data_.reserve(N); }
68 
70  void shrink_to_fit() { data_.shrink_to_fit(); }
71 
73  double ess() const { return ess_; }
74 
76  const double *data() const { return data_.data(); }
77 
79  template <typename OutputIter>
80  OutputIter read_weight(OutputIter first) const
81  {
82  return std::copy(data_.begin(), data_.end(), first);
83  }
84 
86  template <typename RandomIter>
87  RandomIter read_weight(RandomIter first, int stride) const
88  {
89  for (std::size_t i = 0; i != size(); ++i, first += stride)
90  *first = data_[i];
91 
92  return first;
93  }
94 
96  void set_equal()
97  {
98  std::fill(data_.begin(), data_.end(), 1.0 / size());
99  ess_ = static_cast<double>(size());
100  }
101 
103  template <typename InputIter>
104  void set(InputIter first)
105  {
106  std::copy_n(first, size(), data_.begin());
107  normalize(false);
108  }
109 
111  template <typename RandomIter>
112  void set(RandomIter first, int stride)
113  {
114  if (stride == 1) {
115  set(first);
116  return;
117  }
118 
119  for (std::size_t i = 0; i != size(); ++i, first += stride)
120  data_[i] = *first;
121  normalize(false);
122  }
123 
125  template <typename InputIter>
126  void mul(InputIter first)
127  {
128  for (std::size_t i = 0; i != size(); ++i, ++first)
129  data_[i] *= *first;
130  normalize(false);
131  }
132 
134  void mul(const double *first)
135  {
136  ::vsmc::mul(size(), first, data_.data(), data_.data());
137  normalize(false);
138  }
139 
141  void mul(double *first) { mul(const_cast<const double *>(first)); }
142 
144  template <typename RandomIter>
145  void mul(RandomIter first, int stride)
146  {
147  if (stride == 1) {
148  mul(first);
149  return;
150  }
151 
152  for (std::size_t i = 0; i != size(); ++i, first += stride)
153  data_[i] *= *first;
154  normalize(false);
155  }
156 
158  template <typename InputIter>
159  void set_log(InputIter first)
160  {
161  std::copy_n(first, size(), data_.begin());
162  normalize(true);
163  }
164 
166  template <typename RandomIter>
167  void set_log(RandomIter first, int stride)
168  {
169  if (stride == 1) {
170  set_log(first);
171  return;
172  }
173 
174  for (std::size_t i = 0; i != size(); ++i, first += stride)
175  data_[i] = *first;
176  normalize(true);
177  }
178 
180  template <typename InputIter>
181  void add_log(InputIter first)
182  {
183  log(size(), data_.data(), data_.data());
184  for (std::size_t i = 0; i != size(); ++i)
185  data_[i] += *first;
186  normalize(true);
187  }
188 
190  void add_log(const double *first)
191  {
192  log(size(), data_.data(), data_.data());
193  add(size(), first, data_.data(), data_.data());
194  normalize(true);
195  }
196 
198  void add_log(double *first) { add_log(const_cast<const double *>(first)); }
199 
201  template <typename RandomIter>
202  void add_log(RandomIter first, int stride)
203  {
204  if (stride == 1) {
205  add_log(first);
206  return;
207  }
208 
209  log(size(), data_.data(), data_.data());
210  for (std::size_t i = 0; i != size(); ++i, first += stride)
211  data_[i] += *first;
212  normalize(true);
213  }
214 
217  template <typename RNGType>
218  size_type draw(RNGType &rng) const
219  {
220  return draw_(rng, data_.begin(), data_.end(), true);
221  }
222 
223  private:
224  double ess_;
225  Vector<double> data_;
227 
228  template <typename InputIter>
229  double max_element(std::size_t n, InputIter first)
230  {
231  using value_type =
232  typename std::iterator_traits<InputIter>::value_type;
233 
234  value_type v = -std::numeric_limits<value_type>::infinity();
235  for (std::size_t i = 0; i != n; ++i, ++first)
236  if (v < *first)
237  v = *first;
238 
239  return static_cast<double>(v);
240  }
241 
242  void normalize(bool use_log)
243  {
244  double *w = data_.data();
245  double accw = 0;
246  double essw = 0;
247  const double lmax = use_log ? max_element(size(), w) : 0;
248  const std::size_t k = internal::BufferSize<double>::value;
249  const std::size_t m = size() / k;
250  const std::size_t l = size() % k;
251  for (std::size_t i = 0; i != m; ++i, w += k)
252  normalize(k, w, accw, essw, use_log, lmax);
253  normalize(l, w, accw, essw, use_log, lmax);
254  ::vsmc::mul(size(), 1 / accw, data_.data(), data_.data());
255  ess_ = accw * accw / essw;
256  }
257 
258  void normalize(std::size_t n, double *w, double &accw, double &essw,
259  bool use_log, double lmax)
260  {
261  if (use_log) {
262  sub(n, w, lmax, w);
263  exp(n, w, w);
264  }
265  accw = std::accumulate(w, w + n, accw);
266  essw +=
267  internal::cblas_ddot(static_cast<VSMC_BLAS_INT>(n), w, 1, w, 1);
268  }
269 }; // class Weight
270 
281 {
282  public:
283  using size_type = std::size_t;
284 
285  explicit WeightNull(size_type) {}
286 
287  size_type size() const { return 0; }
288 
289  void resize(size_type) {}
290 
292 
293  void shrink_to_fit() {}
294 
295  double ess() const { return std::numeric_limits<double>::quiet_NaN(); }
296 
297  const double *data() const { return nullptr; }
298 
299  template <typename OutputIter>
300  void read_weight(OutputIter) const
301  {
302  }
303 
304  template <typename RandomIter>
305  void read_weight(RandomIter, int) const
306  {
307  }
308 
309  void set_equal() {}
310 
311  template <typename InputIter>
312  void set(InputIter)
313  {
314  }
315 
316  template <typename RandomIter>
317  void set(RandomIter, int)
318  {
319  }
320 
321  template <typename InputIter>
322  void mul(InputIter)
323  {
324  }
325 
326  template <typename RandomIter>
327  void mul(RandomIter, int)
328  {
329  }
330 
331  template <typename InputIter>
332  void set_log(InputIter)
333  {
334  }
335 
336  template <typename RandomIter>
337  void set_log(RandomIter, int)
338  {
339  }
340 
341  template <typename InputIter>
342  void add_log(InputIter)
343  {
344  }
345 
346  template <typename RandomIter>
347  void add_log(RandomIter, int)
348  {
349  }
350 
351  template <typename RNGType>
352  size_type draw(RNGType &) const
353  {
354  return 0;
355  }
356 }; // class WeightNull
357 
361 
362 } // namespace vsmc
363 
364 #endif // VSMC_CORE_WEIGHT_HPP
#define VSMC_DEFINE_TYPE_DISPATCH_TRAIT(Outer, Inner, Default)
Definition: traits.hpp:40
std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
Definition: monitor.hpp:48
std::size_t size_type
Definition: weight.hpp:46
Weight(size_type N=0)
Definition: weight.hpp:48
double ess() const
Return the ESS of the particle system.
Definition: weight.hpp:73
size_type draw(RNGType &) const
Definition: weight.hpp:352
OutputIter read_weight(OutputIter first) const
Read all normalized weights to an output iterator.
Definition: weight.hpp:80
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:77
void add_log(RandomIter first, int stride)
Set .
Definition: weight.hpp:202
void add_log(const double *first)
Set .
Definition: weight.hpp:190
double ess() const
Definition: weight.hpp:295
void set_log(InputIter first)
Set .
Definition: weight.hpp:159
WeightNull(size_type)
Definition: weight.hpp:285
void set_equal()
Set .
Definition: weight.hpp:96
void shrink_to_fit()
Definition: weight.hpp:293
size_type draw(RNGType &rng) const
Draw integer index in the range according to the weights.
Definition: weight.hpp:218
void shrink_to_fit()
Shrink to fit.
Definition: weight.hpp:70
void set_log(RandomIter first, int stride)
Set .
Definition: weight.hpp:167
void add_log(RandomIter, int)
Definition: weight.hpp:347
void add_log(InputIter)
Definition: weight.hpp:342
RandomIter read_weight(RandomIter first, int stride) const
Read all normalized weights to a random access iterator.
Definition: weight.hpp:87
void add_log(double *first)
Set .
Definition: weight.hpp:198
void mul(InputIter first)
Set .
Definition: weight.hpp:126
void mul(RandomIter, int)
Definition: weight.hpp:327
void set_equal()
Definition: weight.hpp:309
void mul(InputIter)
Definition: weight.hpp:322
void resize(size_type)
Definition: weight.hpp:289
void set_log(RandomIter, int)
Definition: weight.hpp:337
Weight class.
Definition: weight.hpp:43
void set_log(InputIter)
Definition: weight.hpp:332
void read_weight(OutputIter) const
Definition: weight.hpp:300
void exp(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:115
const double * data() const
Definition: weight.hpp:297
void resize(size_type N)
Resize the Weight object.
Definition: weight.hpp:57
void reserve(size_type)
Definition: weight.hpp:291
An empty weight set class.
Definition: weight.hpp:280
void reserve(size_type N)
Reserve space.
Definition: weight.hpp:67
size_type size() const
Size of this Weight object.
Definition: weight.hpp:51
void sub(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:75
std::size_t size_type
Definition: weight.hpp:283
typename WeightTypeTrait< T >::type WeightType
Definition: weight.hpp:360
void mul(const double *first)
Set .
Definition: weight.hpp:134
void add(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:74
void read_weight(RandomIter, int) const
Definition: weight.hpp:305
size_type size() const
Definition: weight.hpp:287
void mul(double *first)
Set .
Definition: weight.hpp:141
const double * data() const
Pointer to data of the normalized weight.
Definition: weight.hpp:76
void log(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:117
void mul(RandomIter first, int stride)
Set .
Definition: weight.hpp:145
void add_log(InputIter first)
Set .
Definition: weight.hpp:181