1use hashbrown::HashSet;
21use indexmap::map::Entry;
22use indexmap::IndexSet;
23use petgraph::visit::{IntoNeighborsDirected, NodeCount};
24use petgraph::Direction::Outgoing;
25use std::iter;
26use std::{hash::Hash, iter::FromIterator};
27
28use crate::dictmap::*;
29
30pub fn all_simple_paths_multiple_targets<G>(
59 graph: G,
60 from: G::NodeId,
61 to: &HashSet<G::NodeId>,
62 min_intermediate_nodes: usize,
63 max_intermediate_nodes: Option<usize>,
64) -> DictMap<G::NodeId, Vec<Vec<G::NodeId>>>
65where
66 G: NodeCount,
67 G: IntoNeighborsDirected,
68 G::NodeId: Eq + Hash,
69{
70 let max_length = if let Some(l) = max_intermediate_nodes {
74 l + 1
75 } else {
76 graph.node_count() - 1
77 };
78
79 let min_length = min_intermediate_nodes + 1;
80
81 let mut visited: IndexSet<G::NodeId> = IndexSet::from_iter(Some(from));
83 let mut stack = vec![graph.neighbors_directed(from, Outgoing)];
86
87 let mut output: DictMap<G::NodeId, Vec<Vec<G::NodeId>>> = DictMap::with_capacity(to.len());
88
89 while let Some(children) = stack.last_mut() {
90 if let Some(child) = children.next() {
91 if visited.len() < max_length {
92 if !visited.contains(&child) {
93 if to.contains(&child) && visited.len() >= min_length {
94 let new_path: Vec<G::NodeId> =
95 visited.iter().chain(&[child]).copied().collect();
96 match output.entry(child) {
97 Entry::Vacant(e) => {
98 e.insert(vec![new_path]);
99 }
100 Entry::Occupied(mut e) => {
101 e.get_mut().push(new_path);
102 }
103 }
104 }
105 visited.insert(child);
106 if to.iter().any(|n| !visited.contains(n)) {
107 stack.push(graph.neighbors_directed(child, Outgoing));
108 } else {
109 visited.pop();
110 }
111 }
112 } else {
114 for c in children.chain(iter::once(child)) {
115 if to.contains(&c) && !visited.contains(&c) && visited.len() >= min_length {
116 let new_path: Vec<G::NodeId> =
117 visited.iter().chain(&[c]).copied().collect();
118 match output.entry(c) {
119 Entry::Vacant(e) => {
120 e.insert(vec![new_path]);
121 }
122 Entry::Occupied(mut e) => {
123 e.get_mut().push(new_path);
124 }
125 }
126 }
127 }
128 stack.pop();
129 visited.pop();
130 }
131 } else {
132 stack.pop();
133 visited.pop();
134 }
135 }
136 output
137}
138
139pub fn longest_simple_path_multiple_targets<G>(
166 graph: G,
167 from: G::NodeId,
168 to: &HashSet<G::NodeId>,
169) -> Option<Vec<G::NodeId>>
170where
171 G: NodeCount,
172 G: IntoNeighborsDirected,
173 G::NodeId: Eq + Hash,
174{
175 let mut visited: IndexSet<G::NodeId> = IndexSet::from_iter(Some(from));
177 let mut stack = vec![graph.neighbors_directed(from, Outgoing)];
180
181 let mut output_path: Option<Vec<G::NodeId>> = None;
182
183 let update_path = |new_path: Vec<G::NodeId>,
184 output_path: &Option<Vec<G::NodeId>>|
185 -> Option<Vec<G::NodeId>> {
186 match output_path.as_ref() {
187 None => Some(new_path),
188 Some(path) => {
189 if path.len() < new_path.len() {
190 Some(new_path)
191 } else {
192 None
193 }
194 }
195 }
196 };
197
198 while let Some(children) = stack.last_mut() {
199 if let Some(child) = children.next() {
200 if !visited.contains(&child) {
201 if to.contains(&child) {
202 let new_path: Vec<G::NodeId> =
203 visited.iter().chain(&[child]).copied().collect();
204 let temp = update_path(new_path, &output_path);
205 if temp.is_some() {
206 output_path = temp;
207 }
208 }
209 visited.insert(child);
210 if to.iter().any(|n| !visited.contains(n)) {
211 stack.push(graph.neighbors_directed(child, Outgoing));
212 } else {
213 visited.pop();
214 }
215 }
216 } else {
217 stack.pop();
218 visited.pop();
219 }
220 }
221 output_path
222}
223
224#[cfg(test)]
225mod tests {
226 use crate::connectivity::{
227 all_simple_paths_multiple_targets, longest_simple_path_multiple_targets,
228 };
229 use hashbrown::HashSet;
230 use petgraph::prelude::*;
231
232 #[test]
233 fn test_all_simple_paths() {
234 let mut graph = Graph::new_undirected();
236 let a = graph.add_node(0);
237 let b = graph.add_node(1);
238 let c = graph.add_node(2);
239 let d = graph.add_node(3);
240 let e = graph.add_node(4);
241
242 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
243
244 let mut to_set = HashSet::new();
245 to_set.insert(d);
246
247 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, None);
248
249 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
250 }
251
252 #[test]
253 fn test_all_simple_paths_with_two_targets_emits_two_paths() {
254 let mut graph = Graph::new_undirected();
256 let a = graph.add_node(0);
257 let b = graph.add_node(1);
258 let c = graph.add_node(2);
259 let d = graph.add_node(3);
260 let e = graph.add_node(4);
261
262 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
263
264 let mut to_set = HashSet::new();
265 to_set.insert(d);
266 to_set.insert(e);
267
268 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, None);
269
270 assert_eq!(
271 paths.get(&d).unwrap(),
272 &vec![vec![a, b, c, e, d], vec![a, b, c, d]]
273 );
274 assert_eq!(
275 paths.get(&e).unwrap(),
276 &vec![vec![a, b, c, e], vec![a, b, c, d, e]]
277 );
278 }
279
280 #[test]
281 fn test_digraph_all_simple_paths_with_two_targets_emits_two_paths() {
282 let mut graph = Graph::new();
284 let a = graph.add_node(0);
285 let b = graph.add_node(1);
286 let c = graph.add_node(2);
287 let d = graph.add_node(3);
288 let e = graph.add_node(4);
289
290 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
291
292 let mut to_set = HashSet::new();
293 to_set.insert(d);
294 to_set.insert(e);
295
296 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, None);
297
298 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
299 assert_eq!(
300 paths.get(&e).unwrap(),
301 &vec![vec![a, b, c, e], vec![a, b, c, d, e]]
302 );
303 }
304
305 #[test]
306 fn test_all_simple_paths_max_nodes() {
307 let mut graph = Graph::new_undirected();
309 let a = graph.add_node(0);
310 let b = graph.add_node(1);
311 let c = graph.add_node(2);
312 let d = graph.add_node(3);
313 let e = graph.add_node(4);
314
315 graph.extend_with_edges([
316 (a, b, 1),
317 (a, c, 1),
318 (a, d, 1),
319 (a, e, 1),
320 (b, c, 1),
321 (b, d, 1),
322 (b, e, 1),
323 (c, d, 1),
324 (c, e, 1),
325 (d, e, 1),
326 ]);
327
328 let mut to_set = HashSet::new();
329 to_set.insert(b);
330
331 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, Some(0));
332
333 assert_eq!(paths.get(&b).unwrap(), &vec![vec![a, b]]);
334
335 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, Some(1));
336
337 assert_eq!(
338 paths.get(&b).unwrap(),
339 &vec![vec![a, e, b], vec![a, d, b], vec![a, c, b], vec![a, b],]
340 );
341 }
342
343 #[test]
344 fn test_all_simple_paths_with_two_targets_max_nodes() {
345 let mut graph = Graph::new_undirected();
347 let a = graph.add_node(0);
348 let b = graph.add_node(1);
349 let c = graph.add_node(2);
350 let d = graph.add_node(3);
351 let e = graph.add_node(4);
352
353 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
354
355 let mut to_set = HashSet::new();
356 to_set.insert(d);
357 to_set.insert(e);
358
359 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, Some(2));
360
361 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
362 assert_eq!(paths.get(&e).unwrap(), &vec![vec![a, b, c, e]]);
363 }
364
365 #[test]
366 fn test_digraph_all_simple_paths_with_two_targets_max_nodes() {
367 let mut graph = Graph::new();
369 let a = graph.add_node(0);
370 let b = graph.add_node(1);
371 let c = graph.add_node(2);
372 let d = graph.add_node(3);
373 let e = graph.add_node(4);
374
375 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
376
377 let mut to_set = HashSet::new();
378 to_set.insert(d);
379 to_set.insert(e);
380
381 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, Some(2));
382
383 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
384 assert_eq!(paths.get(&e).unwrap(), &vec![vec![a, b, c, e]]);
385 }
386
387 #[test]
388 fn test_all_simple_paths_with_two_targets_in_line_emits_two_paths() {
389 let mut graph = Graph::new_undirected();
391 let a = graph.add_node(0);
392 let b = graph.add_node(1);
393 let c = graph.add_node(2);
394 let d = graph.add_node(3);
395 let e = graph.add_node(4);
396
397 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
398
399 let mut to_set = HashSet::new();
400 to_set.insert(c);
401 to_set.insert(d);
402
403 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, None);
404
405 assert_eq!(paths.get(&c).unwrap(), &vec![vec![a, b, c]]);
406 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
407 }
408
409 #[test]
410 fn test_all_simple_paths_min_nodes() {
411 let mut graph = Graph::new();
413 let a = graph.add_node(0);
414 let b = graph.add_node(1);
415 let c = graph.add_node(2);
416 let d = graph.add_node(3);
417
418 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, a, 1), (b, d, 1)]);
419
420 let mut to_set = HashSet::new();
421 to_set.insert(d);
422
423 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 2, None);
424
425 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
426 }
427
428 #[test]
429 fn test_all_simple_paths_with_two_targets_min_nodes() {
430 let mut graph = Graph::new();
432 let a = graph.add_node(0);
433 let b = graph.add_node(1);
434 let c = graph.add_node(2);
435 let d = graph.add_node(3);
436
437 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, a, 1), (b, d, 1)]);
438
439 let mut to_set = HashSet::new();
440 to_set.insert(c);
441 to_set.insert(d);
442
443 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 2, None);
444
445 assert_eq!(paths.get(&c), None);
446 assert_eq!(paths.get(&d).unwrap(), &vec![vec![a, b, c, d]]);
447 }
448
449 #[test]
450 fn test_all_simple_paths_source_target() {
451 let mut graph = Graph::new_undirected();
453 let a = graph.add_node(0);
454 let b = graph.add_node(1);
455 let c = graph.add_node(2);
456 let d = graph.add_node(3);
457 let e = graph.add_node(4);
458
459 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
460
461 let mut to_set = HashSet::new();
462 to_set.insert(a);
463
464 let paths = all_simple_paths_multiple_targets(&graph, a, &to_set, 0, None);
465
466 assert_eq!(paths.get(&a), None);
467 }
468
469 #[test]
470 fn test_all_simple_paths_on_non_trivial_graph() {
471 let mut graph = Graph::new();
473 let a = graph.add_node(0);
474 let b = graph.add_node(1);
475 let c = graph.add_node(2);
476 let d = graph.add_node(3);
477 let e = graph.add_node(4);
478 let f = graph.add_node(5);
479
480 graph.extend_with_edges([
481 (a, b, 1),
482 (b, c, 1),
483 (c, d, 1),
484 (d, e, 1),
485 (e, f, 1),
486 (a, f, 1),
487 (b, f, 1),
488 (b, d, 1),
489 (f, e, 1),
490 (e, c, 1),
491 (e, d, 1),
492 ]);
493
494 let mut to_set = HashSet::new();
495 to_set.insert(c);
496 to_set.insert(d);
497
498 let paths = all_simple_paths_multiple_targets(&graph, b, &to_set, 0, None);
499
500 assert_eq!(
501 paths.get(&c).unwrap(),
502 &vec![vec![b, d, e, c], vec![b, f, e, c], vec![b, c]]
503 );
504 assert_eq!(
505 paths.get(&d).unwrap(),
506 &vec![
507 vec![b, d],
508 vec![b, f, e, d],
509 vec![b, f, e, c, d],
510 vec![b, c, d]
511 ]
512 );
513
514 let paths = all_simple_paths_multiple_targets(&graph, b, &to_set, 1, None);
515
516 assert_eq!(
517 paths.get(&c).unwrap(),
518 &vec![vec![b, d, e, c], vec![b, f, e, c]]
519 );
520 assert_eq!(
521 paths.get(&d).unwrap(),
522 &vec![vec![b, f, e, d], vec![b, f, e, c, d], vec![b, c, d]]
523 );
524
525 let paths = all_simple_paths_multiple_targets(&graph, b, &to_set, 0, Some(2));
526
527 assert_eq!(
528 paths.get(&c).unwrap(),
529 &vec![vec![b, d, e, c], vec![b, f, e, c], vec![b, c]]
530 );
531 assert_eq!(
532 paths.get(&d).unwrap(),
533 &vec![vec![b, d], vec![b, f, e, d], vec![b, c, d]]
534 );
535 }
536
537 #[test]
538 fn test_longest_simple_path() {
539 let mut graph = Graph::new_undirected();
541 let a = graph.add_node(0);
542 let b = graph.add_node(1);
543 let c = graph.add_node(2);
544 let d = graph.add_node(3);
545 let e = graph.add_node(4);
546
547 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
548
549 let mut to_set = HashSet::new();
550 to_set.insert(d);
551
552 let path = longest_simple_path_multiple_targets(&graph, a, &to_set);
553
554 assert_eq!(path.unwrap(), vec![a, b, c, d]);
555 }
556
557 #[test]
558 fn test_longest_simple_path_with_two_targets_emits_two_paths() {
559 let mut graph = Graph::new_undirected();
561 let a = graph.add_node(0);
562 let b = graph.add_node(1);
563 let c = graph.add_node(2);
564 let d = graph.add_node(3);
565 let e = graph.add_node(4);
566
567 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
568
569 let mut to_set = HashSet::new();
570 to_set.insert(d);
571 to_set.insert(e);
572
573 let path = longest_simple_path_multiple_targets(&graph, a, &to_set);
574
575 assert_eq!(path.unwrap(), vec![a, b, c, e, d]);
576 }
577
578 #[test]
579 fn test_digraph_longest_simple_path_with_two_targets_emits_two_paths() {
580 let mut graph = Graph::new();
582 let a = graph.add_node(0);
583 let b = graph.add_node(1);
584 let c = graph.add_node(2);
585 let d = graph.add_node(3);
586 let e = graph.add_node(4);
587
588 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1), (c, e, 1)]);
589
590 let mut to_set = HashSet::new();
591 to_set.insert(d);
592 to_set.insert(e);
593
594 let path = longest_simple_path_multiple_targets(&graph, a, &to_set);
595
596 assert_eq!(path.unwrap(), vec![a, b, c, d, e]);
597 }
598
599 #[test]
600 fn test_longest_simple_paths_with_two_targets_in_line_emits_two_paths() {
601 let mut graph = Graph::new_undirected();
603 let a = graph.add_node(0);
604 let b = graph.add_node(1);
605 let c = graph.add_node(2);
606 let d = graph.add_node(3);
607 let e = graph.add_node(4);
608
609 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
610
611 let mut to_set = HashSet::new();
612 to_set.insert(c);
613 to_set.insert(d);
614
615 let path = longest_simple_path_multiple_targets(&graph, a, &to_set);
616
617 assert_eq!(path.unwrap(), vec![a, b, c, d]);
618 }
619
620 #[test]
621 fn test_longest_simple_paths_source_target() {
622 let mut graph = Graph::new_undirected();
624 let a = graph.add_node(0);
625 let b = graph.add_node(1);
626 let c = graph.add_node(2);
627 let d = graph.add_node(3);
628 let e = graph.add_node(4);
629
630 graph.extend_with_edges([(a, b, 1), (b, c, 1), (c, d, 1), (d, e, 1)]);
631
632 let mut to_set = HashSet::new();
633 to_set.insert(a);
634
635 let path = longest_simple_path_multiple_targets(&graph, a, &to_set);
636
637 assert_eq!(path, None);
638 }
639
640 #[test]
641 fn test_longest_simple_paths_on_non_trivial_graph() {
642 let mut graph = Graph::new();
644 let a = graph.add_node(0);
645 let b = graph.add_node(1);
646 let c = graph.add_node(2);
647 let d = graph.add_node(3);
648 let e = graph.add_node(4);
649 let f = graph.add_node(5);
650
651 graph.extend_with_edges([
652 (a, b, 1),
653 (b, c, 1),
654 (c, d, 1),
655 (d, e, 1),
656 (e, f, 1),
657 (a, f, 1),
658 (b, f, 1),
659 (b, d, 1),
660 (f, e, 1),
661 (e, c, 1),
662 (e, d, 1),
663 ]);
664
665 let mut to_set = HashSet::new();
666 to_set.insert(c);
667 to_set.insert(d);
668
669 let path = longest_simple_path_multiple_targets(&graph, b, &to_set);
670
671 assert_eq!(path.unwrap(), vec![b, f, e, c, d],);
672 }
673}