Medusa  1.1
Coordinate Free Mehless Method implementation
randutils.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_UTILS_RANDUTILS_HPP_
2 #define MEDUSA_BITS_UTILS_RANDUTILS_HPP_
3 
11 #include <medusa/Config.hpp>
14 #include <random>
15 #include <chrono>
16 
17 namespace mm {
18 
25 inline unsigned int get_seed() {
26  try {
27  std::random_device rd;
28  return rd();
29  } catch (std::exception& e) {
30  return std::chrono::system_clock::now().time_since_epoch().count();
31  }
32 }
33 
34 template <typename T, typename URNG>
35 T random_choice(const Range<T>& elements, const Range<double>& weights, bool normed,
36  URNG& generator);
37 
50 template <typename T>
51 T random_choice(const Range<T>& elements, const Range<double>& weights = {},
52  bool normed = false) {
53  std::mt19937 generator(get_seed());
54  return random_choice(elements, weights, normed, generator);
55 }
56 
58 template <typename T, typename URNG>
59 T random_choice(const Range<T>& elements, const Range<double>& weights, bool normed,
60  URNG& generator) {
61  Range<double> actual_weights = weights;
62  if (actual_weights.empty()) {
63  normed = true;
64  actual_weights.assign(elements.size(), 1.0 / elements.size());
65  }
66  assert_msg(actual_weights.size() == elements.size(),
67  "Weights not specified for all elements. Got %d weights but %d elements.",
68  weights.size(), elements.size());
69  if (!normed) { // must be 0.0 so that the inferred type is double
70  double sum = std::accumulate(actual_weights.begin(), actual_weights.end(), 0.0);
71  for (auto& w : actual_weights) w /= sum;
72  }
73  std::uniform_real_distribution<double> uniform(0, 1);
74  double x = uniform(generator);
75  for (int i = 0; i < elements.size(); ++i) {
76  if (x < actual_weights[i]) return elements[i];
77  x -= actual_weights[i];
78  }
79  assert_msg(false, "Should never get here, you might have claimed the weights "
80  "are normalized, but weren't.");
81  return elements[0];
82 }
83 
84 } // namespace mm
85 
86 #endif // MEDUSA_BITS_UTILS_RANDUTILS_HPP_
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
Config.hpp
mm::get_seed
unsigned int get_seed()
Return a random seed.
Definition: randutils.hpp:25
assert.hpp
mm::Range::size
int size() const
Returns number of elements.
Definition: Range_fwd.hpp:185
mm::Range< T >
mm::random_choice
T random_choice(const Range< T > &elements, const Range< double > &weights, bool normed, URNG &generator)
Overload for custom generator.
Definition: randutils.hpp:59
Range.hpp