petgraph/visit/
undirected_adaptor.rs

1use crate::visit::{
2    Data, GraphBase, GraphProp, GraphRef, IntoEdgeReferences, IntoEdges, IntoEdgesDirected,
3    IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences,
4    NodeCompactIndexable, NodeCount, NodeIndexable, Visitable,
5};
6use crate::Direction;
7
8/// An edge direction removing graph adaptor.
9#[derive(Copy, Clone, Debug)]
10pub struct UndirectedAdaptor<G>(pub G);
11
12impl<G: GraphRef> GraphRef for UndirectedAdaptor<G> {}
13
14impl<G> IntoNeighbors for UndirectedAdaptor<G>
15where
16    G: IntoNeighborsDirected,
17{
18    type Neighbors = std::iter::Chain<G::NeighborsDirected, G::NeighborsDirected>;
19    fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
20        self.0
21            .neighbors_directed(n, Direction::Incoming)
22            .chain(self.0.neighbors_directed(n, Direction::Outgoing))
23    }
24}
25
26impl<G> IntoEdges for UndirectedAdaptor<G>
27where
28    G: IntoEdgesDirected,
29{
30    type Edges = std::iter::Chain<G::EdgesDirected, G::EdgesDirected>;
31    fn edges(self, a: Self::NodeId) -> Self::Edges {
32        self.0
33            .edges_directed(a, Direction::Incoming)
34            .chain(self.0.edges_directed(a, Direction::Outgoing))
35    }
36}
37
38impl<G> GraphProp for UndirectedAdaptor<G>
39where
40    G: GraphBase,
41{
42    type EdgeType = crate::Undirected;
43
44    fn is_directed(&self) -> bool {
45        false
46    }
47}
48
49macro_rules! access0 {
50    ($e:expr) => {
51        $e.0
52    };
53}
54
55GraphBase! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
56Data! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
57IntoEdgeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
58Visitable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
59NodeIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
60NodeCompactIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
61IntoNodeIdentifiers! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
62IntoNodeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
63NodeCount! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::graph::{DiGraph, Graph};
69    use crate::visit::Dfs;
70
71    static LINEAR_EDGES: [(u32, u32); 5] = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)];
72
73    #[test]
74    pub fn test_is_reachable() {
75        // create a linear digraph, choose a node in the centre and check all nodes are visited
76        // by a dfs
77
78        let graph = DiGraph::<(), ()>::from_edges(&LINEAR_EDGES);
79
80        let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
81        nodes.sort();
82
83        let graph = UndirectedAdaptor(&graph);
84
85        use crate::visit::Walker;
86        let mut visited_nodes: Vec<_> = Dfs::new(&graph, nodes[2]).iter(&graph).collect();
87        visited_nodes.sort();
88        assert_eq!(visited_nodes, nodes);
89    }
90
91    #[test]
92    pub fn test_neighbors_count() {
93        {
94            let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
95            let graph = UndirectedAdaptor(&graph);
96
97            let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
98            nodes.sort();
99            assert_eq!(graph.neighbors(nodes[1]).count(), 2);
100        }
101
102        {
103            let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
104            let graph = UndirectedAdaptor(&graph);
105
106            let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
107            nodes.sort();
108            assert_eq!(graph.neighbors(nodes[1]).count(), 2);
109        }
110    }
111}