diff --git a/bins/inbreeding/src/environment.rs b/bins/inbreeding/src/environment.rs index 2b1feaeb8438f2fb29919a02b72056f91b9c0403..11357823e32f5f68886ac738c1efdfa79a175368 100644 --- a/bins/inbreeding/src/environment.rs +++ b/bins/inbreeding/src/environment.rs @@ -1,4 +1,6 @@ -use rand::{seq::SliceRandom, Rng, RngCore}; +use rand::{Rng, RngCore}; + +use crate::random::draw_unique_elements; #[derive(Debug, PartialEq)] pub(super) enum Environment { @@ -14,28 +16,23 @@ impl Environment { /// `update(things, rng)` is `things` with some elements potentially removed according to the /// [`Environment`] type pub(super) fn update<T: Clone>(&self, things: &[T], rng: &mut impl RngCore) -> Vec<T> { - let mut things = things.to_vec(); - things.shuffle(rng); - - match self { - Environment::Fixed { n } => things.iter().take(things.len() - n), + let nb_to_take = match self { + Environment::Fixed { n } => things.len() - n, Environment::RandomFixed { p, n } => { if rng.gen::<f64>() > *p { - return things; + return things.to_vec(); } - things.iter().take(things.len() - n) + things.len() - n } Environment::RandomDynamic { p, q } => { if rng.gen::<f64>() > *p { - return things; + return things.to_vec(); } - things - .iter() - .take((things.len() as f64 * (1.0 - q)) as usize) + (things.len() as f64 * (1.0 - q)) as usize } - } - .cloned() - .collect() + }; + + draw_unique_elements(things, nb_to_take, rng) } pub(super) fn from_str(s: &str) -> Result<Self, String> { diff --git a/bins/inbreeding/src/main.rs b/bins/inbreeding/src/main.rs index 71beb012f7f0bc3b0351ef11e7aa2e87ee7bb097..51f2d08b22af02b937b1760744b89177aac6c33e 100644 --- a/bins/inbreeding/src/main.rs +++ b/bins/inbreeding/src/main.rs @@ -9,9 +9,11 @@ use komodo::{ fec::{self, Shard}, linalg::Matrix, }; -use rand::{rngs::StdRng, seq::SliceRandom, Rng, RngCore, SeedableRng}; +use rand::{rngs::StdRng, Rng, RngCore, SeedableRng}; +use random::draw_unique_elements; mod environment; +mod random; mod strategy; use crate::{environment::Environment, strategy::Strategy}; @@ -38,16 +40,13 @@ fn measure_inbreeding<F: PrimeField>( sty: &ProgressStyle, rng: &mut impl RngCore, ) -> f64 { - let mut s: Vec<_> = shards.to_vec(); let mut count = 0; let pb = mp.add(ProgressBar::new(nb_measurements as u64)); pb.set_style(sty.clone()); pb.set_message("measure"); for _ in 0..nb_measurements { - // get any k of the shards - s.shuffle(rng); - if fec::decode(s.iter().take(k).cloned().collect()).is_ok() { + if fec::decode(draw_unique_elements(shards, k, rng)).is_ok() { count += 1; } pb.inc(1); diff --git a/bins/inbreeding/src/random.rs b/bins/inbreeding/src/random.rs new file mode 100644 index 0000000000000000000000000000000000000000..8593049f05550f136ac7af8aac0ebaa144e949e6 --- /dev/null +++ b/bins/inbreeding/src/random.rs @@ -0,0 +1,25 @@ +use rand::{Rng, RngCore}; +use std::collections::HashSet; + +fn draw_unique_indices(n: usize, vec_len: usize, rng: &mut impl RngCore) -> HashSet<usize> { + let mut indices = HashSet::new(); + + while indices.len() < n { + let idx = rng.gen_range(0..vec_len); + indices.insert(idx); + } + + indices +} + +pub(super) fn draw_unique_elements<T: Clone>( + things: &[T], + n: usize, + rng: &mut impl RngCore, +) -> Vec<T> { + let mut res = vec![]; + for i in draw_unique_indices(n, things.len(), rng) { + res.push(things[i].clone()); + } + res +} diff --git a/bins/inbreeding/src/strategy.rs b/bins/inbreeding/src/strategy.rs index f8f8143e63940a8bc9fdea4d01f15a72f4fed31e..ffe573606c721a452802bd4f95ec1d0905255593 100644 --- a/bins/inbreeding/src/strategy.rs +++ b/bins/inbreeding/src/strategy.rs @@ -1,4 +1,6 @@ -use rand::{seq::SliceRandom, Rng, RngCore}; +use rand::{Rng, RngCore}; + +use crate::random::draw_unique_elements; #[derive(Debug, PartialEq)] pub(super) enum Strategy { @@ -8,9 +10,6 @@ pub(super) enum Strategy { impl Strategy { pub(super) fn draw<T: Clone>(&self, things: &[T], rng: &mut impl RngCore) -> Vec<T> { - let mut things = things.to_vec(); - things.shuffle(rng); - let nb_to_take = match self { Self::Single { n } => *n, Self::Double { p, n, m } => { @@ -22,7 +21,7 @@ impl Strategy { } }; - things.iter().take(nb_to_take).cloned().collect() + draw_unique_elements(things, nb_to_take, rng) } pub(super) fn from_str(s: &str) -> Result<Self, String> {