des_sim/modeling/sampler/instance/
uniform.rs1use crate::modeling::sampler::{DurationSampler, PendingDuration};
9use crate::primitive::time::SimTime;
10use rand::Rng;
11use rand::distr::{Distribution, Uniform, uniform};
12
13#[derive(Debug, Clone)]
15pub struct UniformSampler {
16 dist: Uniform<f64>,
17}
18
19impl DurationSampler for UniformSampler {
20 fn sample(&mut self, rng: &mut dyn Rng, _current_tick: SimTime) -> PendingDuration {
21 PendingDuration::new(self.dist.sample(rng))
22 }
23}
24
25impl UniformSampler {
26 pub fn new(lower_bound: f64, higher_bound: f64) -> Result<UniformSampler, uniform::Error> {
29 let uniform = Uniform::new(lower_bound, higher_bound)?;
30
31 Ok(UniformSampler { dist: uniform })
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_uniform_sampler() {
43 let mut rng = SmallRng::seed_from_u64(2);
44 let lower_bound = 5.0;
45 let higher_bound = 15.0;
46 let mut sampler = UniformSampler::new(lower_bound, higher_bound).unwrap();
47
48 let mut samples = Vec::new();
49 for _ in 0..10000 {
50 samples.push(sampler.sample(&mut rng, SimTime::from_ticks(0)).raw_value());
51 }
52
53 assert!(
55 samples
56 .iter()
57 .all(|&x| x >= lower_bound && x < higher_bound)
58 );
59
60 let sample_mean: f64 = samples.iter().sum::<f64>() / samples.len() as f64;
61 let expected_mean = (lower_bound + higher_bound) / 2.0;
62
63 assert!(
65 (sample_mean - expected_mean).abs() < 0.1,
66 "Mean: {}, Expected: {}",
67 sample_mean,
68 expected_mean
69 );
70 }
71
72 #[test]
73 fn test_uniform_sampler_invalid_bounds() {
74 let sampler_empty_range = UniformSampler::new(10.0, 5.0);
76 assert_eq!(sampler_empty_range.err(), Some(uniform::Error::EmptyRange));
77 }
78
79 #[test]
80 fn test_uniform_sampler_invalid_infinite_bounds() {
81 let sampler_infinite_range = UniformSampler::new(10.0, f64::INFINITY);
83 assert_eq!(
84 sampler_infinite_range.err(),
85 Some(uniform::Error::NonFinite)
86 );
87 }
88}