traitgraph_algo/traversal/
univocal_traversal.rs1use crate::traversal::{
2 BackwardNeighborStrategy, ForwardNeighborStrategy, TraversalNeighborStrategy,
3};
4use std::marker::PhantomData;
5use traitgraph::interface::{GraphBase, NavigableGraph, NodeOrEdge, StaticGraph};
6
7pub struct UnivocalIterator<'a, Graph: GraphBase, NeighborStrategy> {
12 graph: &'a Graph,
13 neighbor_strategy: PhantomData<NeighborStrategy>,
14 current_node: Option<Graph::NodeIndex>,
15 current_edge: Option<Graph::EdgeIndex>,
16}
17
18impl<'a, Graph: NavigableGraph, NeighborStrategy: 'a + TraversalNeighborStrategy<Graph>>
19 UnivocalIterator<'a, Graph, NeighborStrategy>
20{
21 pub fn new(
23 graph: &'a Graph,
24 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
25 ) -> Self {
26 let (current_node, current_edge) = match start_element {
27 NodeOrEdge::Node(node) => (Some(node), None),
28 NodeOrEdge::Edge(edge) => (None, Some(edge)),
29 };
30 Self {
31 graph,
32 neighbor_strategy: Default::default(),
33 current_node,
34 current_edge,
35 }
36 }
37
38 pub fn new_without_start(
40 graph: &'a Graph,
41 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
42 ) -> impl 'a + Iterator<Item = NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>> {
43 Self::new(graph, start_element).skip(1)
44 }
45}
46
47impl<'a, Graph: NavigableGraph> UnivocalIterator<'a, Graph, ForwardNeighborStrategy>
48where
49 ForwardNeighborStrategy: TraversalNeighborStrategy<Graph>,
50{
51 pub fn new_forward(
53 graph: &'a Graph,
54 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
55 ) -> Self {
56 Self::new(graph, start_element)
57 }
58
59 pub fn new_forward_without_start(
61 graph: &'a Graph,
62 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
63 ) -> impl 'a + Iterator<Item = NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>> {
64 Self::new_without_start(graph, start_element)
65 }
66}
67
68impl<'a, Graph: NavigableGraph> UnivocalIterator<'a, Graph, BackwardNeighborStrategy>
69where
70 BackwardNeighborStrategy: TraversalNeighborStrategy<Graph>,
71{
72 pub fn new_backward(
74 graph: &'a Graph,
75 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
76 ) -> Self {
77 Self::new(graph, start_element)
78 }
79
80 pub fn new_backward_without_start(
82 graph: &'a Graph,
83 start_element: NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>,
84 ) -> impl 'a + Iterator<Item = NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>> {
85 Self::new_without_start(graph, start_element)
86 }
87}
88
89impl<Graph: NavigableGraph, NeighborStrategy: TraversalNeighborStrategy<Graph>> Iterator
90 for UnivocalIterator<'_, Graph, NeighborStrategy>
91{
92 type Item = NodeOrEdge<Graph::NodeIndex, Graph::EdgeIndex>;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 match (self.current_node, self.current_edge) {
96 (Some(_), Some(edge)) => {
97 self.current_edge = None;
98 Some(NodeOrEdge::Edge(edge))
99 }
100 (Some(node), None) => {
101 let mut next_neighbor_iter = NeighborStrategy::neighbor_iterator(self.graph, node);
102 if let Some(neighbor) = next_neighbor_iter.next() {
103 let next_node = neighbor.node_id;
104 let next_edge = neighbor.edge_id;
105
106 if next_neighbor_iter.next().is_none() {
107 self.current_node = Some(next_node);
108 self.current_edge = Some(next_edge);
109 } else {
110 self.current_node = None;
111 }
112 } else {
113 self.current_node = None;
114 self.current_edge = None;
115 }
116
117 Some(NodeOrEdge::Node(node))
118 }
119 (None, Some(edge)) => {
120 let mut next_node_iter = NeighborStrategy::edge_neighbor_iterator(self.graph, edge);
121 let next_node = next_node_iter
122 .next()
123 .expect("Edge does not have a node as successor.");
124 debug_assert!(
125 next_node_iter.next().is_none(),
126 "Edge has more than one node as successor."
127 );
128 self.current_node = Some(next_node);
129 self.current_edge = None;
130 Some(NodeOrEdge::Edge(edge))
131 }
132 (None, None) => None,
133 }
134 }
135}
136
137pub fn is_edge_self_bivalent<Graph: StaticGraph>(graph: &Graph, edge_id: Graph::EdgeIndex) -> bool {
139 let forward_iter =
140 UnivocalIterator::new_forward_without_start(graph, NodeOrEdge::Edge(edge_id));
141 let mut backward_iter = UnivocalIterator::new_backward(graph, NodeOrEdge::Edge(edge_id));
142
143 let mut last_element = None;
144 for element in forward_iter {
145 match element {
146 NodeOrEdge::Edge(edge) => {
147 if edge == edge_id {
148 return true;
149 }
150 last_element = Some(NodeOrEdge::Edge(edge));
151 }
152 node => last_element = Some(node),
153 }
154 }
155
156 let last_element = last_element.expect(
157 "Forward univocal extension is empty, but should at least contain the start edge itself",
158 );
159 backward_iter.any(|e| e == last_element)
160}
161
162#[cfg(test)]
163mod tests {
164 use crate::traversal::univocal_traversal::is_edge_self_bivalent;
165 use traitgraph::implementation::petgraph_impl::PetGraph;
166 use traitgraph::interface::MutableGraphContainer;
167
168 #[test]
169 fn test_is_edge_self_bivalent_simple() {
170 let mut graph = PetGraph::new();
171 let n0 = graph.add_node(());
172 let n1 = graph.add_node(());
173 let n2 = graph.add_node(());
174 let n3 = graph.add_node(());
175 let n4 = graph.add_node(());
176 let e0 = graph.add_edge(n0, n1, ());
177 let e1 = graph.add_edge(n0, n2, ());
178 let e2 = graph.add_edge(n3, n0, ());
179 let e3 = graph.add_edge(n4, n0, ());
180 let e4 = graph.add_edge(n1, n3, ());
181 let e5 = graph.add_edge(n1, n3, ());
182 let e6 = graph.add_edge(n2, n4, ());
183 let e7 = graph.add_edge(n2, n4, ());
184 let e8 = graph.add_edge(n0, n0, ());
185
186 debug_assert!(!is_edge_self_bivalent(&graph, e0));
187 debug_assert!(!is_edge_self_bivalent(&graph, e1));
188 debug_assert!(!is_edge_self_bivalent(&graph, e2));
189 debug_assert!(!is_edge_self_bivalent(&graph, e3));
190 debug_assert!(is_edge_self_bivalent(&graph, e4));
191 debug_assert!(is_edge_self_bivalent(&graph, e5));
192 debug_assert!(is_edge_self_bivalent(&graph, e6));
193 debug_assert!(is_edge_self_bivalent(&graph, e7));
194 debug_assert!(is_edge_self_bivalent(&graph, e8));
195 }
196
197 #[test]
198 fn test_is_edge_self_bivalent_cycle() {
199 let mut graph = PetGraph::new();
200 let n0 = graph.add_node(());
201 let n1 = graph.add_node(());
202 let n2 = graph.add_node(());
203 let e0 = graph.add_edge(n0, n1, ());
204 let e1 = graph.add_edge(n1, n2, ());
205 let e2 = graph.add_edge(n2, n0, ());
206
207 debug_assert!(is_edge_self_bivalent(&graph, e0));
208 debug_assert!(is_edge_self_bivalent(&graph, e1));
209 debug_assert!(is_edge_self_bivalent(&graph, e2));
210 }
211}