pub trait ErdosRenyi {
#[must_use]
fn erdos_renyi(order: usize, p: f64, seed: u64) -> Self;
}
#[macro_export]
macro_rules! test_erdos_renyi {
($type:ty) => {
#[test]
#[should_panic(expected = "a digraph has at least one vertex")]
fn erdos_renyi_0() {
drop(<$type>::erdos_renyi(0, 0.5, 0));
}
#[test]
#[should_panic(expected = "p = -0.1 must be in [0, 1]")]
fn erdos_renyi_p_negative() {
drop(<$type>::erdos_renyi(2, -0.1, 0));
}
#[test]
#[should_panic(expected = "p = 1.1 must be in [0, 1]")]
fn erdos_renyi_p_gt_1() {
drop(<$type>::erdos_renyi(2, 1.1, 0));
}
};
}
#[macro_export]
macro_rules! proptest_erdos_renyi {
($type:ty) => {
use {
proptest::proptest,
$crate::{
Degree,
IsSubdigraph,
IsSuperdigraph,
},
};
proptest! {
#[test]
fn erdos_renyi_degree(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
let max_degree = (order - 1) * 2;
assert!(digraph.vertices().all(|u| {
(0..=max_degree).contains(&digraph.degree(u))
}));
}
#[test]
fn erdos_renyi_degree_sum_equals_2size(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert_eq!(
digraph
.vertices()
.fold(0, |acc, u| acc + digraph.degree(u)),
2 * digraph.size()
);
}
#[test]
fn erdos_renyi_even_number_odd_degrees(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert_eq!(
digraph
.vertices()
.filter(|&u| digraph.degree(u) % 2 == 1)
.count()
% 2,
0
);
}
#[test]
fn erdos_renyi_has_arc(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert!(digraph.vertices().all(|u| !digraph.has_arc(u, u) ));
}
#[test]
fn erdos_renyi_indegree(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert!(digraph.vertices().all(|v| {
(0..order).contains(&digraph.indegree(v))
}));
}
#[test]
fn erdos_renyi_is_complete(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
if p == 0.0 {
assert!(!<$type>::erdos_renyi(order, p, seed).is_complete());
} else if order == 1 {
assert!(<$type>::erdos_renyi(order, p, seed).is_complete());
}
}
#[test]
fn erdos_renyi_is_simple(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
assert!(<$type>::erdos_renyi(order, p, seed).is_simple());
}
#[test]
fn erdos_renyi_is_subdigraph(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert!(digraph.is_subdigraph(&digraph));
}
#[test]
fn erdos_renyi_is_superdigraph(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert!(digraph.is_superdigraph(&digraph));
}
#[test]
fn erdos_renyi_order(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
assert_eq!(<$type>::erdos_renyi(order, p, seed).order(), order);
}
#[test]
fn erdos_renyi_outdegree(
order in 1..5_usize,
p in 0.0..1.0,
seed in 0..1000_u64
) {
let digraph = <$type>::erdos_renyi(order, p, seed);
assert!(digraph.vertices().all(|u| {
(0..order).contains(&digraph.outdegree(u))
}));
}
#[test]
fn erdos_renyi_size_p_0(order in 1..5_usize, seed: u64) {
assert_eq!(<$type>::erdos_renyi(order, 0.0, seed).size(), 0);
}
#[test]
fn erdos_renyi_size_p_1(order in 1..5_usize, seed: u64) {
assert_eq!(
<$type>::erdos_renyi(order, 1.0, seed).size(),
order * (order - 1)
);
}
}
};
}