use itertools::Itertools;
use rand::{Rng, RngExt};
use crate::{
models::{Graph, UnGraph},
random::Random,
types::{Error, Labels, Result},
};
pub struct RngUnGraph<'a, R> {
rng: &'a mut R,
labels: &'a Labels,
p: f64,
}
impl<'a, R> RngUnGraph<'a, R> {
pub fn new(rng: &'a mut R, labels: &'a Labels, p: f64) -> Result<Self> {
if !(0.0..=1.0).contains(&p) {
return Err(Error::InvalidParameter("p", "must be in [0, 1]"));
}
Ok(Self { rng, labels, p })
}
}
impl<R: Rng> Random for RngUnGraph<'_, R> {
type Output = Result<UnGraph>;
fn random(&mut self) -> Self::Output {
let mut g = UnGraph::empty(self.labels)?;
let n = self.labels.len();
(0..n)
.combinations(2)
.filter(|_| self.rng.random_bool(self.p))
.try_for_each(|idx| -> Result<()> {
let (i, j) = (idx[0], idx[1]);
g.add_edge(i, j)?;
Ok(())
})?;
Ok(g)
}
}