uni_algo/algo/algorithms/
degree_centrality.rs1use crate::algo::GraphProjection;
10use crate::algo::algorithms::Algorithm;
11use uni_common::core::id::Vid;
12
13pub struct DegreeCentrality;
14
15#[derive(Debug, Clone)]
16pub struct DegreeCentralityConfig {
17 pub direction: DegreeDirection,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum DegreeDirection {
22 Incoming,
23 Outgoing,
24 Both,
25}
26
27impl Default for DegreeCentralityConfig {
28 fn default() -> Self {
29 Self {
30 direction: DegreeDirection::Outgoing,
31 }
32 }
33}
34
35pub struct DegreeCentralityResult {
36 pub scores: Vec<(Vid, f64)>,
37}
38
39impl Algorithm for DegreeCentrality {
40 type Config = DegreeCentralityConfig;
41 type Result = DegreeCentralityResult;
42
43 fn name() -> &'static str {
44 "degree_centrality"
45 }
46
47 fn run(graph: &GraphProjection, config: Self::Config) -> Self::Result {
48 let n = graph.vertex_count();
49 if n == 0 {
50 return DegreeCentralityResult { scores: Vec::new() };
51 }
52
53 let mut scores = Vec::with_capacity(n);
54
55 for i in 0..n as u32 {
56 let degree = match config.direction {
57 DegreeDirection::Outgoing => graph.out_degree(i),
58 DegreeDirection::Incoming => {
59 if graph.has_reverse() {
60 graph.in_degree(i)
61 } else {
62 0
66 }
67 }
68 DegreeDirection::Both => {
69 let out_d = graph.out_degree(i);
70 let in_d = if graph.has_reverse() {
71 graph.in_degree(i)
72 } else {
73 0
74 };
75 out_d + in_d
76 }
77 };
78 scores.push((graph.to_vid(i), degree as f64));
79 }
80
81 DegreeCentralityResult { scores }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::algo::test_utils::build_test_graph;
89
90 #[test]
91 fn test_degree_centrality_outgoing() {
92 let vids = vec![Vid::from(0), Vid::from(1), Vid::from(2)];
94 let edges = vec![(Vid::from(0), Vid::from(1)), (Vid::from(0), Vid::from(2))];
95 let graph = build_test_graph(vids, edges);
96
97 let config = DegreeCentralityConfig {
98 direction: DegreeDirection::Outgoing,
99 };
100 let result = DegreeCentrality::run(&graph, config);
101
102 let map: std::collections::HashMap<_, _> = result.scores.into_iter().collect();
103 assert_eq!(map[&Vid::from(0)], 2.0);
104 assert_eq!(map[&Vid::from(1)], 0.0);
105 assert_eq!(map[&Vid::from(2)], 0.0);
106 }
107}