32 #ifndef MCKL_ALGORITHM_RESAMPLE_HPP 33 #define MCKL_ALGORITHM_RESAMPLE_HPP 63 template <std::
size_t K,
typename RealType>
65 const RealType *
u01, RealType *r, std::size_t N, RealType &lmax)
73 std::size_t m = N - n0;
75 for (std::size_t i = n0; i != n; ++i, ++j, --m) {
79 exp(n - n0, s.data(), s.data());
80 sub(n - n0, const_one<RealType>(), s.data(), r);
83 template <std::
size_t K,
typename RealType,
typename RNGType>
85 RealType *r, std::size_t N, RealType &lmax)
92 u01_trans_sorted_impl<K>(n0, n, r, r, N, lmax);
95 template <
typename RealType>
97 const RealType *
u01, RealType *r, RealType delta)
104 for (std::size_t i = n0; i != n; ++i, ++j) {
105 r[j] = u01[j] +
static_cast<RealType
>(i);
107 mul(n - n0, delta, r, r);
110 template <
typename RealType,
typename RNGType>
112 RNGType &rng, std::size_t n0, std::size_t n, RealType *r, RealType delta)
122 template <
typename RealType>
124 std::size_t n0, std::size_t n, RealType u, RealType *r, RealType delta)
131 for (std::size_t i = n0; i != n; ++i, ++j) {
132 r[j] =
static_cast<RealType
>(i);
134 muladd(n - n0, r, delta, u, r);
142 template <
typename RealType>
145 static_assert(std::is_floating_point<RealType>::value,
146 "**u01_trans_sorted** used with RealType other than floating point " 154 const std::size_t m = N / k;
157 for (std::size_t i = 0; i != m; ++i, n0 += k, u01 += k, r += k) {
158 internal::u01_trans_sorted_impl<k>(n0, n0 + k,
u01, r, N, lmax);
160 internal::u01_trans_sorted_impl<k>(n0, N,
u01, r, N, lmax);
166 template <
typename RealType>
168 std::size_t N,
const RealType *
u01, RealType *r)
170 static_assert(std::is_floating_point<RealType>::value,
171 "**u01_trans_stratified** used with RealType other than floating " 179 const std::size_t m = N / k;
181 const RealType delta = 1 /
static_cast<RealType
>(N);
182 for (std::size_t i = 0; i != m; ++i, n0 += k, u01 += k, r += k) {
191 template <
typename RealType>
193 std::size_t N,
const RealType *
u01, RealType *r)
195 static_assert(std::is_floating_point<RealType>::value,
196 "**u01_trans_systematic** used with RealType other than floating " 204 const std::size_t m = N / k;
206 const RealType delta = 1 /
static_cast<RealType
>(N);
207 const RealType u = u01[0] * delta;
208 for (std::size_t i = 0; i != m; ++i, n0 += k, r += k) {
216 template <
typename RealType,
typename RNGType>
219 static_assert(std::is_floating_point<RealType>::value,
220 "**u01_rand_sorted** used with RealType other than floating point " 228 const std::size_t m = N / k;
231 for (std::size_t i = 0; i != m; ++i, n0 += k, r += k) {
232 internal::u01_rand_sorted_impl<k>(rng, n0, n0 + k, r, N, lmax);
234 internal::u01_rand_sorted_impl<k>(rng, n0, N, r, N, lmax);
239 template <
typename RealType,
typename RNGType>
242 static_assert(std::is_floating_point<RealType>::value,
243 "**u01_rand_stratified** used with RealType other than floating point " 247 const std::size_t m = N / k;
249 const RealType delta = 1 /
static_cast<RealType
>(N);
250 for (std::size_t i = 0; i != m; ++i, n0 += k, r += k) {
258 template <
typename RealType,
typename RNGType>
261 static_assert(std::is_floating_point<RealType>::value,
262 "**u01_rand_systematic** used with RealType other than floating point " 266 RealType
u01 = ru01(rng);
275 template <
typename RealType>
281 template <
typename RealType,
typename RNG>
293 template <
typename RealType>
299 template <
typename RealType,
typename RNG>
311 template <
typename RealType>
317 template <
typename RealType,
typename RNG>
333 template <
typename InputIter,
typename OutputIterR,
typename OutputIterI>
335 InputIter weight, OutputIterR resid, OutputIterI integ)
337 using resid_type =
typename std::iterator_traits<OutputIterR>::value_type;
338 using integ_type =
typename std::iterator_traits<OutputIterI>::value_type;
340 static_assert(std::is_floating_point<resid_type>::value,
341 "**resample_trans_residual** used resid other than floating point " 344 resid_type sum_resid = 0;
345 integ_type sum_integ = 0;
346 OutputIterR resid_i = resid;
347 OutputIterI integ_i = integ;
348 const resid_type coeff =
static_cast<resid_type
>(M);
349 for (std::size_t i = 0; i != N; ++i, ++weight, ++resid_i, ++integ_i) {
350 const resid_type w = coeff *
static_cast<resid_type
>(*weight);
353 *integ_i =
static_cast<integ_type
>(integral);
354 sum_resid += *resid_i;
355 sum_integ += *integ_i;
358 const resid_type mul_resid = 1 / sum_resid;
359 for (std::size_t i = 0; i != N; ++i, ++resid) {
363 return M -
static_cast<std::size_t
>(sum_integ);
374 template <
typename InputIter,
typename OutputIter,
typename U01SeqType>
376 InputIter weight, U01SeqType &&u01seq, OutputIter replication)
378 using real_type =
typename std::iterator_traits<InputIter>::value_type;
379 using rep_type =
typename std::iterator_traits<OutputIter>::value_type;
386 *replication++ =
static_cast<rep_type
>(M);
390 OutputIter rep = std::fill_n(replication, N, const_zero<rep_type>());
397 for (std::size_t i = 0; i != N - 1; ++i, ++weight, ++replication) {
399 while (j != M && static_cast<real_type>(u01seq[j]) < accw) {
404 *replication++ =
static_cast<rep_type
>(M - j);
416 template <
typename InputIter,
typename OutputIter>
418 std::size_t N, std::size_t M, InputIter replication, OutputIter index)
420 using rep_type =
typename std::iterator_traits<InputIter>::value_type;
421 using idx_type =
typename std::iterator_traits<OutputIter>::value_type;
423 if (N == 0 || M == 0) {
427 const std::size_t K = std::min(N, M);
430 InputIter rep = replication;
432 auto seek = [N, K, &time, &src, &rep]() {
433 if (src < K && *rep < time + 2) {
438 }
while (src < K && *rep < time + 2);
440 if (src >= K && *rep < time + 1) {
445 }
while (src < N && *rep < time + 1);
449 for (std::size_t dst = 0; dst != K; ++dst, ++replication, ++index) {
450 if (*replication > 0) {
451 *index =
static_cast<idx_type
>(dst);
454 *index =
static_cast<idx_type
>(src);
459 for (std::size_t dst = K; dst < M; ++dst, ++index) {
461 *index =
static_cast<idx_type
>(src);
470 template <
typename T>
474 using eval_type = std::function<void(std::size_t, std::size_t,
487 template <
typename Eval>
490 eval_ = std::forward<Eval>(eval);
497 "**ResampleEval::operator()** invalid evaluation object");
501 const std::size_t N =
static_cast<std::size_t
>(particle.
size());
504 eval_(N, N, particle.
rng(), particle.
weight().data(), rep.data());
515 template <
typename U01SeqType,
bool Res
idual>
526 template <
typename RNGType,
typename InputIter,
typename OutputIter>
528 InputIter weight, OutputIter replication)
const 530 eval(N, M, rng, weight, replication,
531 std::integral_constant<bool, Residual>());
537 template <
typename RNGType,
typename InputIter,
typename OutputIter>
538 void eval(std::size_t N, std::size_t M, RNGType &rng, InputIter weight,
539 OutputIter replication, std::false_type)
const 541 using real_type =
typename std::iterator_traits<InputIter>::value_type;
544 u01seq_(rng, M, u01.data());
548 template <
typename RNGType,
typename InputIter,
typename OutputIter>
549 void eval(std::size_t N, std::size_t M, RNGType &rng, InputIter weight,
550 OutputIter replication, std::true_type)
const 552 using real_type =
typename std::iterator_traits<InputIter>::value_type;
553 using rep_type =
typename std::iterator_traits<OutputIter>::value_type;
561 u01seq_(rng, R, u01.data());
563 for (std::size_t i = 0; i != N; ++i, ++replication) {
564 *replication += integ[i];
597 template <
typename IntType = std::
size_t>
611 if (index_.size() == 0) {
614 return index_.back().size();
618 std::size_t
size(std::size_t iter)
const 620 if (iter >= index_.size()) {
623 return index_[iter].size();
637 if (index_.size() < num_iter_) {
638 index_.push_back(identity_);
640 index_[num_iter_ - 1] = identity_;
645 template <
typename InputIter>
649 if (index_.size() < num_iter_) {
650 index_.emplace_back(N);
652 index_[num_iter_ - 1].resize(N);
654 std::copy_n(first, N, index_[num_iter_ - 1].begin());
659 return index(
id, num_iter_ - 1, 0);
664 return index(
id, iter_back, 0);
669 std::size_t
id, std::size_t iter_back, std::size_t iter)
const 672 "**ResampleIndex::index** iteration numbers out of range");
675 while (iter_back > iter) {
677 idx = index_[iter_back][idx];
685 return index_matrix_nrow(num_iter_ - 1);
691 "**ResampleIndex::index_matrix_nrow** iteration numbers out of " 694 return index_[iter_back].size();
699 return index_matrix_ncol(num_iter_ - 1, 0);
704 return index_matrix_ncol(iter_back, 0);
708 std::size_t iter_back, std::size_t iter)
const 711 "**ResampleIndex::index_matrix_ncol** iteration numbers out of " 714 return iter_back - iter + 1;
719 return index_matrix(layout, num_iter_ - 1, 0);
725 return index_matrix(layout, iter_back, 0);
730 MatrixLayout layout, std::size_t iter_back, std::size_t iter)
const 733 "**ResampleIndex::index_matrix** iteration numbers out of range");
736 index_matrix_nrow(iter_back) * index_matrix_ncol(iter_back, iter));
737 read_index_matrix(layout, idxmat.begin(), iter_back, iter);
742 template <
typename RandomIter>
745 return read_index_matrix(layout, first, num_iter_ - 1, 0);
748 template <
typename RandomIter>
750 MatrixLayout layout, RandomIter first, std::size_t iter_back)
const 752 return read_index_matrix(layout, first, iter_back, 0);
764 template <
typename RandomIter>
766 std::size_t iter_back, std::size_t iter)
const 769 "**ResampleIndex::read_index_matrix** iteration numbers out of " 772 using difference_type =
773 typename std::iterator_traits<RandomIter>::difference_type;
774 const std::size_t N = index_matrix_nrow(iter_back);
775 const std::size_t R = index_matrix_ncol(iter_back, iter);
778 RandomIter back = first +
static_cast<difference_type
>(R - 1);
779 const index_type *idx = index_[iter_back].data();
780 for (std::size_t i = 0; i != N; ++i) {
781 back[
static_cast<difference_type
>(i * R)] = idx[i];
783 for (std::size_t r = 1; r != R; ++r) {
784 const std::size_t j = iter_back - r;
785 RandomIter last = back;
787 idx = index_[j].data();
788 for (std::size_t i = 0; i != N; ++i) {
789 back[
static_cast<difference_type
>(i * R)] =
790 idx[static_cast<std::size_t>(
791 last[static_cast<difference_type>(i * R)])];
798 first +
static_cast<difference_type
>(N * (R - 1));
799 const index_type *idx = index_[iter_back].data();
800 std::copy_n(idx, N, back);
801 for (std::size_t r = 1; r != R; ++r) {
802 const std::size_t j = iter_back - r;
803 RandomIter last = back;
804 back -=
static_cast<difference_type
>(N);
805 idx = index_[j].data();
806 for (std::size_t i = 0; i != N; ++i) {
807 back[
static_cast<difference_type
>(i)] =
808 idx[static_cast<std::size_t>(
809 last[static_cast<difference_type>(i)])];
814 return first +
static_cast<difference_type
>(N * R);
818 std::size_t num_iter_;
822 void resize_identity(std::size_t N)
824 std::size_t n = identity_.size();
827 for (std::size_t i = n; i != N; ++i) {
836 #endif // MCKL_ALGORITHM_RESAMPLE_HPP Counter based RNG engine.
void mul(std::size_t n, const float *a, const float *b, float *y)
void operator()(RNG &rng, std::size_t N, RealType *r) const
std::size_t index_matrix_ncol(std::size_t iter_back) const
void operator()(std::size_t N, const RealType *u01, RealType *r) const
Stratified resampling on residuals.
void u01_trans_systematic(std::size_t N, const RealType *u01, RealType *r)
Transform a single standard uniform random number to a systematic sequence.
void select(size_type n, InputIter index)
Resize by selecting according to user supplied index vector.
index_type index(std::size_t id, std::size_t iter_back, std::size_t iter) const
Get the index given the particle ID and iteration number.
void operator()(std::size_t N, const RealType *u01, RealType *r) const
RandomIter read_index_matrix(MatrixLayout layout, RandomIter first) const
std::size_t index_matrix_ncol(std::size_t iter_back, std::size_t iter) const
void clear()
Release memory.
RandomIter read_index_matrix(MatrixLayout layout, RandomIter first, std::size_t iter_back, std::size_t iter) const
Read the resampling index matrix into an random access iterator.
std::size_t size(std::size_t iter) const
The sample size of a given iteration.
void u01_trans_systematic_impl(std::size_t n0, std::size_t n, RealType u, RealType *r, RealType delta)
Vector< index_type > index_matrix(MatrixLayout layout) const
std::size_t num_iter() const
Number of iterations recorded.
OutputIter resample_trans_rep_index(std::size_t N, std::size_t M, InputIter replication, OutputIter index)
Transform replication numbers into parent indices.
void u01_rand_stratified_impl(RNGType &rng, std::size_t n0, std::size_t n, RealType *r, RealType delta)
Sorted of standard uniform numbers.
ResampleScheme
Resampling schemes.
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
void operator()(std::size_t, Particle< T > &particle) const
Resample a particle collection.
void log(std::size_t n, const float *a, float *y)
rng_type & rng(size_type i)
Get an (parallel) RNG stream for a given particle.
RandomIter read_index_matrix(MatrixLayout layout, RandomIter first, std::size_t iter_back) const
Systematic standard uniform numbers.
void push_back(std::size_t N)
Append an identity resampling index.
RealType u01(UIntType u)
Convert uniform unsigned integers to floating points within [0, 1].
std::function< void(std::size_t, std::size_t, typename Particle< T >::rng_type &, const double *, typename Particle< T >::size_type *)> eval_type
void u01_trans_sorted(std::size_t N, const RealType *u01, RealType *r)
Tranform a sequence of standard uniform random numbers to sorted sequence.
Stratified standard uniform numbers.
Record and trace resampling index.
index_type index(std::size_t id, std::size_t iter_back) const
std::size_t index_matrix_nrow(std::size_t iter_back) const
Systematic resampling on residuals.
void u01_trans_sorted_impl(std::size_t n0, std::size_t n, const RealType *u01, RealType *r, std::size_t N, RealType &lmax)
void sub(std::size_t n, const float *a, const float *b, float *y)
weight_type & weight()
Read and write access to the weight collection object.
void u01_rand_sorted(RNGType &rng, std::size_t N, RealType *r)
Generate sorted standard uniform numbers with cost.
Vector< index_type > index_matrix(MatrixLayout layout, std::size_t iter_back) const
typename rng_set_type::rng_type rng_type
void u01_rand_stratified(RNGType &rng, std::size_t N, RealType *r)
Generate stratified standard uniform numbers.
void modf(std::size_t n, const float *a, float *y, float *z)
std::size_t resample_trans_residual(std::size_t N, std::size_t M, InputIter weight, OutputIterR resid, OutputIterI integ)
Transform normalized weights to normalized residual and integrals,.
Vector< index_type > index_matrix(MatrixLayout layout, std::size_t iter_back, std::size_t iter) const
Get the resampling index matrix.
void reset()
Reset history.
SMCSampler<T>::eval_type subtype.
OutputIter resample_trans_u01_rep(std::size_t N, std::size_t M, InputIter weight, U01SeqType &&u01seq, OutputIter replication)
Transform uniform [0, 1) sequence into replication numbers.
size_type size() const
The number of particles.
void push_back(std::size_t N, InputIter first)
Append a resampling index.
void operator()(RNG &rng, std::size_t N, RealType *r) const
void exp(std::size_t n, const float *a, float *y)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
void operator()(std::size_t N, const RealType *u01, RealType *r) const
Standard uniform distribution on [0, 1)
std::size_t index_matrix_nrow() const
std::size_t size() const
The sample size of the last iteration.
void u01_trans_stratified(std::size_t N, const RealType *u01, RealType *r)
Transform a sequence of standard uniform random numbers to a stratified sequence. ...
void operator()(std::size_t N, std::size_t M, RNGType &rng, InputIter weight, OutputIter replication) const
Generate replication numbers from normalized weights.
void selection(Eval &&eval)
Set a new evaluation object of type eval_type.
std::size_t index_matrix_ncol() const
void u01_trans_stratified_impl(std::size_t n0, std::size_t n, const RealType *u01, RealType *r, RealType delta)
void u01_rand_sorted_impl(RNGType &rng, std::size_t n0, std::size_t n, RealType *r, std::size_t N, RealType &lmax)
index_type index(std::size_t id) const
void operator()(RNG &rng, std::size_t N, RealType *r) const
ResampleEval(const eval_type &eval)
Construct a Sampler::move_type object.
void runtime_assert(bool cond, const char *msg, bool soft=false)
MatrixLayout
Matrix layout.
void u01_rand_systematic(RNGType &rng, std::size_t N, RealType *r)
Generate systematic standard uniform numbers.
void u01_distribution(RNGType &rng, std::size_t n, RealType *r)