1use num_traits::{Bounded, Signed, Zero};
4use rustc_hash::{FxHashMap, FxHashSet};
5use std::collections::VecDeque;
6use std::hash::Hash;
7
8#[derive(Clone, Debug)]
10pub struct IndexedGraph<C> {
11 adjacency: Vec<Vec<(usize, C)>>,
12}
13
14impl<C> IndexedGraph<C> {
15 #[must_use]
17 pub const fn from_adjacency(adjacency: Vec<Vec<(usize, C)>>) -> Self {
18 Self { adjacency }
19 }
20
21 #[must_use]
23 pub const fn node_count(&self) -> usize {
24 self.adjacency.len()
25 }
26
27 #[must_use]
29 pub const fn len(&self) -> usize {
30 self.adjacency.len()
31 }
32
33 #[must_use]
35 pub const fn is_empty(&self) -> bool {
36 self.adjacency.is_empty()
37 }
38
39 #[must_use]
41 pub fn successors(&self, node: usize) -> &[(usize, C)] {
42 &self.adjacency[node]
43 }
44
45 #[must_use]
47 pub fn adjacency(&self) -> &[Vec<(usize, C)>] {
48 &self.adjacency
49 }
50
51 pub fn astar<FH, FS>(
53 &self,
54 start: usize,
55 mut heuristic: FH,
56 mut success: FS,
57 ) -> Option<(Vec<usize>, C)>
58 where
59 C: Zero + Ord + Copy,
60 FH: FnMut(usize) -> C,
61 FS: FnMut(usize) -> bool,
62 {
63 crate::directed::astar::astar(
64 &start,
65 |node| self.successors(*node).iter().copied(),
66 |node| heuristic(*node),
67 |node| success(*node),
68 )
69 }
70
71 pub fn astar_bag<FH, FS>(
73 &self,
74 start: usize,
75 mut heuristic: FH,
76 mut success: FS,
77 ) -> Option<(impl Iterator<Item = Vec<usize>>, C)>
78 where
79 C: Zero + Ord + Copy,
80 FH: FnMut(usize) -> C,
81 FS: FnMut(usize) -> bool,
82 {
83 crate::directed::astar::astar_bag(
84 &start,
85 |node| self.successors(*node).iter().copied(),
86 |node| heuristic(*node),
87 |node| success(*node),
88 )
89 }
90
91 pub fn astar_bag_collect<FH, FS>(
93 &self,
94 start: usize,
95 mut heuristic: FH,
96 mut success: FS,
97 ) -> Option<(Vec<Vec<usize>>, C)>
98 where
99 C: Zero + Ord + Copy,
100 FH: FnMut(usize) -> C,
101 FS: FnMut(usize) -> bool,
102 {
103 crate::directed::astar::astar_bag_collect(
104 &start,
105 |node| self.successors(*node).iter().copied(),
106 |node| heuristic(*node),
107 |node| success(*node),
108 )
109 }
110
111 pub fn bfs<FS>(&self, start: usize, mut success: FS) -> Option<Vec<usize>>
113 where
114 FS: FnMut(usize) -> bool,
115 {
116 crate::directed::bfs::bfs(
117 &start,
118 |node| self.successors(*node).iter().map(|edge| edge.0),
119 |node| success(*node),
120 )
121 }
122
123 #[must_use]
125 pub fn bfs_loop(&self, start: usize) -> Option<Vec<usize>> {
126 crate::directed::bfs::bfs_loop(&start, |node| {
127 self.successors(*node).iter().map(|edge| edge.0)
128 })
129 }
130
131 #[must_use]
133 pub fn bfs_bidirectional(&self, start: usize, end: usize) -> Option<Vec<usize>> {
134 let mut predecessors = vec![Vec::new(); self.node_count()];
135 for (from, edges) in self.adjacency.iter().enumerate() {
136 for &(to, _) in edges {
137 predecessors[to].push(from);
138 }
139 }
140
141 crate::directed::bfs::bfs_bidirectional(
142 &start,
143 &end,
144 |node| {
145 self.successors(*node)
146 .iter()
147 .map(|edge| edge.0)
148 .collect::<Vec<_>>()
149 },
150 |node| predecessors[*node].clone(),
151 )
152 }
153
154 pub fn bfs_reach(&self, start: usize) -> impl Iterator<Item = usize> + '_ {
156 crate::directed::bfs::bfs_reach(start, |node| {
157 self.successors(*node).iter().map(|edge| edge.0)
158 })
159 }
160
161 pub fn dfs<FS>(&self, start: usize, mut success: FS) -> Option<Vec<usize>>
163 where
164 FS: FnMut(usize) -> bool,
165 {
166 crate::directed::dfs::dfs(
167 start,
168 |node| self.successors(*node).iter().map(|edge| edge.0),
169 |node| success(*node),
170 )
171 }
172
173 pub fn dfs_reach(&self, start: usize) -> impl Iterator<Item = usize> + '_ {
175 crate::directed::dfs::dfs_reach(start, |node| {
176 self.successors(*node).iter().map(|edge| edge.0)
177 })
178 }
179
180 pub fn iddfs<FS>(&self, start: usize, mut success: FS) -> Option<Vec<usize>>
182 where
183 FS: FnMut(usize) -> bool,
184 {
185 crate::directed::iddfs::iddfs(
186 start,
187 |node| self.successors(*node).iter().map(|edge| edge.0),
188 |node| success(*node),
189 )
190 }
191
192 pub fn idastar<FH, FS>(
194 &self,
195 start: usize,
196 mut heuristic: FH,
197 mut success: FS,
198 ) -> Option<(Vec<usize>, C)>
199 where
200 C: Zero + Ord + Copy,
201 FH: FnMut(usize) -> C,
202 FS: FnMut(usize) -> bool,
203 {
204 crate::directed::idastar::idastar(
205 &start,
206 |node| self.successors(*node).iter().copied(),
207 |node| heuristic(*node),
208 |node| success(*node),
209 )
210 }
211
212 pub fn dijkstra<FS>(&self, start: usize, mut success: FS) -> Option<(Vec<usize>, C)>
214 where
215 C: Zero + Ord + Copy,
216 FS: FnMut(usize) -> bool,
217 {
218 crate::directed::dijkstra::dijkstra(
219 &start,
220 |node| self.successors(*node).iter().copied(),
221 |node| success(*node),
222 )
223 }
224
225 pub fn dijkstra_all(&self, start: usize) -> Vec<Option<(usize, C)>>
227 where
228 C: Zero + Ord + Copy,
229 {
230 let parents = crate::directed::dijkstra::dijkstra_all(&start, |node| {
231 self.successors(*node).iter().copied()
232 });
233 let mut out = vec![None; self.node_count()];
234 for (node, (parent, cost)) in parents {
235 out[node] = Some((parent, cost));
236 }
237 out
238 }
239
240 pub fn dijkstra_partial<FS>(
242 &self,
243 start: usize,
244 mut stop: FS,
245 ) -> (Vec<Option<(usize, C)>>, Option<usize>)
246 where
247 C: Zero + Ord + Copy,
248 FS: FnMut(usize) -> bool,
249 {
250 let (parents, reached) = crate::directed::dijkstra::dijkstra_partial(
251 &start,
252 |node| self.successors(*node).iter().copied(),
253 |node| stop(*node),
254 );
255 let mut out = vec![None; self.node_count()];
256 for (node, (parent, cost)) in parents {
257 out[node] = Some((parent, cost));
258 }
259 (out, reached)
260 }
261
262 pub fn dijkstra_reach(
264 &self,
265 start: usize,
266 ) -> impl Iterator<Item = (usize, Option<usize>, C)> + '_
267 where
268 C: Zero + Ord + Copy + Hash,
269 {
270 crate::directed::dijkstra::dijkstra_reach(&start, |node| {
271 self.successors(*node).iter().copied()
272 })
273 .map(|item| (item.node, item.parent, item.total_cost))
274 }
275
276 pub fn bmssp<FS>(&self, start: usize, success: FS) -> Option<(Vec<usize>, C)>
278 where
279 C: Zero + Ord + Copy,
280 FS: FnMut(usize) -> bool,
281 {
282 crate::directed::bmssp::bmssp_indexed(
283 start,
284 |node| self.successors(node).iter().copied(),
285 success,
286 self.node_count(),
287 )
288 }
289
290 #[must_use]
292 pub fn bmssp_all(&self, start: usize) -> Vec<Option<(usize, C)>>
293 where
294 C: Zero + Ord + Copy,
295 {
296 crate::directed::bmssp::bmssp_all_indexed(
297 start,
298 |node| self.successors(node).iter().copied(),
299 self.node_count(),
300 )
301 }
302
303 pub fn fringe<FH, FS>(
305 &self,
306 start: usize,
307 mut heuristic: FH,
308 mut success: FS,
309 ) -> Option<(Vec<usize>, C)>
310 where
311 C: Bounded + Zero + Ord + Copy,
312 FH: FnMut(usize) -> C,
313 FS: FnMut(usize) -> bool,
314 {
315 crate::directed::fringe::fringe(
316 &start,
317 |node| self.successors(*node).iter().copied(),
318 |node| heuristic(*node),
319 |node| success(*node),
320 )
321 }
322
323 pub fn topological_sort(&self) -> Result<Vec<usize>, usize> {
329 let nodes = (0..self.node_count()).collect::<Vec<_>>();
330 crate::directed::topological_sort::topological_sort(&nodes, |node| {
331 self.successors(*node).iter().map(|edge| edge.0)
332 })
333 }
334
335 #[must_use]
337 pub fn strongly_connected_components(&self) -> Vec<Vec<usize>> {
338 let nodes = (0..self.node_count()).collect::<Vec<_>>();
339 crate::directed::strongly_connected_components::strongly_connected_components(
340 &nodes,
341 |node| self.successors(*node).iter().map(|edge| edge.0),
342 )
343 }
344
345 #[must_use]
347 pub fn strongly_connected_components_from(&self, start: usize) -> Vec<Vec<usize>> {
348 crate::directed::strongly_connected_components::strongly_connected_components_from(
349 &start,
350 |node| self.successors(*node).iter().map(|edge| edge.0),
351 )
352 }
353
354 #[must_use]
356 pub fn strongly_connected_component(&self, node: usize) -> Vec<usize> {
357 crate::directed::strongly_connected_components::strongly_connected_component(&node, |n| {
358 self.successors(*n).iter().map(|edge| edge.0)
359 })
360 }
361
362 pub fn count_paths<FS>(&self, start: usize, mut success: FS) -> usize
364 where
365 FS: FnMut(usize) -> bool,
366 {
367 crate::directed::count_paths::count_paths(
368 start,
369 |node| self.successors(*node).iter().map(|edge| edge.0),
370 |node| success(*node),
371 )
372 }
373
374 pub fn yen<FS>(&self, start: usize, mut success: FS, k: usize) -> Vec<(Vec<usize>, C)>
376 where
377 C: Zero + Ord + Copy,
378 FS: FnMut(usize) -> bool,
379 {
380 crate::directed::yen::yen(
381 &start,
382 |node| self.successors(*node).iter().copied(),
383 |node| success(*node),
384 k,
385 )
386 }
387
388 #[expect(clippy::too_many_lines)]
394 #[expect(clippy::type_complexity)]
395 #[must_use]
396 pub fn edmonds_karp(
397 &self,
398 source: usize,
399 sink: usize,
400 ) -> (Vec<((usize, usize), C)>, C, Vec<((usize, usize), C)>)
401 where
402 C: Copy + Zero + Signed + Ord + Bounded,
403 {
404 let node_count = self.node_count();
405 if node_count == 0 || source == sink {
406 return (Vec::new(), Zero::zero(), Vec::new());
407 }
408 assert!(source < node_count, "source out of bounds");
409 assert!(sink < node_count, "sink out of bounds");
410
411 let mut capacity = vec![vec![C::zero(); node_count]; node_count];
412 for (from, edges) in self.adjacency.iter().enumerate() {
413 for &(to, weight) in edges {
414 capacity[from][to] = capacity[from][to] + weight;
415 }
416 }
417
418 let mut predecessors = vec![Vec::new(); node_count];
419 for (from, edges) in self.adjacency.iter().enumerate() {
420 for &(to, _) in edges {
421 predecessors[to].push(from);
422 }
423 }
424
425 let mut flow = vec![vec![C::zero(); node_count]; node_count];
426 let mut total = C::zero();
427
428 loop {
429 let mut parent = vec![usize::MAX; node_count];
430 let mut direction = vec![true; node_count];
431 let mut path_capacity = vec![C::zero(); node_count];
432 let mut queue = VecDeque::new();
433
434 parent[source] = source;
435 path_capacity[source] = C::max_value();
436 queue.push_back(source);
437
438 while let Some(node) = queue.pop_front() {
439 let capacity_so_far = path_capacity[node];
440 for &(next, _) in &self.adjacency[node] {
441 if parent[next] != usize::MAX || next == source {
442 continue;
443 }
444 let residual = capacity[node][next] - flow[node][next];
445 if residual <= Zero::zero() {
446 continue;
447 }
448 parent[next] = node;
449 direction[next] = true;
450 path_capacity[next] = if capacity_so_far < residual {
451 capacity_so_far
452 } else {
453 residual
454 };
455 if next == sink {
456 break;
457 }
458 queue.push_back(next);
459 }
460 if parent[sink] != usize::MAX {
461 break;
462 }
463 for &prev in &predecessors[node] {
464 if parent[prev] != usize::MAX || prev == source {
465 continue;
466 }
467 let residual = flow[prev][node];
468 if residual <= Zero::zero() {
469 continue;
470 }
471 parent[prev] = node;
472 direction[prev] = false;
473 path_capacity[prev] = if capacity_so_far < residual {
474 capacity_so_far
475 } else {
476 residual
477 };
478 if prev == sink {
479 break;
480 }
481 queue.push_back(prev);
482 }
483 if parent[sink] != usize::MAX {
484 break;
485 }
486 }
487
488 if parent[sink] == usize::MAX {
489 break;
490 }
491
492 let augment = path_capacity[sink];
493 let mut node = sink;
494 while node != source {
495 let prev = parent[node];
496 if direction[node] {
497 flow[prev][node] = flow[prev][node] + augment;
498 } else {
499 flow[node][prev] = flow[node][prev] - augment;
500 }
501 node = prev;
502 }
503 total = total + augment;
504 }
505
506 let mut reachable = vec![false; node_count];
507 let mut queue = VecDeque::new();
508 reachable[source] = true;
509 queue.push_back(source);
510 while let Some(node) = queue.pop_front() {
511 for &(next, _) in &self.adjacency[node] {
512 if reachable[next] {
513 continue;
514 }
515 let residual = capacity[node][next] - flow[node][next];
516 if residual > Zero::zero() {
517 reachable[next] = true;
518 queue.push_back(next);
519 }
520 }
521 for &prev in &predecessors[node] {
522 if reachable[prev] {
523 continue;
524 }
525 if flow[prev][node] > Zero::zero() {
526 reachable[prev] = true;
527 queue.push_back(prev);
528 }
529 }
530 }
531
532 let mut flows = Vec::new();
533 for (from, edges) in self.adjacency.iter().enumerate() {
534 for &(to, _) in edges {
535 let value = flow[from][to];
536 if value > Zero::zero() {
537 flows.push(((from, to), value));
538 }
539 }
540 }
541
542 let mut cuts = Vec::new();
543 for (from, edges) in self.adjacency.iter().enumerate() {
544 if !reachable[from] {
545 continue;
546 }
547 for &(to, _) in edges {
548 if reachable[to] {
549 continue;
550 }
551 let cap = capacity[from][to];
552 if cap > Zero::zero() {
553 cuts.push(((from, to), cap));
554 }
555 }
556 }
557
558 (flows, total, cuts)
559 }
560}
561
562#[derive(Clone, Debug)]
564pub struct IndexedUndirectedGraph<C> {
565 adjacency: Vec<Vec<(usize, C)>>,
566 edges: Vec<(usize, usize, C)>,
567}
568
569impl<C> IndexedUndirectedGraph<C> {
570 #[must_use]
572 pub fn from_edges(node_count: usize, edges: Vec<(usize, usize, C)>) -> Self
573 where
574 C: Clone,
575 {
576 let mut adjacency = vec![Vec::new(); node_count];
577 for (u, v, w) in &edges {
578 debug_assert!(*u < node_count, "edge start out of bounds");
579 debug_assert!(*v < node_count, "edge end out of bounds");
580 adjacency[*u].push((*v, w.clone()));
581 adjacency[*v].push((*u, w.clone()));
582 }
583 Self { adjacency, edges }
584 }
585
586 #[must_use]
588 pub const fn node_count(&self) -> usize {
589 self.adjacency.len()
590 }
591
592 #[must_use]
594 pub fn successors(&self, node: usize) -> &[(usize, C)] {
595 &self.adjacency[node]
596 }
597
598 #[must_use]
600 pub fn edges(&self) -> &[(usize, usize, C)] {
601 &self.edges
602 }
603
604 #[must_use]
606 pub fn adjacency(&self) -> &[Vec<(usize, C)>] {
607 &self.adjacency
608 }
609
610 #[must_use]
612 pub fn connected_components(&self) -> Vec<Vec<usize>> {
613 let nodes = (0..self.node_count()).collect::<Vec<_>>();
614 let components =
615 crate::undirected::connected_components::connected_components(&nodes, |n| {
616 self.successors(*n).iter().map(|edge| edge.0)
617 });
618 components
619 .into_iter()
620 .map(|set| set.into_iter().collect())
621 .collect()
622 }
623
624 #[must_use]
626 pub fn component_index(&self) -> Vec<usize> {
627 let components = self.connected_components();
628 let mut index = vec![usize::MAX; self.node_count()];
629 for (component_idx, component) in components.iter().enumerate() {
630 for &node in component {
631 index[node] = component_idx;
632 }
633 }
634 index
635 }
636
637 #[must_use]
639 pub fn components(&self) -> Vec<Vec<usize>> {
640 self.connected_components()
641 }
642
643 #[must_use]
645 pub fn separate_components(&self) -> (Vec<usize>, Vec<usize>) {
646 let groups = (0..self.node_count())
647 .map(|node| {
648 let mut group = Vec::with_capacity(self.adjacency[node].len() + 1);
649 group.push(node);
650 group.extend(self.adjacency[node].iter().map(|edge| edge.0));
651 group
652 })
653 .collect::<Vec<_>>();
654 let (mapping, group_indices) =
655 crate::undirected::connected_components::separate_components(&groups);
656 let mut node_components = vec![usize::MAX; self.node_count()];
657 for (node, component) in mapping {
658 node_components[*node] = component;
659 }
660 (node_components, group_indices)
661 }
662
663 #[must_use]
665 pub fn maximal_cliques_collect(&self) -> Vec<Vec<usize>> {
666 let adjacency_sets = self.adjacency_sets();
667 let mut connected = |a: &usize, b: &usize| adjacency_sets[*a].contains(b);
668 crate::undirected::cliques::maximal_cliques_collect(0..self.node_count(), &mut connected)
669 .into_iter()
670 .map(|set| set.into_iter().collect())
671 .collect()
672 }
673
674 pub fn maximal_cliques<CO>(&self, mut consumer: CO)
676 where
677 CO: FnMut(&Vec<usize>),
678 {
679 let adjacency_sets = self.adjacency_sets();
680 let mut connected = |a: &usize, b: &usize| adjacency_sets[*a].contains(b);
681 let mut adapter = |clique: &std::collections::HashSet<usize>| {
682 let clique_vec = clique.iter().copied().collect::<Vec<_>>();
683 consumer(&clique_vec);
684 };
685 crate::undirected::cliques::maximal_cliques(
686 0..self.node_count(),
687 &mut connected,
688 &mut adapter,
689 );
690 }
691
692 #[must_use]
694 pub fn kruskal(&self) -> Vec<(usize, usize, C)>
695 where
696 C: Clone + Ord,
697 {
698 self.kruskal_indices().collect()
699 }
700
701 pub fn kruskal_indices(&self) -> impl Iterator<Item = (usize, usize, C)>
703 where
704 C: Clone + Ord,
705 {
706 crate::undirected::kruskal::kruskal_indices(self.node_count(), self.edges())
707 }
708
709 #[must_use]
711 pub fn prim(&self) -> Vec<(usize, usize, C)>
712 where
713 C: Clone + Ord,
714 {
715 crate::undirected::prim::prim(self.edges())
716 .into_iter()
717 .map(|(a, b, c)| (*a, *b, c))
718 .collect()
719 }
720
721 fn adjacency_sets(&self) -> Vec<FxHashSet<usize>> {
722 self.adjacency
723 .iter()
724 .map(|edges| edges.iter().map(|edge| edge.0).collect())
725 .collect()
726 }
727}
728
729#[derive(Clone, Debug)]
731pub struct IndexedGraphMap<N, C> {
732 graph: IndexedGraph<C>,
733 nodes: Vec<N>,
734 index: FxHashMap<N, usize>,
735}
736
737impl<N, C> IndexedGraphMap<N, C>
738where
739 N: Eq + Hash + Clone,
740{
741 pub fn from_nodes_and_successors<I, FN, IN>(nodes: I, mut successors: FN) -> Self
743 where
744 I: IntoIterator<Item = N>,
745 FN: FnMut(&N) -> IN,
746 IN: IntoIterator<Item = (N, C)>,
747 {
748 let mut mapped = Self {
749 graph: IndexedGraph::from_adjacency(Vec::new()),
750 nodes: Vec::new(),
751 index: FxHashMap::default(),
752 };
753
754 for node in nodes {
755 mapped.ensure_index(node);
756 }
757
758 let mut cursor = 0usize;
759 while cursor < mapped.nodes.len() {
760 let node = mapped.nodes[cursor].clone();
761 let mut edges = Vec::new();
762 for (neighbor, cost) in successors(&node) {
763 let neighbor_idx = mapped.ensure_index(neighbor);
764 edges.push((neighbor_idx, cost));
765 }
766 if cursor >= mapped.graph.adjacency.len() {
767 mapped.graph.adjacency.push(edges);
768 } else {
769 mapped.graph.adjacency[cursor] = edges;
770 }
771 cursor += 1;
772 }
773
774 mapped
775 }
776
777 #[must_use]
779 pub const fn graph(&self) -> &IndexedGraph<C> {
780 &self.graph
781 }
782
783 #[must_use]
785 pub fn into_graph(self) -> IndexedGraph<C> {
786 self.graph
787 }
788
789 #[must_use]
791 pub const fn node_count(&self) -> usize {
792 self.graph.node_count()
793 }
794
795 #[must_use]
797 pub fn index_of(&self, node: &N) -> Option<usize> {
798 self.index.get(node).copied()
799 }
800
801 #[must_use]
803 pub fn node(&self, index: usize) -> Option<&N> {
804 self.nodes.get(index)
805 }
806
807 #[must_use]
809 pub fn nodes(&self) -> &[N] {
810 &self.nodes
811 }
812
813 fn ensure_index(&mut self, node: N) -> usize {
814 if let Some(&idx) = self.index.get(&node) {
815 return idx;
816 }
817 let idx = self.nodes.len();
818 self.nodes.push(node.clone());
819 self.index.insert(node, idx);
820 self.graph.adjacency.push(Vec::new());
821 idx
822 }
823}