des_sim/modeling/sampler/instance/
poisson.rs1use crate::modeling::sampler::{DurationSampler, PendingDuration};
9use crate::primitive::time::SimTime;
10use rand::Rng;
11use rand::distr::Distribution;
12use rand_distr::{Poisson, PoissonError};
13
14#[derive(Debug, Clone)]
16pub struct PoissonSampler {
17 dist: Poisson<f64>,
18}
19
20impl DurationSampler for PoissonSampler {
21 fn sample(&mut self, rng: &mut dyn Rng, _current_tick: SimTime) -> PendingDuration {
22 PendingDuration::new(self.dist.sample(rng))
24 }
25}
26
27impl PoissonSampler {
28 pub fn new(lambda: f64) -> Result<Self, PoissonError> {
31 Poisson::new(lambda).map(|dist| PoissonSampler { dist })
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38 use rand::SeedableRng;
39 use rand::rngs::SmallRng;
40
41 #[test]
42 fn test_poisson_sampler() {
43 let mut rng = SmallRng::seed_from_u64(2);
44 let lambda = 5.0; let mut sampler = PoissonSampler::new(lambda).unwrap();
46
47 let mut samples = Vec::new();
48 for _ in 0..10000 {
49 samples.push(sampler.sample(&mut rng, SimTime::from_ticks(0)).raw_value());
50 }
51
52 let sample_mean: f64 = samples.iter().sum::<f64>() / samples.len() as f64;
53 let variance: f64 = samples
54 .iter()
55 .map(|x| (x - sample_mean).powi(2))
56 .sum::<f64>()
57 / samples.len() as f64;
58
59 assert!(
61 (sample_mean - lambda).abs() < 0.1,
62 "Mean: {}, Expected: {}",
63 sample_mean,
64 lambda
65 );
66 assert!(
67 (variance - lambda).abs() < 0.1,
68 "Variance: {}, Expected: {}",
69 variance,
70 lambda
71 );
72
73 assert!(samples.iter().all(|&x| x >= 0.0 && x.fract() == 0.0));
75 }
76
77 #[test]
78 fn test_poisson_sampler_invalid_zero_lambda() {
79 let sampler = PoissonSampler::new(0.0);
80 assert_eq!(sampler.err(), Some(PoissonError::ShapeTooSmall));
81 let sampler = PoissonSampler::new(-0.01);
82 assert_eq!(sampler.err(), Some(PoissonError::ShapeTooSmall));
83 }
84
85 #[test]
86 fn test_poisson_sampler_invalid_infinity_lambda() {
87 let sampler = PoissonSampler::new(f64::INFINITY);
88 assert_eq!(sampler.err(), Some(PoissonError::NonFinite));
89 let sampler = PoissonSampler::new(f64::NAN);
90 assert_eq!(sampler.err(), Some(PoissonError::NonFinite));
91 }
92
93 #[test]
94 fn test_poisson_sampler_invalid_lambda() {
95 let sampler = PoissonSampler::new(Poisson::<f64>::MAX_LAMBDA * 2.0);
97 assert_eq!(sampler.err(), Some(PoissonError::ShapeTooLarge));
98 }
99}