@@ -56,7 +56,6 @@ pub fn run(graph: &GraphInput, config: &RunConfig) -> Result<RunOutcome, HitLeid
5656 & mut partition_state,
5757 graph,
5858 config. resolution ,
59- config. refinement_gamma ,
6059 config. mode ,
6160 config. max_iterations ,
6261 ) ;
@@ -65,9 +64,10 @@ pub fn run(graph: &GraphInput, config: &RunConfig) -> Result<RunOutcome, HitLeid
6564 // across runs with identical partition structure.
6665 canonicalize_community_ids_in_place ( & mut partition_state. node_to_comm ) ;
6766
67+ let ds_id = graph. dataset_id . as_deref ( ) . unwrap_or ( "" ) ;
6868 let execution = RunExecution {
69- run_id : format ! ( "run:{}" , graph . dataset_id ) ,
70- dataset_id : graph . dataset_id . clone ( ) ,
69+ run_id : format ! ( "run:{}" , ds_id ) ,
70+ dataset_id : ds_id . to_string ( ) ,
7171 config_id : "default" . to_string ( ) ,
7272 started_at,
7373 completed_at : Some (
@@ -78,15 +78,7 @@ pub fn run(graph: &GraphInput, config: &RunConfig) -> Result<RunOutcome, HitLeid
7878 ) ,
7979 status : RunStatus :: Succeeded ,
8080 backend : BackendType :: PureRust ,
81- graph_source_resolved : match resolution_meta. source_resolved {
82- crate :: core:: backend:: GraphSource :: File => crate :: core:: types:: GraphSourceType :: File ,
83- crate :: core:: backend:: GraphSource :: Neo4jSnapshot => {
84- crate :: core:: types:: GraphSourceType :: Neo4jSnapshot
85- }
86- crate :: core:: backend:: GraphSource :: LiveNeo4j => {
87- crate :: core:: types:: GraphSourceType :: Neo4jSnapshot
88- } // Fallback
89- } ,
81+ graph_source_resolved : resolution_meta. source_resolved ,
9082 fallback_reason : resolution_meta. fallback_reason ,
9183 } ;
9284
@@ -119,7 +111,7 @@ pub fn run(graph: &GraphInput, config: &RunConfig) -> Result<RunOutcome, HitLeid
119111}
120112
121113/// Compute standard modularity: Q = (1/2m) * sum_ij [ A_ij - k_i*k_j/(2m) ] * delta(c_i, c_j)
122- fn compute_modularity ( graph : & GraphInput , node_to_community : & [ usize ] ) -> f64 {
114+ pub ( crate ) fn compute_modularity ( graph : & GraphInput , node_to_community : & [ usize ] ) -> f64 {
123115 let n = graph. node_count ;
124116
125117 // Compute node degrees from edge list
@@ -165,11 +157,10 @@ fn compute_modularity(graph: &GraphInput, node_to_community: &[usize]) -> f64 {
165157/// subcommunities (connected components), aggregate based on subcommunities, and repeat.
166158/// The refinement step prevents mega-communities by ensuring the coarsened graph
167159/// represents subcommunity-level structure, following the standard Leiden approach.
168- fn multilevel_leiden (
160+ pub ( crate ) fn multilevel_leiden (
169161 state : & mut PartitionState ,
170162 graph : & GraphInput ,
171163 gamma : f64 ,
172- refinement_gamma : f64 ,
173164 mode : crate :: core:: config:: RunMode ,
174165 max_levels : usize ,
175166) -> ( usize , Vec < Vec < usize > > ) {
@@ -197,12 +188,10 @@ fn multilevel_leiden(
197188
198189 // Refinement: within each community, merge singletons into subcommunities.
199190 // Uses the SAME resolution as movement for the quality function.
200- // The refinement_gamma (0.05) is only for the connectivity criterion.
201191 let mut subcommunities = refine_singleton_merge (
202192 & state. supergraphs [ 0 ] ,
203193 & state. community_mapping_per_level [ 0 ] ,
204194 gamma,
205- refinement_gamma,
206195 ) ;
207196
208197 // The community assignment (for final output) comes from movement
@@ -279,7 +268,6 @@ fn multilevel_leiden(
279268 & state. supergraphs [ 0 ] ,
280269 & state. node_to_comm ,
281270 gamma,
282- refinement_gamma,
283271 ) ;
284272 let new_subcomm_count = count_unique ( & subcommunities) ;
285273
@@ -360,7 +348,7 @@ fn count_unique(v: &[usize]) -> usize {
360348
361349/// Deterministically rewrite community labels to contiguous IDs [0..k-1]
362350/// by scanning nodes in index order and assigning first-seen labels.
363- fn canonicalize_community_ids_in_place ( node_to_community : & mut [ usize ] ) {
351+ pub ( crate ) fn canonicalize_community_ids_in_place ( node_to_community : & mut [ usize ] ) {
364352 let mut remap: HashMap < usize , usize > = HashMap :: new ( ) ;
365353 let mut next_id = 0usize ;
366354
@@ -455,7 +443,6 @@ fn refine_singleton_merge(
455443 graph : & crate :: core:: graph:: in_memory:: InMemoryGraph ,
456444 node_to_community : & [ usize ] ,
457445 gamma : f64 ,
458- _refinement_gamma : f64 ,
459446) -> Vec < usize > {
460447 let n = graph. node_count ;
461448 if n == 0 {
@@ -1809,7 +1796,7 @@ mod tests {
18091796 /// Helper: build a GraphInput from an edge list with unit weights.
18101797 fn graph ( node_count : usize , edges : & [ ( usize , usize ) ] ) -> GraphInput {
18111798 GraphInput {
1812- dataset_id : "test" . to_string ( ) ,
1799+ dataset_id : Some ( "test" . to_string ( ) ) ,
18131800 node_count,
18141801 edges : edges. iter ( ) . map ( |& ( u, v) | ( u, v, Some ( 1.0 ) ) ) . collect ( ) ,
18151802 }
@@ -1818,7 +1805,7 @@ mod tests {
18181805 /// Helper: build a GraphInput with explicit weights.
18191806 fn weighted_graph ( node_count : usize , edges : & [ ( usize , usize , f64 ) ] ) -> GraphInput {
18201807 GraphInput {
1821- dataset_id : "test" . to_string ( ) ,
1808+ dataset_id : Some ( "test" . to_string ( ) ) ,
18221809 node_count,
18231810 edges : edges. iter ( ) . map ( |& ( u, v, w) | ( u, v, Some ( w) ) ) . collect ( ) ,
18241811 }
@@ -1905,7 +1892,7 @@ mod tests {
19051892 #[ test]
19061893 fn test_should_skip_aggregation_when_no_delta_and_no_refinement ( ) {
19071894 let delta = GraphInput {
1908- dataset_id : "test" . to_string ( ) ,
1895+ dataset_id : Some ( "test" . to_string ( ) ) ,
19091896 node_count : 4 ,
19101897 edges : vec ! [ ] ,
19111898 } ;
@@ -1916,15 +1903,15 @@ mod tests {
19161903 #[ test]
19171904 fn test_should_not_skip_aggregation_when_delta_or_refinement_exists ( ) {
19181905 let delta_non_empty = GraphInput {
1919- dataset_id : "test" . to_string ( ) ,
1906+ dataset_id : Some ( "test" . to_string ( ) ) ,
19201907 node_count : 4 ,
19211908 edges : vec ! [ ( 0 , 1 , Some ( 1.0 ) ) ] ,
19221909 } ;
19231910 let refined_empty = bitvec ! [ 0 , 0 , 0 , 0 ] ;
19241911 assert ! ( !should_skip_aggregation( & delta_non_empty, & refined_empty) ) ;
19251912
19261913 let delta_empty = GraphInput {
1927- dataset_id : "test" . to_string ( ) ,
1914+ dataset_id : Some ( "test" . to_string ( ) ) ,
19281915 node_count : 4 ,
19291916 edges : vec ! [ ] ,
19301917 } ;
@@ -2138,7 +2125,7 @@ mod tests {
21382125 let inmem = InMemoryGraph :: from ( & g) ;
21392126
21402127 let delta = GraphInput {
2141- dataset_id : "test" . to_string ( ) ,
2128+ dataset_id : Some ( "test" . to_string ( ) ) ,
21422129 node_count : 3 ,
21432130 edges : vec ! [ ] ,
21442131 } ;
@@ -2243,7 +2230,7 @@ mod tests {
22432230 fn test_modularity_empty_graph ( ) {
22442231 // No edges => Q = 0
22452232 let g = GraphInput {
2246- dataset_id : "test" . to_string ( ) ,
2233+ dataset_id : Some ( "test" . to_string ( ) ) ,
22472234 node_count : 3 ,
22482235 edges : vec ! [ ] ,
22492236 } ;
@@ -2373,7 +2360,7 @@ mod tests {
23732360 ) ;
23742361 let mut state = PartitionState :: identity( 6 ) ;
23752362
2376- let ( iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , 0.05 , mode, 10 ) ;
2363+ let ( iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , mode, 10 ) ;
23772364
23782365 assert!( iters > 0 , "should take at least 1 iteration" ) ;
23792366 assert!(
@@ -2400,13 +2387,13 @@ mod tests {
24002387 dual_mode_test ! ( test_multilevel_leiden_single_node, |mode| {
24012388 // Single node graph, no edges.
24022389 let g = GraphInput {
2403- dataset_id: "test" . to_string( ) ,
2390+ dataset_id: Some ( "test" . to_string( ) ) ,
24042391 node_count: 1 ,
24052392 edges: vec![ ] ,
24062393 } ;
24072394 let mut state = PartitionState :: identity( 1 ) ;
24082395
2409- let ( iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , 0.05 , mode, 10 ) ;
2396+ let ( iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , mode, 10 ) ;
24102397
24112398 assert_eq!( state. node_to_comm, vec![ 0 ] ) ;
24122399 assert!( iters >= 1 , "should still complete at least 1 iteration" ) ;
@@ -2416,13 +2403,13 @@ mod tests {
24162403 dual_mode_test ! ( test_multilevel_leiden_disconnected_components, |mode| {
24172404 // 4 disconnected nodes: each should be its own community.
24182405 let g = GraphInput {
2419- dataset_id: "test" . to_string( ) ,
2406+ dataset_id: Some ( "test" . to_string( ) ) ,
24202407 node_count: 4 ,
24212408 edges: vec![ ] ,
24222409 } ;
24232410 let mut state = PartitionState :: identity( 4 ) ;
24242411
2425- let ( _iters, _hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , 0.05 , mode, 10 ) ;
2412+ let ( _iters, _hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , mode, 10 ) ;
24262413
24272414 let comm_count = count_unique( & state. node_to_comm) ;
24282415 assert_eq!(
@@ -2437,7 +2424,7 @@ mod tests {
24372424 let g = graph( 6 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 0 , 2 ) , ( 3 , 4 ) , ( 4 , 5 ) , ( 3 , 5 ) , ( 2 , 3 ) ] ) ;
24382425 let mut state = PartitionState :: identity( 6 ) ;
24392426
2440- let ( _iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , 0.05 , mode, 10 ) ;
2427+ let ( _iters, hierarchy) = multilevel_leiden( & mut state, & g, 1.0 , mode, 10 ) ;
24412428
24422429 // Each level should have exactly node_count entries
24432430 for ( i, level) in hierarchy. iter( ) . enumerate( ) {
@@ -2976,7 +2963,7 @@ mod tests {
29762963 refined. set ( 2 , true ) ; // Only node 2 was refined
29772964
29782965 let delta = GraphInput {
2979- dataset_id : "test" . to_string ( ) ,
2966+ dataset_id : Some ( "test" . to_string ( ) ) ,
29802967 node_count : 3 ,
29812968 edges : vec ! [ ] ,
29822969 } ;
@@ -3124,7 +3111,7 @@ mod tests {
31243111 ) ;
31253112 let mut state = PartitionState :: identity( 6 ) ;
31263113 state. supergraphs. push( InMemoryGraph :: from( & GraphInput {
3127- dataset_id: "test" . to_string( ) ,
3114+ dataset_id: Some ( "test" . to_string( ) ) ,
31283115 node_count: 6 ,
31293116 edges: vec![ ] ,
31303117 } ) ) ;
@@ -3158,7 +3145,7 @@ mod tests {
31583145 ) ;
31593146 let mut state = PartitionState :: identity( 6 ) ;
31603147 state. supergraphs. push( InMemoryGraph :: from( & GraphInput {
3161- dataset_id: "test" . to_string( ) ,
3148+ dataset_id: Some ( "test" . to_string( ) ) ,
31623149 node_count: 6 ,
31633150 edges: vec![ ] ,
31643151 } ) ) ;
@@ -3190,7 +3177,7 @@ mod tests {
31903177 ) ;
31913178 let mut state = PartitionState :: identity( 4 ) ;
31923179 state. supergraphs. push( InMemoryGraph :: from( & GraphInput {
3193- dataset_id: "test" . to_string( ) ,
3180+ dataset_id: Some ( "test" . to_string( ) ) ,
31943181 node_count: 4 ,
31953182 edges: vec![ ] ,
31963183 } ) ) ;
@@ -3233,7 +3220,7 @@ mod tests {
32333220 ) ;
32343221 let mut state = PartitionState :: identity( 8 ) ;
32353222 state. supergraphs. push( InMemoryGraph :: from( & GraphInput {
3236- dataset_id: "test" . to_string( ) ,
3223+ dataset_id: Some ( "test" . to_string( ) ) ,
32373224 node_count: 8 ,
32383225 edges: vec![ ] ,
32393226 } ) ) ;
@@ -3343,7 +3330,7 @@ mod tests {
33433330 fn test_connected_components_single_node ( ) {
33443331 // Single node with no edges: 1 component of size 1.
33453332 let g = GraphInput {
3346- dataset_id : "test" . to_string ( ) ,
3333+ dataset_id : Some ( "test" . to_string ( ) ) ,
33473334 node_count : 1 ,
33483335 edges : vec ! [ ] ,
33493336 } ;
0 commit comments