11use crate :: connectivity:: conn_components:: connected_components;
22use crate :: dictmap:: * ;
3- use crate :: shortest_path:: dijkstra;
3+ use crate :: shortest_path:: { astar , dijkstra} ;
44use crate :: Result ;
55use hashbrown:: { HashMap , HashSet } ;
6- use petgraph:: algo:: { astar , min_spanning_tree, Measure } ;
6+ use petgraph:: algo:: { min_spanning_tree, Measure } ;
77use petgraph:: csr:: { DefaultIx , IndexType } ;
88use petgraph:: data:: { DataMap , Element } ;
99use petgraph:: graph:: Graph ;
@@ -13,6 +13,7 @@ use petgraph::visit::{
1313 IntoNeighborsDirected , IntoNodeIdentifiers , IntoNodeReferences , NodeIndexable , Visitable ,
1414} ;
1515use petgraph:: Undirected ;
16+ use std:: cmp:: Ordering ;
1617use std:: convert:: Infallible ;
1718use std:: hash:: Hash ;
1819
3940 G :: NodeId : Eq + Hash ,
4041 G :: EdgeWeight : Clone ,
4142 F : FnMut ( G :: EdgeRef ) -> Result < K , E > ,
42- K : Clone + PartialOrd + Copy + Measure + Default + Ord ,
43+ K : Clone + PartialOrd + Copy + Measure + Default ,
4344{
4445 components
4546 . into_iter ( )
7778 } )
7879 . collect ( )
7980}
80- pub fn minimum_cycle_basis < G , F , K , E > ( graph : G , mut weight_fn : F ) -> Result < Vec < Vec < NodeIndex > > , E >
81+ pub fn minimal_cycle_basis < G , F , K , E > ( graph : G , mut weight_fn : F ) -> Result < Vec < Vec < NodeIndex > > , E >
8182where
8283 G : EdgeCount
8384 + IntoNodeIdentifiers
@@ -88,10 +89,10 @@ where
8889 + IntoNeighborsDirected
8990 + Visitable
9091 + IntoEdges ,
91- G :: EdgeWeight : Clone + PartialOrd ,
92+ G :: EdgeWeight : Clone ,
9293 G :: NodeId : Eq + Hash ,
9394 F : FnMut ( G :: EdgeRef ) -> Result < K , E > ,
94- K : Clone + PartialOrd + Copy + Measure + Default + Ord ,
95+ K : Clone + PartialOrd + Copy + Measure + Default ,
9596{
9697 let conn_components = connected_components ( & graph) ;
9798 let mut min_cycle_basis = Vec :: new ( ) ;
@@ -136,7 +137,7 @@ where
136137 H :: EdgeWeight : Clone + PartialOrd ,
137138 H :: NodeId : Eq + Hash ,
138139 F : FnMut ( H :: EdgeRef ) -> Result < K , E > ,
139- K : Clone + PartialOrd + Copy + Measure + Default + Ord ,
140+ K : Clone + PartialOrd + Copy + Measure + Default ,
140141{
141142 let mut sub_cb: Vec < Vec < usize > > = Vec :: new ( ) ;
142143 let num_edges = subgraph. edge_count ( ) ;
@@ -243,7 +244,7 @@ where
243244 H : IntoNodeReferences + IntoEdgeReferences + DataMap + NodeIndexable + EdgeIndexable ,
244245 H :: NodeId : Eq + Hash ,
245246 F : FnMut ( H :: EdgeRef ) -> Result < K , E > ,
246- K : Clone + PartialOrd + Copy + Measure + Default + Ord ,
247+ K : Clone + PartialOrd + Copy + Measure + Default ,
247248{
248249 let mut gi = Graph :: < _ , _ , petgraph:: Undirected > :: default ( ) ;
249250 let mut subgraph_gi_map = HashMap :: new ( ) ;
@@ -290,31 +291,36 @@ where
290291 |edge| Ok ( * edge. weight ( ) ) ,
291292 None ,
292293 ) ;
293- // Find the shortest distance in the result and store it in the shortest_path_map
294294 let spl = result. unwrap ( ) [ & gi_lifted_nodeidx] ;
295295 shortest_path_map. insert ( subnodeid, spl) ;
296296 }
297- let min_start = shortest_path_map. iter ( ) . min_by_key ( |x| x. 1 ) . unwrap ( ) . 0 ;
297+ let min_start = shortest_path_map
298+ . iter ( )
299+ . min_by ( |a, b| a. 1 . partial_cmp ( b. 1 ) . unwrap_or ( Ordering :: Equal ) )
300+ . unwrap ( )
301+ . 0 ;
298302 let min_start_node = subgraph_gi_map[ min_start] . 0 ;
299303 let min_start_lifted_node = subgraph_gi_map[ min_start] . 1 ;
300- let result = astar (
304+ let result: Result < Option < ( K , Vec < NodeIndex > ) > > = astar (
301305 & gi,
302- min_start_node,
303- |finish| finish == min_start_lifted_node,
304- |e| * e. weight ( ) ,
305- |_| K :: default ( ) ,
306+ min_start_node. clone ( ) ,
307+ |finish| Ok ( finish == min_start_lifted_node. clone ( ) ) ,
308+ |e| Ok ( * e. weight ( ) ) ,
309+ |_| Ok ( K :: default ( ) ) ,
306310 ) ;
311+
307312 let mut min_path: Vec < usize > = Vec :: new ( ) ;
308313 match result {
309- Some ( ( _cost, path) ) => {
314+ Ok ( Some ( ( _cost, path) ) ) => {
310315 for node in path {
311316 if let Some ( & subgraph_nodeid) = gi_subgraph_map. get ( & node) {
312317 let subgraph_node = NodeIndexable :: to_index ( & subgraph, subgraph_nodeid) ;
313318 min_path. push ( subgraph_node. index ( ) ) ;
314319 }
315320 }
316321 }
317- None => { }
322+ Ok ( None ) => { }
323+ Err ( _) => { }
318324 }
319325 let edgelist = min_path
320326 . windows ( 2 )
@@ -344,9 +350,9 @@ where
344350}
345351
346352#[ cfg( test) ]
347- mod test_minimum_cycle_basis {
348- use crate :: connectivity:: minimum_cycle_basis :: minimum_cycle_basis ;
349- use petgraph:: graph:: Graph ;
353+ mod test_minimal_cycle_basis {
354+ use crate :: connectivity:: minimal_cycle_basis :: minimal_cycle_basis ;
355+ use petgraph:: graph:: { Graph , NodeIndex } ;
350356 use petgraph:: Undirected ;
351357 use std:: convert:: Infallible ;
352358
@@ -356,7 +362,7 @@ mod test_minimum_cycle_basis {
356362 let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
357363 Ok ( * edge. weight ( ) )
358364 } ;
359- let output = minimum_cycle_basis ( & graph, weight_fn) . unwrap ( ) ;
365+ let output = minimal_cycle_basis ( & graph, weight_fn) . unwrap ( ) ;
360366 assert_eq ! ( output. len( ) , 0 ) ;
361367 }
362368
@@ -372,8 +378,7 @@ mod test_minimum_cycle_basis {
372378 let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
373379 Ok ( * edge. weight ( ) )
374380 } ;
375- let cycles = minimum_cycle_basis ( & graph, weight_fn) ;
376- println ! ( "Cycles {:?}" , cycles. as_ref( ) . unwrap( ) ) ;
381+ let cycles = minimal_cycle_basis ( & graph, weight_fn) ;
377382 assert_eq ! ( cycles. unwrap( ) . len( ) , 1 ) ;
378383 }
379384
@@ -393,10 +398,60 @@ mod test_minimum_cycle_basis {
393398 let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
394399 Ok ( * edge. weight ( ) )
395400 } ;
396- let cycles = minimum_cycle_basis ( & graph, weight_fn) ;
401+ let cycles = minimal_cycle_basis ( & graph, weight_fn) ;
397402 assert_eq ! ( cycles. unwrap( ) . len( ) , 2 ) ;
398403 }
399404
405+ #[ test]
406+ fn test_non_trivial_graph ( ) {
407+ let mut g = Graph :: < & str , i32 , Undirected > :: new_undirected ( ) ;
408+ let a = g. add_node ( "A" ) ;
409+ let b = g. add_node ( "B" ) ;
410+ let c = g. add_node ( "C" ) ;
411+ let d = g. add_node ( "D" ) ;
412+ let e = g. add_node ( "E" ) ;
413+ let f = g. add_node ( "F" ) ;
414+
415+ g. add_edge ( a, b, 7 ) ;
416+ g. add_edge ( c, a, 9 ) ;
417+ g. add_edge ( a, d, 11 ) ;
418+ g. add_edge ( b, c, 10 ) ;
419+ g. add_edge ( d, c, 2 ) ;
420+ g. add_edge ( d, e, 9 ) ;
421+ g. add_edge ( b, f, 15 ) ;
422+ g. add_edge ( c, f, 11 ) ;
423+ g. add_edge ( e, f, 6 ) ;
424+
425+ let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
426+ Ok ( * edge. weight ( ) )
427+ } ;
428+ let output = minimal_cycle_basis ( & g, weight_fn) ;
429+ let mut actual_output = output. unwrap ( ) ;
430+ for cycle in & mut actual_output {
431+ cycle. sort ( ) ;
432+ }
433+ actual_output. sort ( ) ;
434+
435+ let expected_output: Vec < Vec < NodeIndex > > = vec ! [
436+ vec![
437+ NodeIndex :: new( 5 ) ,
438+ NodeIndex :: new( 2 ) ,
439+ NodeIndex :: new( 3 ) ,
440+ NodeIndex :: new( 4 ) ,
441+ ] ,
442+ vec![ NodeIndex :: new( 2 ) , NodeIndex :: new( 5 ) , NodeIndex :: new( 1 ) ] ,
443+ vec![ NodeIndex :: new( 0 ) , NodeIndex :: new( 2 ) , NodeIndex :: new( 1 ) ] ,
444+ vec![ NodeIndex :: new( 2 ) , NodeIndex :: new( 3 ) , NodeIndex :: new( 0 ) ] ,
445+ ] ;
446+ let mut sorted_expected_output = expected_output. clone ( ) ;
447+ for cycle in & mut sorted_expected_output {
448+ cycle. sort ( ) ;
449+ }
450+ sorted_expected_output. sort ( ) ;
451+
452+ assert_eq ! ( actual_output, sorted_expected_output) ;
453+ }
454+
400455 #[ test]
401456 fn test_weighted_diamond_graph ( ) {
402457 let mut weighted_diamond = Graph :: < ( ) , i32 , Undirected > :: new_undirected ( ) ;
@@ -412,20 +467,19 @@ mod test_minimum_cycle_basis {
412467 let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
413468 Ok ( * edge. weight ( ) )
414469 } ;
415- let output = minimum_cycle_basis ( & weighted_diamond, weight_fn) ;
416- let expected_output: Vec < Vec < usize > > = vec ! [ vec![ 0 , 1 , 3 ] , vec![ 0 , 1 , 2 , 3 ] ] ;
470+ let output = minimal_cycle_basis ( & weighted_diamond, weight_fn) ;
471+ let expected_output1: Vec < Vec < usize > > = vec ! [ vec![ 0 , 1 , 3 ] , vec![ 0 , 1 , 2 , 3 ] ] ;
472+ let expected_output2: Vec < Vec < usize > > = vec ! [ vec![ 1 , 2 , 3 ] , vec![ 0 , 1 , 2 , 3 ] ] ;
417473 for cycle in output. unwrap ( ) . iter ( ) {
418- println ! ( "{:?}" , cycle) ;
419474 let mut node_indices: Vec < usize > = Vec :: new ( ) ;
420475 for node in cycle. iter ( ) {
421476 node_indices. push ( node. index ( ) ) ;
422477 }
423478 node_indices. sort ( ) ;
424- println ! ( "Node indices {:?}" , node_indices) ;
425- if expected_output. contains ( & node_indices) {
426- println ! ( "Found cycle {:?}" , node_indices) ;
427- }
428- assert ! ( expected_output. contains( & node_indices) ) ;
479+ assert ! (
480+ expected_output1. contains( & node_indices)
481+ || expected_output2. contains( & node_indices)
482+ ) ;
429483 }
430484 }
431485
@@ -444,7 +498,7 @@ mod test_minimum_cycle_basis {
444498 let weight_fn =
445499 |_edge : petgraph:: graph:: EdgeReference < ( ) > | -> Result < i32 , Infallible > { Ok ( 1 ) } ;
446500
447- let output = minimum_cycle_basis ( & unweighted_diamond, weight_fn) ;
501+ let output = minimal_cycle_basis ( & unweighted_diamond, weight_fn) ;
448502 let expected_output: Vec < Vec < usize > > = vec ! [ vec![ 0 , 1 , 3 ] , vec![ 1 , 2 , 3 ] ] ;
449503 for cycle in output. unwrap ( ) . iter ( ) {
450504 let mut node_indices: Vec < usize > = Vec :: new ( ) ;
@@ -476,7 +530,7 @@ mod test_minimum_cycle_basis {
476530 let weight_fn = |edge : petgraph:: graph:: EdgeReference < i32 > | -> Result < i32 , Infallible > {
477531 Ok ( * edge. weight ( ) )
478532 } ;
479- let output = minimum_cycle_basis ( & complete_graph, weight_fn) ;
533+ let output = minimal_cycle_basis ( & complete_graph, weight_fn) ;
480534 for cycle in output. unwrap ( ) . iter ( ) {
481535 assert_eq ! ( cycle. len( ) , 3 ) ;
482536 }
0 commit comments