Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
sampling_scheme.hpp
1// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
2
3/*********************************************************************** * This program is free software; you can
4 *redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free
5 *Software Foundation; either version 2 of the License, or * (at your option) any later version. *
6 * *
7 ***************************************************************************/
8
9#ifndef __SAMPLING_SCHEME_H_INCLUDED__
10#define __SAMPLING_SCHEME_H_INCLUDED__
11
12#include <map>
13#include <random>
14
15namespace quetzal::sampling
16{
17
20{
21 private:
22 unsigned int _n;
23
24 public:
25 /* Constructor
26 * @param n sampling size
27 */
28 param_base_class(unsigned int n) : _n(n)
29 {
30 }
31
32 param_base_class() = default;
33
34 /* Read the sampling size parameter
35 */
36 unsigned int sampling_size() const
37 {
38 return _n;
39 }
40
41 /* Set the sampling size parameter
42 */
43 void sampling_size(unsigned int n)
44 {
45 this->_n = n;
46 }
47};
48
50template <typename X, typename N> class constrained_sampling
51{
52 public:
53 /* @brief parameter of the sampling scheme
54 */
56 {
57 using param_base_class::param_base_class;
58 };
59
60 /* @brief type used to refer geographic coordinates
61 */
62 using coord_type = X;
63
64 /* @brief type of the function. Signature must be equivalent to `double (coord_type const& x)`
65 * and returns the weight associated to x.
66 */
67
68 private:
69 std::vector<double> _weights;
70 const std::vector<coord_type> &_space;
71 N _population_size;
72 param_type _param;
73
74 template <typename F> auto compute_weights(std::vector<coord_type> const &space, F f) const
75 {
76 std::vector<double> w(space.size(), 0);
77 std::transform(space.cbegin(), space.cend(), w.begin(), f);
78 return w;
79 }
80
81 public:
82 template <typename F1>
83 constrained_sampling(std::vector<coord_type> const &space, F1 f, N pop_size, unsigned int n)
84 : _weights(compute_weights(space, f)), _space(space), _population_size(pop_size), _param(n)
85 {
86 assert(n > 0);
87 }
88
89 param_type param() const
90 {
91 return _param;
92 }
93
94 void param(unsigned int n)
95 {
96 _param = param_type(n);
97 }
98
99 /* @brief Sample points in a discrete space, uniformely at random
100 * @remark a same coordinates can be sampled several times
101 *
102 * @tparam Cont a container of coordinates
103 * @tparam Generator a RandomNumberGenerator
104 *
105 * @param space coordinates to be sampled
106 * @param n the number of points to sample
107 * @param gen a random number generator
108 *
109 * @return a 'std::map<Cont::value_type, unsigned int>' giving the sampling intensities
110 * at the sampled coordinates.
111 */
112 template <typename Generator> auto operator()(Generator &gen) const
113 {
114 std::discrete_distribution<size_t> dist(_weights.begin(), _weights.end());
115 std::map<coord_type, unsigned int> sample;
116 unsigned int i = 0;
117 unsigned int nb_try = 0;
118 while (i < _param.sampling_size() && nb_try < 10 * (_param.sampling_size()))
119 {
120 auto id = dist(gen);
121 if (sample[_space[id]] < _population_size(_space[id]))
122 {
123 sample[_space[id]] += 1;
124 ++i;
125 }
126 ++nb_try;
127 }
128 if (sample.empty())
129 {
130 throw std::logic_error("Sampling scheme unable to populate a sample.");
131 }
132 return sample;
133 }
134
135}; // constrained_sampling
136
137template <typename X, typename F, typename N>
138auto make_constrained_sampler(std::vector<X> const &space, F f, N pop_size, unsigned int n)
139{
140 if (space.empty())
141 {
142 throw std::logic_error("Space for sampling scheme is empty.");
143 }
144 return constrained_sampling<X, N>(space, f, pop_size, n);
145}
146
147template <typename X, typename N>
148auto make_unif_constrained_sampler(std::vector<X> const &space, N pop_size, unsigned int n)
149{
150 if (space.empty())
151 {
152 throw std::logic_error("Space for sampling scheme is empty.");
153 }
154 auto uniform_weighting = [](X) -> double { return 1.0; };
155 return constrained_sampling<X, N>(space, uniform_weighting, pop_size, n);
156}
157
158} // namespace quetzal::sampling
159
160#endif
Policy to sample coordinates at random in a space.
Definition sampling_scheme.hpp:51
Base class for sampling schemes parameter classes.
Definition sampling_scheme.hpp:20
Sampling schemes for Pseudo-Observed Data generation.
Definition sampling.hpp:15