Kea 1.5.0
random_number_generator.h
Go to the documentation of this file.
1// Copyright (C) 2010-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#ifndef NSAS_RANDOM_NUMBER_GENERATOR_H
8#define NSAS_RANDOM_NUMBER_GENERATOR_H
9
10#include <algorithm>
11#include <cmath>
12#include <iterator>
13#include <numeric>
14#include <vector>
15
17
18#include <boost/random/mersenne_twister.hpp>
19#include <boost/random/uniform_int.hpp>
20#include <boost/random/uniform_real.hpp>
21#include <boost/random/variate_generator.hpp>
22
24
25namespace isc {
26namespace util {
27namespace random {
28
30public:
31 InvalidLimits(const char* file, size_t line, const char* what) :
32 isc::BadValue(file, line, what) {}
33};
34
35class SumNotOne : public isc::BadValue {
36public:
37 SumNotOne(const char* file, size_t line, const char* what) :
38 isc::BadValue(file, line, what) {}
39};
40
42public:
43 InvalidProbValue(const char* file, size_t line, const char* what) :
44 isc::BadValue(file, line, what) {}
45};
46
47
48
53public:
59 min_(std::min(min, max)), max_(std::max(min, max)),
60 dist_(min_, max_), generator_(rng_, dist_)
61 {
62 // To preserve the restriction of the underlying uniform_int class (and
63 // to retain compatibility with earlier versions of the class), we will
64 // abort if the minimum and maximum given are the wrong way round.
65 if (min > max) {
66 isc_throw(InvalidLimits, "minimum limit is greater than maximum "
67 "when initializing UniformRandomIntegerGenerator");
68 }
69
70 // Init with the current time
71 rng_.seed(time(NULL));
72 }
73
75 int operator()() { return generator_(); }
76private:
80
81 int min_;
82 int max_;
83 boost::uniform_int<> dist_;
84 boost::mt19937 rng_;
85 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > generator_;
86};
87
92public:
102 WeightedRandomIntegerGenerator(const std::vector<double>& probabilities,
103 size_t min = 0):
104 dist_(0, 1.0), uniform_real_gen_(rng_, dist_), min_(min)
105 {
106 // The probabilities must be valid. Checking is quite an expensive
107 // operation, so is only done in a debug build.
108 assert(areProbabilitiesValid(probabilities));
109
110 // Calculate the partial sum of probabilities
111 std::partial_sum(probabilities.begin(), probabilities.end(),
112 std::back_inserter(cumulative_));
113 // Init with the current time
114 rng_.seed(time(NULL));
115 }
116
120 dist_(0, 1.0), uniform_real_gen_(rng_, dist_), min_(0)
121 {
122 }
123
129 void reset(const std::vector<double>& probabilities, size_t min = 0)
130 {
131 // The probabilities must be valid.
132 assert(areProbabilitiesValid(probabilities));
133
134 // Reset the cumulative sum
135 cumulative_.clear();
136
137 // Calculate the partial sum of probabilities
138 std::partial_sum(probabilities.begin(), probabilities.end(),
139 std::back_inserter(cumulative_));
140
141 // Reset the minimum integer
142 min_ = min;
143 }
144
146 size_t operator()()
147 {
148 return std::lower_bound(cumulative_.begin(), cumulative_.end(), uniform_real_gen_())
149 - cumulative_.begin() + min_;
150 }
151
152private:
164 bool areProbabilitiesValid(const std::vector<double>& probabilities) const
165 {
166 typedef std::vector<double>::const_iterator Iterator;
167 double sum = probabilities.empty() ? 1.0 : 0.0;
168 for(Iterator it = probabilities.begin(); it != probabilities.end(); ++it){
169 //The probability must be in [0, 1.0]
170 if(*it < 0.0 || *it > 1.0) {
172 "probability must be in the range 0..1");
173 }
174
175 sum += *it;
176 }
177
178 double epsilon = 0.0001;
179 // The sum must be equal to 1
180 if (std::fabs(sum - 1.0) >= epsilon) {
181 isc_throw(SumNotOne, "Sum of probabilities is not equal to 1");
182 }
183
184 return true;
185 }
186
187 std::vector<double> cumulative_;
188 boost::mt19937 rng_;
189 boost::uniform_real<> dist_;
190
191 // Shortcut typedef
192 // This typedef is placed directly before its use, as the sunstudio
193 // compiler could not handle it being anywhere else (don't know why)
194 typedef boost::variate_generator<boost::mt19937&, boost::uniform_real<> > UniformRealGenerator;
195 UniformRealGenerator uniform_real_gen_;
196
197 size_t min_;
198};
199
200} // namespace random
201} // namespace util
202} // namespace isc
203
204#endif//NSAS_RANDOM_NUMBER_GENERATOR_H
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
InvalidLimits(const char *file, size_t line, const char *what)
InvalidProbValue(const char *file, size_t line, const char *what)
SumNotOne(const char *file, size_t line, const char *what)
int operator()()
Generate uniformly distributed integer.
size_t operator()()
Generate weighted random integer.
WeightedRandomIntegerGenerator(const std::vector< double > &probabilities, size_t min=0)
Constructor.
void reset(const std::vector< double > &probabilities, size_t min=0)
Reset the probabilities.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-dhcp-ddns.