mod bfs_visit;
mod dfs_edges;
mod dfs_visit;
mod dijkstra_visit;
use petgraph::prelude::*;
use petgraph::visit::GraphRef;
use petgraph::visit::IntoNeighborsDirected;
use petgraph::visit::Reversed;
use petgraph::visit::VisitMap;
use petgraph::visit::Visitable;
pub use bfs_visit::{breadth_first_search, BfsEvent};
pub use dfs_edges::dfs_edges;
pub use dfs_visit::{depth_first_search, DfsEvent};
pub use dijkstra_visit::{dijkstra_search, DijkstraEvent};
macro_rules! try_control {
($e:expr, $p:stmt) => {
try_control!($e, $p, ());
};
($e:expr, $p:stmt, $q:stmt) => {
match $e {
x => {
if x.should_break() {
return x;
} else if x.should_prune() {
$p
} else {
$q
}
}
}
};
}
use try_control;
struct AncestryWalker<G, N, VM> {
graph: G,
walker: Bfs<N, VM>,
}
impl<
G: GraphRef + Visitable + IntoNeighborsDirected<NodeId = N>,
N: Copy + Clone + PartialEq,
VM: VisitMap<N>,
> Iterator for AncestryWalker<G, N, VM>
{
type Item = N;
fn next(&mut self) -> Option<Self::Item> {
self.walker.next(self.graph)
}
}
pub fn ancestors<G>(graph: G, node: G::NodeId) -> impl Iterator<Item = G::NodeId>
where
G: GraphRef + Visitable + IntoNeighborsDirected,
{
let reversed = Reversed(graph);
AncestryWalker {
graph: reversed,
walker: Bfs::new(reversed, node),
}
}
pub fn descendants<G>(graph: G, node: G::NodeId) -> impl Iterator<Item = G::NodeId>
where
G: GraphRef + Visitable + IntoNeighborsDirected,
{
AncestryWalker {
graph,
walker: Bfs::new(graph, node),
}
}
struct BFSAncestryWalker<G, N, VM> {
graph: G,
walker: Bfs<N, VM>,
}
impl<
G: GraphRef + Visitable + IntoNeighborsDirected<NodeId = N>,
N: Copy + Clone + PartialEq,
VM: VisitMap<N>,
> Iterator for BFSAncestryWalker<G, N, VM>
{
type Item = (N, Vec<N>);
fn next(&mut self) -> Option<Self::Item> {
self.walker.next(self.graph).map(|nx| {
(
nx,
self.graph
.neighbors_directed(nx, petgraph::Direction::Outgoing)
.collect(),
)
})
}
}
pub fn bfs_successors<G>(
graph: G,
node: G::NodeId,
) -> impl Iterator<Item = (G::NodeId, Vec<G::NodeId>)>
where
G: GraphRef + Visitable + IntoNeighborsDirected,
{
BFSAncestryWalker {
graph,
walker: Bfs::new(graph, node),
}
}
pub fn bfs_predecessors<G>(
graph: G,
node: G::NodeId,
) -> impl Iterator<Item = (G::NodeId, Vec<G::NodeId>)>
where
G: GraphRef + Visitable + IntoNeighborsDirected,
{
let reversed = Reversed(graph);
BFSAncestryWalker {
graph: reversed,
walker: Bfs::new(reversed, node),
}
}
#[cfg(test)]
mod test_bfs_ancestry {
use super::{bfs_predecessors, bfs_successors};
use crate::petgraph::graph::DiGraph;
use crate::petgraph::stable_graph::{NodeIndex, StableDiGraph};
#[test]
fn test_bfs_predecessors_digraph() {
let graph: DiGraph<(), ()> =
DiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let predecessors: Vec<(usize, Vec<usize>)> = bfs_predecessors(&graph, NodeIndex::new(3))
.map(|(x, succ)| (x.index(), succ.iter().map(|y| y.index()).collect()))
.collect();
assert_eq!(
vec![(3_usize, vec![1_usize]), (1, vec![0]), (0, vec![])],
predecessors
);
}
#[test]
fn test_bfs_successors() {
let graph: DiGraph<(), ()> =
DiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let successors: Vec<(usize, Vec<usize>)> = bfs_successors(&graph, NodeIndex::new(3))
.map(|(x, succ)| (x.index(), succ.iter().map(|y| y.index()).collect()))
.collect();
assert_eq!(
vec![(3_usize, vec![4_usize]), (4, vec![5]), (5, vec![])],
successors
);
}
#[test]
fn test_no_predecessors() {
let graph: StableDiGraph<(), ()> =
StableDiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let predecessors: Vec<(usize, Vec<usize>)> = bfs_predecessors(&graph, NodeIndex::new(0))
.map(|(x, succ)| (x.index(), succ.iter().map(|y| y.index()).collect()))
.collect();
assert_eq!(vec![(0_usize, vec![])], predecessors);
}
#[test]
fn test_no_successors() {
let graph: StableDiGraph<(), ()> =
StableDiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let successors: Vec<(usize, Vec<usize>)> = bfs_successors(&graph, NodeIndex::new(5))
.map(|(x, succ)| (x.index(), succ.iter().map(|y| y.index()).collect()))
.collect();
assert_eq!(vec![(5_usize, vec![])], successors);
}
}
#[cfg(test)]
mod test_ancestry {
use super::{ancestors, descendants};
use crate::petgraph::graph::DiGraph;
use crate::petgraph::stable_graph::{NodeIndex, StableDiGraph};
#[test]
fn test_ancestors_digraph() {
let graph: DiGraph<(), ()> =
DiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let ancestors: Vec<usize> = ancestors(&graph, NodeIndex::new(3))
.map(|x| x.index())
.collect();
assert_eq!(vec![3_usize, 1, 0], ancestors);
}
#[test]
fn test_descendants() {
let graph: DiGraph<(), ()> =
DiGraph::from_edges([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]);
let descendants: Vec<usize> = descendants(&graph, NodeIndex::new(3))
.map(|x| x.index())
.collect();
assert_eq!(vec![3_usize, 4, 5], descendants);
}
#[test]
fn test_no_ancestors() {
let mut graph: StableDiGraph<(), ()> = StableDiGraph::new();
let index = graph.add_node(());
let res = ancestors(&graph, index);
assert_eq!(vec![index], res.collect::<Vec<NodeIndex>>())
}
#[test]
fn test_no_descendants() {
let mut graph: StableDiGraph<(), ()> = StableDiGraph::new();
let index = graph.add_node(());
let res = descendants(&graph, index);
assert_eq!(vec![index], res.collect::<Vec<NodeIndex>>())
}
}