traitgraph/walks.rs
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
use crate::interface::{GraphBase, StaticGraph};
use traitsequence::interface::Sequence;
/// A sequence of nodes in a graph, where each consecutive pair of nodes is connected by an edge.
pub trait NodeWalk<Graph: GraphBase, NodeSubwalk: NodeWalk<Graph, NodeSubwalk> + ?Sized>:
Sequence<Graph::NodeIndex, NodeSubwalk>
{
/// Returns the edge walk represented by this node walk.
/// If there is a consecutive pair of nodes with a multiedge, then None is returned.
/// If this walk contains less than two nodes, then None is returned.
/// If there is a consecutive pair of node not connected by an edge, then this method panics.
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))
}
/// Returns true if this is a proper subwalk of the given walk.
/// Proper means that the walks are not equal.
fn is_proper_subwalk_of(&self, other: &Self) -> bool
where
Graph::NodeIndex: Eq,
{
self.is_proper_subsequence_of(other)
}
}
/// A sequence of edges in a graph, where each consecutive pair of edges is connected by a node.
pub trait EdgeWalk<Graph: GraphBase, EdgeSubwalk: EdgeWalk<Graph, EdgeSubwalk> + ?Sized>:
Sequence<Graph::EdgeIndex, EdgeSubwalk>
{
/// Returns the node walk represented by this edge walk.
/// If this walk contains no edge, then None is returned.
/// If there is a consecutive pair of edges not connected by a node, then this method panics.
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))
}
/// Returns true if this is a proper subwalk of the given walk.
/// Proper means that the walks are not equal.
fn is_proper_subwalk_of(&self, other: &Self) -> bool
where
Graph::EdgeIndex: Eq,
{
self.is_proper_subsequence_of(other)
}
/// Returns true if this is a valid circular walk in the given graph.
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
}
}
////////////////////
////// Slices //////
////////////////////
impl<Graph: GraphBase> NodeWalk<Graph, [Graph::NodeIndex]> for [Graph::NodeIndex] {}
impl<Graph: GraphBase> EdgeWalk<Graph, [Graph::EdgeIndex]> for [Graph::EdgeIndex] {}
/////////////////////////
////// VecNodeWalk //////
/////////////////////////
/// A node walk that is represented as a vector of node indices.
pub type VecNodeWalk<Graph> = Vec<<Graph as GraphBase>::NodeIndex>;
impl<Graph: GraphBase> NodeWalk<Graph, [Graph::NodeIndex]> for VecNodeWalk<Graph> {}
/////////////////////////
////// VecEdgeWalk //////
/////////////////////////
/// An edge walk that is represented as a vector of edge indices.
pub type VecEdgeWalk<Graph> = Vec<<Graph as GraphBase>::EdgeIndex>;
impl<Graph: GraphBase> EdgeWalk<Graph, [Graph::EdgeIndex]> for VecEdgeWalk<Graph> {}