use criterion::{Criterion, criterion_group, criterion_main};
use itertools::Itertools;
use pathfinding::prelude::separate_components;
use rand::{Rng as _, RngExt as _, SeedableRng as _, prelude::SliceRandom};
use rand_xorshift::XorShiftRng;
use std::collections::HashSet;
fn larger_separate_components() {
let mut rng = XorShiftRng::from_seed([
3, 42, 93, 129, 1, 85, 72, 42, 84, 23, 95, 212, 253, 10, 4, 2,
]);
let mut seen = HashSet::new();
let mut components = (0..100)
.map(|_| {
let mut component = Vec::new();
for _ in 0..100 {
let node = rng.next_u64();
if !seen.contains(&node) {
seen.insert(node);
component.push(node);
}
}
component.sort_unstable();
assert!(
!component.is_empty(),
"component is empty, rng seed needs changing"
);
component
})
.collect_vec();
components.sort_unstable_by_key(|c| c[0]);
let mut groups = components
.iter()
.flat_map(|component| {
let mut component = component.clone();
component.shuffle(&mut rng);
let mut subcomponents = Vec::new();
while !component.is_empty() {
let cut = rng.random_range(0..component.len());
let mut subcomponent = component.drain(cut..).collect_vec();
if !component.is_empty() {
subcomponent.push(component[0]);
}
subcomponent.shuffle(&mut rng);
subcomponents.push(subcomponent);
}
subcomponents
})
.collect_vec();
groups.shuffle(&mut rng);
let (_, group_mappings) = separate_components(&groups);
let mut out_groups = vec![HashSet::new(); groups.len()];
for (i, n) in group_mappings.into_iter().enumerate() {
assert!(
n < groups.len(),
"group index is greater than expected: {}/{}",
n,
groups.len()
);
for e in &groups[i] {
out_groups[n].insert(*e);
}
}
let out_groups = out_groups
.into_iter()
.map(|g| g.into_iter().collect_vec())
.collect_vec();
let mut out_groups = out_groups
.into_iter()
.filter_map(|mut group| {
if group.is_empty() {
None
} else {
group.sort_unstable();
Some(group)
}
})
.collect_vec();
out_groups.sort_by_key(|c| c[0]);
assert_eq!(out_groups, components);
}
fn bench_separate_components(c: &mut Criterion) {
c.bench_function("separate_components", |b| {
b.iter(larger_separate_components);
});
}
criterion_group!(benches, bench_separate_components);
criterion_main!(benches);