1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//! This crate implements standard graph algorithms without requiring
//! a specific graph representation.
//!
//! It's quite common for graph structures to be defined implicitly by
//! other data structures.  This crate lets you run standard graph
//! algorithms without having to translate your data structures into a
//! specific graph representation.
//!
//! # Usage
//!
//! To define a graph, implement the `DirectedGraph` trait on some
//! data structure can be treated as agraph.  You can then run the
//! various generic graph algorithms which take a generic type
//! implementing `DirectedGraph`.
//!
//! # History
//!
//! This crate began as a port of the [`aga`][1] and [`agar`][2] modules
//! from ccan.
//!
//! [1]: https://ccodearchive.net/info/aga.html
//! [2]: https://ccodearchive.net/info/agar.html

pub mod dfs;
pub mod bfs;

/// The trait for types representing a single graph edge from a known
/// graph node
///
/// This could be a reference to some internal part of your data
/// structure, an index or whatever else is suitable for your graph
/// representation.
pub trait OutEdge<N> {
    /// Returns the destination node of `self`
    fn destination(&self) -> N;

    /// Consume `self` and return its destination node instead
    fn into_destination(self) -> N
    where
        Self: Sized
    {
        self.destination()
    }
}

/// An iterator through the neighbors of a given node (nodes reachable
/// by a single edge transition from the given node) in a graph.
pub struct Neighbors<G: DirectedGraph> {
    i: <G::Edges as IntoIterator>::IntoIter,
}

impl<G: DirectedGraph> Iterator for Neighbors<G> {
    type Item = G::Node;
    fn next(&mut self) -> Option<Self::Item> {
        Some(self.i.next()?.into_destination())
    }
}

/// The trait for types (implicitly or explicitly) representing a
/// directed graph structure
///
/// To implement this trait:
///
///  * Set the `Node` associated type to a convenient representation
///    for graph nodes
///
///  * Set the `Edge` associated types to a convenient representation
///    for an edge in your graph.  For simple cases you can use
///    `SimpleEdge<Self::Node>`, which is a trivial representation of
///    an (unweighted, directed) edge by its destination.  
///
///  * Set the `Edges` associated type to a convenient representation
///    of a list of edges (usually an iterator or collection).  For
///    simple cases you can use `SimpleEdges` which transforms an
///    iterator over nodes (an adjacency list) into an iterator over
///    edges.
///
///  * Implement `edges_from()` to return the list of edges
///    originating at a specific node.
///
/// Theoretically infinite graphs are permitted, though you obviously
/// won't be able to fully traverse them.
pub trait DirectedGraph where
    Self: Sized,
    Self::Node : Clone,
    Self::Edge : OutEdge<Self::Node>,
    Self::Edges : std::iter::IntoIterator<Item=Self::Edge>,
{
    /// Represents a node in the graph.
    type Node;

    /// Represents an edge in the graph.
    ///
    /// Implements the `OutEdge<Self::Node>` trait.  Only needs to
    /// represent an edge given it's origin node, so it need not be
    /// globally unique (or even locally, you can return the same
    /// `Edge` twice from `edges_from` if you want and the algorithms
    /// will treat them as distinct edges).
    type Edge;

    /// Represents a list of graph edges (with a common origin) in the
    /// graph
    ///
    /// Implements `IntoIterator<Item=Self::Edge>`, with that iterator
    /// stepping through each ednge outgoing from a single node.
    type Edges;

    /// Returns the list of edges originating from node `from`
    fn edges_from(&self, from: Self::Node) -> Self::Edges;

    /// Returns the (outgoing) adjacency list for node `from`
    ///
    /// This is the list (represented by an iterator) of nodes
    /// reachable from `from` by exactly one edge transition.
    fn neighbors(&self, from: Self::Node) -> Neighbors<Self> {
        Neighbors {
            i: self.edges_from(from).into_iter(),
        }
    }

    /// Traverse `self` in breadth-first order from `start`
    fn bfs(&self, start: Self::Node) -> bfs::BreadthFirstSearch<'_, Self>
    where
        Self::Node: Eq+std::hash::Hash,
    {
        let mut bfs = bfs::BreadthFirstSearch::new(self);
        bfs.search_from(start);
        bfs
    }


    /// Traverse `self` in depth-first order from `start`
    fn dfs(&self, start: Self::Node) -> dfs::DepthFirstSearch<'_, Self>
    where
        Self::Node: Eq+std::hash::Hash,
    {
        let mut dfs = dfs::DepthFirstSearch::new(self);
        dfs.search_from(start);
        dfs
    }
}

/// A trivial graph edge representation, whose only information is the
/// destination node
///
/// A single outgoing edge from a known node to another node of type
/// `N`
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct SimpleEdge<N> ( N );

impl<N> SimpleEdge<N> {
    /// Return a new `SimpleEdge` with destination node `to`
    pub fn from_destination(to: N) -> Self {
        SimpleEdge(to)
    }
}

impl<N: Clone> OutEdge<N> for SimpleEdge<N> {
    fn destination(&self) -> N {
        self.0.clone()
    }
    fn into_destination(self) -> N {
        self.0
    }
}

/// A trivial wrapper around an iterator across nodes, changing it to
/// an iterator across `SimpleEdge`s with those nodes as their
/// destinations.
pub struct SimpleEdges<I: Iterator> {
    i: I,
}

impl<I: Iterator> SimpleEdges<I> {
    /// Return a new `SimpleEdges` which for each node yielded by `i`
    /// will yield a `SimpleEdge` to that node.
    pub fn new(i: impl IntoIterator<IntoIter=I, Item=I::Item>) -> SimpleEdges<I> {
        SimpleEdges {
            i: i.into_iter()
        }
    }
}

impl<I: Iterator> Iterator for SimpleEdges<I> {
    type Item = SimpleEdge<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        Some(SimpleEdge::from_destination(self.i.next()?))
    }
}