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