vSMC
vSMC: 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-2015, 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 inline double weight_ess(std::size_t N, const double *first)
44 {
45  return 1 / dot(N, first, 1, first, 1);
46 }
47 
50 inline void weight_normalize(std::size_t N, double *first)
51 {
52  mul(N, 1 / std::accumulate(first, first + N, 0.0), first, first);
53 }
54 
57 inline void weight_normalize_log(std::size_t N, double *first)
58 {
59  double wmax = *(std::max_element(first, first + N));
60  for (std::size_t i = 0; i != N; ++i)
61  first[i] -= wmax;
62 }
63 
66 class Weight
67 {
68  public:
69  using size_type = std::size_t;
70 
71  explicit Weight(size_type N) : ess_(0), data_(N) {}
72 
73  size_type size() const { return data_.size(); }
74 
75  size_type resample_size() const { return size(); }
76 
77  double ess() const { return ess_; }
78 
79  const double *data() const { return data_.data(); }
80 
81  const double *resample_data() const { return data_.data(); }
82 
83  template <typename OutputIter>
84  void read_weight(OutputIter first) const
85  {
86  std::copy(data_.begin(), data_.end(), first);
87  }
88 
89  template <typename RandomIter>
90  void read_weight(RandomIter first, int stride) const
91  {
92  for (size_type i = 0; i != size(); ++i, first += stride)
93  *first = data_[i];
94  }
95 
96  void read_resample_weight(double *first) const { read_weight(first); }
97 
98  void set_equal()
99  {
100  std::fill(data_.begin(), data_.end(), 1.0 / resample_size());
101  post_set();
102  }
103 
104  template <typename InputIter>
105  void set(InputIter first)
106  {
107  std::copy_n(first, size(), data_.begin());
108  post_set();
109  }
110 
111  template <typename RandomIter>
112  void set(RandomIter first, int stride)
113  {
114  for (size_type i = 0; i != size(); ++i, first += stride)
115  data_[i] = *first;
116  post_set();
117  }
118 
119  template <typename InputIter>
120  void mul(InputIter first)
121  {
122  for (size_type i = 0; i != size(); ++i, ++first)
123  data_[i] *= *first;
124  post_set();
125  }
126 
127  void mul(const double *first)
128  {
129  ::vsmc::mul(size(), first, data_.data(), data_.data());
130  post_set();
131  }
132 
133  void mul(double *first) { mul(const_cast<const double *>(first)); }
134 
135  template <typename RandomIter>
136  void mul(RandomIter first, int stride)
137  {
138  for (size_type i = 0; i != size(); ++i, first += stride)
139  data_[i] *= *first;
140  post_set();
141  }
142 
143  template <typename InputIter>
144  void set_log(InputIter first)
145  {
146  std::copy_n(first, size(), data_.begin());
147  post_set_log();
148  }
149 
150  template <typename RandomIter>
151  void set_log(RandomIter first, int stride)
152  {
153  for (size_type i = 0; i != size(); ++i, first += stride)
154  data_[i] = *first;
155  post_set_log();
156  }
157 
158  template <typename InputIter>
159  void add_log(InputIter first)
160  {
161  log(size(), data_.data(), data_.data());
162  for (size_type i = 0; i != size(); ++i, ++first)
163  data_[i] += *first;
164  post_set_log();
165  }
166 
167  void add_log(const double *first)
168  {
169  log(size(), data_.data(), data_.data());
170  add(size(), data_.data(), first, data_.data());
171  post_set_log();
172  }
173 
174  void add_log(double *first) { add_log(const_cast<const double *>(first)); }
175 
176  template <typename RandomIter>
177  void add_log(RandomIter first, int stride)
178  {
179  log(size(), data_.data(), data_.data());
180  for (size_type i = 0; i != size(); ++i, first += stride)
181  data_[i] += *first;
182  post_set_log();
183  }
184 
185  template <typename URNG>
186  size_type draw(URNG &eng) const
187  {
188  return draw_(eng, data_.begin(), data_.end(), true);
189  }
190 
191  protected:
192  double *mutable_data() { return data_.data(); }
193 
194  private:
195  double ess_;
196  Vector<double> data_;
198 
199  void post_set() { ess_ = normalize(false); }
200 
201  void post_set_log()
202  {
203  weight_normalize_log(size(), data_.data());
204  ess_ = normalize(true);
205  }
206 
207  double normalize(bool use_log)
208  {
209  double *w = data_.data();
210  double accw = 0;
211  const std::size_t k = 1000;
212  const std::size_t m = size() / k;
213  const std::size_t l = size() % k;
214  for (std::size_t i = 0; i != m; ++i, w += k)
215  normalize_eval(k, w, accw, use_log);
216  normalize_eval(l, w, accw, use_log);
217  ::vsmc::mul(size(), 1 / accw, data_.data(), data_.data());
218 
219  return 1 / dot(size(), data_.data(), 1, data_.data(), 1);
220  }
221 
222  void normalize_eval(std::size_t n, double *w, double &accw, bool use_log)
223  {
224  if (use_log)
225  exp(n, w, w);
226  accw = std::accumulate(w, w + n, accw);
227  }
228 }; // class Weight
229 
240 {
241  public:
242  using size_type = std::size_t;
243 
244  explicit WeightNull(size_type) {}
245 
246  size_type size() const { return 0; }
247 
248  size_type resample_size() const { return 0; }
249 
250  double ess() const { return std::numeric_limits<double>::quiet_NaN(); }
251 
252  const double *resample_data() const { return nullptr; }
253 
254  const double *data() const { return nullptr; }
255 
256  template <typename OutputIter>
257  void read_weight(OutputIter) const
258  {
259  }
260 
261  template <typename RandomIter>
262  void read_weight(RandomIter, int) const
263  {
264  }
265 
266  void read_resample_weight(double *) const {}
267 
268  void set_equal() {}
269 
270  template <typename InputIter>
271  void set(InputIter)
272  {
273  }
274 
275  template <typename RandomIter>
276  void set(RandomIter, int)
277  {
278  }
279 
280  template <typename InputIter>
281  void mul(InputIter)
282  {
283  }
284 
285  template <typename RandomIter>
286  void mul(RandomIter, int)
287  {
288  }
289 
290  template <typename InputIter>
291  void set_log(InputIter)
292  {
293  }
294 
295  template <typename RandomIter>
296  void set_log(RandomIter, int)
297  {
298  }
299 
300  template <typename InputIter>
301  void add_log(InputIter)
302  {
303  }
304 
305  template <typename RandomIter>
306  void add_log(RandomIter, int)
307  {
308  }
309 
310  template <typename URNG>
311  size_type draw(URNG &) const
312  {
313  return 0;
314  }
315 }; // class WeightNull
316 
320 
321 } // namespace vsmc
322 
323 #endif // VSMC_CORE_WEIGHT_HPP
T dot(std::size_t n, const T *x, std::size_t incx, const T *y, std::size_t incy)
Computes a vector-vector dot product.
Definition: cblas.hpp:93
#define VSMC_DEFINE_TYPE_DISPATCH_TRAIT(Outer, Inner, Default)
Definition: traits.hpp:40
Definition: monitor.hpp:49
std::size_t size_type
Definition: weight.hpp:69
double ess() const
Definition: weight.hpp:77
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:112
void add_log(RandomIter first, int stride)
Definition: weight.hpp:177
void add_log(const double *first)
Definition: weight.hpp:167
double ess() const
Definition: weight.hpp:250
void read_weight(RandomIter first, int stride) const
Definition: weight.hpp:90
void set_log(InputIter first)
Definition: weight.hpp:144
WeightNull(size_type)
Definition: weight.hpp:244
void set_equal()
Definition: weight.hpp:98
void weight_normalize_log(std::size_t N, double *first)
Normalize logarithm weights such that the maximum is zero.
Definition: weight.hpp:57
typename std::conditional< std::is_scalar< T >::value, std::vector< T, AlignedAllocator< T >>, std::vector< T >>::type Vector
AlignedVector for scalar type and std::vector for others.
void set_log(RandomIter first, int stride)
Definition: weight.hpp:151
void add_log(RandomIter, int)
Definition: weight.hpp:306
void add_log(InputIter)
Definition: weight.hpp:301
void add_log(double *first)
Definition: weight.hpp:174
size_type draw(URNG &) const
Definition: weight.hpp:311
void mul(InputIter first)
Definition: weight.hpp:120
void mul(RandomIter, int)
Definition: weight.hpp:286
void set_equal()
Definition: weight.hpp:268
void mul(InputIter)
Definition: weight.hpp:281
void copy(std::size_t n, const T *x, std::size_t incx, T *y, std::size_t incy)
Copies vector to another vector.
Definition: cblas.hpp:82
double * mutable_data()
Definition: weight.hpp:192
void set_log(RandomIter, int)
Definition: weight.hpp:296
Weight class.
Definition: weight.hpp:66
void read_resample_weight(double *) const
Definition: weight.hpp:266
void set_log(InputIter)
Definition: weight.hpp:291
void read_weight(OutputIter) const
Definition: weight.hpp:257
const double * resample_data() const
Definition: weight.hpp:252
void exp(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:146
size_type draw(URNG &eng) const
Definition: weight.hpp:186
const double * resample_data() const
Definition: weight.hpp:81
const double * data() const
Definition: weight.hpp:254
void weight_normalize(std::size_t N, double *first)
Normalize weights such that the summation is one.
Definition: weight.hpp:50
An empty weight set class.
Definition: weight.hpp:239
size_type size() const
Definition: weight.hpp:73
std::size_t size_type
Definition: weight.hpp:242
typename WeightTypeTrait< T >::type WeightType
Definition: weight.hpp:319
void mul(const double *first)
Definition: weight.hpp:127
Weight(size_type N)
Definition: weight.hpp:71
void add(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:109
void read_weight(RandomIter, int) const
Definition: weight.hpp:262
size_type size() const
Definition: weight.hpp:246
void read_resample_weight(double *first) const
Definition: weight.hpp:96
void mul(double *first)
Definition: weight.hpp:133
double weight_ess(std::size_t N, const double *first)
Compute the ess given normalized weights.
Definition: weight.hpp:43
const double * data() const
Definition: weight.hpp:79
size_type resample_size() const
Definition: weight.hpp:75
size_type resample_size() const
Definition: weight.hpp:248
void read_weight(OutputIter first) const
Definition: weight.hpp:84
void log(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:148
void mul(RandomIter first, int stride)
Definition: weight.hpp:136
void add_log(InputIter first)
Definition: weight.hpp:159