uni_algo/algo/algorithms/
kcore.rs1use crate::algo::GraphProjection;
7use crate::algo::algorithms::Algorithm;
8use uni_common::core::id::Vid;
9
10pub struct KCore;
11
12#[derive(Debug, Clone, Default)]
13pub struct KCoreConfig {
14 pub k: Option<usize>, }
16
17pub struct KCoreResult {
18 pub core_numbers: Vec<(Vid, u32)>,
19}
20
21impl Algorithm for KCore {
22 type Config = KCoreConfig;
23 type Result = KCoreResult;
24
25 fn name() -> &'static str {
26 "kCore"
27 }
28
29 fn needs_reverse() -> bool {
30 true
32 }
33
34 fn run(graph: &GraphProjection, config: Self::Config) -> Self::Result {
35 let n = graph.vertex_count();
36 if n == 0 {
37 return KCoreResult {
38 core_numbers: Vec::new(),
39 };
40 }
41
42 let mut degrees = vec![0u32; n];
44 let mut max_degree = 0;
45
46 for (v, deg_ref) in degrees.iter_mut().enumerate() {
47 let mut deg = graph.out_degree(v as u32);
48 if graph.has_reverse() {
49 deg += graph.in_degree(v as u32);
50 }
51 *deg_ref = deg;
52 if deg > max_degree {
53 max_degree = deg;
54 }
55 }
56 let mut vert = vec![0u32; n];
66 let mut pos = vec![0usize; n];
67 let mut bin = vec![0usize; max_degree as usize + 1];
68
69 for &d in °rees {
71 bin[d as usize] += 1;
72 }
73
74 let mut start = 0;
76 for b in &mut bin {
77 let num = *b;
78 *b = start;
79 start += num;
80 }
81
82 for v in 0..n {
84 let d = degrees[v] as usize;
85 pos[v] = bin[d];
86 vert[pos[v]] = v as u32;
87 bin[d] += 1;
88 }
89
90 for d in (1..=max_degree as usize).rev() {
92 bin[d] = bin[d - 1];
93 }
94 bin[0] = 0;
95
96 for i in 0..n {
99 let v = vert[i]; let deg_v = degrees[v as usize];
101
102 let mut neighbors = Vec::new();
105 neighbors.extend_from_slice(graph.out_neighbors(v));
106 if graph.has_reverse() {
107 neighbors.extend_from_slice(graph.in_neighbors(v));
108 }
109 neighbors.sort_unstable();
110 neighbors.dedup();
111
112 for &u in &neighbors {
113 let u_idx = u as usize;
114 if degrees[u_idx] > deg_v {
115 let deg_u = degrees[u_idx] as usize;
116 let pos_u = pos[u_idx];
117 let pos_w = bin[deg_u];
118 let w = vert[pos_w]; if u != w {
122 pos[u_idx] = pos_w;
123 pos[w as usize] = pos_u;
124 vert[pos_u] = w;
125 vert[pos_w] = u;
126 }
127
128 bin[deg_u] += 1;
130 degrees[u_idx] -= 1;
132 }
133 }
134 }
135
136 let mut results = Vec::new();
137 if let Some(k) = config.k {
138 for (v, °) in degrees.iter().enumerate() {
139 if deg >= k as u32 {
140 results.push((graph.to_vid(v as u32), deg));
141 }
142 }
143 } else {
144 for (v, °) in degrees.iter().enumerate() {
145 results.push((graph.to_vid(v as u32), deg));
146 }
147 }
148
149 KCoreResult {
150 core_numbers: results,
151 }
152 }
153}