MCKL
Monte Carlo Kernel Library
coupon_collector_test.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/coupon_collector_test.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, 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 MCKL_RANDOM_COUPON_COLLECTOR_TEST_HPP
33 #define MCKL_RANDOM_COUPON_COLLECTOR_TEST_HPP
34 
37 #include <bitset>
38 
39 namespace mckl {
40 
45 template <std::size_t D,
46  std::size_t NTrialMax = std::numeric_limits<std::size_t>::max()>
48  : public ChiSquaredTest<CouponCollectorTest<D, NTrialMax>>
49 {
50  static_assert(D > 1, "**CouponCollectorTest** used with D less than two");
51 
52  public:
53  CouponCollectorTest(std::size_t n) : n_(n), tmin_(0), tmax_(0)
54  {
55  internal::StirlingMatrix2 stirling(T_ - 2, D - 1);
56  double d = D;
57  double lfact = std::lgamma(d + 1);
58  double ld = std::log(d);
59  Vector<double> np_all(T_ - D + 1);
60  for (std::size_t k = D; k < T_; ++k) {
61  np_all[k - D] =
62  n * std::exp(lfact - k * ld) * stirling(k - 1, D - 1);
63  }
64  np_all[T_ - D] =
65  n - std::accumulate(np_all.data(), np_all.data() + T_ - D, 0.0);
66  internal::group_np(static_cast<double>(n), np_all, np_, tmin_, tmax_);
67  }
68 
70 
71  template <typename RNGType, typename U01DistributionType>
72  double operator()(RNGType &rng, U01DistributionType &u01)
73  {
74  using result_type = typename U01DistributionType::result_type;
75 
76  const std::size_t k = internal::BufferSize<result_type>::value;
78  count_.resize(np_.size());
79  std::fill(count_.begin(), count_.end(), 0);
80 
81  std::size_t uidx = k;
82  std::size_t s = 0;
83  while (s < n_) {
84  std::size_t t = 0;
85  std::size_t v = 0;
86  std::bitset<D> occurs;
87  while (v < D) {
88  if (t >= NTrialMax) {
89  return 0;
90  }
91  if (uidx == k) {
92  rand(rng, u01, k, r.data());
93  mul(k, static_cast<double>(D), r.data(), r.data());
94  uidx = 0;
95  }
96  ++t;
97  std::size_t u = internal::ftoi<std::size_t, D>(r[uidx++]);
98  if (!occurs.test(u)) {
99  occurs.set(u);
100  ++v;
101  }
102  if (v == D) {
103  t -= D;
104  if (t <= tmin_) {
105  count_.front() += 1;
106  } else if (t >= tmax_) {
107  count_.back() += 1;
108  } else {
109  count_[t - tmin_] += 1;
110  }
111  ++s;
112  break;
113  }
114  }
115  }
116 
117  return this->stat(np_.size(), count_.data(), np_.data());
118  }
119 
120  double degree_of_freedom() const
121  {
122  return static_cast<double>(np_.size() - 1);
123  }
124 
125  private:
126  static constexpr std::size_t T_ = D + 256;
127 
128  std::size_t n_;
129  std::size_t tmin_;
130  std::size_t tmax_;
131  Vector<double> np_;
132  Vector<double> count_;
133 }; // class CouponCollectorTest
134 
135 } // namespace mckl
136 
137 #endif // MCKL_RANDOM_COUPON_COLLECTOR_TEST_HPP
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmf.hpp:124
double stat(std::size_t m, const double *count, const double *np) const
void group_np(double n, const Vector< double > &np_all, Vector< double > &np, std::size_t &kmin, std::size_t &kmax)
void lgamma(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:303
double operator()(RNGType &rng, U01DistributionType &u01)
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
Definition: memory.hpp:435
void log(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:226
RealType u01(UIntType u)
Convert uniform unsigned integers to floating points within [0, 1].
Definition: u01.hpp:88
#define MCKL_DEFINE_RANDOM_TEST_OPERATOR(ResultType)
Definition: mcmc.hpp:40
void exp(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:221
void rand(RNGType &rng, ArcsineDistribution< RealType > &distribution, std::size_t N, RealType *r)
Coupon collector&#39;s test.
Tests based on the -distribution.