CYCLUS
Loading...
Searching...
No Matches
random_number_generator.h
Go to the documentation of this file.
1#ifndef CYCLUS_SRC_RNG_H
2#define CYCLUS_SRC_RNG_H
3
4#include <boost/random.hpp>
5#include <cstdint>
6
7#include "error.h"
8
9class SimInitTest;
10class RandomTest;
11
12namespace cyclus {
13
14class SimInfo;
15
16typedef boost::random::mt19937 Generator;
17typedef boost::random::variate_generator<Generator&,
18 boost::random::normal_distribution<>>
20
21/// A random number generator.
23 friend class ::SimInitTest;
24 friend class ::RandomTest;
25
26 // all distributions are fiends
27 friend class FixedDoubleDist;
28 friend class UniformDoubleDist;
29 friend class NormalDoubleDist;
30 friend class PoissonDoubleDist;
32 friend class BinaryDoubleDist;
33 friend class FixedIntDist;
34 friend class UniformIntDist;
35 friend class NormalIntDist;
36 friend class BinomialIntDist;
38 friend class PoissonIntDist;
39 friend class ExponentialIntDist;
40 friend class BinaryIntDist;
41
42 private:
43 /// Returns a random number for use in a distribution
44 static Generator gen_;
45
46 public:
47 /// Initialize from seed
48 void Initialize(SimInfo si);
49
50 std::uint32_t random();
51
52 // in archetype code
53 //
54 // #include "random_number_generator.h"
55 //
56 // class Foo:
57 // private:
58 // NormalDist myNormalDist;
59 //
60 // Foo::Foo() {
61 // myNormalDist = RandomNumberGenerator::makeNormalDist(mean, std_dev, min,
62 // max);
63 // }
64 //
65 // void Foo::Tick() {
66 // bar = myNormalDist();
67 // }
68 //
69
70 static NormalDist makeNormalDist(double mean, double std_dev, double min,
71 double max) {
72 boost::random::normal_distribution<> dist(mean, std_dev);
73 NormalDist rn(gen_, dist);
74
75 return rn;
76 }
77
78 /// wrappers for boost::random distributions
79
80 /// generate a random number between [0, 1)
81 double random_01();
82
83 /// generate a random integer between [low, high)
84 int random_uniform_int(int low, int high);
85
86 /// generate a random real number between [low, high)
87 double random_uniform_real(double low, double high);
88
89 /// generate a double from a normal distribution, with truncation
90 /// at low and high
91 double random_normal_real(double mean, double std_dev, double low = 0,
92 double high = std::numeric_limits<double>::max());
93
94 /// generates an integer from a normal distribution, with truncation
95 /// uses rounding to convert double to int
96 int random_normal_int(double mean, double std_dev, int low = 0,
97 int high = std::numeric_limits<int>::max());
98};
99
101 public:
102 typedef boost::shared_ptr<DoubleDistribution> Ptr;
103
104 virtual double sample() = 0;
105 virtual double max() = 0;
106};
107
109 private:
110 double value;
111
112 public:
113 typedef boost::shared_ptr<FixedDoubleDist> Ptr;
114
115 FixedDoubleDist(double value_) : value(value_){};
116 virtual double sample() { return value; };
117 virtual double max() { return value; };
118};
119
121 private:
122 boost::random::uniform_real_distribution<> dist;
123
124 public:
125 typedef boost::shared_ptr<UniformDoubleDist> Ptr;
126
127 UniformDoubleDist(double min = 0, double max = 1) : dist(min, max){};
128 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
129 virtual double max() { return dist.max(); }
130};
131
133 private:
134 boost::random::normal_distribution<> dist;
135 double min_;
136 double max_;
137
138 public:
139 typedef boost::shared_ptr<NormalDoubleDist> Ptr;
140
141 NormalDoubleDist(double mean, double std_dev, double min = 0, double max = 1)
142 : dist(mean, std_dev), min_(min), max_(max) {
143 if (min_ == max_) {
144 throw ValueError(
145 "Min and max cannot be equal for a normal distribution. Either use "
146 "FixedDoubleDist or change the min/max.");
147 }
148 if (max_ < (mean - 3 * std_dev) || min_ > (mean + 3 * std_dev)) {
150 "Dist is sampling from a tail of a truncated normal more than 3 "
151 "standard deviations from the mean. Drawing sampling may be "
152 "inefficient");
153 }
154 };
155 virtual double sample();
156 virtual double max() { return max_; }
157};
158
159/// Poisson distribution requires a mean
161 private:
162 boost::random::poisson_distribution<> dist;
163 double mean_;
164
165 public:
166 typedef boost::shared_ptr<PoissonDoubleDist> Ptr;
167
168 PoissonDoubleDist(double mean) : dist(mean_) {
169 if (mean_ < 0) {
170 throw ValueError("Mean must be positive");
171 }
172 };
173 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
174 virtual double mean() { return dist.mean(); }
175};
176
177/// Exponential distribution requires lambda
179 private:
180 boost::random::exponential_distribution<> dist;
181 double lambda_;
182
183 public:
184 typedef boost::shared_ptr<ExponentialDoubleDist> Ptr;
185
186 ExponentialDoubleDist(double lambda) : dist(lambda), lambda_(lambda) {
187 if (lambda_ < 0) {
188 throw ValueError("Lambda must be positive");
189 }
190 };
191 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
192 virtual double lambda() { return lambda_; }
193};
194
195/// Binary distribution requires twp options and a probability
197 private:
198 boost::random::binomial_distribution<int> dist;
199 double p_success_;
200 double choice_a_, choice_b_;
201
202 public:
203 BinaryDoubleDist(double p_success, double choice_a, double choice_b)
204 : dist(1, p_success), choice_a_(choice_a), choice_b_(choice_b) {
205 if (p_success < 0) {
206 throw ValueError("Probability of choice A must be positive");
207 }
208 };
209 virtual double sample() {
210 return dist(RandomNumberGenerator::gen_) ? choice_a_ : choice_b_;
211 }
212 virtual double p() { return p_success_; }
213};
214
216 public:
217 typedef boost::shared_ptr<IntDistribution> Ptr;
218 virtual int sample() = 0;
219};
220
222 private:
223 int value;
224
225 public:
226 typedef boost::shared_ptr<FixedIntDist> Ptr;
227
228 FixedIntDist(int value_) : value(value_){};
229 virtual int sample() { return value; };
230};
231
233 private:
234 boost::random::uniform_int_distribution<> dist;
235
236 public:
237 typedef boost::shared_ptr<UniformIntDist> Ptr;
238
239 UniformIntDist(int min = 0, int max = 1) : dist(min, max){};
240 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
241 virtual int max() { return dist.max(); }
242};
243
245 private:
246 boost::random::normal_distribution<> dist;
247 int min_;
248 int max_;
249
250 public:
251 typedef boost::shared_ptr<NormalIntDist> Ptr;
252
253 NormalIntDist(double mean, double std_dev, int min = 0, int max = 1)
254 : dist(mean, std_dev), min_(min), max_(max) {
255 if (min_ == max_) {
256 throw ValueError(
257 "Min and max cannot be equal for a normal distribution. Either use "
258 "FixedIntDist or change the min/max.");
259 }
260 if (max_ < (mean - 3 * std_dev) || min_ > (mean + 3 * std_dev)) {
262 "Dist is sampling from a tail of a truncated normal more than 3 "
263 "standard deviations from the mean. Drawing sampling may be "
264 "inefficient");
265 }
266 };
267 virtual int sample();
268 virtual int max() { return max_; }
269};
270
271/// Binomial distribution requries an integer number of trials and a
272/// probability of success for each trial. Sampling returns the number of
273/// successes. When trials is one, this is equivalent to a Bernoulli dist
275 private:
276 boost::random::binomial_distribution<int> dist;
277 int trials_;
278 double p_success_;
279
280 public:
281 typedef boost::shared_ptr<BinomialIntDist> Ptr;
282
283 BinomialIntDist(int trials, double p_success)
284 : dist(trials, p_success), trials_(trials), p_success_(p_success) {
285 if (trials_ < 1) {
286 throw ValueError("Max must be positive and greater than zero");
287 }
288 if (p_success_ > 1 || p_success_ < 0) {
289 throw ValueError("Probability must be between zero and one");
290 }
291 };
292 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
293 virtual int trials() { return trials_; }
294 virtual int p() { return p_success_; }
295};
296
297/// NegativeBinomialIntDist takes the number of successes desired and a
298/// probability of success on a single trial and returns the number of trials
299/// needed to reach the desired successes. When successes is one, this is
300/// equivalent to a Geometric distribution.
302 private:
303 boost::random::negative_binomial_distribution<> dist;
304 int successes_;
305 double p_success_;
306
307 public:
308 typedef boost::shared_ptr<NegativeBinomialIntDist> Ptr;
309
310 NegativeBinomialIntDist(int successes, double p_success)
311 : dist(successes, p_success),
312 successes_(successes),
313 p_success_(p_success) {
314 if (successes < 1) {
315 throw ValueError("Successes must be positive and greater than zero");
316 }
317 if (p_success > 1 || p_success < 0) {
318 throw ValueError("Probability must be between zero and one");
319 }
320 };
321 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
322 virtual int successes() { return successes_; }
323 virtual int p() { return p_success_; }
324};
325
326/// Poisson distribution requires a mean
328 private:
329 boost::random::poisson_distribution<> dist;
330 double mean_;
331
332 public:
333 typedef boost::shared_ptr<PoissonIntDist> Ptr;
334
335 PoissonIntDist(double mean) : dist(mean_) {
336 if (mean_ < 0) {
337 throw ValueError("Mean must be positive");
338 }
339 };
340 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
341 virtual double mean() { return dist.mean(); }
342};
343
344/// Exponential distribution requires lambda
346 private:
347 boost::random::exponential_distribution<> dist;
348 double lambda_;
349
350 public:
351 typedef boost::shared_ptr<ExponentialIntDist> Ptr;
352
353 ExponentialIntDist(double lambda) : dist(lambda), lambda_(lambda) {
354 if (lambda_ < 0) {
355 throw ValueError("Lambda must be positive");
356 }
357 };
358 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
359 virtual double lambda() { return lambda_; }
360};
361
362/// Binary distribution requires twp options and a probability
364 private:
365 boost::random::binomial_distribution<int> dist;
366 double p_success_;
367 int choice_a_, choice_b_;
368
369 public:
370 BinaryIntDist(double p_success, int choice_a, int choice_b)
371 : dist(1, p_success), choice_a_(choice_a), choice_b_(choice_b) {
372 if (p_success < 0) {
373 throw ValueError("Probability of choice A must be positive");
374 }
375 };
376 virtual int sample() {
377 return dist(RandomNumberGenerator::gen_) ? choice_a_ : choice_b_;
378 }
379 virtual double p() { return p_success_; }
380};
381
382} // namespace cyclus
383
384#endif // CYCLUS_SRC_RNG_H
BinaryDoubleDist(double p_success, double choice_a, double choice_b)
BinaryIntDist(double p_success, int choice_a, int choice_b)
boost::shared_ptr< BinomialIntDist > Ptr
BinomialIntDist(int trials, double p_success)
virtual double max()=0
boost::shared_ptr< DoubleDistribution > Ptr
virtual double sample()=0
boost::shared_ptr< ExponentialDoubleDist > Ptr
boost::shared_ptr< ExponentialIntDist > Ptr
boost::shared_ptr< FixedDoubleDist > Ptr
boost::shared_ptr< FixedIntDist > Ptr
boost::shared_ptr< IntDistribution > Ptr
virtual int sample()=0
NegativeBinomialIntDist(int successes, double p_success)
boost::shared_ptr< NegativeBinomialIntDist > Ptr
boost::shared_ptr< NormalDoubleDist > Ptr
NormalDoubleDist(double mean, double std_dev, double min=0, double max=1)
NormalIntDist(double mean, double std_dev, int min=0, int max=1)
boost::shared_ptr< NormalIntDist > Ptr
boost::shared_ptr< PoissonDoubleDist > Ptr
boost::shared_ptr< PoissonIntDist > Ptr
double random_01()
wrappers for boost::random distributions
int random_uniform_int(int low, int high)
generate a random integer between [low, high)
double random_uniform_real(double low, double high)
generate a random real number between [low, high)
void Initialize(SimInfo si)
Initialize from seed.
double random_normal_real(double mean, double std_dev, double low=0, double high=std::numeric_limits< double >::max())
generate a double from a normal distribution, with truncation at low and high
int random_normal_int(double mean, double std_dev, int low=0, int high=std::numeric_limits< int >::max())
generates an integer from a normal distribution, with truncation uses rounding to convert double to i...
static NormalDist makeNormalDist(double mean, double std_dev, double min, double max)
Container for a static simulation-global parameters that both describe the simulation and affect its ...
Definition context.h:49
boost::shared_ptr< UniformDoubleDist > Ptr
UniformDoubleDist(double min=0, double max=1)
boost::shared_ptr< UniformIntDist > Ptr
UniformIntDist(int min=0, int max=1)
For values that are too big, too small, etc.
Definition error.h:37
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or....
Definition agent.cc:14
boost::random::mt19937 Generator
boost::random::variate_generator< Generator &, boost::random::normal_distribution<> > NormalDist
void Warn(const std::string &msg)
Issue a warning with the approriate message, accoring to the current warning settings.
Definition error.h:108