1
1
//! Random variables underpin both stochastic and deterministic model
2
2
//! behaviors, in that deterministic operation is simply a random variable
3
3
//! with a single value of probability 1. Common distributions, with their
4
- //! common parameterizations, are wrapped in enums
5
- //! `ContinuousRandomVariable`, `BooleanRandomVariable`,
6
- //! `DiscreteRandomVariable`, and `IndexRandomVariable`.
4
+ //! common parameterizations, are wrapped in enums `Continuous`, `Boolean`,
5
+ //! `Discrete`, and `Index`.
7
6
8
7
use rand:: distributions:: Distribution ;
9
8
use serde:: { Deserialize , Serialize } ;
@@ -13,11 +12,11 @@ use rand_distr::{Beta, Exp, Gamma, LogNormal, Normal, Triangular, Uniform, Weibu
13
12
use rand_distr:: { Bernoulli , Geometric , Poisson , WeightedIndex } ;
14
13
15
14
use super :: UniformRNG ;
16
- use crate :: utils:: error :: SimulationError ;
15
+ use crate :: utils:: errors :: SimulationError ;
17
16
18
17
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
19
18
#[ serde( rename_all = "camelCase" ) ]
20
- pub enum ContinuousRandomVariable {
19
+ pub enum Continuous {
21
20
Beta { alpha : f64 , beta : f64 } ,
22
21
Exp { lambda : f64 } ,
23
22
Gamma { shape : f64 , scale : f64 } ,
@@ -30,13 +29,13 @@ pub enum ContinuousRandomVariable {
30
29
31
30
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
32
31
#[ serde( rename_all = "camelCase" ) ]
33
- pub enum BooleanRandomVariable {
32
+ pub enum Boolean {
34
33
Bernoulli { p : f64 } ,
35
34
}
36
35
37
36
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
38
37
#[ serde( rename_all = "camelCase" ) ]
39
- pub enum DiscreteRandomVariable {
38
+ pub enum Discrete {
40
39
Geometric {
41
40
p : f64 ,
42
41
} ,
@@ -52,7 +51,7 @@ pub enum DiscreteRandomVariable {
52
51
53
52
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
54
53
#[ serde( rename_all = "camelCase" ) ]
55
- pub enum IndexRandomVariable {
54
+ pub enum Index {
56
55
/// Range is inclusive of min, exclusive of max: [min, max)
57
56
Uniform {
58
57
min : usize ,
@@ -63,41 +62,39 @@ pub enum IndexRandomVariable {
63
62
} ,
64
63
}
65
64
66
- impl ContinuousRandomVariable {
65
+ impl Continuous {
67
66
/// The generation of random variates drives stochastic behaviors during
68
67
/// simulation execution. This function requires the random number
69
68
/// generator of the simulation, and produces a f64 random variate.
70
69
pub fn random_variate ( & mut self , uniform_rng : & mut UniformRNG ) -> Result < f64 , SimulationError > {
71
70
match self {
72
- ContinuousRandomVariable :: Beta { alpha, beta } => {
71
+ Continuous :: Beta { alpha, beta } => {
73
72
Ok ( Beta :: new ( * alpha, * beta) ?. sample ( uniform_rng. rng ( ) ) )
74
73
}
75
- ContinuousRandomVariable :: Exp { lambda } => {
76
- Ok ( Exp :: new ( * lambda) ?. sample ( uniform_rng. rng ( ) ) )
77
- }
78
- ContinuousRandomVariable :: Gamma { shape, scale } => {
74
+ Continuous :: Exp { lambda } => Ok ( Exp :: new ( * lambda) ?. sample ( uniform_rng. rng ( ) ) ) ,
75
+ Continuous :: Gamma { shape, scale } => {
79
76
Ok ( Gamma :: new ( * shape, * scale) ?. sample ( uniform_rng. rng ( ) ) )
80
77
}
81
- ContinuousRandomVariable :: LogNormal { mu, sigma } => {
78
+ Continuous :: LogNormal { mu, sigma } => {
82
79
Ok ( LogNormal :: new ( * mu, * sigma) ?. sample ( uniform_rng. rng ( ) ) )
83
80
}
84
- ContinuousRandomVariable :: Normal { mean, std_dev } => {
81
+ Continuous :: Normal { mean, std_dev } => {
85
82
Ok ( Normal :: new ( * mean, * std_dev) ?. sample ( uniform_rng. rng ( ) ) )
86
83
}
87
- ContinuousRandomVariable :: Triangular { min, max, mode } => {
84
+ Continuous :: Triangular { min, max, mode } => {
88
85
Ok ( Triangular :: new ( * min, * max, * mode) ?. sample ( uniform_rng. rng ( ) ) )
89
86
}
90
- ContinuousRandomVariable :: Uniform { min, max } => {
87
+ Continuous :: Uniform { min, max } => {
91
88
Ok ( Uniform :: new ( * min, * max) . sample ( uniform_rng. rng ( ) ) )
92
89
}
93
- ContinuousRandomVariable :: Weibull { shape, scale } => {
90
+ Continuous :: Weibull { shape, scale } => {
94
91
Ok ( Weibull :: new ( * shape, * scale) ?. sample ( uniform_rng. rng ( ) ) )
95
92
}
96
93
}
97
94
}
98
95
}
99
96
100
- impl BooleanRandomVariable {
97
+ impl Boolean {
101
98
/// The generation of random variates drives stochastic behaviors during
102
99
/// simulation execution. This function requires the random number
103
100
/// generator of the simulation, and produces a boolean random variate.
@@ -106,33 +103,29 @@ impl BooleanRandomVariable {
106
103
uniform_rng : & mut UniformRNG ,
107
104
) -> Result < bool , SimulationError > {
108
105
match self {
109
- BooleanRandomVariable :: Bernoulli { p } => {
110
- Ok ( Bernoulli :: new ( * p) ?. sample ( uniform_rng. rng ( ) ) )
111
- }
106
+ Boolean :: Bernoulli { p } => Ok ( Bernoulli :: new ( * p) ?. sample ( uniform_rng. rng ( ) ) ) ,
112
107
}
113
108
}
114
109
}
115
110
116
- impl DiscreteRandomVariable {
111
+ impl Discrete {
117
112
/// The generation of random variates drives stochastic behaviors during
118
113
/// simulation execution. This function requires the random number
119
114
/// generator of the simulation, and produces a u64 random variate.
120
115
pub fn random_variate ( & mut self , uniform_rng : & mut UniformRNG ) -> Result < u64 , SimulationError > {
121
116
match self {
122
- DiscreteRandomVariable :: Geometric { p } => {
123
- Ok ( Geometric :: new ( * p) ?. sample ( uniform_rng. rng ( ) ) )
124
- }
125
- DiscreteRandomVariable :: Poisson { lambda } => {
117
+ Discrete :: Geometric { p } => Ok ( Geometric :: new ( * p) ?. sample ( uniform_rng. rng ( ) ) ) ,
118
+ Discrete :: Poisson { lambda } => {
126
119
Ok ( Poisson :: new ( * lambda) ?. sample ( uniform_rng. rng ( ) ) as u64 )
127
120
}
128
- DiscreteRandomVariable :: Uniform { min, max } => {
121
+ Discrete :: Uniform { min, max } => {
129
122
Ok ( Uniform :: new ( * min, * max) . sample ( uniform_rng. rng ( ) ) )
130
123
}
131
124
}
132
125
}
133
126
}
134
127
135
- impl IndexRandomVariable {
128
+ impl Index {
136
129
/// The generation of random variates drives stochastic behaviors during
137
130
/// simulation execution. This function requires the random number
138
131
/// generator of the simulation, and produces a usize random variate.
@@ -141,10 +134,8 @@ impl IndexRandomVariable {
141
134
uniform_rng : & mut UniformRNG ,
142
135
) -> Result < usize , SimulationError > {
143
136
match self {
144
- IndexRandomVariable :: Uniform { min, max } => {
145
- Ok ( Uniform :: new ( * min, * max) . sample ( uniform_rng. rng ( ) ) )
146
- }
147
- IndexRandomVariable :: WeightedIndex { weights } => {
137
+ Index :: Uniform { min, max } => Ok ( Uniform :: new ( * min, * max) . sample ( uniform_rng. rng ( ) ) ) ,
138
+ Index :: WeightedIndex { weights } => {
148
139
Ok ( WeightedIndex :: new ( weights. clone ( ) ) ?. sample ( uniform_rng. rng ( ) ) )
149
140
}
150
141
}
@@ -156,25 +147,25 @@ mod tests {
156
147
use super :: * ;
157
148
158
149
enum RandomVariable {
159
- Continuous ( ContinuousRandomVariable ) ,
160
- Discrete ( DiscreteRandomVariable ) ,
150
+ Continuous ( Continuous ) ,
151
+ Discrete ( Discrete ) ,
161
152
}
162
153
163
154
enum ChiSquareTest {
164
155
Continuous {
165
- variable : ContinuousRandomVariable ,
156
+ variable : Continuous ,
166
157
bin_mapping_fn : fn ( f64 ) -> usize ,
167
158
} ,
168
159
Boolean {
169
- variable : BooleanRandomVariable ,
160
+ variable : Boolean ,
170
161
bin_mapping_fn : fn ( bool ) -> usize ,
171
162
} ,
172
163
Discrete {
173
- variable : DiscreteRandomVariable ,
164
+ variable : Discrete ,
174
165
bin_mapping_fn : fn ( u64 ) -> usize ,
175
166
} ,
176
167
Index {
177
- variable : IndexRandomVariable ,
168
+ variable : Index ,
178
169
bin_mapping_fn : fn ( usize ) -> usize ,
179
170
} ,
180
171
}
@@ -231,7 +222,7 @@ mod tests {
231
222
232
223
#[ test]
233
224
fn beta_samples_match_expectation ( ) {
234
- let variable = ContinuousRandomVariable :: Beta {
225
+ let variable = Continuous :: Beta {
235
226
alpha : 7.0 ,
236
227
beta : 11.0 ,
237
228
} ;
@@ -242,15 +233,15 @@ mod tests {
242
233
243
234
#[ test]
244
235
fn exponential_samples_match_expectation ( ) {
245
- let variable = ContinuousRandomVariable :: Exp { lambda : 7.0 } ;
236
+ let variable = Continuous :: Exp { lambda : 7.0 } ;
246
237
let mean = empirical_mean ( & mut RandomVariable :: Continuous ( variable) , 10000 ) ;
247
238
let expected = 1.0 / 7.0 ;
248
239
assert ! ( ( mean - expected) . abs( ) / expected < 0.025 ) ;
249
240
}
250
241
251
242
#[ test]
252
243
fn gamma_samples_match_expectation ( ) {
253
- let variable = ContinuousRandomVariable :: Gamma {
244
+ let variable = Continuous :: Gamma {
254
245
shape : 7.0 ,
255
246
scale : 11.0 ,
256
247
} ;
@@ -261,7 +252,7 @@ mod tests {
261
252
262
253
#[ test]
263
254
fn lognormal_samples_match_expectation ( ) {
264
- let variable = ContinuousRandomVariable :: LogNormal {
255
+ let variable = Continuous :: LogNormal {
265
256
mu : 11.0 ,
266
257
sigma : 1.0 ,
267
258
} ;
@@ -293,7 +284,7 @@ mod tests {
293
284
7
294
285
}
295
286
}
296
- let variable = ContinuousRandomVariable :: Normal {
287
+ let variable = Continuous :: Normal {
297
288
mean : 11.0 ,
298
289
std_dev : 3.0 ,
299
290
} ;
@@ -318,7 +309,7 @@ mod tests {
318
309
fn bins_mapping ( variate : f64 ) -> usize {
319
310
( ( variate - 5.0 ) / 5.0 ) as usize
320
311
}
321
- let variable = ContinuousRandomVariable :: Triangular {
312
+ let variable = Continuous :: Triangular {
322
313
min : 5.0 ,
323
314
max : 25.0 ,
324
315
mode : 15.0 ,
@@ -345,7 +336,7 @@ mod tests {
345
336
let max = 11.0 ;
346
337
( ( variate - min) * ( max - 1.0 ) ) as usize
347
338
}
348
- let variable = ContinuousRandomVariable :: Uniform {
339
+ let variable = Continuous :: Uniform {
349
340
min : 7.0 ,
350
341
max : 11.0 ,
351
342
} ;
@@ -366,7 +357,7 @@ mod tests {
366
357
367
358
#[ test]
368
359
fn weibull_samples_match_expectation ( ) {
369
- let variable = ContinuousRandomVariable :: Weibull {
360
+ let variable = Continuous :: Weibull {
370
361
shape : 7.0 ,
371
362
scale : 0.5 ,
372
363
} ;
@@ -380,7 +371,7 @@ mod tests {
380
371
fn bins_mapping ( variate : bool ) -> usize {
381
372
variate as usize
382
373
}
383
- let variable = BooleanRandomVariable :: Bernoulli { p : 0.3 } ;
374
+ let variable = Boolean :: Bernoulli { p : 0.3 } ;
384
375
// Failures (false == 0) is 70% of trials and success (true == 1) is 30% of trials
385
376
let expected_counts: [ usize ; 2 ] = [ 7000 , 3000 ] ;
386
377
let chi_square_actual = chi_square (
@@ -398,15 +389,15 @@ mod tests {
398
389
399
390
#[ test]
400
391
fn geometric_samples_match_expectation ( ) {
401
- let variable = DiscreteRandomVariable :: Geometric { p : 0.2 } ;
392
+ let variable = Discrete :: Geometric { p : 0.2 } ;
402
393
let mean = empirical_mean ( & mut RandomVariable :: Discrete ( variable) , 10000 ) ;
403
394
let expected = ( 1.0 - 0.2 ) / 0.2 ;
404
395
assert ! ( ( mean - expected) . abs( ) / expected < 0.025 ) ;
405
396
}
406
397
407
398
#[ test]
408
399
fn poisson_samples_match_expectation ( ) {
409
- let variable = DiscreteRandomVariable :: Poisson { lambda : 7.0 } ;
400
+ let variable = Discrete :: Poisson { lambda : 7.0 } ;
410
401
let mean = empirical_mean ( & mut RandomVariable :: Discrete ( variable) , 10000 ) ;
411
402
let expected = 7.0 ;
412
403
assert ! ( ( mean - expected) . abs( ) / expected < 0.025 ) ;
@@ -418,7 +409,7 @@ mod tests {
418
409
let min = 7 ;
419
410
( variate - min) as usize
420
411
}
421
- let variable = DiscreteRandomVariable :: Uniform { min : 7 , max : 11 } ;
412
+ let variable = Discrete :: Uniform { min : 7 , max : 11 } ;
422
413
// Constant bin counts, due to uniformity of distribution
423
414
let expected_counts: [ usize ; 4 ] = [ 2500 ; 4 ] ;
424
415
let chi_square_actual = chi_square (
@@ -439,7 +430,7 @@ mod tests {
439
430
fn bins_mapping ( variate : usize ) -> usize {
440
431
variate
441
432
}
442
- let variable = IndexRandomVariable :: WeightedIndex {
433
+ let variable = Index :: WeightedIndex {
443
434
weights : vec ! [ 1 , 2 , 3 , 4 ] ,
444
435
} ;
445
436
// The expected bin counts scale linearly with the weights
@@ -463,7 +454,7 @@ mod tests {
463
454
let min = 7 ;
464
455
variate - min
465
456
}
466
- let variable = IndexRandomVariable :: Uniform { min : 7 , max : 11 } ;
457
+ let variable = Index :: Uniform { min : 7 , max : 11 } ;
467
458
// Constant bin counts, due to uniformity of distribution
468
459
let expected_counts: [ usize ; 4 ] = [ 2500 ; 4 ] ;
469
460
let chi_square_actual = chi_square (
0 commit comments