ruvector_mincut/algorithm/
replacement.rs1use crate::graph::VertexId;
7use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
8
9pub type EdgeKey = (VertexId, VertexId);
11
12#[inline]
14fn normalize_edge(u: VertexId, v: VertexId) -> EdgeKey {
15 if u < v {
16 (u, v)
17 } else {
18 (v, u)
19 }
20}
21
22#[derive(Debug, Clone)]
32pub struct ReplacementEdgeIndex {
33 max_level: usize,
35 level_edges: Vec<BTreeSet<EdgeKey>>,
38 edge_level: HashMap<EdgeKey, usize>,
40 tree_edges: HashSet<EdgeKey>,
42 level_adjacency: Vec<HashMap<VertexId, BTreeSet<VertexId>>>,
44 component_size: HashMap<VertexId, usize>,
46}
47
48impl ReplacementEdgeIndex {
49 pub fn new(n: usize) -> Self {
51 let max_level = (n as f64).log2().ceil() as usize + 1;
53 let max_level = max_level.max(1);
54
55 Self {
56 max_level,
57 level_edges: vec![BTreeSet::new(); max_level],
58 edge_level: HashMap::new(),
59 tree_edges: HashSet::new(),
60 level_adjacency: vec![HashMap::new(); max_level],
61 component_size: HashMap::new(),
62 }
63 }
64
65 pub fn add_tree_edge(&mut self, u: VertexId, v: VertexId) {
67 let key = normalize_edge(u, v);
68 self.tree_edges.insert(key);
69 }
70
71 pub fn remove_tree_edge(&mut self, u: VertexId, v: VertexId) -> bool {
73 let key = normalize_edge(u, v);
74 self.tree_edges.remove(&key)
75 }
76
77 pub fn add_non_tree_edge(&mut self, u: VertexId, v: VertexId) {
79 let key = normalize_edge(u, v);
80
81 if self.tree_edges.contains(&key) {
83 return;
84 }
85
86 if self.level_edges[0].insert(key) {
88 self.edge_level.insert(key, 0);
89
90 self.level_adjacency[0].entry(u).or_default().insert(v);
92 self.level_adjacency[0].entry(v).or_default().insert(u);
93 }
94 }
95
96 pub fn remove_non_tree_edge(&mut self, u: VertexId, v: VertexId) {
98 let key = normalize_edge(u, v);
99
100 if let Some(level) = self.edge_level.remove(&key) {
101 self.level_edges[level].remove(&key);
102
103 if let Some(adj) = self.level_adjacency[level].get_mut(&u) {
105 adj.remove(&v);
106 }
107 if let Some(adj) = self.level_adjacency[level].get_mut(&v) {
108 adj.remove(&u);
109 }
110 }
111 }
112
113 pub fn find_replacement(
120 &mut self,
121 u: VertexId,
122 v: VertexId,
123 tree_adjacency: &HashMap<VertexId, HashSet<VertexId>>,
124 ) -> Option<EdgeKey> {
125 let key = normalize_edge(u, v);
126
127 if !self.tree_edges.contains(&key) {
129 return None;
130 }
131
132 let (smaller_vertices, _larger_vertices) =
134 self.find_components_after_cut(u, v, tree_adjacency);
135
136 for level in (0..self.max_level).rev() {
138 if let Some(replacement) = self.find_replacement_at_level(level, &smaller_vertices) {
139 return Some(replacement);
140 }
141 }
142
143 self.promote_edges(&smaller_vertices);
145
146 None
147 }
148
149 pub fn find_replacement_fast(&self, smaller_component: &HashSet<VertexId>) -> Option<EdgeKey> {
154 for level in 0..self.max_level {
156 if let Some(replacement) = self.find_replacement_at_level(level, smaller_component) {
157 return Some(replacement);
158 }
159 }
160 None
161 }
162
163 fn find_replacement_at_level(
165 &self,
166 level: usize,
167 component: &HashSet<VertexId>,
168 ) -> Option<EdgeKey> {
169 for &vertex in component {
171 if let Some(neighbors) = self.level_adjacency[level].get(&vertex) {
172 for &neighbor in neighbors {
173 if !component.contains(&neighbor) {
174 return Some(normalize_edge(vertex, neighbor));
176 }
177 }
178 }
179 }
180 None
181 }
182
183 fn find_components_after_cut(
185 &self,
186 u: VertexId,
187 v: VertexId,
188 tree_adj: &HashMap<VertexId, HashSet<VertexId>>,
189 ) -> (HashSet<VertexId>, HashSet<VertexId>) {
190 let mut comp_u = HashSet::new();
191 let mut stack = vec![u];
192 comp_u.insert(u);
193
194 while let Some(x) = stack.pop() {
195 if let Some(neighbors) = tree_adj.get(&x) {
196 for &y in neighbors {
197 if (x == u && y == v) || (x == v && y == u) {
199 continue;
200 }
201 if comp_u.insert(y) {
202 stack.push(y);
203 }
204 }
205 }
206 }
207
208 let mut comp_v = HashSet::new();
209 stack.push(v);
210 comp_v.insert(v);
211
212 while let Some(x) = stack.pop() {
213 if let Some(neighbors) = tree_adj.get(&x) {
214 for &y in neighbors {
215 if (x == u && y == v) || (x == v && y == u) {
216 continue;
217 }
218 if comp_v.insert(y) {
219 stack.push(y);
220 }
221 }
222 }
223 }
224
225 if comp_u.len() <= comp_v.len() {
227 (comp_u, comp_v)
228 } else {
229 (comp_v, comp_u)
230 }
231 }
232
233 fn promote_edges(&mut self, component: &HashSet<VertexId>) {
235 let mut to_promote = Vec::new();
236
237 for level in 0..self.max_level.saturating_sub(1) {
239 for &vertex in component {
240 if let Some(neighbors) = self.level_adjacency[level].get(&vertex).cloned() {
241 for neighbor in neighbors {
242 if component.contains(&neighbor) {
243 let key = normalize_edge(vertex, neighbor);
244 to_promote.push((key, level));
245 }
246 }
247 }
248 }
249 }
250
251 for (key, old_level) in to_promote {
253 let new_level = (old_level + 1).min(self.max_level - 1);
254 if new_level != old_level {
255 let (u, v) = key;
256
257 self.level_edges[old_level].remove(&key);
259 if let Some(adj) = self.level_adjacency[old_level].get_mut(&u) {
260 adj.remove(&v);
261 }
262 if let Some(adj) = self.level_adjacency[old_level].get_mut(&v) {
263 adj.remove(&u);
264 }
265
266 self.level_edges[new_level].insert(key);
268 self.edge_level.insert(key, new_level);
269 self.level_adjacency[new_level]
270 .entry(u)
271 .or_default()
272 .insert(v);
273 self.level_adjacency[new_level]
274 .entry(v)
275 .or_default()
276 .insert(u);
277 }
278 }
279 }
280
281 pub fn stats(&self) -> ReplacementIndexStats {
283 let edges_per_level: Vec<usize> = self.level_edges.iter().map(|s| s.len()).collect();
284
285 ReplacementIndexStats {
286 max_level: self.max_level,
287 tree_edges: self.tree_edges.len(),
288 non_tree_edges: self.edge_level.len(),
289 edges_per_level,
290 }
291 }
292}
293
294#[derive(Debug, Clone)]
296pub struct ReplacementIndexStats {
297 pub max_level: usize,
299 pub tree_edges: usize,
301 pub non_tree_edges: usize,
303 pub edges_per_level: Vec<usize>,
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310
311 #[test]
312 fn test_new_index() {
313 let idx = ReplacementEdgeIndex::new(100);
314 assert!(idx.max_level >= 7); assert_eq!(idx.tree_edges.len(), 0);
316 }
317
318 #[test]
319 fn test_add_tree_edge() {
320 let mut idx = ReplacementEdgeIndex::new(10);
321 idx.add_tree_edge(1, 2);
322 idx.add_tree_edge(2, 3);
323
324 assert!(idx.tree_edges.contains(&(1, 2)));
325 assert!(idx.tree_edges.contains(&(2, 3)));
326 }
327
328 #[test]
329 fn test_add_non_tree_edge() {
330 let mut idx = ReplacementEdgeIndex::new(10);
331 idx.add_tree_edge(1, 2);
332 idx.add_non_tree_edge(1, 3);
333 idx.add_non_tree_edge(2, 4);
334
335 assert!(idx.level_edges[0].contains(&(1, 3)));
337 assert!(idx.level_edges[0].contains(&(2, 4)));
338 assert_eq!(idx.edge_level.get(&(1, 3)), Some(&0));
339 }
340
341 #[test]
342 fn test_find_replacement_simple() {
343 let mut idx = ReplacementEdgeIndex::new(10);
344
345 idx.add_tree_edge(1, 2);
347 idx.add_tree_edge(2, 3);
348
349 idx.add_non_tree_edge(1, 3);
351
352 let mut tree_adj: HashMap<VertexId, HashSet<VertexId>> = HashMap::new();
354 tree_adj.entry(1).or_default().insert(2);
355 tree_adj.entry(2).or_default().insert(1);
356 tree_adj.entry(2).or_default().insert(3);
357 tree_adj.entry(3).or_default().insert(2);
358
359 let replacement = idx.find_replacement(1, 2, &tree_adj);
361 assert_eq!(replacement, Some((1, 3)));
362 }
363
364 #[test]
365 fn test_find_replacement_none() {
366 let mut idx = ReplacementEdgeIndex::new(10);
367
368 idx.add_tree_edge(1, 2);
370 idx.add_tree_edge(2, 3);
371
372 let mut tree_adj: HashMap<VertexId, HashSet<VertexId>> = HashMap::new();
373 tree_adj.entry(1).or_default().insert(2);
374 tree_adj.entry(2).or_default().insert(1);
375 tree_adj.entry(2).or_default().insert(3);
376 tree_adj.entry(3).or_default().insert(2);
377
378 let replacement = idx.find_replacement(1, 2, &tree_adj);
380 assert!(replacement.is_none());
381 }
382
383 #[test]
384 fn test_find_replacement_fast() {
385 let mut idx = ReplacementEdgeIndex::new(10);
386
387 idx.add_non_tree_edge(1, 4);
389 idx.add_non_tree_edge(2, 5);
390
391 let component: HashSet<VertexId> = [1, 2, 3].into_iter().collect();
393
394 let replacement = idx.find_replacement_fast(&component);
396 assert!(replacement.is_some());
397 let (u, v) = replacement.unwrap();
398 assert!(component.contains(&u) != component.contains(&v));
399 }
400
401 #[test]
402 fn test_stats() {
403 let mut idx = ReplacementEdgeIndex::new(100);
404 idx.add_tree_edge(1, 2);
405 idx.add_tree_edge(2, 3);
406 idx.add_non_tree_edge(1, 3);
407 idx.add_non_tree_edge(3, 4);
408
409 let stats = idx.stats();
410 assert_eq!(stats.tree_edges, 2);
411 assert_eq!(stats.non_tree_edges, 2);
412 assert_eq!(stats.edges_per_level[0], 2);
413 }
414
415 #[test]
416 fn test_remove_edges() {
417 let mut idx = ReplacementEdgeIndex::new(10);
418
419 idx.add_tree_edge(1, 2);
420 idx.add_non_tree_edge(1, 3);
421
422 assert!(idx.remove_tree_edge(1, 2));
423 assert!(!idx.tree_edges.contains(&(1, 2)));
424
425 idx.remove_non_tree_edge(1, 3);
426 assert!(!idx.level_edges[0].contains(&(1, 3)));
427 }
428}