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&, boost::random::normal_distribution<> > NormalDist;
18
19/// A random number generator.
21 friend class ::SimInitTest;
22 friend class ::RandomTest;
23
24 // all distributions are fiends
25 friend class FixedDoubleDist;
26 friend class UniformDoubleDist;
27 friend class NormalDoubleDist;
28 friend class PoissonDoubleDist;
30 friend class BinaryDoubleDist;
31 friend class FixedIntDist;
32 friend class UniformIntDist;
33 friend class NormalIntDist;
34 friend class BinomialIntDist;
36 friend class PoissonIntDist;
37 friend class ExponentialIntDist;
38 friend class BinaryIntDist;
39
40 private:
41 /// Returns a random number for use in a distribution
42 static Generator gen_;
43
44 public:
45 /// Initialize from seed
46 void Initialize(SimInfo si);
47
48 std::uint32_t random();
49
50 // in archetype code
51 //
52 // #include "random_number_generator.h"
53 //
54 // class Foo:
55 // private:
56 // NormalDist myNormalDist;
57 //
58 // Foo::Foo() {
59 // myNormalDist = RandomNumberGenerator::makeNormalDist(mean, std_dev, min, max);
60 // }
61 //
62 // void Foo::Tick() {
63 // bar = myNormalDist();
64 // }
65 //
66
67 static NormalDist makeNormalDist(double mean, double std_dev, double min, double max) {
68 boost::random::normal_distribution<> dist(mean, std_dev);
69 NormalDist rn(gen_, dist);
70
71 return rn;
72 }
73
74 /// wrappers for boost::random distributions
75
76 /// generate a random number between [0, 1)
77 double random_01();
78
79 /// generate a random integer between [low, high)
80 int random_uniform_int(int low, int high);
81
82 /// generate a random real number between [low, high)
83 double random_uniform_real(double low, double high);
84
85 /// generate a double from a normal distribution, with truncation
86 /// at low and high
87 double random_normal_real(double mean, double std_dev, double low=0,
88 double high=std::numeric_limits<double>::max());
89
90 /// generates an integer from a normal distribution, with truncation
91 /// uses rounding to convert double to int
92 int random_normal_int(double mean, double std_dev, int low=0,
93 int high=std::numeric_limits<int>::max());
94
95};
96
98 public:
99 typedef boost::shared_ptr<DoubleDistribution> Ptr;
100
101 virtual double sample() = 0;
102 virtual double max() = 0;
103};
104
106 private:
107 double value;
108 public:
109 typedef boost::shared_ptr<FixedDoubleDist> Ptr;
110
111 FixedDoubleDist(double value_) : value(value_) {};
112 virtual double sample() { return value; };
113 virtual double max() { return value; };
114};
115
117 private:
118 boost::random::uniform_real_distribution<> dist;
119 public:
120 typedef boost::shared_ptr<UniformDoubleDist> Ptr;
121
122 UniformDoubleDist(double min = 0, double max=1) : dist(min, max) {};
123 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
124 virtual double max() { return dist.max(); }
125};
126
128 private:
129 boost::random::normal_distribution<> dist;
130 double min_;
131 double max_;
132 public:
133 typedef boost::shared_ptr<NormalDoubleDist> Ptr;
134
135 NormalDoubleDist(double mean, double std_dev, double min=0, double max=1) : dist(mean, std_dev), min_(min), max_(max) {
136 if (min_ == max_) {
137 throw ValueError("Min and max cannot be equal for a normal distribution. Either use FixedDoubleDist or change the min/max.");
138 }
139 if (max_ < (mean - 3*std_dev) || min_ > (mean + 3*std_dev)) {
140 Warn<VALUE_WARNING>("Dist is sampling from a tail of a truncated normal more than 3 standard deviations from the mean. Drawing sampling may be inefficient");
141 }
142 };
143 virtual double sample();
144 virtual double max() { return max_; }
145};
146
147/// Poisson distribution requires a mean
149 private:
150 boost::random::poisson_distribution<> dist;
151 double mean_;
152 public:
153 typedef boost::shared_ptr<PoissonDoubleDist> Ptr;
154
155 PoissonDoubleDist(double mean) : dist(mean_) {
156 if (mean_ < 0) {
157 throw ValueError("Mean must be positive");
158 }
159 };
160 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
161 virtual double mean() { return dist.mean(); }
162};
163
164/// Exponential distribution requires lambda
166 private:
167 boost::random::exponential_distribution<> dist;
168 double lambda_;
169 public:
170 typedef boost::shared_ptr<ExponentialDoubleDist> Ptr;
171
172 ExponentialDoubleDist(double lambda) : dist(lambda), lambda_(lambda) {
173 if (lambda_ < 0) {
174 throw ValueError("Lambda must be positive");
175 }
176 };
177 virtual double sample() { return dist(RandomNumberGenerator::gen_); }
178 virtual double lambda() { return lambda_; }
179};
180
181
182/// Binary distribution requires twp options and a probability
184 private:
185 boost::random::binomial_distribution<int> dist;
186 double p_success_;
187 double choice_a_, choice_b_;
188 public:
189
190 BinaryDoubleDist(double p_success, double choice_a, double choice_b) :
191 dist(1, p_success),choice_a_(choice_a), choice_b_(choice_b) {
192 if (p_success < 0) {
193 throw ValueError("Probability of choice A must be positive");
194 }
195 };
196 virtual double sample() {
197 return dist(RandomNumberGenerator::gen_) ? choice_a_ : choice_b_; }
198 virtual double p() { return p_success_; }
199};
200
202 public:
203 typedef boost::shared_ptr<IntDistribution> Ptr;
204 virtual int sample() = 0;
205};
206
208 private:
209 int value;
210 public:
211 typedef boost::shared_ptr<FixedIntDist> Ptr;
212
213 FixedIntDist(int value_) : value(value_) {};
214 virtual int sample() { return value; };
215};
216
218 private:
219 boost::random::uniform_int_distribution<> dist;
220 public:
221 typedef boost::shared_ptr<UniformIntDist> Ptr;
222
223 UniformIntDist(int min = 0, int max=1) : dist(min, max) {};
224 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
225 virtual int max() { return dist.max(); }
226};
227
229 private:
230 boost::random::normal_distribution<> dist;
231 int min_;
232 int max_;
233 public:
234 typedef boost::shared_ptr<NormalIntDist> Ptr;
235
236 NormalIntDist(double mean, double std_dev, int min=0, int max=1) : dist(mean, std_dev), min_(min), max_(max) {
237 if (min_ == max_) {
238 throw ValueError("Min and max cannot be equal for a normal distribution. Either use FixedIntDist or change the min/max.");
239 }
240 if (max_ < (mean - 3*std_dev) || min_ > (mean + 3*std_dev)) {
241 Warn<VALUE_WARNING>("Dist is sampling from a tail of a truncated normal more than 3 standard deviations from the mean. Drawing sampling may be inefficient");
242 }
243 };
244 virtual int sample();
245 virtual int max() { return max_; }
246};
247
248/// Binomial distribution requries an integer number of trials and a
249/// probability of success for each trial. Sampling returns the number of
250/// successes. When trials is one, this is equivalent to a Bernoulli dist
252 private:
253 boost::random::binomial_distribution<int> dist;
254 int trials_;
255 double p_success_;
256 public:
257 typedef boost::shared_ptr<BinomialIntDist> Ptr;
258
259 BinomialIntDist(int trials, double p_success) : dist(trials, p_success), trials_(trials), p_success_(p_success) {
260 if (trials_ < 1) {
261 throw ValueError("Max must be positive and greater than zero");
262 }
263 if (p_success_ > 1 || p_success_ < 0) {
264 throw ValueError("Probability must be between zero and one");
265 }
266 };
267 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
268 virtual int trials() { return trials_; }
269 virtual int p() { return p_success_; }
270};
271
272/// NegativeBinomialIntDist takes the number of successes desired and a
273/// probability of success on a single trial and returns the number of trials
274/// needed to reach the desired successes. When successes is one, this is
275/// equivalent to a Geometric distribution.
277 private:
278 boost::random::negative_binomial_distribution<> dist;
279 int successes_;
280 double p_success_;
281 public:
282 typedef boost::shared_ptr<NegativeBinomialIntDist> Ptr;
283
284 NegativeBinomialIntDist(int successes, double p_success) : dist(successes, p_success), successes_(successes), p_success_(p_success) {
285 if (successes < 1) {
286 throw ValueError("Successes 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 successes() { return successes_; }
294 virtual int p() { return p_success_; }
295};
296
297/// Poisson distribution requires a mean
299 private:
300 boost::random::poisson_distribution<> dist;
301 double mean_;
302 public:
303 typedef boost::shared_ptr<PoissonIntDist> Ptr;
304
305 PoissonIntDist(double mean) : dist(mean_) {
306 if (mean_ < 0) {
307 throw ValueError("Mean must be positive");
308 }
309 };
310 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
311 virtual double mean() { return dist.mean(); }
312};
313
314/// Exponential distribution requires lambda
316 private:
317 boost::random::exponential_distribution<> dist;
318 double lambda_;
319 public:
320 typedef boost::shared_ptr<ExponentialIntDist> Ptr;
321
322 ExponentialIntDist(double lambda) : dist(lambda), lambda_(lambda) {
323 if (lambda_ < 0) {
324 throw ValueError("Lambda must be positive");
325 }
326 };
327 virtual int sample() { return dist(RandomNumberGenerator::gen_); }
328 virtual double lambda() { return lambda_; }
329};
330
331/// Binary distribution requires twp options and a probability
333 private:
334 boost::random::binomial_distribution<int> dist;
335 double p_success_;
336 int choice_a_, choice_b_;
337 public:
338
339 BinaryIntDist(double p_success, int choice_a, int choice_b) :
340 dist(1, p_success),choice_a_(choice_a), choice_b_(choice_b) {
341 if (p_success < 0) {
342 throw ValueError("Probability of choice A must be positive");
343 }
344 };
345 virtual int sample() {
346 return dist(RandomNumberGenerator::gen_) ? choice_a_ : choice_b_; }
347 virtual double p() { return p_success_; }
348};
349
350
351}
352
353#endif // CYCLUS_SRC_RNG_H
Binary distribution requires twp options and a probability.
BinaryDoubleDist(double p_success, double choice_a, double choice_b)
Binary distribution requires twp options and a probability.
BinaryIntDist(double p_success, int choice_a, int choice_b)
Binomial distribution requries an integer number of trials and a probability of success for each tria...
boost::shared_ptr< BinomialIntDist > Ptr
BinomialIntDist(int trials, double p_success)
virtual double max()=0
boost::shared_ptr< DoubleDistribution > Ptr
virtual double sample()=0
Exponential distribution requires lambda.
boost::shared_ptr< ExponentialDoubleDist > Ptr
Exponential distribution requires lambda.
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 takes the number of successes desired and a probability of success on a singl...
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
Poisson distribution requires a mean.
boost::shared_ptr< PoissonDoubleDist > Ptr
Poisson distribution requires a mean.
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:45
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:41
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:115