1use std::collections::{HashMap, HashSet};
2use std::fmt::Debug;
3use std::hash::Hash;
4pub mod connected_graph;
5
6pub const DEFAULT_CONNECTIONS_PER_VERTEX: usize = 4;
8
9#[derive(Clone, Debug, Default)]
12pub struct Graph<T: Hash + Eq> {
13 verts: HashMap<T, HashSet<T>>,
14 edge_per_vertex_capacity: usize,
15}
16
17impl<T: Hash + Eq + Clone> Graph<T> {
18 pub fn new() -> Self {
20 Self {
21 verts: HashMap::new(),
22 edge_per_vertex_capacity: DEFAULT_CONNECTIONS_PER_VERTEX,
23 }
24 }
25
26 pub fn with_capacity(vertices_capacity: usize, edge_per_vertex_capacity: usize) -> Self {
32 Self {
33 verts: HashMap::with_capacity(vertices_capacity),
34 edge_per_vertex_capacity,
35 }
36 }
37
38 pub fn from_data(
43 vertices: impl Iterator<Item=T>,
44 edges: impl Iterator<Item=(T, T)>,
45 ) -> Self {
46 let verts: HashMap<T, HashSet<T>> = vertices
47 .map(|v| (v, HashSet::with_capacity(DEFAULT_CONNECTIONS_PER_VERTEX)))
48 .collect();
49
50 let mut temp = Self {
51 verts,
52 edge_per_vertex_capacity: DEFAULT_CONNECTIONS_PER_VERTEX,
53 };
54
55 for (v1, v2) in edges {
56 temp.add_edge(&v1, &v2);
57 }
58
59 temp
60 }
61
62 pub fn contains(&self, v: &T) -> bool {
64 self.verts.contains_key(v)
65 }
66
67 pub fn add_vertex(&mut self, v: T) -> bool {
73 if self.verts.contains_key(&v) {
74 return false;
75 }
76 self.verts
77 .insert(v, HashSet::with_capacity(self.edge_per_vertex_capacity));
78 true
79 }
80
81 pub fn remove_vertex(&mut self, v: &T) -> Option<HashSet<T>> {
87 if let Some(connections) = self.verts.remove(v) {
88 for c in &connections {
89 self.verts.get_mut(c).unwrap().remove(v);
90 }
91 return Some(connections);
92 }
93
94 None
95 }
96
97 pub fn add_edge(&mut self, v1: &T, v2: &T) -> bool {
105 if self.verts.contains_key(v1) && self.verts.contains_key(v2) {
106 if v1 == v2 {
107 return false;
108 }
109 self.verts.get_mut(v1).unwrap().insert(v2.clone());
110 self.verts.get_mut(v2).unwrap().insert(v1.clone());
111 return true;
112 }
113 false
114 }
115
116 pub fn remove_edge(&mut self, v1: &T, v2: &T) -> bool {
125 if self.verts.contains_key(v1) && self.verts.contains_key(v2) {
126 self.verts.get_mut(v1).unwrap().remove(v2);
127 self.verts.get_mut(v2).unwrap().remove(v1);
128 return true;
129 }
130 false
131 }
132
133 pub fn is_connected(&self, v1: &T, v2: &T) -> bool {
140 if let Some(v) = self.verts.get(v1) {
141 if v1 == v2 {
142 return true;
143 }
144 return v.contains(v2);
145 }
146 false
147 }
148
149 pub fn connects_of(&self, v: &T) -> Option<&HashSet<T>> {
155 self.verts.get(v)
156 }
157
158 pub fn vertices(&self) -> impl Iterator<Item=&T> {
160 self.verts.keys()
161 }
162
163 pub fn len(&self) -> usize {
165 self.verts.len()
166 }
167
168 pub fn is_empty(&self) -> bool {
170 self.verts.is_empty()
171 }
172
173 pub fn remove_weak_connected(&mut self, weak_level: usize) -> HashSet<T> {
193 let mut to_process: HashSet<T> = self.verts.iter()
194 .filter(|(_, c)| c.len() < weak_level)
195 .map(|(v, _)| v.clone()).collect();
196
197 let mut all_removed = HashSet::with_capacity(self.len());
198
199 while !to_process.is_empty() {
200 let processing = to_process;
201 to_process = HashSet::with_capacity(processing.len() * 4);
202 for v in processing {
203 if self.contains(&v) {
204 let removed_vert_neighbors = self.remove_vertex(&v).unwrap();
205 all_removed.insert(v);
206 let weak_connected_neighbors = removed_vert_neighbors
207 .into_iter()
208 .filter(|n| self.connects_of(n).unwrap().len() < weak_level);
209 to_process.extend(weak_connected_neighbors);
210 }
211 }
212 }
213 all_removed
214 }
215
216 pub fn verts_with_path_to(&self, vertex: &T) -> HashSet<T> {
218 let mut to_process = HashSet::with_capacity(self.len());
219 to_process.insert(vertex.clone());
220 let mut separate_part_verts = HashSet::with_capacity(self.len());
221 while !to_process.is_empty() {
222 let to_process_iter = to_process.into_iter();
223 to_process = HashSet::with_capacity(self.len());
224 for v in to_process_iter {
225 let connections_iter = self.verts.get(&v).unwrap().clone().into_iter();
226 to_process.extend(connections_iter.filter(|c| !separate_part_verts.contains(c)));
227 separate_part_verts.insert(v);
228 }
229 }
230 separate_part_verts
231 }
232
233 pub fn take_connected_graph(&mut self, vertex: &T) -> Self {
235 if !self.verts.contains_key(vertex) {
236 return Self::new();
237 }
238
239 let separate_part_verts = self.verts_with_path_to(vertex);
240
241 let mut separate_part = Self::with_capacity(self.len(), self.edge_per_vertex_capacity);
242 for v in separate_part_verts {
243 let (v, c) = self.verts.remove_entry(&v).unwrap();
244 separate_part.verts.insert(v, c);
245 }
246
247 separate_part
248 }
249
250 pub fn into_connected_graphs(mut self) -> Vec<Self> {
252 let separate_part_capacity = 4;
253 let mut separate_parts = Vec::with_capacity(separate_part_capacity);
254 while !self.is_empty() {
255 let start = self.verts.iter().next().unwrap().0.clone();
256 separate_parts.push(self.take_connected_graph(&start));
257 }
258
259 separate_parts
260 }
261}
262
263impl<T: Eq + Hash> PartialEq<Graph<T>> for Graph<T> {
264 fn eq(&self, other: &Graph<T>) -> bool {
265 self.verts == other.verts
266 }
267}
268
269impl<T: Eq + Hash> Eq for Graph<T> {}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274
275 fn test_data() -> (Vec<i32>, Vec<(i32, i32)>) {
276 let verts = vec![0, 1, 2, 3, 4, 10];
277 let conns = vec![(0, 1), (1, 2), (2, 3), (3, 4), (10, 0), (4, 10), ];
278 (verts, conns)
279 }
280
281 fn test_graph() -> Graph<i32> {
282 let (verts, conns) = test_data();
283 Graph::from_data(verts.into_iter(), conns.into_iter())
284 }
285
286 #[test]
287 fn from_data() {
288 let verts = test_data().0;
289 let g = test_graph();
290
291 assert_eq!(verts.len(), g.len());
292
293 assert_test_data(g);
294 }
295
296 fn assert_test_data(g: Graph<i32>) {
297 assert!(g.contains(&0));
298 assert!(g.contains(&1));
299 assert!(g.contains(&2));
300 assert!(g.contains(&3));
301 assert!(g.contains(&4));
302 assert!(g.contains(&10));
303 assert!(g.is_connected(&0, &10));
304 assert!(g.is_connected(&0, &1));
305 assert!(g.is_connected(&1, &0));
306 assert!(g.is_connected(&1, &2));
307 assert!(g.is_connected(&2, &3));
308 assert!(g.is_connected(&2, &1));
309 assert!(g.is_connected(&3, &2));
310 assert!(g.is_connected(&3, &4));
311 assert!(g.is_connected(&4, &3));
312 assert!(g.is_connected(&4, &10));
313 assert!(g.is_connected(&10, &0));
314 assert!(g.is_connected(&10, &4));
315 }
316
317 #[test]
318 fn add_vertex() {
319 let mut g = test_graph();
320 let new_vertex = 15;
321 assert!(g.add_vertex(new_vertex));
322 let presented_vertex = 3;
323 assert!(!g.add_vertex(presented_vertex));
324 assert!(g.contains(&new_vertex));
325 assert!(g.contains(&presented_vertex));
326 assert!(g.connects_of(&new_vertex).unwrap().is_empty());
327 assert_eq!(g.connects_of(&presented_vertex).unwrap().len(), 2);
328 }
329
330 #[test]
331 fn remove_vertex() {
332 let mut g = test_graph();
333 assert!(g.remove_vertex(&22).is_none());
334 let c = g.remove_vertex(&2);
335 assert!(c.is_some());
336 let c = c.unwrap();
337 assert_eq!(c.len(), 2);
338 assert!(c.contains(&1));
339 assert!(c.contains(&3));
340 }
341
342 #[test]
343 fn add_edge() {
344 let mut g = test_graph();
345 g.add_edge(&1, &4);
346 assert!(g.is_connected(&1, &4));
347 assert!(g.is_connected(&4, &1));
348 }
349
350 #[test]
351 fn remove_edge() {
352 let mut g = test_graph();
353 assert!(g.remove_edge(&0, &1));
354 assert!(!g.is_connected(&0, &1));
355 assert!(!g.is_connected(&1, &0));
356 g.remove_edge(&1, &0);
357 }
358
359 #[test]
360 fn remove_weak_connected() {
361 let mut g = test_graph();
362 g.add_vertex(11);
363 g.add_vertex(12);
364 g.add_edge(&0, &11);
365 g.add_edge(&11, &12);
366 g.add_edge(&2, &4);
367 g.add_edge(&10, &3);
368 g.add_edge(&10, &2);
369 g.add_edge(&1, &2);
370 assert_eq!(g.len(), 8);
371 g.remove_weak_connected(2);
372 assert_eq!(g.len(), 6);
373 assert!(g.contains(&0));
374 assert!(g.contains(&1));
375 assert!(g.contains(&2));
376 assert!(g.contains(&3));
377 assert!(g.contains(&4));
378 assert!(g.contains(&10));
379 g.remove_weak_connected(3);
380 assert_eq!(g.len(), 4);
381 assert!(g.contains(&2));
382 assert!(g.contains(&3));
383 assert!(g.contains(&4));
384 assert!(g.contains(&10));
385 }
386
387
388 #[test]
389 fn verts_with_path_to() {
390 let mut g = test_graph();
391 g.add_vertex(20);
392 g.add_vertex(30);
393 g.add_vertex(40);
394 g.add_edge(&20, &30);
395 g.add_edge(&30, &40);
396 g.add_edge(&40, &20);
397
398 let cg1 = g.verts_with_path_to(&0);
399 let cg2 = g.verts_with_path_to(&20);
400
401 assert_eq!(cg1.len(), 6);
402 assert_eq!(cg2.len(), 3);
403
404 assert!(cg1.contains(&0));
405 assert!(cg1.contains(&1));
406 assert!(cg1.contains(&2));
407 assert!(cg1.contains(&3));
408 assert!(cg1.contains(&4));
409 assert!(cg1.contains(&10));
410
411 assert!(cg2.contains(&20));
412 assert!(cg2.contains(&30));
413 assert!(cg2.contains(&40));
414 }
415
416 #[test]
417 fn take_connected_graph() {
418 let mut g = test_graph();
419 g.add_vertex(20);
420 g.add_vertex(30);
421 g.add_vertex(40);
422 g.add_edge(&20, &30);
423 g.add_edge(&30, &40);
424 g.add_edge(&40, &20);
425
426 assert!(g.take_connected_graph(&50).is_empty());
427 assert_eq!(g.len(), 9);
428
429 let sp = g.take_connected_graph(&20);
430 assert_eq!(g.len(), 6);
431 assert_eq!(sp.len(), 3);
432
433 assert_test_data(g);
434
435 assert_separate_part(sp);
436 }
437
438 fn assert_separate_part(sp: Graph<i32>) {
439 assert!(sp.contains(&20));
440 assert!(sp.contains(&30));
441 assert!(sp.contains(&40));
442 assert!(sp.is_connected(&20, &30));
443 assert!(sp.is_connected(&30, &40));
444 assert!(sp.is_connected(&40, &20));
445 }
446
447 #[test]
448 fn into_connected_graphs() {
449 let mut g = test_graph();
450 g.add_vertex(20);
451 g.add_vertex(30);
452 g.add_vertex(40);
453 g.add_edge(&20, &30);
454 g.add_edge(&30, &40);
455 g.add_edge(&40, &20);
456
457 let mut separate_parts = g.into_connected_graphs();
458 assert_eq!(separate_parts.len(), 2);
459
460 if separate_parts[0].contains(&20) {
461 assert_test_data(separate_parts.remove(1));
462 assert_separate_part(separate_parts.remove(0));
463 } else {
464 assert_separate_part(separate_parts.remove(1));
465 assert_test_data(separate_parts.remove(0));
466 }
467 }
468}