blob: d373a3db94e21ba8bc238354562ba4a0d1697b92 [file] [log] [blame]
//! Graph visitor algorithms.
//!
use std::default::Default;
use std::ops::{Add};
use std::collections::{
BinaryHeap,
HashSet,
HashMap,
BitvSet,
RingBuf,
};
use std::collections::hash_map::Hasher;
use std::collections::hash_map::Entry::{
Occupied,
Vacant,
};
use std::hash::Hash;
use super::{
graphmap,
graph,
EdgeType,
EdgeDirection,
Graph,
GraphMap,
MinScored,
};
pub trait Graphlike {
type NodeId: Clone;
}
/// A graph trait for accessing the neighbors iterator
pub trait NeighborIter<'a, N> {
type Iter: Iterator<Item=N>;
fn neighbors(&'a self, n: N) -> Self::Iter;
}
impl<'a, N, E, Ty: EdgeType> NeighborIter<'a, graph::NodeIndex> for Graph<N, E, Ty>
{
type Iter = graph::Neighbors<'a, E>;
fn neighbors(&'a self, n: graph::NodeIndex) -> graph::Neighbors<'a, E>
{
Graph::neighbors(self, n)
}
}
impl<'a, N, E> NeighborIter<'a, N> for GraphMap<N, E>
where N: Copy + Clone + PartialOrd + Hash<Hasher> + Eq
{
type Iter = graphmap::Neighbors<'a, N>;
fn neighbors(&'a self, n: N) -> graphmap::Neighbors<'a, N>
{
GraphMap::neighbors(self, n)
}
}
/// Wrapper type for walking the graph as if it is undirected
pub struct AsUndirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);
impl<'a, 'b, N, E, Ty: EdgeType> NeighborIter<'a, graph::NodeIndex> for AsUndirected<&'b Graph<N, E, Ty>>
{
type Iter = graph::Neighbors<'a, E>;
fn neighbors(&'a self, n: graph::NodeIndex) -> graph::Neighbors<'a, E>
{
Graph::neighbors_undirected(self.0, n)
}
}
impl<'a, 'b, N, E, Ty: EdgeType> NeighborIter<'a, graph::NodeIndex> for Reversed<&'b Graph<N, E, Ty>>
{
type Iter = graph::Neighbors<'a, E>;
fn neighbors(&'a self, n: graph::NodeIndex) -> graph::Neighbors<'a, E>
{
Graph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
}
}
pub trait VisitMap<N> {
/// Return **true** if the value is not already present.
fn visit(&mut self, N) -> bool;
fn contains(&self, &N) -> bool;
}
impl VisitMap<graph::NodeIndex> for BitvSet {
fn visit(&mut self, x: graph::NodeIndex) -> bool {
self.insert(x.0)
}
fn contains(&self, x: &graph::NodeIndex) -> bool {
self.contains(&x.0)
}
}
impl<N: Eq + Hash<Hasher>> VisitMap<N> for HashSet<N> {
fn visit(&mut self, x: N) -> bool {
self.insert(x)
}
fn contains(&self, x: &N) -> bool {
self.contains(x)
}
}
/// Trait for GraphMap that knows which datastructure is the best for its visitor map
pub trait Visitable : Graphlike {
type Map: VisitMap<<Self as Graphlike>::NodeId>;
fn visit_map(&self) -> Self::Map;
}
impl<N, E, Ty> Graphlike for Graph<N, E, Ty> {
type NodeId = graph::NodeIndex;
}
impl<N, E, Ty> Visitable for Graph<N, E, Ty> where
Ty: EdgeType,
{
type Map = BitvSet;
fn visit_map(&self) -> BitvSet { BitvSet::with_capacity(self.node_count()) }
}
impl<N: Clone, E> Graphlike for GraphMap<N, E>
{
type NodeId = N;
}
impl<N, E> Visitable for GraphMap<N, E>
where N: Copy + Clone + Ord + Eq + Hash<Hasher>
{
type Map = HashSet<N>;
fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}
impl<'a, V: Graphlike> Graphlike for AsUndirected<&'a V>
{
type NodeId = <V as Graphlike>::NodeId;
}
impl<'a, V: Graphlike> Graphlike for Reversed<&'a V>
{
type NodeId = <V as Graphlike>::NodeId;
}
impl<'a, V: Visitable> Visitable for AsUndirected<&'a V>
{
type Map = <V as Visitable>::Map;
fn visit_map(&self) -> <V as Visitable>::Map {
self.0.visit_map()
}
}
impl<'a, V: Visitable> Visitable for Reversed<&'a V>
{
type Map = <V as Visitable>::Map;
fn visit_map(&self) -> <V as Visitable>::Map {
self.0.visit_map()
}
}
/// A depth first search (DFS) of a graph.
///
/// Using a **Dfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Dfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut dfs = Dfs::new(&graph, a);
/// while let Some(nx) = dfs.next(&graph) {
/// // we can access `graph` mutably here still
/// graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone)]
pub struct Dfs<N, VM> {
pub stack: Vec<N>,
pub discovered: VM,
}
impl<G: Visitable> Dfs<G::NodeId, <G as Visitable>::Map>
{
/// Create a new **Dfs**, using the graph's visitor map, and put **start**
/// in the stack of nodes to visit.
pub fn new(graph: &G, start: G::NodeId) -> Self
{
let mut dfs = Dfs::empty(graph);
dfs.move_to(start);
dfs
}
/// Create a new **Dfs** using the graph's visitor map, and no stack.
pub fn empty(graph: &G) -> Self
{
Dfs {
stack: Vec::new(),
discovered: graph.visit_map(),
}
}
}
impl<N, VM> Dfs<N, VM> where
N: Clone,
VM: VisitMap<N>
{
/// Keep the discovered map, but clear the visit stack and restart
/// the dfs from a particular node.
pub fn move_to(&mut self, start: N)
{
self.discovered.visit(start.clone());
self.stack.clear();
self.stack.push(start);
}
}
impl<N, VM> Dfs<N, VM> where
N: Clone,
VM: VisitMap<N>
{
/// Return the next node in the dfs, or **None** if the traversal is done.
pub fn next<'a, G>(&mut self, graph: &'a G) -> Option<N> where
G: for<'b> NeighborIter<'b, N>,
<G as NeighborIter<'a, N>>::Iter: Iterator<Item=N>,
{
while let Some(node) = self.stack.pop() {
for succ in graph.neighbors(node.clone()) {
if self.discovered.visit(succ.clone()) {
self.stack.push(succ);
}
}
return Some(node);
}
None
}
}
/// An iterator for a depth first traversal of a graph.
#[derive(Clone)]
pub struct DfsIter<'a, G, N, VM> where
G: 'a,
{
graph: &'a G,
dfs: Dfs<N, VM>,
}
impl<'a, G: Visitable> DfsIter<'a, G, G::NodeId, <G as Visitable>::Map>
{
pub fn new(graph: &'a G, start: G::NodeId) -> DfsIter<'a, G, G::NodeId, <G as Visitable>::Map>
{
DfsIter {
graph: graph,
dfs: Dfs::new(graph, start)
}
}
}
impl<'a, G: Visitable, VM> Iterator for DfsIter<'a, G, G::NodeId, VM> where
G: 'a,
VM: VisitMap<G::NodeId>,
G: for<'b> NeighborIter<'b, G::NodeId>,
<G as NeighborIter<'a, G::NodeId>>::Iter: Iterator<Item=G::NodeId>,
{
type Item = G::NodeId;
fn next(&mut self) -> Option<G::NodeId>
{
self.dfs.next(self.graph)
}
}
/// A breadth first search (BFS) of a graph.
///
/// Using a **Bfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Bfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut bfs = Bfs::new(&graph, a);
/// while let Some(nx) = bfs.next(&graph) {
/// // we can access `graph` mutably here still
/// graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone)]
pub struct Bfs<N, VM> {
pub stack: RingBuf<N>,
pub discovered: VM,
}
impl<N, G> Bfs<N, <G as Visitable>::Map> where
N: Clone,
G: Visitable<NodeId=N>,
<G as Visitable>::Map: VisitMap<N>,
{
/// Create a new **Bfs**, using the graph's visitor map, and put **start**
/// in the stack of nodes to visit.
pub fn new(graph: &G, start: N) -> Self
{
let mut discovered = graph.visit_map();
discovered.visit(start.clone());
let mut stack = RingBuf::new();
stack.push_front(start.clone());
Bfs {
stack: stack,
discovered: discovered,
}
}
}
impl<N, VM> Bfs<N, VM> where
N: Clone,
VM: VisitMap<N>
{
/// Return the next node in the dfs, or **None** if the traversal is done.
pub fn next<'a, G>(&mut self, graph: &'a G) -> Option<N> where
G: for<'b> NeighborIter<'b, N>,
<G as NeighborIter<'a, N>>::Iter: Iterator<Item=N>,
{
while let Some(node) = self.stack.pop_front() {
for succ in graph.neighbors(node.clone()) {
if self.discovered.visit(succ.clone()) {
self.stack.push_back(succ);
}
}
return Some(node);
}
None
}
}
/*
pub struct Visitor<G> where
G: Visitable,
{
stack: Vec<<G as Graphlike>::NodeId>,
discovered: <G as Visitable>::Map,
}
pub fn visitor<G>(graph: &G, start: <G as Graphlike>::NodeId) -> Visitor<G> where
G: Visitable
{
Visitor{
stack: vec![start],
discovered: graph.visit_map(),
}
}
*/
/// An iterator for a breadth first traversal of a graph.
#[derive(Clone)]
pub struct BfsIter<'a, G, N, VM> where
G: 'a,
{
graph: &'a G,
bfs: Bfs<N, VM>,
}
impl<'a, G, N> BfsIter<'a, G, N, <G as Visitable>::Map> where
N: Clone,
G: Visitable<NodeId=N>,
<G as Visitable>::Map: VisitMap<N>,
{
pub fn new(graph: &'a G, start: N) -> BfsIter<'a, G, N, <G as Visitable>::Map>
{
BfsIter {
graph: graph,
bfs: Bfs::new(graph, start)
}
}
}
impl<'a, G, N, VM> Iterator for BfsIter<'a, G, N, VM> where
G: 'a,
N: Clone,
VM: VisitMap<N>,
G: for<'b> NeighborIter<'b, N>,
<G as NeighborIter<'a, N>>::Iter: Iterator<Item=N>,
{
type Item = N;
fn next(&mut self) -> Option<N>
{
self.bfs.next(self.graph)
}
}
/// Dijkstra's shortest path algorithm.
pub fn dijkstra<'a, G, N, K, F, Edges>(graph: &'a G,
start: N,
goal: Option<N>,
mut edges: F) -> HashMap<N, K> where
G: Visitable<NodeId=N>,
N: Clone + Eq + Hash<Hasher>,
K: Default + Add<Output=K> + Copy + PartialOrd,
F: FnMut(&'a G, N) -> Edges,
Edges: Iterator<Item=(N, K)>,
<G as Visitable>::Map: VisitMap<N>,
{
let mut visited = graph.visit_map();
let mut scores = HashMap::new();
let mut predecessor = HashMap::new();
let mut visit_next = BinaryHeap::new();
let zero_score: K = Default::default();
scores.insert(start.clone(), zero_score);
visit_next.push(MinScored(zero_score, start));
while let Some(MinScored(node_score, node)) = visit_next.pop() {
if visited.contains(&node) {
continue
}
for (next, edge) in edges(graph, node.clone()) {
if visited.contains(&next) {
continue
}
let mut next_score = node_score + edge;
match scores.entry(next.clone()) {
Occupied(ent) => if next_score < *ent.get() {
*ent.into_mut() = next_score;
predecessor.insert(next.clone(), node.clone());
} else {
next_score = *ent.get();
},
Vacant(ent) => {
ent.insert(next_score);
predecessor.insert(next.clone(), node.clone());
}
}
visit_next.push(MinScored(next_score, next));
}
if goal.as_ref() == Some(&node) {
break
}
visited.visit(node);
}
scores
}