7979 + GraphProp
8080 + GraphBase
8181 + std:: marker:: Sync ,
82- <G as GraphBase >:: NodeId : std:: cmp:: Eq + Hash + Send ,
82+ <G as GraphBase >:: NodeId : std:: cmp:: Eq + Send ,
8383 // rustfmt deletes the following comments if placed inline above
8484 // + IntoNodeIdentifiers // for node_identifiers()
8585 // + IntoNeighborsDirected // for neighbors()
@@ -184,8 +184,8 @@ where
184184 + EdgeCount
185185 + GraphProp
186186 + Sync ,
187- G :: NodeId : Eq + Hash + Send ,
188- G :: EdgeId : Eq + Hash + Send ,
187+ G :: NodeId : Eq + Send ,
188+ G :: EdgeId : Eq + Send ,
189189{
190190 let max_index = graph. node_bound ( ) ;
191191 let mut betweenness = vec ! [ None ; graph. edge_bound( ) ] ;
@@ -264,16 +264,15 @@ fn _accumulate_vertices<G>(
264264 + GraphProp
265265 + GraphBase
266266 + std:: marker:: Sync ,
267- <G as GraphBase >:: NodeId : std:: cmp:: Eq + Hash ,
267+ <G as GraphBase >:: NodeId : std:: cmp:: Eq ,
268268{
269269 let mut delta = vec ! [ 0.0 ; max_index] ;
270270 for w in & path_calc. verts_sorted_by_distance {
271271 let iw = graph. to_index ( * w) ;
272- let coeff = ( 1.0 + delta[ iw] ) / path_calc. sigma [ w] ;
273- let p_w = path_calc. predecessors . get ( w) . unwrap ( ) ;
274- for v in p_w {
275- let iv = graph. to_index ( * v) ;
276- delta[ iv] += path_calc. sigma [ v] * coeff;
272+ let coeff = ( 1.0 + delta[ iw] ) / path_calc. sigma [ iw] ;
273+ let p_w = path_calc. predecessors . get ( iw) . unwrap ( ) ;
274+ for iv in p_w {
275+ delta[ * iv] += path_calc. sigma [ * iv] * coeff;
277276 }
278277 }
279278 let mut betweenness = locked_betweenness. write ( ) . unwrap ( ) ;
@@ -304,21 +303,21 @@ fn accumulate_edges<G>(
304303 graph : G ,
305304) where
306305 G : NodeIndexable + EdgeIndexable + Sync ,
307- G :: NodeId : Eq + Hash ,
308- G :: EdgeId : Eq + Hash ,
306+ G :: NodeId : Eq ,
307+ G :: EdgeId : Eq ,
309308{
310309 let mut delta = vec ! [ 0.0 ; max_index] ;
311310 for w in & path_calc. verts_sorted_by_distance {
312311 let iw = NodeIndexable :: to_index ( & graph, * w) ;
313- let coeff = ( 1.0 + delta[ iw] ) / path_calc. sigma [ w ] ;
314- let p_w = path_calc. predecessors . get ( w ) . unwrap ( ) ;
315- let e_w = path_calc. predecessor_edges . get ( w ) . unwrap ( ) ;
312+ let coeff = ( 1.0 + delta[ iw] ) / path_calc. sigma [ iw ] ;
313+ let p_w = path_calc. predecessors . get ( iw ) . unwrap ( ) ;
314+ let e_w = path_calc. predecessor_edges . get ( iw ) . unwrap ( ) ;
316315 let mut betweenness = locked_betweenness. write ( ) . unwrap ( ) ;
317316 for i in 0 ..p_w. len ( ) {
318317 let v = p_w[ i] ;
319318 let iv = NodeIndexable :: to_index ( & graph, v) ;
320319 let ie = EdgeIndexable :: to_index ( & graph, e_w[ i] ) ;
321- let c = path_calc. sigma [ & v ] * coeff;
320+ let c = path_calc. sigma [ iv ] * coeff;
322321 betweenness[ ie] = betweenness[ ie] . map ( |x| x + c) ;
323322 delta[ iv] += c;
324323 }
@@ -358,7 +357,7 @@ where
358357 + IntoNeighborsDirected
359358 + NodeCount
360359 + GraphProp ,
361- G :: NodeId : Eq + Hash ,
360+ G :: NodeId : Eq ,
362361{
363362 let node_count = graph. node_count ( ) as f64 ;
364363 let mut centrality = vec ! [ 0.0 ; graph. node_bound( ) ] ;
@@ -396,46 +395,42 @@ where
396395struct ShortestPathData < G >
397396where
398397 G : GraphBase ,
399- <G as GraphBase >:: NodeId : std:: cmp:: Eq + Hash ,
398+ <G as GraphBase >:: NodeId : std:: cmp:: Eq ,
400399{
401400 verts_sorted_by_distance : Vec < G :: NodeId > ,
402- predecessors : HashMap < G :: NodeId , Vec < G :: NodeId > > ,
403- sigma : HashMap < G :: NodeId , f64 > ,
401+ predecessors : Vec < Vec < usize > > ,
402+ sigma : Vec < f64 > ,
404403}
405-
406404fn shortest_path_for_centrality < G > ( graph : G , node_s : & G :: NodeId ) -> ShortestPathData < G >
407405where
408406 G : NodeIndexable + IntoNodeIdentifiers + IntoNeighborsDirected + NodeCount + GraphBase ,
409- <G as GraphBase >:: NodeId : std:: cmp:: Eq + Hash ,
407+ <G as GraphBase >:: NodeId : std:: cmp:: Eq ,
410408{
411- let mut verts_sorted_by_distance: Vec < G :: NodeId > = Vec :: new ( ) ; // a stack
412409 let c = graph. node_count ( ) ;
413- let mut predecessors = HashMap :: < G :: NodeId , Vec < G :: NodeId > > :: with_capacity ( c) ;
414- let mut sigma = HashMap :: < G :: NodeId , f64 > :: with_capacity ( c) ;
415- let mut distance = HashMap :: < G :: NodeId , i64 > :: with_capacity ( c) ;
410+ let max_index = graph. node_bound ( ) ;
411+ let mut verts_sorted_by_distance: Vec < G :: NodeId > = Vec :: with_capacity ( c) ; // a stack
412+ let mut predecessors: Vec < Vec < usize > > = vec ! [ Vec :: new( ) ; max_index] ;
413+ let mut sigma: Vec < f64 > = vec ! [ 0. ; max_index] ;
414+ let mut distance: Vec < Option < usize > > = vec ! [ None ; max_index] ;
416415 #[ allow( non_snake_case) ]
417416 let mut Q : VecDeque < G :: NodeId > = VecDeque :: with_capacity ( c) ;
418-
419- for node in graph. node_identifiers ( ) {
420- predecessors. insert ( node, Vec :: new ( ) ) ;
421- sigma. insert ( node, 0.0 ) ;
422- distance. insert ( node, -1 ) ;
423- }
424- sigma. insert ( * node_s, 1.0 ) ;
425- distance. insert ( * node_s, 0 ) ;
417+ let node_s_index = graph. to_index ( * node_s) ;
418+ sigma[ node_s_index] = 1.0 ;
419+ distance[ node_s_index] = Some ( 0 ) ;
426420 Q . push_back ( * node_s) ;
427421 while let Some ( v) = Q . pop_front ( ) {
428422 verts_sorted_by_distance. push ( v) ;
429- let distance_v = distance[ & v] ;
423+ let v_idx = graph. to_index ( v) ;
424+ let distance_v = distance[ v_idx] . unwrap ( ) ;
430425 for w in graph. neighbors ( v) {
431- if distance[ & w] < 0 {
426+ let w_idx = graph. to_index ( w) ;
427+ if distance[ w_idx] . is_none ( ) {
432428 Q . push_back ( w) ;
433- distance. insert ( w , distance_v + 1 ) ;
429+ distance[ w_idx ] = Some ( distance_v + 1 ) ;
434430 }
435- if distance[ & w] == distance_v + 1 {
436- sigma. insert ( w, sigma[ & w] + sigma[ & v] ) ;
437- let e_p = predecessors. get_mut ( & w) . unwrap ( ) ;
438- e_p. push ( v) ;
431+ if distance[ w_idx] == Some ( distance_v + 1 ) {
432+ sigma[ w_idx] += sigma[ v_idx] ;
433+ predecessors[ w_idx] . push ( v_idx) ;
439434 }
440435 }
441436 }
@@ -450,13 +445,13 @@ where
450445struct ShortestPathDataWithEdges < G >
451446where
452447 G : GraphBase ,
453- G :: NodeId : Eq + Hash ,
454- G :: EdgeId : Eq + Hash ,
448+ G :: NodeId : Eq ,
449+ G :: EdgeId : Eq ,
455450{
456451 verts_sorted_by_distance : Vec < G :: NodeId > ,
457- predecessors : HashMap < G :: NodeId , Vec < G :: NodeId > > ,
458- predecessor_edges : HashMap < G :: NodeId , Vec < G :: EdgeId > > ,
459- sigma : HashMap < G :: NodeId , f64 > ,
452+ predecessors : Vec < Vec < G :: NodeId > > ,
453+ predecessor_edges : Vec < Vec < G :: EdgeId > > ,
454+ sigma : Vec < f64 > ,
460455}
461456
462457fn shortest_path_for_edge_centrality < G > (
@@ -470,41 +465,37 @@ where
470465 + NodeCount
471466 + GraphBase
472467 + IntoEdges ,
473- G :: NodeId : Eq + Hash ,
474- G :: EdgeId : Eq + Hash ,
468+ G :: NodeId : Eq ,
469+ G :: EdgeId : Eq ,
475470{
476471 let mut verts_sorted_by_distance: Vec < G :: NodeId > = Vec :: new ( ) ; // a stack
477- let c = graph. node_count ( ) ;
478- let mut predecessors = HashMap :: < G :: NodeId , Vec < G :: NodeId > > :: with_capacity ( c ) ;
479- let mut predecessor_edges = HashMap :: < G :: NodeId , Vec < G :: EdgeId > > :: with_capacity ( c ) ;
480- let mut sigma = HashMap :: < G :: NodeId , f64 > :: with_capacity ( c ) ;
481- let mut distance = HashMap :: < G :: NodeId , i64 > :: with_capacity ( c ) ;
472+ let c = graph. node_bound ( ) ;
473+ let mut predecessors = vec ! [ Vec :: new ( ) ; c ] ;
474+ let mut predecessor_edges = vec ! [ Vec :: new ( ) ; c ] ;
475+ let mut sigma = vec ! [ 0.0 ; c ] ;
476+ let mut distance: Vec < Option < usize > > = vec ! [ None ; c ] ;
482477 #[ allow( non_snake_case) ]
483478 let mut Q : VecDeque < G :: NodeId > = VecDeque :: with_capacity ( c) ;
484479
485- for node in graph. node_identifiers ( ) {
486- predecessors. insert ( node, Vec :: new ( ) ) ;
487- predecessor_edges. insert ( node, Vec :: new ( ) ) ;
488- sigma. insert ( node, 0.0 ) ;
489- distance. insert ( node, -1 ) ;
490- }
491- sigma. insert ( * node_s, 1.0 ) ;
492- distance. insert ( * node_s, 0 ) ;
480+ sigma[ graph. to_index ( * node_s) ] = 1. ;
481+ distance[ graph. to_index ( * node_s) ] = Some ( 0 ) ;
493482 Q . push_back ( * node_s) ;
494483 while let Some ( v) = Q . pop_front ( ) {
495484 verts_sorted_by_distance. push ( v) ;
496- let distance_v = distance[ & v] ;
485+ let v_index = graph. to_index ( v) ;
486+ let distance_v = distance[ v_index] . unwrap ( ) ;
497487 for edge in graph. edges ( v) {
498488 let w = edge. target ( ) ;
499- if distance[ & w] < 0 {
489+ let w_index = graph. to_index ( w) ;
490+ if distance[ w_index] . is_none ( ) {
500491 Q . push_back ( w) ;
501- distance. insert ( w , distance_v + 1 ) ;
492+ distance[ w_index ] = Some ( distance_v + 1 ) ;
502493 }
503- if distance[ & w ] == distance_v + 1 {
504- sigma. insert ( w , sigma [ & w ] + sigma[ & v ] ) ;
505- let e_p = predecessors. get_mut ( & w ) . unwrap ( ) ;
494+ if distance[ w_index ] == Some ( distance_v + 1 ) {
495+ sigma[ w_index ] += sigma[ v_index ] ;
496+ let e_p = predecessors. get_mut ( w_index ) . unwrap ( ) ;
506497 e_p. push ( v) ;
507- predecessor_edges. get_mut ( & w ) . unwrap ( ) . push ( edge. id ( ) ) ;
498+ predecessor_edges. get_mut ( w_index ) . unwrap ( ) . push ( edge. id ( ) ) ;
508499 }
509500 }
510501 }
@@ -641,6 +632,66 @@ mod test_edge_betweenness_centrality {
641632 let expected_values = vec ! [ Some ( 3.0 ) , None , Some ( 3.0 ) , Some ( 4.0 ) ] ;
642633 assert_eq ! ( result, expected_values) ;
643634 }
635+
636+ #[ test]
637+ fn test_stable_graph_with_removed_nodes_and_edges ( ) {
638+ let mut graph: StableGraph < ( ) , ( ) , Undirected > = StableGraph :: default ( ) ;
639+ let n0 = graph. add_node ( ( ) ) ;
640+ let d0 = graph. add_node ( ( ) ) ;
641+ let n1 = graph. add_node ( ( ) ) ;
642+ let d1 = graph. add_node ( ( ) ) ;
643+ let n2 = graph. add_node ( ( ) ) ;
644+ let d2 = graph. add_node ( ( ) ) ;
645+ let n3 = graph. add_node ( ( ) ) ;
646+
647+ graph. remove_node ( d0) ;
648+ graph. remove_node ( d1) ;
649+ graph. remove_node ( d2) ;
650+
651+ graph. add_edge ( n0, n1, ( ) ) ;
652+ graph. add_edge ( n1, n2, ( ) ) ;
653+ graph. add_edge ( n2, n3, ( ) ) ;
654+ graph. add_edge ( n3, n0, ( ) ) ;
655+
656+ graph. remove_edge ( edge_index ( 1 ) ) ;
657+ let result = edge_betweenness_centrality ( & graph, false , 50 ) ;
658+ let expected_values = vec ! [ Some ( 3.0 ) , None , Some ( 3.0 ) , Some ( 4.0 ) ] ;
659+ assert_eq ! ( result, expected_values) ;
660+ }
661+ }
662+
663+ #[ cfg( test) ]
664+ mod test_betweenness_centrality {
665+ use crate :: centrality:: betweenness_centrality;
666+ use petgraph:: Undirected ;
667+ use petgraph:: graph:: edge_index;
668+ use petgraph:: prelude:: StableGraph ;
669+
670+ #[ test]
671+ fn test_stable_graph_with_removed_nodes_and_edges ( ) {
672+ let mut graph: StableGraph < ( ) , ( ) , Undirected > = StableGraph :: default ( ) ;
673+ let n0 = graph. add_node ( ( ) ) ;
674+ let d0 = graph. add_node ( ( ) ) ;
675+ let n1 = graph. add_node ( ( ) ) ;
676+ let d1 = graph. add_node ( ( ) ) ;
677+ let n2 = graph. add_node ( ( ) ) ;
678+ let d2 = graph. add_node ( ( ) ) ;
679+ let n3 = graph. add_node ( ( ) ) ;
680+
681+ graph. remove_node ( d0) ;
682+ graph. remove_node ( d1) ;
683+ graph. remove_node ( d2) ;
684+
685+ graph. add_edge ( n0, n1, ( ) ) ;
686+ graph. add_edge ( n1, n2, ( ) ) ;
687+ graph. add_edge ( n2, n3, ( ) ) ;
688+ graph. add_edge ( n3, n0, ( ) ) ;
689+ graph. remove_edge ( edge_index ( 1 ) ) ;
690+
691+ let result = betweenness_centrality ( & graph, false , false , 50 ) ;
692+ let expected_values = vec ! [ Some ( 2.0 ) , None , Some ( 0.0 ) , None , Some ( 0.0 ) , None , Some ( 2.0 ) ] ;
693+ assert_eq ! ( result, expected_values) ;
694+ }
644695}
645696
646697/// Compute the eigenvector centrality of a graph
@@ -694,7 +745,7 @@ pub fn eigenvector_centrality<G, F, E>(
694745) -> Result < Option < Vec < f64 > > , E >
695746where
696747 G : NodeIndexable + IntoNodeIdentifiers + IntoNeighbors + IntoEdges + NodeCount ,
697- G :: NodeId : Eq + std :: hash :: Hash ,
748+ G :: NodeId : Eq ,
698749 F : FnMut ( G :: EdgeRef ) -> Result < f64 , E > ,
699750{
700751 let tol: f64 = tol. unwrap_or ( 1e-6 ) ;
@@ -790,7 +841,7 @@ pub fn katz_centrality<G, F, E>(
790841) -> Result < Option < Vec < f64 > > , E >
791842where
792843 G : NodeIndexable + IntoNodeIdentifiers + IntoNeighbors + IntoEdges + NodeCount ,
793- G :: NodeId : Eq + std :: hash :: Hash ,
844+ G :: NodeId : Eq ,
794845 F : FnMut ( G :: EdgeRef ) -> Result < f64 , E > ,
795846{
796847 let alpha: f64 = alpha. unwrap_or ( 0.1 ) ;
0 commit comments