pecos_core/sims_rngs/sim_rng.rs
1// Copyright 2024 The PECOS Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4// in compliance with the License.You may obtain a copy of the License at
5//
6// https://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software distributed under the License
9// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10// or implied. See the License for the specific language governing permissions and limitations under
11// the License.
12
13use crate::sims_rngs::choices::Choices;
14use core::fmt::Debug;
15use rand::distributions::{Bernoulli, Distribution};
16use rand::{RngCore, SeedableRng};
17
18/// Represents the minimal interface needed for simulations.
19/// This trait also allows the blanket implementation provided by Rng to be overridden in favor of
20/// potentially more efficient implementations.
21pub trait SimRng: RngCore + SeedableRng + Debug {
22 /// Generate a single bool where true has a probability of `p`.
23 #[inline]
24 fn gen_bool(&mut self, p: f64) -> bool {
25 Bernoulli::new(p)
26 .expect("Failed to create Bernoulli distribution due to invalid probability")
27 .sample(self)
28 }
29
30 /// Generates a vector of bools, where true has an independent probability of `p`.
31 #[inline]
32 fn gen_bools(&mut self, p: f64, n: usize) -> Vec<bool> {
33 let bernoulli = Bernoulli::new(p)
34 .expect("Failed to create Bernoulli distribution due to invalid probability");
35 (0..n).map(|_| bernoulli.sample(self)).collect()
36 }
37
38 /// Gives true and false each with probability of 50%
39 #[inline]
40 #[allow(clippy::cast_possible_wrap, clippy::as_conversions)]
41 fn coin_flip(&mut self) -> bool {
42 (self.next_u32() as i32) < 0
43 }
44
45 /// Choose between options given a weighted probabilities.
46 #[inline]
47 fn choose_weighted<'a, T>(&mut self, choices: &'a Choices<T>) -> &'a T {
48 choices.sample(self)
49 }
50
51 #[inline]
52 #[must_use]
53 fn from_entropy() -> Self {
54 SeedableRng::from_entropy()
55 }
56}