use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub enum QualityFunction {
#[default]
Modularity,
Cpm {
gamma: f64,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LeidenConfig {
pub seed: u64,
pub max_iterations: usize,
pub quality: QualityFunction,
pub gamma: f64,
pub min_compression_ratio: f64,
pub max_recursion_depth: u32,
}
impl Default for LeidenConfig {
fn default() -> Self {
LeidenConfig {
seed: 42,
max_iterations: 100,
quality: QualityFunction::Modularity,
gamma: 1.0,
min_compression_ratio: 0.1,
max_recursion_depth: 32,
}
}
}
impl LeidenConfig {
pub fn from_sdivi_config(cfg: &sdivi_config::Config) -> Self {
LeidenConfig {
seed: cfg.core.random_seed,
max_iterations: 100,
quality: QualityFunction::Modularity,
gamma: cfg.boundaries.leiden_gamma,
min_compression_ratio: cfg.boundaries.leiden_min_compression_ratio,
max_recursion_depth: cfg.boundaries.leiden_max_recursion_depth,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LeidenPartition {
pub assignments: BTreeMap<usize, usize>,
pub stability: BTreeMap<usize, f64>,
pub modularity: f64,
pub seed: u64,
}
impl LeidenPartition {
pub fn community_count(&self) -> usize {
self.stability.len()
}
pub fn community_of(&self, node: usize) -> Option<usize> {
self.assignments.get(&node).copied()
}
pub fn largest_community_size(&self) -> usize {
let mut counts: BTreeMap<usize, usize> = BTreeMap::new();
for &comm in self.assignments.values() {
*counts.entry(comm).or_insert(0) += 1;
}
counts.values().copied().max().unwrap_or(0)
}
pub fn communities(&self) -> BTreeMap<usize, Vec<usize>> {
let mut map: BTreeMap<usize, Vec<usize>> = BTreeMap::new();
for (&node, &comm) in &self.assignments {
map.entry(comm).or_default().push(node);
}
map
}
pub fn to_json(&self) -> serde_json::Result<String> {
serde_json::to_string(self)
}
pub fn from_json(json: &str) -> serde_json::Result<Self> {
serde_json::from_str(json)
}
}