use crate::graph::topology::Adjacency;
use crate::graph::Graph;
pub struct Paths<'a> {
outgoing: &'a Adjacency,
target: usize,
stack: Vec<(usize, usize)>,
path: Vec<usize>,
}
impl<T> Graph<T> {
#[inline]
#[must_use]
pub fn paths(&self, source: usize, target: usize) -> Paths<'_> {
Paths {
outgoing: self.topology.outgoing(),
target,
stack: Vec::from([(source, 0)]),
path: Vec::from([source]),
}
}
}
impl Iterator for Paths<'_> {
type Item = Vec<usize>;
fn next(&mut self) -> Option<Self::Item> {
while let Some((node, depth)) = self.stack.pop() {
self.path.truncate(depth);
self.path.push(node);
if node == self.target {
return Some(self.path.clone());
}
for &descendant in self.outgoing[node].iter().rev() {
debug_assert!(!self.path.contains(&descendant));
self.stack.push((descendant, depth + 1));
}
}
None
}
}
#[cfg(test)]
mod tests {
mod paths {
use crate::graph;
#[test]
fn handles_graph() {
let graph = graph! {
"a" => "b", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(0, 8).collect::<Vec<_>>(),
vec![
vec![0, 1, 3, 6, 8],
vec![0, 1, 4, 6, 8],
vec![0, 1, 4, 7, 8],
vec![0, 2, 5, 7, 8],
]
);
}
#[test]
fn handles_graph_and_self_path() {
let graph = graph! {
"a" => "b", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(0, 0).collect::<Vec<_>>(), vec![vec![0]]
);
}
#[test]
fn handles_graph_and_non_existing_path() {
let graph = graph! {
"a" => "b", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(8, 0).collect::<Vec<_>>(),
vec![] as Vec<Vec<usize>>
);
}
#[test]
fn handles_multi_graph() {
let graph = graph! {
"a" => "b", "a" => "c", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(0, 8).collect::<Vec<_>>(),
vec![
vec![0, 1, 3, 6, 8],
vec![0, 1, 4, 6, 8],
vec![0, 1, 4, 7, 8],
vec![0, 2, 5, 7, 8],
vec![0, 2, 5, 7, 8],
]
);
}
#[test]
fn handles_multi_graph_and_self_path() {
let graph = graph! {
"a" => "b", "a" => "c", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(0, 0).collect::<Vec<_>>(), vec![vec![0]]
);
}
#[test]
fn handles_multi_graph_and_non_existing_path() {
let graph = graph! {
"a" => "b", "a" => "c", "a" => "c",
"b" => "d", "b" => "e",
"c" => "f",
"d" => "g",
"e" => "g", "e" => "h",
"f" => "h",
"g" => "i",
"h" => "i",
};
assert_eq!(
graph.paths(8, 0).collect::<Vec<_>>(),
vec![] as Vec<Vec<usize>>
);
}
}
}