use crate::graph::*;
#[test]
fn test_empty_graph() {
let g = Graph::new(false);
assert_eq!(g.num_nodes(), 0);
assert_eq!(g.num_edges(), 0);
assert!(!g.is_directed());
}
#[test]
fn test_directed_graph() {
let g = Graph::new(true);
assert!(g.is_directed());
}
#[test]
fn test_from_edges_empty() {
let g = Graph::from_edges(&[], false);
assert_eq!(g.num_nodes(), 0);
assert_eq!(g.num_edges(), 0);
}
#[test]
fn test_from_edges_undirected() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], false);
assert_eq!(g.num_nodes(), 3);
assert_eq!(g.num_edges(), 3);
assert_eq!(g.neighbors(0), &[1, 2]);
assert_eq!(g.neighbors(1), &[0, 2]);
assert_eq!(g.neighbors(2), &[0, 1]);
}
#[test]
fn test_from_edges_directed() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], true);
assert_eq!(g.num_nodes(), 3);
assert_eq!(g.num_edges(), 2);
assert_eq!(g.neighbors(0), &[1]);
assert_eq!(g.neighbors(1), &[2]);
assert!(g.neighbors(2).is_empty()); }
#[test]
fn test_from_edges_with_gaps() {
let g = Graph::from_edges(&[(0, 5), (5, 10)], false);
assert_eq!(g.num_nodes(), 11); assert_eq!(g.num_edges(), 2);
assert_eq!(g.neighbors(0), &[5]);
assert_eq!(g.neighbors(5), &[0, 10]);
assert!(g.neighbors(1).is_empty()); }
#[test]
fn test_from_edges_duplicate_edges() {
let g = Graph::from_edges(&[(0, 1), (0, 1), (1, 0)], false);
assert_eq!(g.num_nodes(), 2);
assert_eq!(g.neighbors(0), &[1]);
assert_eq!(g.neighbors(1), &[0]);
}
#[test]
fn test_from_edges_self_loop() {
let g = Graph::from_edges(&[(0, 0), (0, 1)], false);
assert_eq!(g.num_nodes(), 2);
assert_eq!(g.neighbors(0), &[0, 1]);
}
#[test]
fn test_neighbors_invalid_node() {
let g = Graph::from_edges(&[(0, 1)], false);
assert!(g.neighbors(999).is_empty()); }
#[test]
fn test_degree_centrality_empty() {
let g = Graph::new(false);
let dc = g.degree_centrality();
assert_eq!(dc.len(), 0);
}
#[test]
fn test_degree_centrality_single_node() {
let g = Graph::from_edges(&[(0, 0)], false);
let dc = g.degree_centrality();
assert_eq!(dc[&0], 0.0); }
#[test]
fn test_degree_centrality_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], false);
let dc = g.degree_centrality();
assert_eq!(dc[&0], 1.0); assert!((dc[&1] - 1.0 / 3.0).abs() < 1e-6); assert!((dc[&2] - 1.0 / 3.0).abs() < 1e-6);
assert!((dc[&3] - 1.0 / 3.0).abs() < 1e-6);
}
#[test]
fn test_degree_centrality_complete_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], false);
let dc = g.degree_centrality();
for v in 0..4 {
assert_eq!(dc[&v], 1.0);
}
}
#[test]
fn test_degree_centrality_path_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3)], false);
let dc = g.degree_centrality();
assert!((dc[&0] - 1.0 / 3.0).abs() < 1e-6);
assert!((dc[&1] - 2.0 / 3.0).abs() < 1e-6);
assert!((dc[&2] - 2.0 / 3.0).abs() < 1e-6);
assert!((dc[&3] - 1.0 / 3.0).abs() < 1e-6);
}
#[test]
fn test_degree_centrality_directed() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (1, 2)], true);
let dc = g.degree_centrality();
assert!((dc[&0] - 2.0 / 2.0).abs() < 1e-6); assert!((dc[&1] - 1.0 / 2.0).abs() < 1e-6); assert_eq!(dc[&2], 0.0); }
#[test]
fn test_pagerank_empty() {
let g = Graph::new(true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should succeed for empty graph");
assert!(pr.is_empty());
}
#[test]
fn test_pagerank_single_node() {
let g = Graph::from_edges(&[(0, 0)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should succeed for single node graph");
assert_eq!(pr.len(), 1);
assert!((pr[0] - 1.0).abs() < 1e-6); }
#[test]
fn test_pagerank_sum_equals_one() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should converge for cycle graph");
let sum: f64 = pr.iter().sum();
assert!((sum - 1.0).abs() < 1e-10); }
#[test]
fn test_pagerank_cycle_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should converge for symmetric cycle");
assert_eq!(pr.len(), 3);
assert!((pr[0] - 1.0 / 3.0).abs() < 1e-6);
assert!((pr[1] - 1.0 / 3.0).abs() < 1e-6);
assert!((pr[2] - 1.0 / 3.0).abs() < 1e-6);
}
#[test]
fn test_pagerank_star_graph_directed() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should converge for directed star graph");
assert_eq!(pr.len(), 4);
assert!(pr[0] < pr[1]); assert!((pr[1] - pr[2]).abs() < 1e-6); assert!((pr[2] - pr[3]).abs() < 1e-6);
}
#[test]
fn test_pagerank_convergence() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0), (1, 0)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should converge within max iterations");
assert_eq!(pr.len(), 3);
assert!((pr.iter().sum::<f64>() - 1.0).abs() < 1e-10);
}
#[test]
fn test_pagerank_no_outgoing_edges() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], true);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should handle dangling nodes correctly");
assert_eq!(pr.len(), 3);
assert!(pr[2] > 0.0);
assert!((pr.iter().sum::<f64>() - 1.0).abs() < 1e-10);
}
#[test]
fn test_pagerank_undirected() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], false);
let pr = g
.pagerank(0.85, 100, 1e-6)
.expect("pagerank should converge for undirected path graph");
assert_eq!(pr.len(), 3);
assert!(pr[1] > pr[0]);
assert!(pr[1] > pr[2]);
assert!((pr[0] - pr[2]).abs() < 1e-6); }
#[test]
fn test_betweenness_centrality_empty() {
let g = Graph::new(false);
let bc = g.betweenness_centrality();
assert!(bc.is_empty());
}
#[test]
fn test_betweenness_centrality_single_node() {
let g = Graph::from_edges(&[(0, 0)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 1);
assert_eq!(bc[0], 0.0); }
#[test]
fn test_betweenness_centrality_path_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 3);
assert!(bc[1] > bc[0]);
assert!(bc[1] > bc[2]);
assert!((bc[0] - bc[2]).abs() < 1e-6);
}
#[test]
fn test_betweenness_centrality_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 4);
assert!(bc[0] > bc[1]);
assert!(bc[0] > bc[2]);
assert!(bc[0] > bc[3]);
assert!((bc[1] - bc[2]).abs() < 1e-6);
assert!((bc[2] - bc[3]).abs() < 1e-6);
}
#[test]
fn test_betweenness_centrality_cycle_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 0)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 4);
for i in 0..4 {
for j in i + 1..4 {
assert!((bc[i] - bc[j]).abs() < 1e-6);
}
}
}
#[test]
fn test_betweenness_centrality_complete_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 4);
for i in 0..4 {
for j in i + 1..4 {
assert!((bc[i] - bc[j]).abs() < 1e-6);
}
}
}
#[test]
fn test_betweenness_centrality_bridge_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 4)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 5);
assert!(bc[2] > bc[0]);
assert!(bc[2] > bc[1]);
assert!(bc[2] > bc[3]);
assert!(bc[2] > bc[4]);
assert!(bc[1] > bc[0]);
assert!(bc[3] > bc[4]);
}
#[test]
fn test_betweenness_centrality_directed() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], true);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 3);
assert!(bc.iter().any(|&x| x > 0.0));
}
#[test]
fn test_betweenness_centrality_disconnected() {
let g = Graph::from_edges(&[(0, 1), (2, 3)], false);
let bc = g.betweenness_centrality();
assert_eq!(bc.len(), 4);
assert!((bc[0] - bc[1]).abs() < 1e-6);
assert!((bc[2] - bc[3]).abs() < 1e-6);
}
#[test]
fn test_modularity_empty_graph() {
let g = Graph::new(false);
let communities = vec![];
let modularity = g.modularity(&communities);
assert_eq!(modularity, 0.0);
}
#[test]
fn test_modularity_single_community() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], false);
let communities = vec![vec![0, 1, 2]];
let modularity = g.modularity(&communities);
assert!((modularity - 0.0).abs() < 1e-6);
}
#[test]
fn test_modularity_two_communities() {
let g = Graph::from_edges(
&[
(0, 1),
(1, 2),
(2, 0), (3, 4),
(4, 5),
(5, 3), (2, 3), ],
false,
);
let communities = vec![vec![0, 1, 2], vec![3, 4, 5]];
let modularity = g.modularity(&communities);
assert!(modularity > 0.0);
assert!(modularity < 1.0); }
#[test]
fn test_modularity_perfect_split() {
let g = Graph::from_edges(
&[
(0, 1),
(1, 2),
(2, 0), (3, 4),
(4, 5),
(5, 3), ],
false,
);
let communities = vec![vec![0, 1, 2], vec![3, 4, 5]];
let modularity = g.modularity(&communities);
assert!(modularity > 0.5);
}
include!("core_louvain.rs");
include!("core_density.rs");
include!("core_dijkstra.rs");