use crate::{cn, Network};
use rand::prelude::{Rng, SliceRandom};
#[derive(Debug, Clone, PartialEq)]
pub enum Model {
ER {
p: f64,
whole: bool,
},
BA {
m0: usize,
m: usize,
},
Custom(String),
None,
}
impl Model {
pub fn init_er(net: &mut Network, p: f64, whole: bool) {
let net_len = net.size();
net.disconnect_all();
if p <= 0. || p > 1. {
panic!("{}", cn::Err::BadProbability(p));
}
for i in 0..net_len {
for j in i + 1..net_len {
if net.rng().unwrap().gen::<f64>() <= p {
net.link(i, j).unwrap();
}
}
}
if whole {
net.stitch_together();
}
net.model = Model::ER { p, whole };
}
pub fn init_ba(net: &mut Network, m0: usize, m: usize) {
if m0 < 1 || m == 0 || m > m0 || m0 > net.size() {
panic!("Incorrect model parameters: m0 = {}, m = {}", m0, m);
}
net.disconnect_all();
for i in 0..m0 {
if m0 == 1 {
break;
}
for j in i + 1..m0 {
net.link(i, j).unwrap();
}
}
for current_idx in m0..net.size() {
let chosen: Vec<usize> = net
.nodes()
.filter(|&node| node < current_idx)
.map(|node| (node, net.deg_of(node).unwrap()))
.collect::<Vec<_>>() .choose_multiple_weighted(&mut *net.rng().unwrap(), m, |&(_index, deg)| deg as f64)
.unwrap()
.map(|&(idx, _deg)| idx)
.collect();
for other in chosen {
net.link(current_idx, other).unwrap();
}
}
}
pub fn as_str(&self) -> &str {
match self {
Model::BA{..} => "ba",
Model::ER {..} => "er",
Model::Custom(n) => n,
Model::None => "",
}
}
}
impl Default for Model {
fn default() -> Self {
Model::None
}
}