#![allow(clippy::many_single_char_names)]
use rust_igraph::{
EdgeBetweennessResult, Graph, edge_betweenness_community, edge_betweenness_community_weighted,
modularity_directed, modularity_weighted_directed,
};
fn print_partition(label: &str, g: &Graph, r: &EdgeBetweennessResult, best_q: f64) {
println!("{label}");
println!(" best partition: k = {}, Q = {best_q:.6}", r.nb_clusters);
let mut by_community: Vec<Vec<u32>> = vec![Vec::new(); r.nb_clusters as usize];
for (v, &c) in r.membership.iter().enumerate() {
by_community[c as usize].push(u32::try_from(v).expect("vertex id fits u32"));
}
for (cid, members) in by_community.iter().enumerate() {
println!(" c{cid}: {members:?}");
}
let first_eid = r.removed_edges[0];
let first_eb = r.edge_betweenness[0];
let (u, v) = g.edge(first_eid).expect("removed edge id is valid");
println!(" first removal: eid={first_eid} ({u}->{v}) eb = {first_eb:.4}");
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut g = Graph::new(6, true)?;
for i in 0..5u32 {
g.add_edge(i, i + 1)?;
}
println!(
"directed 6-path: {} vertices, {} edges, directed = {}",
g.vcount(),
g.ecount(),
g.is_directed()
);
let r_unweighted = edge_betweenness_community(&g)?;
let best_q_unweighted = modularity_directed(&g, &r_unweighted.membership, 1.0)?.unwrap_or(0.0);
print_partition("unweighted:", &g, &r_unweighted, best_q_unweighted);
let weights = vec![1.0_f64; g.ecount()];
let r_weighted = edge_betweenness_community_weighted(&g, &weights)?;
let best_q_weighted =
modularity_weighted_directed(&g, &r_weighted.membership, 1.0, &weights)?.unwrap_or(0.0);
print_partition("weighted (unit weights):", &g, &r_weighted, best_q_weighted);
assert_eq!(r_unweighted.membership, r_weighted.membership);
println!("\nunweighted and weighted-unit produce the same partition (as expected).");
Ok(())
}