5252
5353LG_JIT_STRING (
5454typedef struct {
55- uint8_t registers [( 1 << 10 ) ];
55+ uint8_t registers [HLL_REGISTERS ];
5656} HLL ;
5757, HLL_jit )
5858
@@ -156,7 +156,7 @@ LG_JIT_STRING(
156156 if (diff ) {
157157 uint32_t i ;
158158
159- double alpha_mm = 0.7213 / (1.0 + 1.079 / (double )(1 << 10 )) ;
159+ double alpha_mm = 0.7213 / (1.0 + 1.079 / (double )(HLL_REGISTERS )) ;
160160
161161 alpha_mm *= ((double )(HLL_REGISTERS ) * (double )(HLL_REGISTERS )) ;
162162
@@ -241,7 +241,7 @@ GrB_free(&flat_weight); \
241241GrB_free(&delta_vec); \
242242GrB_free(&desc); \
243243GrB_free(&init_hlls); \
244- GrB_free(&shallow_second ); \
244+ GrB_free(&hll_second ); \
245245GrB_free(&merge_hll_biop); \
246246GrB_free(&merge_hll); \
247247GrB_free(&merge_second); \
@@ -271,26 +271,51 @@ int LAGr_HarmonicCentrality(
271271 const GrB_Vector node_weights , // participating nodes and their weights
272272 char * msg
273273) {
274+ // compact G->A: without the nodes with no specified weights
274275 GrB_Matrix _A = NULL ;
275- GxB_Container score_cont = NULL ;
276+
276277 GrB_Index nrows = 0 ;
277278 GrB_Index nvals = 0 ;
278279
280+ // HC score of the nodes
281+ GxB_Container score_cont = NULL ;
282+ GrB_Vector flat_scores = NULL ;
283+
284+ // HyperLogLog GraphBLAS type
279285 GrB_Type hll_t = NULL ;
286+
287+ // Vectors holding the hll sets. After step i, holds the ball of radius i
288+ // around each node
280289 GrB_Vector new_sets = NULL ;
281290 GrB_Vector old_sets = NULL ;
282291 GxB_Container old_cont = NULL ;
283- GrB_Vector flat_scores = NULL ;
292+
293+ // compact wieghts
284294 GrB_Vector flat_weight = NULL ;
295+
296+ // |new_sets| - |old_sets|
285297 GrB_Vector delta_vec = NULL ;
286298
287299 GrB_Descriptor desc = NULL ;
300+
301+ // Operators
302+ // Add the given node with (weight) hashes into its HLL set
288303 GrB_IndexUnaryOp init_hlls = NULL ;
304+
305+ // Query set cardinality
289306 GrB_UnaryOp count_hll = NULL ;
290- GrB_BinaryOp shallow_second = NULL ;
307+
308+ // z = y
309+ GrB_BinaryOp hll_second = NULL ;
310+
311+ // z = x union y
291312 GrB_BinaryOp merge_hll_biop = NULL ;
292313 GrB_Monoid merge_hll = NULL ;
314+
315+ // [merge_hll.hll_second]
293316 GrB_Semiring merge_second = NULL ;
317+
318+ // z = |y| - |x|
294319 GrB_BinaryOp delta_hll = NULL ;
295320
296321 LG_ASSERT (G != NULL , GrB_NULL_POINTER );
@@ -361,33 +386,26 @@ int LAGr_HarmonicCentrality(
361386 GRB_TRY (GxB_Vector_extractTuples_Vector (
362387 NULL , flat_weight , node_weights , NULL )) ;
363388
364- // count op
365389 GRB_TRY (GxB_UnaryOp_new (& count_hll , (GxB_unary_function ) lg_hll_count ,
366390 GrB_FP64 , hll_t , "lg_hll_count" , LG_HLL_COUNT )) ;
367391
368- // init op: weight (INT64) at row index i → HLL seeded with 'weight' hashes
369- GRB_TRY (GrB_IndexUnaryOp_new (
392+ GRB_TRY (GrB_IndexUnaryOp_new (
370393 & init_hlls , (GxB_index_unary_function )lg_hll_init , hll_t ,
371394 GrB_INT64 , GrB_BOOL )) ;
372395
373- // merge binary op (HLL, HLL) -> HLL in-place: z == x required
374396 GRB_TRY (GxB_BinaryOp_new (
375397 & merge_hll_biop , (GxB_binary_function )lg_hll_merge ,
376398 hll_t , hll_t , hll_t , "lg_hll_merge" , LG_HLL_MERGE_STR )) ;
377399
378- // second op
379400 GRB_TRY (GxB_BinaryOp_new (
380- & shallow_second , (GxB_binary_function )lg_hll_second ,
401+ & hll_second , (GxB_binary_function )lg_hll_second ,
381402 hll_t , GrB_BOOL , hll_t , "lg_hll_second" , LG_HLL_SECOND_STR )) ;
382403
383- // merge monoid - identity is an empty (all-zero) HLL sketch
384404 HLL hll_zero = {0 };
385405 GRB_TRY (GrB_Monoid_new_UDT (& merge_hll , merge_hll_biop , & hll_zero )) ;
386406
387- // semiring: add = merge monoid, multiply = copy (pass-through second operand)
388- GRB_TRY (GrB_Semiring_new (& merge_second , merge_hll , shallow_second )) ;
407+ GRB_TRY (GrB_Semiring_new (& merge_second , merge_hll , hll_second )) ;
389408
390- // delta op: (HLL_old, HLL_new) → FP64 cardinality change
391409 GRB_TRY (GxB_BinaryOp_new (
392410 & delta_hll , (GxB_binary_function )lg_hll_delta ,
393411 GrB_FP64 , hll_t , hll_t , "lg_hll_delta" , LG_HLL_DELTA_STR )) ;
@@ -503,16 +521,19 @@ int LAGr_HarmonicCentrality(
503521 GrB_free(&score); \
504522 GrB_free(&desc); \
505523 GrB_free(&node_compact); \
524+ GrB_free(&score_compact); \
525+ GrB_free(&reach_compact); \
506526 LAGraph_Delete(&G_compact, NULL);
507527
508528#undef LG_FREE_ALL
509529#define LG_FREE_ALL \
510530 LG_FREE_WORK ; \
511- GrB_free(scores) ;
531+ GrB_free(scores) ; \
532+ GrB_free(reachable_nodes) ;
512533
513534// This is an exact (but much slower) calculation of harmonic centrality
514535#if LG_SUITESPARSE_GRAPHBLAS_V10
515- int LAGr_HarmonicCentrality_exact (
536+ int LAGr_HarmonicCentrality_exact (
516537 // outputs:
517538 GrB_Vector * scores , // FP64 scores by original node ID
518539 GrB_Vector * reachable_nodes , // [optional] estimate the number of reach-
@@ -523,21 +544,29 @@ int LAGr_HarmonicCentrality_exact(
523544 const GrB_Vector node_weights , // participating nodes and their weights
524545 char * msg
525546) {
547+ // compact G->A
526548 GrB_Matrix _A = NULL ;
549+
550+ // Dimensions of node_weights vector
527551 GrB_Index nrows = 0 ;
528552 GrB_Index nvals = 0 ;
529553
554+ // BFS result
530555 GrB_Vector level = NULL ;
556+
557+ // compacted vectors
531558 GrB_Vector flat_weight = NULL ;
532559 GrB_Vector node_compact = NULL ;
560+ GrB_Vector score_compact = NULL ;
561+ GrB_Vector reach_compact = NULL ;
562+
533563 GxB_Iterator it = NULL ;
534564 GrB_Scalar score = NULL ;
565+ GrB_Index n_reachable = 0 ;
535566
536567 GrB_Descriptor desc = NULL ;
537568 LAGraph_Graph G_compact = NULL ;
538569
539- // TODO:
540- LG_ASSERT (reachable_nodes == NULL , GrB_NOT_IMPLEMENTED );
541570 LG_ASSERT (G != NULL , GrB_NULL_POINTER );
542571 LG_ASSERT (G -> A != NULL , GrB_NULL_POINTER );
543572 LG_ASSERT (scores != NULL , GrB_NULL_POINTER );
@@ -546,6 +575,10 @@ int LAGr_HarmonicCentrality_exact(
546575 GRB_TRY (GrB_Vector_size (& nrows , node_weights )) ;
547576 GRB_TRY (GrB_Vector_nvals (& nvals , node_weights )) ;
548577 GRB_TRY (GrB_Vector_new (scores , GrB_FP64 , nrows )) ;
578+ if (reachable_nodes != NULL )
579+ {
580+ GRB_TRY (GrB_Vector_new (reachable_nodes , GrB_INT64 , nrows )) ;
581+ }
549582
550583 if (nvals == 0 ) {
551584 return GrB_SUCCESS ;
@@ -587,6 +620,8 @@ int LAGr_HarmonicCentrality_exact(
587620 GRB_TRY (GxB_Scalar_new (& score , GrB_FP64 )) ;
588621 GRB_TRY (GxB_Iterator_new (& it )) ;
589622 GRB_TRY (GrB_Vector_new (& node_compact , GrB_INT64 , nvals ));
623+ GRB_TRY (GrB_Vector_new (& score_compact , GrB_FP64 , nvals ));
624+ GRB_TRY (GrB_Vector_new (& reach_compact , GrB_INT64 , nvals ));
590625 GRB_TRY (GxB_Vector_extract_Vector (
591626 node_compact , NULL , NULL , nodes , node_weights , desc )) ;
592627 GRB_TRY (GrB_free (& desc )) ;
@@ -602,15 +637,25 @@ int LAGr_HarmonicCentrality_exact(
602637 GRB_TRY (GrB_Vector_removeElement (level , nodeIdx )) ;
603638
604639 // dot product (plus div)
605- GRB_TRY (GrB_vxm ((GrB_Vector ) score , NULL , NULL , GxB_PLUS_DIV_FP64 ,
640+ GRB_TRY (GrB_vxm ((GrB_Vector ) score , NULL , NULL , GxB_PLUS_DIV_FP64 ,
606641 flat_weight , (GrB_Matrix ) level , NULL )) ;
642+ GRB_TRY (GrB_Vector_nvals (& n_reachable , level ));
607643 GrB_free (& level );
608644
609- GRB_TRY (GrB_Vector_setElement_Scalar (* scores , score , nodeIdx )) ;
645+ GRB_TRY (GrB_Vector_setElement_INT64 (reach_compact , n_reachable , nodeIdx ));
646+ GRB_TRY (GrB_Vector_setElement_Scalar (score_compact , score , nodeIdx )) ;
610647
611648 info = GxB_Vector_Iterator_next (it );
612649 }
613650
651+ GRB_TRY (GxB_Vector_assign_Vector (
652+ * scores , NULL , NULL , score_compact , node_weights , desc )) ;
653+ if (reachable_nodes != NULL )
654+ {
655+ GRB_TRY (GxB_Vector_assign_Vector (
656+ * reachable_nodes , NULL , NULL , reach_compact , node_weights , desc )) ;
657+ }
658+
614659 //--------------------------------------------------------------------------
615660 // cleanup
616661 //--------------------------------------------------------------------------
0 commit comments