1pub mod astar;
8pub mod bellman_ford;
9pub mod coloring;
10pub mod dijkstra;
11pub mod dominators;
12pub mod feedback_arc_set;
13pub mod floyd_warshall;
14pub mod ford_fulkerson;
15pub mod isomorphism;
16pub mod k_shortest_path;
17pub mod matching;
18pub mod min_spanning_tree;
19pub mod page_rank;
20pub mod simple_paths;
21pub mod tred;
22
23use std::num::NonZeroUsize;
24
25use crate::prelude::*;
26
27use super::graph::IndexType;
28use super::unionfind::UnionFind;
29use super::visit::{
30 GraphBase, GraphRef, IntoEdgeReferences, IntoNeighbors, IntoNeighborsDirected,
31 IntoNodeIdentifiers, NodeCompactIndexable, NodeIndexable, Reversed, VisitMap, Visitable,
32};
33use super::EdgeType;
34use crate::visit::Walker;
35
36pub use astar::astar;
37pub use bellman_ford::{bellman_ford, find_negative_cycle};
38pub use coloring::dsatur_coloring;
39pub use dijkstra::dijkstra;
40pub use feedback_arc_set::greedy_feedback_arc_set;
41pub use floyd_warshall::floyd_warshall;
42pub use ford_fulkerson::ford_fulkerson;
43pub use isomorphism::{
44 is_isomorphic, is_isomorphic_matching, is_isomorphic_subgraph, is_isomorphic_subgraph_matching,
45 subgraph_isomorphisms_iter,
46};
47pub use k_shortest_path::k_shortest_path;
48pub use matching::{greedy_matching, maximum_matching, Matching};
49pub use min_spanning_tree::min_spanning_tree;
50pub use page_rank::page_rank;
51pub use simple_paths::all_simple_paths;
52
53pub fn connected_components<G>(g: G) -> usize
92where
93 G: NodeCompactIndexable + IntoEdgeReferences,
94{
95 let mut vertex_sets = UnionFind::new(g.node_bound());
96 for edge in g.edge_references() {
97 let (a, b) = (edge.source(), edge.target());
98
99 vertex_sets.union(g.to_index(a), g.to_index(b));
101 }
102 let mut labels = vertex_sets.into_labeling();
103 labels.sort_unstable();
104 labels.dedup();
105 labels.len()
106}
107
108pub fn is_cyclic_undirected<G>(g: G) -> bool
112where
113 G: NodeIndexable + IntoEdgeReferences,
114{
115 let mut edge_sets = UnionFind::new(g.node_bound());
116 for edge in g.edge_references() {
117 let (a, b) = (edge.source(), edge.target());
118
119 if !edge_sets.union(g.to_index(a), g.to_index(b)) {
122 return true;
123 }
124 }
125 false
126}
127
128pub fn toposort<G>(
140 g: G,
141 space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
142) -> Result<Vec<G::NodeId>, Cycle<G::NodeId>>
143where
144 G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable,
145{
146 with_dfs(g, space, |dfs| {
148 dfs.reset(g);
149 let mut finished = g.visit_map();
150
151 let mut finish_stack = Vec::new();
152 for i in g.node_identifiers() {
153 if dfs.discovered.is_visited(&i) {
154 continue;
155 }
156 dfs.stack.push(i);
157 while let Some(&nx) = dfs.stack.last() {
158 if dfs.discovered.visit(nx) {
159 for succ in g.neighbors(nx) {
161 if succ == nx {
162 return Err(Cycle(nx));
164 }
165 if !dfs.discovered.is_visited(&succ) {
166 dfs.stack.push(succ);
167 }
168 }
169 } else {
170 dfs.stack.pop();
171 if finished.visit(nx) {
172 finish_stack.push(nx);
174 }
175 }
176 }
177 }
178 finish_stack.reverse();
179
180 dfs.reset(g);
181 for &i in &finish_stack {
182 dfs.move_to(i);
183 let mut cycle = false;
184 while let Some(j) = dfs.next(Reversed(g)) {
185 if cycle {
186 return Err(Cycle(j));
187 }
188 cycle = true;
189 }
190 }
191
192 Ok(finish_stack)
193 })
194}
195
196pub fn is_cyclic_directed<G>(g: G) -> bool
201where
202 G: IntoNodeIdentifiers + IntoNeighbors + Visitable,
203{
204 use crate::visit::{depth_first_search, DfsEvent};
205
206 depth_first_search(g, g.node_identifiers(), |event| match event {
207 DfsEvent::BackEdge(_, _) => Err(()),
208 _ => Ok(()),
209 })
210 .is_err()
211}
212
213type DfsSpaceType<G> = DfsSpace<<G as GraphBase>::NodeId, <G as Visitable>::Map>;
214
215#[derive(Clone, Debug)]
217pub struct DfsSpace<N, VM> {
218 dfs: Dfs<N, VM>,
219}
220
221impl<N, VM> DfsSpace<N, VM>
222where
223 N: Copy + PartialEq,
224 VM: VisitMap<N>,
225{
226 pub fn new<G>(g: G) -> Self
227 where
228 G: GraphRef + Visitable<NodeId = N, Map = VM>,
229 {
230 DfsSpace { dfs: Dfs::empty(g) }
231 }
232}
233
234impl<N, VM> Default for DfsSpace<N, VM>
235where
236 VM: VisitMap<N> + Default,
237{
238 fn default() -> Self {
239 DfsSpace {
240 dfs: Dfs {
241 stack: <_>::default(),
242 discovered: <_>::default(),
243 },
244 }
245 }
246}
247
248fn with_dfs<G, F, R>(g: G, space: Option<&mut DfsSpaceType<G>>, f: F) -> R
250where
251 G: GraphRef + Visitable,
252 F: FnOnce(&mut Dfs<G::NodeId, G::Map>) -> R,
253{
254 let mut local_visitor;
255 let dfs = if let Some(v) = space {
256 &mut v.dfs
257 } else {
258 local_visitor = Dfs::empty(g);
259 &mut local_visitor
260 };
261 f(dfs)
262}
263
264pub fn has_path_connecting<G>(
271 g: G,
272 from: G::NodeId,
273 to: G::NodeId,
274 space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
275) -> bool
276where
277 G: IntoNeighbors + Visitable,
278{
279 with_dfs(g, space, |dfs| {
280 dfs.reset(g);
281 dfs.move_to(from);
282 dfs.iter(g).any(|x| x == to)
283 })
284}
285
286#[deprecated(note = "renamed to kosaraju_scc")]
288pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
289where
290 G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
291{
292 kosaraju_scc(g)
293}
294
295pub fn kosaraju_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
307where
308 G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
309{
310 let mut dfs = DfsPostOrder::empty(g);
311
312 let mut finish_order = Vec::with_capacity(0);
315 for i in g.node_identifiers() {
316 if dfs.discovered.is_visited(&i) {
317 continue;
318 }
319
320 dfs.move_to(i);
321 while let Some(nx) = dfs.next(Reversed(g)) {
322 finish_order.push(nx);
323 }
324 }
325
326 let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered);
327 dfs.reset(g);
328 let mut sccs = Vec::new();
329
330 for i in finish_order.into_iter().rev() {
333 if dfs.discovered.is_visited(&i) {
334 continue;
335 }
336 dfs.move_to(i);
338 let mut scc = Vec::new();
339 while let Some(nx) = dfs.next(g) {
340 scc.push(nx);
341 }
342 sccs.push(scc);
343 }
344 sccs
345}
346
347#[derive(Copy, Clone, Debug)]
348struct NodeData {
349 rootindex: Option<NonZeroUsize>,
350}
351
352#[derive(Debug)]
356pub struct TarjanScc<N> {
357 index: usize,
358 componentcount: usize,
359 nodes: Vec<NodeData>,
360 stack: Vec<N>,
361}
362
363impl<N> Default for TarjanScc<N> {
364 fn default() -> Self {
365 Self::new()
366 }
367}
368
369impl<N> TarjanScc<N> {
370 pub fn new() -> Self {
372 TarjanScc {
373 index: 1, componentcount: std::usize::MAX, nodes: Vec::new(),
376 stack: Vec::new(),
377 }
378 }
379
380 pub fn run<G, F>(&mut self, g: G, mut f: F)
396 where
397 G: IntoNodeIdentifiers<NodeId = N> + IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
398 F: FnMut(&[N]),
399 N: Copy + PartialEq,
400 {
401 self.nodes.clear();
402 self.nodes
403 .resize(g.node_bound(), NodeData { rootindex: None });
404
405 for n in g.node_identifiers() {
406 let visited = self.nodes[g.to_index(n)].rootindex.is_some();
407 if !visited {
408 self.visit(n, g, &mut f);
409 }
410 }
411
412 debug_assert!(self.stack.is_empty());
413 }
414
415 fn visit<G, F>(&mut self, v: G::NodeId, g: G, f: &mut F)
416 where
417 G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
418 F: FnMut(&[N]),
419 N: Copy + PartialEq,
420 {
421 macro_rules! node {
422 ($node:expr) => {
423 self.nodes[g.to_index($node)]
424 };
425 }
426
427 let node_v = &mut node![v];
428 debug_assert!(node_v.rootindex.is_none());
429
430 let mut v_is_local_root = true;
431 let v_index = self.index;
432 node_v.rootindex = NonZeroUsize::new(v_index);
433 self.index += 1;
434
435 for w in g.neighbors(v) {
436 if node![w].rootindex.is_none() {
437 self.visit(w, g, f);
438 }
439 if node![w].rootindex < node![v].rootindex {
440 node![v].rootindex = node![w].rootindex;
441 v_is_local_root = false
442 }
443 }
444
445 if v_is_local_root {
446 let mut indexadjustment = 1;
448 let c = NonZeroUsize::new(self.componentcount);
449 let nodes = &mut self.nodes;
450 let start = self
451 .stack
452 .iter()
453 .rposition(|&w| {
454 if nodes[g.to_index(v)].rootindex > nodes[g.to_index(w)].rootindex {
455 true
456 } else {
457 nodes[g.to_index(w)].rootindex = c;
458 indexadjustment += 1;
459 false
460 }
461 })
462 .map(|x| x + 1)
463 .unwrap_or_default();
464 nodes[g.to_index(v)].rootindex = c;
465 self.stack.push(v); f(&self.stack[start..]);
467 self.stack.truncate(start);
468 self.index -= indexadjustment; self.componentcount -= 1;
470 } else {
471 self.stack.push(v); }
473 }
474
475 pub fn node_component_index<G>(&self, g: G, v: N) -> usize
477 where
478 G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
479 N: Copy + PartialEq,
480 {
481 let rindex: usize = self.nodes[g.to_index(v)]
482 .rootindex
483 .map(NonZeroUsize::get)
484 .unwrap_or(0); debug_assert!(
486 rindex != 0,
487 "Tried to get the component index of an unvisited node."
488 );
489 debug_assert!(
490 rindex > self.componentcount,
491 "Given node has been visited but not yet assigned to a component."
492 );
493 std::usize::MAX - rindex
494 }
495}
496
497pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
512where
513 G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable,
514{
515 let mut sccs = Vec::new();
516 {
517 let mut tarjan_scc = TarjanScc::new();
518 tarjan_scc.run(g, |scc| sccs.push(scc.to_vec()));
519 }
520 sccs
521}
522
523pub fn condensation<N, E, Ty, Ix>(
604 g: Graph<N, E, Ty, Ix>,
605 make_acyclic: bool,
606) -> Graph<Vec<N>, E, Ty, Ix>
607where
608 Ty: EdgeType,
609 Ix: IndexType,
610{
611 let sccs = kosaraju_scc(&g);
612 let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());
613
614 let mut node_map = vec![NodeIndex::end(); g.node_count()];
616 for comp in sccs {
617 let new_nix = condensed.add_node(Vec::new());
618 for nix in comp {
619 node_map[nix.index()] = new_nix;
620 }
621 }
622
623 let (nodes, edges) = g.into_nodes_edges();
625 for (nix, node) in nodes.into_iter().enumerate() {
626 condensed[node_map[nix]].push(node.weight);
627 }
628 for edge in edges {
629 let source = node_map[edge.source().index()];
630 let target = node_map[edge.target().index()];
631 if make_acyclic {
632 if source != target {
633 condensed.update_edge(source, target, edge.weight);
634 }
635 } else {
636 condensed.add_edge(source, target, edge.weight);
637 }
638 }
639 condensed
640}
641
642#[derive(Clone, Debug, PartialEq)]
644pub struct Cycle<N>(pub(crate) N);
645
646impl<N> Cycle<N> {
647 pub fn node_id(&self) -> N
649 where
650 N: Copy,
651 {
652 self.0
653 }
654}
655
656#[derive(Clone, Debug, PartialEq)]
658pub struct NegativeCycle(pub ());
659
660pub fn is_bipartite_undirected<G, N, VM>(g: G, start: N) -> bool
666where
667 G: GraphRef + Visitable<NodeId = N, Map = VM> + IntoNeighbors<NodeId = N>,
668 N: Copy + PartialEq + std::fmt::Debug,
669 VM: VisitMap<N>,
670{
671 let mut red = g.visit_map();
672 red.visit(start);
673 let mut blue = g.visit_map();
674
675 let mut stack = ::std::collections::VecDeque::new();
676 stack.push_front(start);
677
678 while let Some(node) = stack.pop_front() {
679 let is_red = red.is_visited(&node);
680 let is_blue = blue.is_visited(&node);
681
682 assert!(is_red ^ is_blue);
683
684 for neighbour in g.neighbors(node) {
685 let is_neigbour_red = red.is_visited(&neighbour);
686 let is_neigbour_blue = blue.is_visited(&neighbour);
687
688 if (is_red && is_neigbour_red) || (is_blue && is_neigbour_blue) {
689 return false;
690 }
691
692 if !is_neigbour_red && !is_neigbour_blue {
693 match (is_red, is_blue) {
696 (true, false) => {
697 blue.visit(neighbour);
698 }
699 (false, true) => {
700 red.visit(neighbour);
701 }
702 (_, _) => {
703 panic!("Invariant doesn't hold");
704 }
705 }
706
707 stack.push_back(neighbour);
708 }
709 }
710 }
711
712 true
713}
714
715use std::fmt::Debug;
716use std::ops::Add;
717
718pub trait Measure: Debug + PartialOrd + Add<Self, Output = Self> + Default + Clone {}
720
721impl<M> Measure for M where M: Debug + PartialOrd + Add<M, Output = M> + Default + Clone {}
722
723pub trait FloatMeasure: Measure + Copy {
725 fn zero() -> Self;
726 fn infinite() -> Self;
727}
728
729impl FloatMeasure for f32 {
730 fn zero() -> Self {
731 0.
732 }
733 fn infinite() -> Self {
734 1. / 0.
735 }
736}
737
738impl FloatMeasure for f64 {
739 fn zero() -> Self {
740 0.
741 }
742 fn infinite() -> Self {
743 1. / 0.
744 }
745}
746
747pub trait BoundedMeasure: Measure + std::ops::Sub<Self, Output = Self> {
748 fn min() -> Self;
749 fn max() -> Self;
750 fn overflowing_add(self, rhs: Self) -> (Self, bool);
751}
752
753macro_rules! impl_bounded_measure_integer(
754 ( $( $t:ident ),* ) => {
755 $(
756 impl BoundedMeasure for $t {
757 fn min() -> Self {
758 std::$t::MIN
759 }
760
761 fn max() -> Self {
762 std::$t::MAX
763 }
764
765 fn overflowing_add(self, rhs: Self) -> (Self, bool) {
766 self.overflowing_add(rhs)
767 }
768 }
769 )*
770 };
771);
772
773impl_bounded_measure_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
774
775macro_rules! impl_bounded_measure_float(
776 ( $( $t:ident ),* ) => {
777 $(
778 impl BoundedMeasure for $t {
779 fn min() -> Self {
780 std::$t::MIN
781 }
782
783 fn max() -> Self {
784 std::$t::MAX
785 }
786
787 fn overflowing_add(self, rhs: Self) -> (Self, bool) {
788 let overflow = self > Self::default() && rhs > Self::default() && self > std::$t::MAX - rhs;
790
791 let underflow = !overflow && self < Self::default() && rhs < Self::default() && self < std::$t::MIN - rhs;
793
794 (self + rhs, overflow || underflow)
795 }
796 }
797 )*
798 };
799);
800
801impl_bounded_measure_float!(f32, f64);
802
803pub trait UnitMeasure:
806 Measure
807 + std::ops::Sub<Self, Output = Self>
808 + std::ops::Mul<Self, Output = Self>
809 + std::ops::Div<Self, Output = Self>
810 + std::iter::Sum
811{
812 fn zero() -> Self;
813 fn one() -> Self;
814 fn from_usize(nb: usize) -> Self;
815 fn default_tol() -> Self;
816}
817
818macro_rules! impl_unit_measure(
819 ( $( $t:ident ),* )=> {
820 $(
821 impl UnitMeasure for $t {
822 fn zero() -> Self {
823 0 as $t
824 }
825 fn one() -> Self {
826 1 as $t
827 }
828
829 fn from_usize(nb: usize) -> Self {
830 nb as $t
831 }
832
833 fn default_tol() -> Self {
834 1e-6 as $t
835 }
836
837 }
838
839 )*
840 }
841);
842impl_unit_measure!(f32, f64);
843
844pub trait PositiveMeasure: Measure + Copy {
847 fn zero() -> Self;
848 fn max() -> Self;
849}
850
851macro_rules! impl_positive_measure(
852 ( $( $t:ident ),* )=> {
853 $(
854 impl PositiveMeasure for $t {
855 fn zero() -> Self {
856 0 as $t
857 }
858 fn max() -> Self {
859 std::$t::MAX
860 }
861 }
862
863 )*
864 }
865);
866
867impl_positive_measure!(u8, u16, u32, u64, u128, usize, f32, f64);