@@ -116,7 +116,8 @@ where
116116 cycles
117117}
118118
119- /// Return a list of edges representing cycles which form a basis for cycles of a given graph.
119+ /// Return a list of edge indices representing cycles which form a basis for
120+ /// cycles of a given graph.
120121///
121122/// A basis for cycles of a graph is a minimal collection of
122123/// cycles such that any cycle in the graph can be written
@@ -145,20 +146,45 @@ where
145146///
146147/// let edge_list = [(0, 1), (0, 3), (0, 5), (1, 2), (2, 3), (3, 4), (4, 5)];
147148/// let graph = UnGraph::<i32, i32>::from_edges(&edge_list);
148- /// let mut res: Vec<Vec<(NodeIndex, NodeIndex) >> = cycle_basis_edges(&graph, Some(NodeIndex::new(0)));
149+ /// let mut res: Vec<Vec<EdgeIndex >> = cycle_basis_edges(&graph, Some(NodeIndex::new(0)));
149150/// ```
150- pub fn cycle_basis_edges < G > ( graph : G , root : Option < G :: NodeId > ) -> Vec < Vec < ( G :: NodeId , G :: NodeId ) > >
151+ pub fn cycle_basis_edges < G > ( graph : G , root : Option < G :: NodeId > ) -> Vec < Vec < G :: EdgeId > >
151152where
152153 G : NodeCount ,
153154 G : IntoNeighbors ,
154155 G : IntoEdges ,
155156 G : IntoNodeIdentifiers ,
156157 G :: NodeId : Eq + Hash ,
158+ G :: EdgeId : Eq + Hash ,
157159{
158160 let mut root_node = root;
159161 let mut graph_nodes: HashSet < G :: NodeId > = graph. node_identifiers ( ) . collect ( ) ;
162+ let mut cycles: Vec < Vec < G :: EdgeId > > = Vec :: new ( ) ;
163+
164+ // Method used to retrieve all the edges between an origin node and a target node.
165+ // Can be used to check if a node loops back to itself by enabling equiv
166+ fn get_edge_between < G > (
167+ orig_graph : G ,
168+ origin : G :: NodeId ,
169+ target : G :: NodeId ,
170+ equiv : bool ,
171+ ) -> Vec < G :: EdgeId >
172+ where
173+ G : IntoEdges ,
174+ {
175+ orig_graph
176+ . edges ( origin)
177+ . filter ( |edge : & G :: EdgeRef | {
178+ if equiv {
179+ edge. source ( ) == target && edge. target ( ) == target
180+ } else {
181+ edge. source ( ) == target || edge. target ( ) == target
182+ }
183+ } )
184+ . map ( |edge : G :: EdgeRef | edge. id ( ) )
185+ . collect ( )
186+ }
160187
161- let mut cycles: Vec < Vec < ( G :: NodeId , G :: NodeId ) > > = Vec :: new ( ) ;
162188 while !graph_nodes. is_empty ( ) {
163189 let temp_value: G :: NodeId ;
164190 // If root_node is not set get an arbitrary node from the set of graph
@@ -194,37 +220,25 @@ where
194220 used. insert ( neighbor, temp_set) ;
195221 // A self loop:
196222 } else if z == neighbor {
197- let cycle_edge: Vec < ( G :: NodeId , G :: NodeId ) > = graph
198- . edges ( z)
199- . filter ( |edge : & G :: EdgeRef | edge. source ( ) == z && edge. target ( ) == z)
200- . map ( |edge : G :: EdgeRef | ( edge. source ( ) , edge. target ( ) ) )
201- . collect ( ) ;
223+ let cycle_edge: Vec < G :: EdgeId > = get_edge_between ( graph, z, z, true ) ;
202224 cycles. push ( cycle_edge) ;
203225 // A cycle was found:
204226 } else if !used. get ( & z) . unwrap ( ) . contains ( & neighbor) {
205227 let pn = used. get ( & neighbor) . unwrap ( ) ;
206- let mut cycle: Vec < ( G :: NodeId , G :: NodeId ) > = vec ! [ ] ;
228+ let mut cycle: Vec < G :: EdgeId > = vec ! [ ] ;
207229 let mut p = pred. get ( & z) . unwrap ( ) ;
208230 // Retreive all edges from z to neighbor and vice versa
209- let mut neigh_edge: Vec < ( G :: NodeId , G :: NodeId ) > = graph
210- . edges ( z)
211- . filter ( |edge : & G :: EdgeRef | {
212- edge. source ( ) == neighbor || edge. target ( ) == neighbor
213- } )
214- . map ( |edge : G :: EdgeRef | ( edge. source ( ) , edge. target ( ) ) )
215- . collect ( ) ;
231+ let mut neigh_edge: Vec < G :: EdgeId > =
232+ get_edge_between ( graph, z, neighbor, false ) ;
216233 // Append to cycle
217234 cycle. append ( & mut neigh_edge) ;
218235 // Make last p_node == z
219236 let mut prev_p: & G :: NodeId = & z;
220237 // While p is in the neighborhood of neighbor
221238 while !pn. contains ( p) {
222239 // Retrieve all edges from prev_p to p and vice versa
223- let mut neigh_edge: Vec < ( G :: NodeId , G :: NodeId ) > = graph
224- . edges ( * prev_p)
225- . filter ( |edge : & G :: EdgeRef | edge. target ( ) == * p || edge. source ( ) == * p)
226- . map ( |edge : G :: EdgeRef | ( edge. source ( ) , edge. target ( ) ) )
227- . collect ( ) ;
240+ let mut neigh_edge: Vec < G :: EdgeId > =
241+ get_edge_between ( graph, * prev_p, * p, false ) ;
228242 // Append to cycle
229243 cycle. append ( & mut neigh_edge) ;
230244 // Update prev_p to p
@@ -233,20 +247,12 @@ where
233247 p = pred. get ( p) . unwrap ( ) ;
234248 }
235249 // When loop ends add remaining edges from prev_p to p.
236- let mut neigh_edge: Vec < ( G :: NodeId , G :: NodeId ) > = graph
237- . edges ( * prev_p)
238- . filter ( |edge : & G :: EdgeRef | edge. target ( ) == * p || edge. source ( ) == * p)
239- . map ( |edge : G :: EdgeRef | ( edge. source ( ) , edge. target ( ) ) )
240- . collect ( ) ;
250+ let mut neigh_edge: Vec < G :: EdgeId > =
251+ get_edge_between ( graph, * prev_p, * p, false ) ;
241252 cycle. append ( & mut neigh_edge) ;
242253 // Also retreive all edges between the last p and neighbor
243- let mut neigh_edge: Vec < ( G :: NodeId , G :: NodeId ) > = graph
244- . edges ( * p)
245- . filter ( |edge : & G :: EdgeRef | {
246- edge. target ( ) == neighbor || edge. source ( ) == neighbor
247- } )
248- . map ( |edge : G :: EdgeRef | ( edge. source ( ) , edge. target ( ) ) )
249- . collect ( ) ;
254+ let mut neigh_edge: Vec < G :: EdgeId > =
255+ get_edge_between ( graph, * p, neighbor, false ) ;
250256 cycle. append ( & mut neigh_edge) ;
251257
252258 // Once all edges within cycle have been found, push to cycle list.
@@ -283,19 +289,10 @@ mod tests {
283289 sorted_cycles
284290 }
285291
286- fn sorted_cycle_edges ( cycles : Vec < Vec < ( NodeIndex , NodeIndex ) > > ) -> Vec < Vec < ( usize , usize ) > > {
287- let mut sorted_cycles: Vec < Vec < ( usize , usize ) > > = vec ! [ ] ;
292+ fn sorted_cycle_edges ( cycles : Vec < Vec < EdgeIndex > > ) -> Vec < Vec < usize > > {
293+ let mut sorted_cycles: Vec < Vec < usize > > = vec ! [ ] ;
288294 for cycle in cycles {
289- let mut cycle: Vec < ( usize , usize ) > = cycle
290- . iter ( )
291- . map ( |x| {
292- if x. 0 < x. 1 {
293- ( x. 0 . index ( ) , x. 1 . index ( ) )
294- } else {
295- ( x. 1 . index ( ) , x. 0 . index ( ) )
296- }
297- } )
298- . collect ( ) ;
295+ let mut cycle: Vec < usize > = cycle. iter ( ) . map ( |x| x. index ( ) ) . collect ( ) ;
299296 cycle. sort ( ) ;
300297 sorted_cycles. push ( cycle) ;
301298 }
@@ -342,7 +339,7 @@ mod tests {
342339 ( 3 , 4 ) ,
343340 ] ;
344341 let graph = UnGraph :: < i32 , i32 > :: from_edges ( & edge_list) ;
345- let expected = vec ! [ vec![ ( 0 , 0 ) ] , vec![ ( 2 , 3 ) , ( 2 , 5 ) , ( 3 , 6 ) , ( 5 , 6 ) ] ] ;
342+ let expected = vec ! [ vec![ 0 ] , vec![ 3 , 4 , 5 , 6 ] ] ;
346343 let res_0 = cycle_basis_edges ( & graph, Some ( NodeIndex :: new ( 0 ) ) ) ;
347344 assert_eq ! ( sorted_cycle_edges( res_0) , expected) ;
348345 let res_1 = cycle_basis_edges ( & graph, Some ( NodeIndex :: new ( 2 ) ) ) ;
@@ -403,10 +400,10 @@ mod tests {
403400 assert_eq ! (
404401 sorted_cycle_edges( res_0) ,
405402 vec![
406- vec![ ( 0 , 1 ) , ( 0 , 3 ) , ( 1 , 2 ) , ( 2 , 3 ) ] ,
407- vec![ ( 0 , 1 ) , ( 0 , 8 ) , ( 1 , 6 ) , ( 6 , 7 ) , ( 7 , 8 ) ] ,
408- vec![ ( 0 , 3 ) , ( 0 , 5 ) , ( 3 , 4 ) , ( 4 , 5 ) ] ,
409- vec![ ( 1 , 1 ) ] ,
403+ vec![ 0 , 1 , 4 , 6 ] ,
404+ vec![ 0 , 3 , 5 , 9 , 10 ] ,
405+ vec![ 1 , 2 , 7 , 8 ] ,
406+ vec![ 12 ] ,
410407 ]
411408 ) ;
412409 }
0 commit comments