Kea 2.2.0
random_number_generator.h
Go to the documentation of this file.
1// Copyright (C) 2010-2021 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 perfdhcp {
27
29public:
30 InvalidLimits(const char* file, size_t line, const char* what) :
31 isc::BadValue(file, line, what) {}
32};
33
34class SumNotOne : public isc::BadValue {
35public:
36 SumNotOne(const char* file, size_t line, const char* what) :
37 isc::BadValue(file, line, what) {}
38};
39
41public:
42 InvalidProbValue(const char* file, size_t line, const char* what) :
43 isc::BadValue(file, line, what) {}
44};
45
46
47
52public:
58 min_(std::min(min, max)), max_(std::max(min, max)),
59 dist_(min_, max_), generator_(rng_, dist_)
60 {
61 // To preserve the restriction of the underlying uniform_int class (and
62 // to retain compatibility with earlier versions of the class), we will
63 // abort if the minimum and maximum given are the wrong way round.
64 if (min > max) {
65 isc_throw(InvalidLimits, "minimum limit is greater than maximum "
66 "when initializing UniformRandomIntegerGenerator");
67 }
68
69 // Init with the current time
70 rng_.seed(time(NULL));
71 }
72
74 int operator()() { return generator_(); }
75private:
79
80 int min_;
81 int max_;
82 boost::uniform_int<> dist_;
83 boost::mt19937 rng_;
84 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > generator_;
85};
86
91public:
101 WeightedRandomIntegerGenerator(const std::vector<double>& probabilities,
102 size_t min = 0):
103 dist_(0, 1.0), uniform_real_gen_(rng_, dist_), min_(min)
104 {
105 // The probabilities must be valid. Checking is quite an expensive
106 // operation, so is only done in a debug build.
107 areProbabilitiesValid(probabilities);
108
109 // Calculate the partial sum of probabilities
110 std::partial_sum(probabilities.begin(), probabilities.end(),
111 std::back_inserter(cumulative_));
112 // Init with the current time
113 rng_.seed(time(NULL));
114 }
115
119 dist_(0, 1.0), uniform_real_gen_(rng_, dist_), min_(0)
120 {
121 }
122
128 void reset(const std::vector<double>& probabilities, size_t min = 0)
129 {
130 // The probabilities must be valid.
131 areProbabilitiesValid(probabilities);
132
133 // Reset the cumulative sum
134 cumulative_.clear();
135
136 // Calculate the partial sum of probabilities
137 std::partial_sum(probabilities.begin(), probabilities.end(),
138 std::back_inserter(cumulative_));
139
140 // Reset the minimum integer
141 min_ = min;
142 }
143
145 size_t operator()()
146 {
147 return std::lower_bound(cumulative_.begin(), cumulative_.end(), uniform_real_gen_())
148 - cumulative_.begin() + min_;
149 }
150
151private:
164 void areProbabilitiesValid(const std::vector<double>& probabilities) const
165 {
166 double sum = probabilities.empty() ? 1.0 : 0.0;
167 for (const double it : probabilities) {
168 //The probability must be in [0, 1.0]
169 if (it < 0.0 || it > 1.0) {
171 "probability must be in the range 0..1");
172 }
173
174 sum += it;
175 }
176
177 double epsilon = 0.0001;
178 // The sum must be equal to 1
179 if (std::fabs(sum - 1.0) >= epsilon) {
180 isc_throw(SumNotOne, "Sum of probabilities is not equal to 1");
181 }
182
183 return;
184 }
185
186 std::vector<double> cumulative_;
187 boost::mt19937 rng_;
188 boost::uniform_real<> dist_;
189
190 // Shortcut typedef
191 // This typedef is placed directly before its use, as the sunstudio
192 // compiler could not handle it being anywhere else (don't know why)
193 typedef boost::variate_generator<boost::mt19937&, boost::uniform_real<> > UniformRealGenerator;
194 UniformRealGenerator uniform_real_gen_;
195
196 size_t min_;
197};
198
199} // namespace perfdhcp
200} // namespace isc
201
202#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.
UniformRandomIntegerGenerator(int min, int max)
Constructor.
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.
size_t operator()()
Generate weighted random integer.
#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-lfc.