vSMC
vSMC: Scalable Monte Carlo
transform.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/resample/transform.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_RESAMPLE_TRANSFORM_HPP
33 #define VSMC_RESAMPLE_TRANSFORM_HPP
34 
36 
37 namespace vsmc
38 {
39 
42 template <typename IntType, typename U01SeqType>
43 inline void resample_trans_u01_rep(std::size_t M, std::size_t N,
44  const double *weight, U01SeqType &&u01seq, IntType *replication)
45 {
46  // Given N sorted U01 random variates
47  // Compute M replication numbers based on M weights
48 
49  if (M == 0)
50  return;
51 
52  if (M == 1) {
53  *replication = static_cast<IntType>(N);
54  return;
55  }
56 
57  std::memset(replication, 0, sizeof(IntType) * M);
58  if (N == 0)
59  return;
60 
61  double accw = 0;
62  std::size_t j = 0;
63  for (std::size_t i = 0; i != M - 1; ++i) {
64  accw += weight[i];
65  while (j != N && u01seq[j] <= accw) {
66  ++replication[i];
67  ++j;
68  }
69  }
70  replication[M - 1] = static_cast<IntType>(N - j);
71 }
72 
75 template <typename IntType, typename U01SeqType>
76 inline void resample_trans_u01_index(std::size_t M, std::size_t N,
77  const double *weight, U01SeqType &&u01seq, IntType *index)
78 {
79  if (M == 0 || N == 0)
80  return;
81 
82  std::memset(index, 0, sizeof(IntType) * N);
83  if (M == 1)
84  return;
85 
86  double accw = 0;
87  std::size_t j = 0;
88  for (std::size_t i = 0; i != M - 1; ++i) {
89  accw += weight[i];
90  while (j != N && u01seq[j] <= accw)
91  index[j++] = static_cast<IntType>(i);
92  }
93  while (j != N)
94  index[j++] = static_cast<IntType>(M - 1);
95 }
96 
99 template <typename IntType1, typename IntType2>
101  std::size_t M, std::size_t N, const IntType1 *replication, IntType2 *index)
102 {
103  if (M == 0 || N == 0)
104  return;
105 
106  if (M != N) {
107  std::size_t dst = 0;
108  for (std::size_t src = 0; src != M; ++src) {
109  const IntType1 rep = replication[src];
110  for (IntType1 r = 0; r != rep; ++r)
111  index[dst++] = static_cast<IntType2>(src);
112  }
113  return;
114  }
115 
116  IntType1 time = 0;
117  std::size_t src = 0;
118  for (std::size_t dst = 0; dst != N; ++dst) {
119  if (replication[dst] != 0) {
120  index[dst] = static_cast<IntType2>(dst);
121  } else {
122  // replication[dst] has zero child, copy from elsewhere
123  if (replication[src] < time + 2) {
124  // only 1 child left on replication[src]
125  time = 0;
126  do // move src to a position with at least 2 children
127  ++src;
128  while (replication[src] < 2);
129  }
130  index[dst] = static_cast<IntType2>(src);
131  ++time;
132  }
133  }
134 }
135 
138 template <typename IntType1, typename IntType2>
140  std::size_t M, std::size_t N, const IntType1 *index, IntType2 *replication)
141 {
142  if (M == 0 || N == 0)
143  return;
144 
145  std::memset(replication, 0, sizeof(IntType2) * M);
146 
147  for (std::size_t i = 0; i != N; ++i)
148  ++replication[index[i]];
149 }
150 
154 template <typename IntType>
155 inline std::size_t resample_trans_residual(std::size_t M, std::size_t N,
156  const double *weight, double *resid, IntType *integ)
157 {
158  double integral = 0;
159  const double coeff = static_cast<double>(N);
160  for (std::size_t i = 0; i != M; ++i) {
161  resid[i] = std::modf(coeff * weight[i], &integral);
162  integ[i] = static_cast<IntType>(integral);
163  }
164  mul(M, 1 / std::accumulate(resid, resid + M, 0.0), resid, resid);
165  IntType R = std::accumulate(integ, integ + M, static_cast<IntType>(0));
166 
167  return N - static_cast<std::size_t>(R);
168 }
169 
170 } // namespace vsmc
171 
172 #endif // VSMC_RESAMPLE_TRANSFORM_HPP
Definition: monitor.hpp:49
void resample_trans_u01_rep(std::size_t M, std::size_t N, const double *weight, U01SeqType &&u01seq, IntType *replication)
Transform uniform [0, 1] sequence into replication numbers.
Definition: transform.hpp:43
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:112
void resample_trans_rep_index(std::size_t M, std::size_t N, const IntType1 *replication, IntType2 *index)
Transform replication numbers into parent indices.
Definition: transform.hpp:100
std::size_t resample_trans_residual(std::size_t M, std::size_t N, const double *weight, double *resid, IntType *integ)
Transform normalized weights to normalized residual and integrals, and return the number of remaining...
Definition: transform.hpp:155
void resample_trans_u01_index(std::size_t M, std::size_t N, const double *weight, U01SeqType &&u01seq, IntType *index)
Transform uniform [0, 1] sequence into parent indices.
Definition: transform.hpp:76
void resample_trans_index_rep(std::size_t M, std::size_t N, const IntType1 *index, IntType2 *replication)
Transform parent indices into replication numbers.
Definition: transform.hpp:139