use crate::interface::{GraphBase, StaticGraph};
use traitsequence::interface::Sequence;
pub trait NodeWalk<Graph: GraphBase, NodeSubwalk: NodeWalk<Graph, NodeSubwalk> + ?Sized>:
Sequence<Graph::NodeIndex, NodeSubwalk>
{
fn clone_as_edge_walk<ResultWalk: From<Vec<Graph::EdgeIndex>>>(
&self,
graph: &Graph,
) -> Option<ResultWalk>
where
Graph: StaticGraph,
{
if self.len() < 2 {
return None;
}
let mut walk = Vec::new();
for node_pair in self.iter().take(self.len() - 1).zip(self.iter().skip(1)) {
let from = *node_pair.0;
let to = *node_pair.1;
let mut edges_between = graph.edges_between(from, to);
if let Some(edge) = edges_between.next() {
walk.push(edge);
} else {
panic!("Not a valid node walk");
}
if edges_between.next().is_some() {
return None;
}
}
Some(ResultWalk::from(walk))
}
fn is_proper_subwalk_of(&self, other: &Self) -> bool
where
Graph::NodeIndex: Eq,
{
self.is_proper_subsequence_of(other)
}
}
pub trait EdgeWalk<Graph: GraphBase, EdgeSubwalk: EdgeWalk<Graph, EdgeSubwalk> + ?Sized>:
Sequence<Graph::EdgeIndex, EdgeSubwalk>
{
fn clone_as_node_walk<ResultWalk: From<Vec<Graph::NodeIndex>>>(
&self,
graph: &Graph,
) -> Option<ResultWalk>
where
Graph: StaticGraph,
{
if self.is_empty() {
return None;
}
let mut walk = vec![
graph
.edge_endpoints(self.first().cloned().unwrap())
.from_node,
];
for edge_pair in self.iter().take(self.len() - 1).zip(self.iter().skip(1)) {
let node = graph.edge_endpoints(*edge_pair.0).to_node;
debug_assert_eq!(
node,
graph.edge_endpoints(*edge_pair.1).from_node,
"Not a valid edge walk"
);
walk.push(node);
}
walk.push(graph.edge_endpoints(self.last().cloned().unwrap()).to_node);
Some(ResultWalk::from(walk))
}
fn is_proper_subwalk_of(&self, other: &Self) -> bool
where
Graph::EdgeIndex: Eq,
{
self.is_proper_subsequence_of(other)
}
fn is_circular_walk(&self, graph: &Graph) -> bool
where
Graph: StaticGraph,
{
if self.is_empty() {
return true;
}
let mut connecting_node = graph.edge_endpoints(*self.last().unwrap()).to_node;
for &edge in self.iter() {
let edge_endpoints = graph.edge_endpoints(edge);
if edge_endpoints.from_node != connecting_node {
return false;
} else {
connecting_node = edge_endpoints.to_node;
}
}
true
}
}
impl<Graph: GraphBase> NodeWalk<Graph, [Graph::NodeIndex]> for [Graph::NodeIndex] {}
impl<Graph: GraphBase> EdgeWalk<Graph, [Graph::EdgeIndex]> for [Graph::EdgeIndex] {}
pub type VecNodeWalk<Graph> = Vec<<Graph as GraphBase>::NodeIndex>;
impl<Graph: GraphBase> NodeWalk<Graph, [Graph::NodeIndex]> for VecNodeWalk<Graph> {}
pub type VecEdgeWalk<Graph> = Vec<<Graph as GraphBase>::EdgeIndex>;
impl<Graph: GraphBase> EdgeWalk<Graph, [Graph::EdgeIndex]> for VecEdgeWalk<Graph> {}