@@ -17,6 +17,13 @@ mod dfs_edges;
1717mod dfs_visit;
1818mod dijkstra_visit;
1919
20+ use petgraph:: prelude:: * ;
21+ use petgraph:: visit:: GraphRef ;
22+ use petgraph:: visit:: IntoNeighborsDirected ;
23+ use petgraph:: visit:: Reversed ;
24+ use petgraph:: visit:: VisitMap ;
25+ use petgraph:: visit:: Visitable ;
26+
2027pub use bfs_visit:: { breadth_first_search, BfsEvent } ;
2128pub use dfs_edges:: dfs_edges;
2229pub use dfs_visit:: { depth_first_search, DfsEvent } ;
@@ -45,3 +52,133 @@ macro_rules! try_control {
4552}
4653
4754use try_control;
55+
56+ struct AncestryWalker < G , N , VM > {
57+ graph : G ,
58+ walker : Bfs < N , VM > ,
59+ }
60+
61+ impl <
62+ G : GraphRef + Visitable + IntoNeighborsDirected < NodeId = N > ,
63+ N : Copy + Clone + PartialEq ,
64+ VM : VisitMap < N > ,
65+ > Iterator for AncestryWalker < G , N , VM >
66+ {
67+ type Item = N ;
68+ fn next ( & mut self ) -> Option < Self :: Item > {
69+ self . walker . next ( self . graph )
70+ }
71+ }
72+
73+ /// Return the ancestors of a node in a graph.
74+ ///
75+ /// `node` is included in the output
76+ ///
77+ /// # Arguments:
78+ ///
79+ /// * `node` - The node to find the ancestors of
80+ ///
81+ /// # Returns
82+ ///
83+ /// An iterator where each item is a node id for an ancestor of ``node``.
84+ /// This includes ``node`` in the returned ids.
85+ ///
86+ /// # Example
87+ ///
88+ /// ```rust
89+ /// use rustworkx_core::traversal::ancestors;
90+ /// use rustworkx_core::petgraph::stable_graph::{StableDiGraph, NodeIndex};
91+ ///
92+ /// let graph: StableDiGraph<(), ()> = StableDiGraph::from_edges(&[
93+ /// (0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)
94+ /// ]);
95+ /// let ancestors: Vec<usize> = ancestors(&graph, NodeIndex::new(3)).map(|x| x.index()).collect();
96+ /// assert_eq!(vec![3_usize, 1, 0], ancestors);
97+ /// ```
98+ pub fn ancestors < G > ( graph : G , node : G :: NodeId ) -> impl Iterator < Item = G :: NodeId >
99+ where
100+ G : GraphRef + Visitable + IntoNeighborsDirected ,
101+ {
102+ let reversed = Reversed ( graph) ;
103+ AncestryWalker {
104+ graph : reversed,
105+ walker : Bfs :: new ( reversed, node) ,
106+ }
107+ }
108+
109+ /// Return the descendants of a node in a graph.
110+ ///
111+ /// `node` is included in the output.
112+ /// # Arguments:
113+ ///
114+ /// * `node` - The node to find the ancestors of
115+ ///
116+ /// # Returns
117+ ///
118+ /// An iterator where each item is a node id for an ancestor of ``node``.
119+ /// This includes ``node`` in the returned ids.
120+ ///
121+ /// # Example
122+ ///
123+ /// ```rust
124+ /// use rustworkx_core::traversal::descendants;
125+ /// use rustworkx_core::petgraph::stable_graph::{StableDiGraph, NodeIndex};
126+ ///
127+ /// let graph: StableDiGraph<(), ()> = StableDiGraph::from_edges(&[
128+ /// (0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)
129+ /// ]);
130+ /// let descendants: Vec<usize> = descendants(&graph, NodeIndex::new(3)).map(|x| x.index()).collect();
131+ /// assert_eq!(vec![3_usize, 4, 5], descendants);
132+ /// ```
133+ pub fn descendants < G > ( graph : G , node : G :: NodeId ) -> impl Iterator < Item = G :: NodeId >
134+ where
135+ G : GraphRef + Visitable + IntoNeighborsDirected ,
136+ {
137+ AncestryWalker {
138+ graph,
139+ walker : Bfs :: new ( graph, node) ,
140+ }
141+ }
142+
143+ #[ cfg( test) ]
144+ mod test_ancestry {
145+ use super :: { ancestors, descendants} ;
146+ use crate :: petgraph:: graph:: DiGraph ;
147+ use crate :: petgraph:: stable_graph:: { NodeIndex , StableDiGraph } ;
148+
149+ #[ test]
150+ fn test_ancestors_digraph ( ) {
151+ let graph: DiGraph < ( ) , ( ) > =
152+ DiGraph :: from_edges ( & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 4 ) , ( 3 , 4 ) , ( 4 , 5 ) ] ) ;
153+ let ancestors: Vec < usize > = ancestors ( & graph, NodeIndex :: new ( 3 ) )
154+ . map ( |x| x. index ( ) )
155+ . collect ( ) ;
156+ assert_eq ! ( vec![ 3_usize , 1 , 0 ] , ancestors) ;
157+ }
158+
159+ #[ test]
160+ fn test_descendants ( ) {
161+ let graph: DiGraph < ( ) , ( ) > =
162+ DiGraph :: from_edges ( & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 4 ) , ( 3 , 4 ) , ( 4 , 5 ) ] ) ;
163+ let descendants: Vec < usize > = descendants ( & graph, NodeIndex :: new ( 3 ) )
164+ . map ( |x| x. index ( ) )
165+ . collect ( ) ;
166+ assert_eq ! ( vec![ 3_usize , 4 , 5 ] , descendants) ;
167+ }
168+
169+ #[ test]
170+ fn test_no_ancestors ( ) {
171+ let mut graph: StableDiGraph < ( ) , ( ) > = StableDiGraph :: new ( ) ;
172+ let index = graph. add_node ( ( ) ) ;
173+ let res = ancestors ( & graph, index) ;
174+ assert_eq ! ( vec![ index] , res. collect:: <Vec <NodeIndex >>( ) )
175+ }
176+
177+ #[ test]
178+ fn test_no_descendants ( ) {
179+ let mut graph: StableDiGraph < ( ) , ( ) > = StableDiGraph :: new ( ) ;
180+ let index = graph. add_node ( ( ) ) ;
181+ let res = descendants ( & graph, index) ;
182+ assert_eq ! ( vec![ index] , res. collect:: <Vec <NodeIndex >>( ) )
183+ }
184+ }
0 commit comments