#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Partition {
community: Vec<usize>,
num_communities: usize,
}
impl Partition {
pub fn new(n: usize) -> Self {
Self {
community: (0..n).collect(),
num_communities: n,
}
}
pub fn from_membership(membership: Vec<usize>) -> Self {
let num_communities = if membership.is_empty() {
0
} else {
*membership.iter().max().unwrap() + 1
};
Self {
community: membership,
num_communities,
}
}
pub fn community_of(&self, node: usize) -> usize {
self.community[node]
}
pub fn move_node(&mut self, node: usize, new_community: usize) {
self.community[node] = new_community;
if new_community >= self.num_communities {
self.num_communities = new_community + 1;
}
}
pub fn num_communities(&self) -> usize {
self.num_communities
}
pub fn nodes_in_community(&self, community: usize) -> Vec<usize> {
self.community
.iter()
.enumerate()
.filter_map(|(node, &comm)| if comm == community { Some(node) } else { None })
.collect()
}
pub fn community_sizes(&self) -> Vec<usize> {
if self.community.is_empty() {
return vec![];
}
let max_comm = *self.community.iter().max().unwrap();
let mut sizes = vec![0usize; max_comm + 1];
for &comm in &self.community {
sizes[comm] += 1;
}
sizes
}
pub fn renumber(&mut self) {
if self.community.is_empty() {
self.num_communities = 0;
return;
}
let max_comm = self.community.iter().copied().max().unwrap_or(0);
let mut mapping: Vec<usize> = vec![usize::MAX; max_comm + 1];
let mut next_id = 0usize;
for comm in self.community.iter_mut() {
if mapping[*comm] == usize::MAX {
mapping[*comm] = next_id;
next_id += 1;
}
*comm = mapping[*comm];
}
self.num_communities = next_id;
}
pub fn as_slice(&self) -> &[usize] {
&self.community
}
pub fn len(&self) -> usize {
self.community.len()
}
pub fn is_empty(&self) -> bool {
self.community.is_empty()
}
pub fn communities(&self) -> Vec<(usize, Vec<usize>)> {
if self.community.is_empty() {
return Vec::new();
}
let max_comm = *self.community.iter().max().unwrap_or(&0);
let mut buckets: Vec<Vec<usize>> = vec![Vec::new(); max_comm + 1];
for (node, &comm) in self.community.iter().enumerate() {
buckets[comm].push(node);
}
buckets
.into_iter()
.enumerate()
.filter(|(_, nodes)| !nodes.is_empty())
.collect()
}
pub fn iter(&self) -> impl Iterator<Item = (usize, usize)> + '_ {
self.community.iter().copied().enumerate()
}
}