@@ -56,6 +56,7 @@ impl CentralityMetrics {
5656 /// Calculate betweenness centrality
5757 fn calculate_betweenness ( & self , graph : & CodeGraph ) -> HashMap < String , f64 > {
5858 debug ! ( "Calculating betweenness centrality" ) ;
59+ println ! ( "[CENTRALITY] Betweenness: node_count = {}" , graph. graph. node_count( ) ) ;
5960
6061 let mut betweenness = HashMap :: new ( ) ;
6162 let node_count = graph. graph . node_count ( ) ;
@@ -77,20 +78,50 @@ impl CentralityMetrics {
7778 }
7879 }
7980
80- // Simple betweenness centrality calculation
81- // For each pair of nodes, find shortest paths and count
82- for source in graph. graph . node_indices ( ) {
83- let paths = petgraph:: algo:: dijkstra ( & graph. graph , source, None , |_| 1.0 ) ;
81+ // For large graphs, use sampling to avoid O(n³) complexity
82+ const MAX_FULL_CALC_NODES : usize = 100 ;
83+ const SAMPLE_SIZE : usize = 50 ;
84+
85+ if node_count > MAX_FULL_CALC_NODES {
86+ println ! ( "[CENTRALITY] Large graph detected ({} nodes), using sampling approach" , node_count) ;
87+
88+ // Sample a subset of source nodes for approximation
89+ let node_indices: Vec < _ > = graph. graph . node_indices ( ) . collect ( ) ;
90+ let sample_size = SAMPLE_SIZE . min ( node_count) ;
91+ let step = node_count / sample_size;
8492
85- for target in graph. graph . node_indices ( ) {
86- if source != target {
87- // Count paths through intermediate nodes
88- for intermediate in graph. graph . node_indices ( ) {
89- if intermediate != source && intermediate != target {
90- // Simplified: increment if on a path
91- if paths. contains_key ( & intermediate) && paths. contains_key ( & target) {
92- if let Some ( node) = graph. graph . node_weight ( intermediate) {
93- * betweenness. entry ( node. id . clone ( ) ) . or_insert ( 0.0 ) += 1.0 ;
93+ for ( i, & source) in node_indices. iter ( ) . step_by ( step. max ( 1 ) ) . enumerate ( ) {
94+ if i >= sample_size {
95+ break ;
96+ }
97+
98+ // Use petgraph's built-in betweenness calculation for this source
99+ let paths = petgraph:: algo:: dijkstra ( & graph. graph , source, None , |_| 1.0 ) ;
100+
101+ // Just count nodes on shortest paths (simplified)
102+ for ( node_idx, _) in paths. iter ( ) {
103+ if let Some ( node) = graph. graph . node_weight ( * node_idx) {
104+ * betweenness. entry ( node. id . clone ( ) ) . or_insert ( 0.0 ) += 1.0 ;
105+ }
106+ }
107+ }
108+ } else {
109+ println ! ( "[CENTRALITY] Small graph ({} nodes), using full calculation" , node_count) ;
110+
111+ // Original O(n³) algorithm for small graphs
112+ for source in graph. graph . node_indices ( ) {
113+ let paths = petgraph:: algo:: dijkstra ( & graph. graph , source, None , |_| 1.0 ) ;
114+
115+ for target in graph. graph . node_indices ( ) {
116+ if source != target {
117+ // Count paths through intermediate nodes
118+ for intermediate in graph. graph . node_indices ( ) {
119+ if intermediate != source && intermediate != target {
120+ // Simplified: increment if on a path
121+ if paths. contains_key ( & intermediate) && paths. contains_key ( & target) {
122+ if let Some ( node) = graph. graph . node_weight ( intermediate) {
123+ * betweenness. entry ( node. id . clone ( ) ) . or_insert ( 0.0 ) += 1.0 ;
124+ }
94125 }
95126 }
96127 }
@@ -182,7 +213,7 @@ impl CentralityMetrics {
182213 }
183214
184215 /// Calculate eigenvector centrality
185- fn calculate_eigenvector ( & self , graph : & CodeGraph ) -> HashMap < String , f64 > {
216+ fn calculate_eigenvector_centrality ( & self , graph : & CodeGraph ) -> HashMap < String , f64 > {
186217 debug ! ( "Calculating eigenvector centrality" ) ;
187218
188219 let node_count = graph. graph . node_count ( ) ;
@@ -407,14 +438,21 @@ impl CentralityMetrics {
407438
408439impl Metric for CentralityMetrics {
409440 fn calculate ( & self , graph : & CodeGraph ) -> Result < MetricResults > {
441+ println ! ( "[CENTRALITY] Starting centrality metrics calculation" ) ;
410442 let mut results = MetricResults :: new ( "centrality" . to_string ( ) ) ;
411443
412444 // Calculate all centrality metrics
445+ println ! ( "[CENTRALITY] Calculating degree centrality..." ) ;
413446 let degree_centrality = self . calculate_degree ( graph) ;
447+ println ! ( "[CENTRALITY] Degree centrality done. Calculating betweenness..." ) ;
414448 let betweenness = self . calculate_betweenness ( graph) ;
449+ println ! ( "[CENTRALITY] Betweenness done. Calculating closeness..." ) ;
415450 let closeness = self . calculate_closeness ( graph) ;
451+ println ! ( "[CENTRALITY] Closeness done. Calculating k-core..." ) ;
416452 let k_core = self . calculate_k_core ( graph) ;
453+ println ! ( "[CENTRALITY] K-core done. Calculating clustering..." ) ;
417454 let clustering = self . calculate_clustering ( graph) ;
455+ println ! ( "[CENTRALITY] Clustering done." ) ;
418456
419457 // Store degree centrality
420458 for ( node_id, ( in_degree, out_degree) ) in degree_centrality {
@@ -469,7 +507,7 @@ impl Metric for CentralityMetrics {
469507
470508 // Calculate eigenvector if enabled
471509 if self . calculate_eigenvector {
472- let eigenvector = self . calculate_eigenvector ( graph) ;
510+ let eigenvector = self . calculate_eigenvector_centrality ( graph) ;
473511 results. add_value ( "eigenvector_map" . to_string ( ) , MetricValue :: Map ( eigenvector. clone ( ) ) ) ;
474512 for ( node_id, value) in eigenvector {
475513 results. add_value (
0 commit comments