petgraph/algo/
mod.rs

1//! Graph algorithms.
2//!
3//! It is a goal to gradually migrate the algorithms to be based on graph traits
4//! so that they are generally applicable. For now, some of these still require
5//! the `Graph` type.
6
7pub mod articulation_points;
8pub mod astar;
9pub mod bellman_ford;
10pub mod bridges;
11pub mod coloring;
12pub mod dijkstra;
13pub mod dominators;
14pub mod feedback_arc_set;
15pub mod floyd_warshall;
16pub mod ford_fulkerson;
17pub mod isomorphism;
18pub mod johnson;
19pub mod k_shortest_path;
20pub mod matching;
21pub mod maximal_cliques;
22pub mod min_spanning_tree;
23pub mod page_rank;
24pub mod simple_paths;
25pub mod spfa;
26#[cfg(feature = "stable_graph")]
27pub mod steiner_tree;
28pub mod tred;
29
30use alloc::{vec, vec::Vec};
31use core::num::NonZeroUsize;
32
33use crate::prelude::*;
34
35use super::graph::IndexType;
36use super::unionfind::UnionFind;
37use super::visit::{
38    GraphBase, GraphRef, IntoEdgeReferences, IntoNeighbors, IntoNeighborsDirected,
39    IntoNodeIdentifiers, NodeCompactIndexable, NodeIndexable, Reversed, VisitMap, Visitable,
40};
41use super::EdgeType;
42use crate::visit::Walker;
43
44pub use astar::astar;
45pub use bellman_ford::{bellman_ford, find_negative_cycle};
46pub use bridges::bridges;
47pub use coloring::dsatur_coloring;
48pub use dijkstra::dijkstra;
49pub use feedback_arc_set::greedy_feedback_arc_set;
50pub use floyd_warshall::floyd_warshall;
51pub use ford_fulkerson::ford_fulkerson;
52pub use isomorphism::{
53    is_isomorphic, is_isomorphic_matching, is_isomorphic_subgraph, is_isomorphic_subgraph_matching,
54    subgraph_isomorphisms_iter,
55};
56pub use johnson::johnson;
57pub use k_shortest_path::k_shortest_path;
58pub use matching::{greedy_matching, maximum_matching, Matching};
59pub use maximal_cliques::maximal_cliques;
60pub use min_spanning_tree::{min_spanning_tree, min_spanning_tree_prim};
61pub use page_rank::page_rank;
62pub use simple_paths::all_simple_paths;
63pub use spfa::spfa;
64#[cfg(feature = "stable_graph")]
65pub use steiner_tree::steiner_tree;
66
67#[cfg(feature = "rayon")]
68pub use johnson::parallel_johnson;
69
70/// \[Generic\] Return the number of connected components of the graph.
71///
72/// For a directed graph, this is the *weakly* connected components.
73///
74/// # Arguments
75/// * `g`: an input graph.
76///
77/// # Returns
78/// * `usize`: the number of connected components if `g` is undirected
79///   or number of *weakly* connected components if `g` is directed.
80///
81/// # Complexity
82/// * Time complexity: amortized **O(|E| + |V|log|V|)**.
83/// * Auxiliary space: **O(|V|)**.
84///
85/// where **|V|** is the number of nodes and **|E|** is the number of edges.
86///
87/// # Example
88/// ```rust
89/// use petgraph::Graph;
90/// use petgraph::algo::connected_components;
91/// use petgraph::prelude::*;
92///
93/// let mut graph : Graph<(),(),Directed>= Graph::new();
94/// let a = graph.add_node(()); // node with no weight
95/// let b = graph.add_node(());
96/// let c = graph.add_node(());
97/// let d = graph.add_node(());
98/// let e = graph.add_node(());
99/// let f = graph.add_node(());
100/// let g = graph.add_node(());
101/// let h = graph.add_node(());
102///
103/// graph.extend_with_edges(&[
104///     (a, b),
105///     (b, c),
106///     (c, d),
107///     (d, a),
108///     (e, f),
109///     (f, g),
110///     (g, h),
111///     (h, e)
112/// ]);
113/// // a ----> b       e ----> f
114/// // ^       |       ^       |
115/// // |       v       |       v
116/// // d <---- c       h <---- g
117///
118/// assert_eq!(connected_components(&graph),2);
119/// graph.add_edge(b,e,());
120/// assert_eq!(connected_components(&graph),1);
121/// ```
122pub fn connected_components<G>(g: G) -> usize
123where
124    G: NodeCompactIndexable + IntoEdgeReferences,
125{
126    let mut node_sets = UnionFind::new(g.node_bound());
127    for edge in g.edge_references() {
128        let (a, b) = (edge.source(), edge.target());
129
130        // union the two nodes of the edge
131        node_sets.union(g.to_index(a), g.to_index(b));
132    }
133
134    let mut labels = node_sets.into_labeling();
135    labels.sort_unstable();
136    labels.dedup();
137    labels.len()
138}
139
140/// \[Generic\] Return `true` if the input graph contains a cycle.
141///
142/// Always treats the input graph as if undirected.
143///
144/// # Arguments:
145/// `g`: an input graph that always treated as undirected.
146///
147/// # Returns
148/// `true`: if the input graph contains a cycle.
149/// `false`: otherwise.
150///
151/// # Complexity
152/// * Time complexity: amortized **O(|E|)**.
153/// * Auxiliary space: **O(|V|)**.
154///
155/// where **|V|** is the number of nodes and **|E|** is the number of edges.
156pub fn is_cyclic_undirected<G>(g: G) -> bool
157where
158    G: NodeIndexable + IntoEdgeReferences,
159{
160    let mut edge_sets = UnionFind::new(g.node_bound());
161    for edge in g.edge_references() {
162        let (a, b) = (edge.source(), edge.target());
163
164        // union the two nodes of the edge
165        //  -- if they were already the same, then we have a cycle
166        if !edge_sets.union(g.to_index(a), g.to_index(b)) {
167            return true;
168        }
169    }
170    false
171}
172
173/// \[Generic\] Perform a topological sort of a directed graph.
174///
175/// `toposort` returns `Err` on graphs with cycles.
176/// To handle graphs with cycles, use the one of scc algorithms or
177/// [`DfsPostOrder`](struct@crate::visit::DfsPostOrder)
178///   instead of this function.
179///
180/// The implementation is iterative.
181///
182/// # Arguments
183/// * `g`: an acyclic directed graph.
184/// * `space`: optional [`DfsSpace`]. If `space` is not `None`,
185///   it is used instead of creating a new workspace for graph traversal.
186///
187/// # Returns
188/// * `Ok`: a vector of nodes in topological order: each node is ordered before its successors
189///   (if the graph was acyclic).
190/// * `Err`: [`Cycle`] if the graph was not acyclic. Self loops are also cycles this case.
191///
192/// # Complexity
193/// * Time complexity: **O(|V| + |E|)**.
194/// * Auxiliary space: **O(|V|)**.
195///
196/// where **|V|** is the number of nodes and **|E|** is the number of edges.
197pub fn toposort<G>(
198    g: G,
199    space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
200) -> Result<Vec<G::NodeId>, Cycle<G::NodeId>>
201where
202    G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable,
203{
204    // based on kosaraju scc
205    with_dfs(g, space, |dfs| {
206        dfs.reset(g);
207        let mut finished = g.visit_map();
208
209        let mut finish_stack = Vec::new();
210        for i in g.node_identifiers() {
211            if dfs.discovered.is_visited(&i) {
212                continue;
213            }
214            dfs.stack.push(i);
215            while let Some(&nx) = dfs.stack.last() {
216                if dfs.discovered.visit(nx) {
217                    // First time visiting `nx`: Push neighbors, don't pop `nx`
218                    for succ in g.neighbors(nx) {
219                        if succ == nx {
220                            // self cycle
221                            return Err(Cycle(nx));
222                        }
223                        if !dfs.discovered.is_visited(&succ) {
224                            dfs.stack.push(succ);
225                        }
226                    }
227                } else {
228                    dfs.stack.pop();
229                    if finished.visit(nx) {
230                        // Second time: All reachable nodes must have been finished
231                        finish_stack.push(nx);
232                    }
233                }
234            }
235        }
236        finish_stack.reverse();
237
238        dfs.reset(g);
239        for &i in &finish_stack {
240            dfs.move_to(i);
241            let mut cycle = false;
242            while let Some(j) = dfs.next(Reversed(g)) {
243                if cycle {
244                    return Err(Cycle(j));
245                }
246                cycle = true;
247            }
248        }
249
250        Ok(finish_stack)
251    })
252}
253
254/// \[Generic\] Return `true` if the input directed graph contains a cycle.
255///
256/// This implementation is recursive; use [`toposort`] if an alternative is needed.
257///
258/// # Arguments:
259/// `g`: a directed graph.
260///
261/// # Returns
262/// `true`: if the input graph contains a cycle.
263/// `false`: otherwise.
264///
265/// # Complexity
266/// * Time complexity: **O(|V| + |E|)**.
267/// * Auxiliary space: **O(|V|)**.
268///
269/// where **|V|** is the number of nodes and **|E|** is the number of edges.
270pub fn is_cyclic_directed<G>(g: G) -> bool
271where
272    G: IntoNodeIdentifiers + IntoNeighbors + Visitable,
273{
274    use crate::visit::{depth_first_search, DfsEvent};
275
276    depth_first_search(g, g.node_identifiers(), |event| match event {
277        DfsEvent::BackEdge(_, _) => Err(()),
278        _ => Ok(()),
279    })
280    .is_err()
281}
282
283type DfsSpaceType<G> = DfsSpace<<G as GraphBase>::NodeId, <G as Visitable>::Map>;
284
285/// Workspace for a graph traversal.
286#[derive(Clone, Debug)]
287pub struct DfsSpace<N, VM> {
288    dfs: Dfs<N, VM>,
289}
290
291impl<N, VM> DfsSpace<N, VM>
292where
293    N: Copy + PartialEq,
294    VM: VisitMap<N>,
295{
296    pub fn new<G>(g: G) -> Self
297    where
298        G: GraphRef + Visitable<NodeId = N, Map = VM>,
299    {
300        DfsSpace { dfs: Dfs::empty(g) }
301    }
302}
303
304impl<N, VM> Default for DfsSpace<N, VM>
305where
306    VM: VisitMap<N> + Default,
307{
308    fn default() -> Self {
309        DfsSpace {
310            dfs: Dfs {
311                stack: <_>::default(),
312                discovered: <_>::default(),
313            },
314        }
315    }
316}
317
318/// Create a Dfs if it's needed
319fn with_dfs<G, F, R>(g: G, space: Option<&mut DfsSpaceType<G>>, f: F) -> R
320where
321    G: GraphRef + Visitable,
322    F: FnOnce(&mut Dfs<G::NodeId, G::Map>) -> R,
323{
324    let mut local_visitor;
325    let dfs = if let Some(v) = space {
326        &mut v.dfs
327    } else {
328        local_visitor = Dfs::empty(g);
329        &mut local_visitor
330    };
331    f(dfs)
332}
333
334/// \[Generic\] Check if there exists a path starting at `from` and reaching `to`.
335///
336/// If `from` and `to` are equal, this function returns true.
337///
338/// # Arguments:
339/// * `g`: an input graph.
340/// * `from`: the first node of a desired path.
341/// * `to`: the last node of a desired path.
342/// * `space`: optional [`DfsSpace`]. If `space` is not `None`,
343///   it is used instead of creating a new workspace for graph traversal.
344///
345/// # Returns
346/// * `true`: if there exists a path starting at `from` and reaching
347///   `to` or `from` and `to` are equal.
348/// * `false`: otherwise.
349///
350/// # Complexity
351/// * Time complexity: **O(|V| + |E|)**.
352/// * Auxiliary space: **O(|V|)** or **O(1)** if `space` was provided.
353///
354/// where **|V|** is the number of nodes and **|E|** is the number of edges.
355pub fn has_path_connecting<G>(
356    g: G,
357    from: G::NodeId,
358    to: G::NodeId,
359    space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
360) -> bool
361where
362    G: IntoNeighbors + Visitable,
363{
364    with_dfs(g, space, |dfs| {
365        dfs.reset(g);
366        dfs.move_to(from);
367        dfs.iter(g).any(|x| x == to)
368    })
369}
370
371/// Renamed to `kosaraju_scc`.
372#[deprecated(note = "renamed to kosaraju_scc")]
373pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
374where
375    G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
376{
377    kosaraju_scc(g)
378}
379
380/// \[Generic\] Compute the *strongly connected components* using [Kosaraju's algorithm][1].
381///
382/// This implementation is iterative and does two passes over the nodes.
383///
384/// # Arguments
385/// * `g`: a directed or undirected graph.
386///
387/// # Returns
388/// Return a vector where each element is a strongly connected component (scc).
389/// The order of node ids within each scc is arbitrary, but the order of
390/// the sccs is their postorder (reverse topological sort).
391///
392/// For an undirected graph, the sccs are simply the connected components.
393///
394/// # Complexity
395/// * Time complexity: **O(|V| + |E|)**.
396/// * Auxiliary space: **O(|V|)**.
397///
398/// where **|V|** is the number of nodes and **|E|** is the number of edges.
399///
400/// [1]: https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
401pub fn kosaraju_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
402where
403    G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
404{
405    let mut dfs = DfsPostOrder::empty(g);
406
407    // First phase, reverse dfs pass, compute finishing times.
408    // http://stackoverflow.com/a/26780899/161659
409    let mut finish_order = Vec::with_capacity(0);
410    for i in g.node_identifiers() {
411        if dfs.discovered.is_visited(&i) {
412            continue;
413        }
414
415        dfs.move_to(i);
416        while let Some(nx) = dfs.next(Reversed(g)) {
417            finish_order.push(nx);
418        }
419    }
420
421    let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered);
422    dfs.reset(g);
423    let mut sccs = Vec::new();
424
425    // Second phase
426    // Process in decreasing finishing time order
427    for i in finish_order.into_iter().rev() {
428        if dfs.discovered.is_visited(&i) {
429            continue;
430        }
431        // Move to the leader node `i`.
432        dfs.move_to(i);
433        let mut scc = Vec::new();
434        while let Some(nx) = dfs.next(g) {
435            scc.push(nx);
436        }
437        sccs.push(scc);
438    }
439    sccs
440}
441
442#[derive(Copy, Clone, Debug)]
443struct NodeData {
444    rootindex: Option<NonZeroUsize>,
445}
446
447/// A reusable state for computing the *strongly connected components* using [Tarjan's algorithm][1].
448///
449/// [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
450#[derive(Debug)]
451pub struct TarjanScc<N> {
452    index: usize,
453    componentcount: usize,
454    nodes: Vec<NodeData>,
455    stack: Vec<N>,
456}
457
458impl<N> Default for TarjanScc<N> {
459    fn default() -> Self {
460        Self::new()
461    }
462}
463
464impl<N> TarjanScc<N> {
465    /// Creates a new `TarjanScc`
466    pub fn new() -> Self {
467        TarjanScc {
468            index: 1,                   // Invariant: index < componentcount at all times.
469            componentcount: usize::MAX, // Will hold if componentcount is initialized to number of nodes - 1 or higher.
470            nodes: Vec::new(),
471            stack: Vec::new(),
472        }
473    }
474
475    /// \[Generic\] Compute the *strongly connected components* using Algorithm 3 in
476    /// [A Space-Efficient Algorithm for Finding Strongly Connected Components][1] by David J. Pierce,
477    /// which is a memory-efficient variation of [Tarjan's algorithm][2].
478    ///
479    ///
480    /// [1]: https://homepages.ecs.vuw.ac.nz/~djp/files/P05.pdf
481    /// [2]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
482    ///
483    /// Calls `f` for each strongly strongly connected component (scc).
484    /// The order of node ids within each scc is arbitrary, but the order of
485    /// the sccs is their postorder (reverse topological sort).
486    ///
487    /// For an undirected graph, the sccs are simply the connected components.
488    ///
489    /// This implementation is recursive and does one pass over the nodes.
490    pub fn run<G, F>(&mut self, g: G, mut f: F)
491    where
492        G: IntoNodeIdentifiers<NodeId = N> + IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
493        F: FnMut(&[N]),
494        N: Copy + PartialEq,
495    {
496        self.nodes.clear();
497        self.nodes
498            .resize(g.node_bound(), NodeData { rootindex: None });
499
500        for n in g.node_identifiers() {
501            let visited = self.nodes[g.to_index(n)].rootindex.is_some();
502            if !visited {
503                self.visit(n, g, &mut f);
504            }
505        }
506
507        debug_assert!(self.stack.is_empty());
508    }
509
510    fn visit<G, F>(&mut self, v: G::NodeId, g: G, f: &mut F)
511    where
512        G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
513        F: FnMut(&[N]),
514        N: Copy + PartialEq,
515    {
516        macro_rules! node {
517            ($node:expr) => {
518                self.nodes[g.to_index($node)]
519            };
520        }
521
522        let node_v = &mut node![v];
523        debug_assert!(node_v.rootindex.is_none());
524
525        let mut v_is_local_root = true;
526        let v_index = self.index;
527        node_v.rootindex = NonZeroUsize::new(v_index);
528        self.index += 1;
529
530        for w in g.neighbors(v) {
531            if node![w].rootindex.is_none() {
532                self.visit(w, g, f);
533            }
534            if node![w].rootindex < node![v].rootindex {
535                node![v].rootindex = node![w].rootindex;
536                v_is_local_root = false
537            }
538        }
539
540        if v_is_local_root {
541            // Pop the stack and generate an SCC.
542            let mut indexadjustment = 1;
543            let c = NonZeroUsize::new(self.componentcount);
544            let nodes = &mut self.nodes;
545            let start = self
546                .stack
547                .iter()
548                .rposition(|&w| {
549                    if nodes[g.to_index(v)].rootindex > nodes[g.to_index(w)].rootindex {
550                        true
551                    } else {
552                        nodes[g.to_index(w)].rootindex = c;
553                        indexadjustment += 1;
554                        false
555                    }
556                })
557                .map(|x| x + 1)
558                .unwrap_or_default();
559            nodes[g.to_index(v)].rootindex = c;
560            self.stack.push(v); // Pushing the component root to the back right before getting rid of it is somewhat ugly, but it lets it be included in f.
561            f(&self.stack[start..]);
562            self.stack.truncate(start);
563            self.index -= indexadjustment; // Backtrack index back to where it was before we ever encountered the component.
564            self.componentcount -= 1;
565        } else {
566            self.stack.push(v); // Stack is filled up when backtracking, unlike in Tarjans original algorithm.
567        }
568    }
569
570    /// Returns the index of the component in which v has been assigned. Allows for using self as a lookup table for an scc decomposition produced by self.run().
571    pub fn node_component_index<G>(&self, g: G, v: N) -> usize
572    where
573        G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
574        N: Copy + PartialEq,
575    {
576        let rindex: usize = self.nodes[g.to_index(v)]
577            .rootindex
578            .map(NonZeroUsize::get)
579            .unwrap_or(0); // Compiles to no-op.
580        debug_assert!(
581            rindex != 0,
582            "Tried to get the component index of an unvisited node."
583        );
584        debug_assert!(
585            rindex > self.componentcount,
586            "Given node has been visited but not yet assigned to a component."
587        );
588        usize::MAX - rindex
589    }
590}
591
592/// \[Generic\] Compute the *strongly connected components* using [Tarjan's algorithm][1].
593///
594/// This implementation is recursive and does one pass over the nodes. It is based on
595/// [A Space-Efficient Algorithm for Finding Strongly Connected Components][2] by David J. Pierce,
596/// to provide a memory-efficient implementation of [Tarjan's algorithm][1].
597///
598/// # Arguments
599/// * `g`: a directed or undirected graph.
600///
601/// # Returns
602/// Return a vector where each element is a strongly connected component (scc).
603/// The order of node ids within each scc is arbitrary, but the order of
604/// the sccs is their postorder (reverse topological sort).
605///
606/// For an undirected graph, the sccs are simply the connected components.
607///
608/// # Complexity
609/// * Time complexity: **O(|V| + |E|)**.
610/// * Auxiliary space: **O(|V|)**.
611///
612/// where **|V|** is the number of nodes and **|E|** is the number of edges.
613///
614/// [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
615/// [2]: https://www.researchgate.net/publication/283024636_A_space-efficient_algorithm_for_finding_strongly_connected_components
616pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
617where
618    G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable,
619{
620    let mut sccs = Vec::new();
621    {
622        let mut tarjan_scc = TarjanScc::new();
623        tarjan_scc.run(g, |scc| sccs.push(scc.to_vec()));
624    }
625    sccs
626}
627
628/// [Graph] Condense every strongly connected component into a single node and return the result.
629///
630/// # Arguments
631/// * `g`: an input [`Graph`].
632/// * `make_acyclic`: if `true`, self-loops and multi edges are ignored, guaranteeing that
633///   the output is acyclic.
634///
635/// # Returns
636/// Returns a `Graph` with nodes `Vec<N>` representing strongly connected components.
637///
638/// # Complexity
639/// * Time complexity: **O(|V| + |E|)**.
640/// * Auxiliary space: **O(|V| + |E|)**.
641///
642/// where **|V|** is the number of nodes and **|E|** is the number of edges.
643///
644/// # Examples
645/// ```rust
646/// use petgraph::Graph;
647/// use petgraph::algo::condensation;
648/// use petgraph::prelude::*;
649///
650/// let mut graph : Graph<(),(),Directed> = Graph::new();
651/// let a = graph.add_node(()); // node with no weight
652/// let b = graph.add_node(());
653/// let c = graph.add_node(());
654/// let d = graph.add_node(());
655/// let e = graph.add_node(());
656/// let f = graph.add_node(());
657/// let g = graph.add_node(());
658/// let h = graph.add_node(());
659///
660/// graph.extend_with_edges(&[
661///     (a, b),
662///     (b, c),
663///     (c, d),
664///     (d, a),
665///     (b, e),
666///     (e, f),
667///     (f, g),
668///     (g, h),
669///     (h, e)
670/// ]);
671///
672/// // a ----> b ----> e ----> f
673/// // ^       |       ^       |
674/// // |       v       |       v
675/// // d <---- c       h <---- g
676///
677/// let condensed_graph = condensation(graph,false);
678/// let A = NodeIndex::new(0);
679/// let B = NodeIndex::new(1);
680/// assert_eq!(condensed_graph.node_count(), 2);
681/// assert_eq!(condensed_graph.edge_count(), 9);
682/// assert_eq!(condensed_graph.neighbors(A).collect::<Vec<_>>(), vec![A, A, A, A]);
683/// assert_eq!(condensed_graph.neighbors(B).collect::<Vec<_>>(), vec![A, B, B, B, B]);
684/// ```
685/// If `make_acyclic` is true, self-loops and multi edges are ignored:
686///
687/// ```rust
688/// # use petgraph::Graph;
689/// # use petgraph::algo::condensation;
690/// # use petgraph::prelude::*;
691/// #
692/// # let mut graph : Graph<(),(),Directed> = Graph::new();
693/// # let a = graph.add_node(()); // node with no weight
694/// # let b = graph.add_node(());
695/// # let c = graph.add_node(());
696/// # let d = graph.add_node(());
697/// # let e = graph.add_node(());
698/// # let f = graph.add_node(());
699/// # let g = graph.add_node(());
700/// # let h = graph.add_node(());
701/// #
702/// # graph.extend_with_edges(&[
703/// #    (a, b),
704/// #    (b, c),
705/// #    (c, d),
706/// #    (d, a),
707/// #    (b, e),
708/// #    (e, f),
709/// #    (f, g),
710/// #    (g, h),
711/// #    (h, e)
712/// # ]);
713/// let acyclic_condensed_graph = condensation(graph, true);
714/// let A = NodeIndex::new(0);
715/// let B = NodeIndex::new(1);
716/// assert_eq!(acyclic_condensed_graph.node_count(), 2);
717/// assert_eq!(acyclic_condensed_graph.edge_count(), 1);
718/// assert_eq!(acyclic_condensed_graph.neighbors(B).collect::<Vec<_>>(), vec![A]);
719/// ```
720pub fn condensation<N, E, Ty, Ix>(
721    g: Graph<N, E, Ty, Ix>,
722    make_acyclic: bool,
723) -> Graph<Vec<N>, E, Ty, Ix>
724where
725    Ty: EdgeType,
726    Ix: IndexType,
727{
728    let sccs = kosaraju_scc(&g);
729    let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());
730
731    // Build a map from old indices to new ones.
732    let mut node_map = vec![NodeIndex::end(); g.node_count()];
733    for comp in sccs {
734        let new_nix = condensed.add_node(Vec::new());
735        for nix in comp {
736            node_map[nix.index()] = new_nix;
737        }
738    }
739
740    // Consume nodes and edges of the old graph and insert them into the new one.
741    let (nodes, edges) = g.into_nodes_edges();
742    for (nix, node) in nodes.into_iter().enumerate() {
743        condensed[node_map[nix]].push(node.weight);
744    }
745    for edge in edges {
746        let source = node_map[edge.source().index()];
747        let target = node_map[edge.target().index()];
748        if make_acyclic {
749            if source != target {
750                condensed.update_edge(source, target, edge.weight);
751            }
752        } else {
753            condensed.add_edge(source, target, edge.weight);
754        }
755    }
756    condensed
757}
758
759/// An algorithm error: a cycle was found in the graph.
760#[derive(Clone, Debug, PartialEq)]
761pub struct Cycle<N>(pub(crate) N);
762
763impl<N> Cycle<N> {
764    /// Return a node id that participates in the cycle
765    pub fn node_id(&self) -> N
766    where
767        N: Copy,
768    {
769        self.0
770    }
771}
772
773/// An algorithm error: a cycle of negative weights was found in the graph.
774#[derive(Clone, Debug, PartialEq)]
775pub struct NegativeCycle(pub ());
776
777/// Return `true` if the graph\* is bipartite.
778///
779/// A graph is bipartite if its nodes can be divided into
780/// two disjoint and indepedent sets U and V such that every edge connects U to one in V.
781///
782/// This algorithm implements 2-coloring algorithm based on the BFS algorithm.
783/// Always treats the input graph as if undirected.
784///
785/// \* The algorithm checks only the subgraph that is reachable from the `start`.
786///
787/// # Arguments
788/// * `g`: an input graph.
789/// * `start`: some node of the graph.
790///
791/// # Returns
792/// * `true`: if the subgraph accessible from the start node is bipartite.
793/// * `false`: if such a subgraph is not bipartite.
794///
795/// # Complexity
796/// * Time complexity: **O(|V| + |E|)**.
797/// * Auxiliary space: **O(|V|)**.
798///
799/// where **|V|** is the number of nodes and **|E|** is the number of edges.
800pub fn is_bipartite_undirected<G, N, VM>(g: G, start: N) -> bool
801where
802    G: GraphRef + Visitable<NodeId = N, Map = VM> + IntoNeighbors<NodeId = N>,
803    N: Copy + PartialEq + core::fmt::Debug,
804    VM: VisitMap<N>,
805{
806    let mut red = g.visit_map();
807    red.visit(start);
808    let mut blue = g.visit_map();
809
810    let mut stack = ::alloc::collections::VecDeque::new();
811    stack.push_front(start);
812
813    while let Some(node) = stack.pop_front() {
814        let is_red = red.is_visited(&node);
815        let is_blue = blue.is_visited(&node);
816
817        assert!(is_red ^ is_blue);
818
819        for neighbour in g.neighbors(node) {
820            let is_neigbour_red = red.is_visited(&neighbour);
821            let is_neigbour_blue = blue.is_visited(&neighbour);
822
823            if (is_red && is_neigbour_red) || (is_blue && is_neigbour_blue) {
824                return false;
825            }
826
827            if !is_neigbour_red && !is_neigbour_blue {
828                //hasn't been visited yet
829
830                match (is_red, is_blue) {
831                    (true, false) => {
832                        blue.visit(neighbour);
833                    }
834                    (false, true) => {
835                        red.visit(neighbour);
836                    }
837                    (_, _) => {
838                        panic!("Invariant doesn't hold");
839                    }
840                }
841
842                stack.push_back(neighbour);
843            }
844        }
845    }
846
847    true
848}
849
850use core::fmt::Debug;
851use core::ops::Add;
852
853/// Associated data that can be used for measures (such as length).
854pub trait Measure: Debug + PartialOrd + Add<Self, Output = Self> + Default + Clone {}
855
856impl<M> Measure for M where M: Debug + PartialOrd + Add<M, Output = M> + Default + Clone {}
857
858/// A floating-point measure.
859pub trait FloatMeasure: Measure + Copy {
860    fn zero() -> Self;
861    fn infinite() -> Self;
862    fn from_f32(val: f32) -> Self;
863    fn from_f64(val: f64) -> Self;
864}
865
866impl FloatMeasure for f32 {
867    fn zero() -> Self {
868        0.
869    }
870    fn infinite() -> Self {
871        1. / 0.
872    }
873    fn from_f32(val: f32) -> Self {
874        val
875    }
876    fn from_f64(val: f64) -> Self {
877        val as f32
878    }
879}
880
881impl FloatMeasure for f64 {
882    fn zero() -> Self {
883        0.
884    }
885    fn infinite() -> Self {
886        1. / 0.
887    }
888    fn from_f32(val: f32) -> Self {
889        val as f64
890    }
891    fn from_f64(val: f64) -> Self {
892        val
893    }
894}
895
896pub trait BoundedMeasure: Measure + core::ops::Sub<Self, Output = Self> {
897    fn min() -> Self;
898    fn max() -> Self;
899    fn overflowing_add(self, rhs: Self) -> (Self, bool);
900    fn from_f32(val: f32) -> Self;
901    fn from_f64(val: f64) -> Self;
902}
903
904macro_rules! impl_bounded_measure_integer(
905    ( $( $t:ident ),* ) => {
906        $(
907            impl BoundedMeasure for $t {
908                fn min() -> Self {
909                    $t::MIN
910                }
911
912                fn max() -> Self {
913                    $t::MAX
914                }
915
916                fn overflowing_add(self, rhs: Self) -> (Self, bool) {
917                    self.overflowing_add(rhs)
918                }
919
920                fn from_f32(val: f32) -> Self {
921                    val as $t
922                }
923
924                fn from_f64(val: f64) -> Self {
925                    val as $t
926                }
927            }
928        )*
929    };
930);
931
932impl_bounded_measure_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
933
934macro_rules! impl_bounded_measure_float(
935    ( $( $t:ident ),* ) => {
936        $(
937            impl BoundedMeasure for $t {
938                fn min() -> Self {
939                    $t::MIN
940                }
941
942                fn max() -> Self {
943                    $t::MAX
944                }
945
946                fn overflowing_add(self, rhs: Self) -> (Self, bool) {
947                    // for an overflow: a + b > max: both values need to be positive and a > max - b must be satisfied
948                    let overflow = self > Self::default() && rhs > Self::default() && self > $t::MAX - rhs;
949
950                    // for an underflow: a + b < min: overflow can not happen and both values must be negative and a < min - b must be satisfied
951                    let underflow = !overflow && self < Self::default() && rhs < Self::default() && self < $t::MIN - rhs;
952
953                    (self + rhs, overflow || underflow)
954                }
955
956                fn from_f32(val: f32) -> Self {
957                    val as $t
958                }
959
960                fn from_f64(val: f64) -> Self {
961                    val as $t
962                }
963            }
964        )*
965    };
966);
967
968impl_bounded_measure_float!(f32, f64);
969
970/// A floating-point measure that can be computed from `usize`
971/// and with a default measure of proximity.  
972pub trait UnitMeasure:
973    Measure
974    + core::ops::Sub<Self, Output = Self>
975    + core::ops::Mul<Self, Output = Self>
976    + core::ops::Div<Self, Output = Self>
977    + core::iter::Sum
978{
979    fn zero() -> Self;
980    fn one() -> Self;
981    fn from_usize(nb: usize) -> Self;
982    fn default_tol() -> Self;
983    fn from_f32(val: f32) -> Self;
984    fn from_f64(val: f64) -> Self;
985}
986
987macro_rules! impl_unit_measure(
988    ( $( $t:ident ),* )=> {
989        $(
990            impl UnitMeasure for $t {
991                fn zero() -> Self {
992                    0 as $t
993                }
994                fn one() -> Self {
995                    1 as $t
996                }
997
998                fn from_usize(nb: usize) -> Self {
999                    nb as $t
1000                }
1001
1002                fn default_tol() -> Self {
1003                    1e-6 as $t
1004                }
1005
1006                fn from_f32(val: f32) -> Self {
1007                    val as $t
1008                }
1009
1010                fn from_f64(val: f64) -> Self {
1011                    val as $t
1012                }
1013            }
1014
1015        )*
1016    }
1017);
1018impl_unit_measure!(f32, f64);
1019
1020/// Some measure of positive numbers, assuming positive
1021/// float-pointing numbers
1022pub trait PositiveMeasure: Measure + Copy {
1023    fn zero() -> Self;
1024    fn max() -> Self;
1025}
1026
1027macro_rules! impl_positive_measure(
1028    ( $( $t:ident ),* )=> {
1029        $(
1030            impl PositiveMeasure for $t {
1031                fn zero() -> Self {
1032                    0 as $t
1033                }
1034                fn max() -> Self {
1035                    $t::MAX
1036                }
1037            }
1038
1039        )*
1040    }
1041);
1042
1043impl_positive_measure!(u8, u16, u32, u64, u128, usize, f32, f64);