use rust_igraph::{
Graph, GraphBuilder, betweenness, connected_components, degree_sequence, density, louvain,
pagerank,
};
fn main() {
let graph = GraphBuilder::undirected()
.vertices(9)
.edges(&[
(0, 1),
(0, 2),
(1, 2),
(1, 3),
(2, 3),
(0, 3),
(5, 6),
(5, 7),
(6, 7),
(6, 8),
(7, 8),
(3, 4),
(4, 5),
])
.build()
.unwrap();
let vcount = graph.vcount();
let ecount = graph.ecount();
let d = density(&graph).unwrap().unwrap_or(0.0);
println!("=== Graph Overview ===");
println!("Vertices: {vcount}");
println!("Edges: {ecount}");
println!("Density: {d:.4}");
println!("Directed: {}", graph.is_directed());
println!();
let components = connected_components(&graph).unwrap();
let comp_count = components.count;
let largest = components.membership.iter().filter(|&&c| c == 0).count();
println!("=== Connectivity ===");
println!("Connected components: {comp_count}");
println!("Largest component size: {largest}");
println!();
let degrees = degree_sequence(&graph, rust_igraph::DegreeMode::All).unwrap();
let max_degree = degrees.iter().max().copied().unwrap_or(0);
let avg_degree = f64::from(degrees.iter().sum::<u32>()) / f64::from(graph.vcount());
println!("=== Degree Statistics ===");
println!("Degree sequence: {degrees:?}");
println!("Max degree: {max_degree}");
println!("Average degree: {avg_degree:.2}");
println!();
let pr = pagerank(&graph).unwrap();
let bc = betweenness(&graph).unwrap();
println!("=== Centrality (top 3 by PageRank) ===");
let mut ranked: Vec<(usize, f64)> = pr.iter().copied().enumerate().collect();
ranked.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
for (rank, &(vertex, score)) in ranked.iter().take(3).enumerate() {
let r = rank + 1;
let b = bc[vertex];
println!(" #{r}: vertex {vertex} (PageRank={score:.4}, betweenness={b:.2})");
}
println!();
let communities = louvain(&graph).unwrap();
let modularity = communities.modularity;
println!("=== Community Detection (Louvain) ===");
println!("Modularity: {modularity:.4}");
println!("Membership: {:?}", communities.membership);
let num_communities = *communities.membership.iter().max().unwrap_or(&0) + 1;
println!("Number of communities: {num_communities}");
println!();
println!("=== Bridge Edges (betweenness > 4.0) ===");
for (u, v) in &graph {
let edge_bc = f64::midpoint(bc[u as usize], bc[v as usize]);
if edge_bc > 4.0 {
println!(" {u} -- {v} (avg vertex betweenness: {edge_bc:.2})");
}
}
let subgraph_a = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], false, None).unwrap();
let subgraph_b = Graph::from_edges(&[(1, 2), (2, 3), (3, 1)], false, None).unwrap();
let merged = &subgraph_a | &subgraph_b;
let mv = merged.vcount();
let me = merged.ecount();
println!();
println!("=== Graph Algebra ===");
println!("Union of two triangles: {mv} vertices, {me} edges");
}