From af7f75b050ab99e63ccc0675f591dd8ac691510b Mon Sep 17 00:00:00 2001 From: peicasey Date: Fri, 21 Feb 2025 17:47:37 -0600 Subject: [PATCH 01/10] initial setup --- .../LAGr_EdgeBetweennessCentrality.c | 306 ++++++++++++++++++ include/LAGraphX.h | 14 + 2 files changed, 320 insertions(+) create mode 100644 experimental/algorithm/LAGr_EdgeBetweennessCentrality.c diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c new file mode 100644 index 0000000000..244b35d4aa --- /dev/null +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -0,0 +1,306 @@ +//------------------------------------------------------------------------------ +// LAGr_EdgeBetweennessCentrality: edge betweenness-centrality +//------------------------------------------------------------------------------ + +// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved. +// SPDX-Licene-Identifier: BSD-2-Clause +// +// For additional details (including references to third party source code and +// other files) see the LICEnE file or contact permission@sei.cmu.edu. See +// Contributors.txt for a full list of contributors. Created, in part, with +// funding and support from the U.S. Government (see Acknowledgments.txt file). +// DM22-0790 + +// Contributed by Casey and Tim Davis, Texas A&M University; +// Adapted and revised from GraphBLAS C API Spec, Appendix B.4. + +//------------------------------------------------------------------------------ + +// LAGr_EdgeBetweennessCentrality: Batch algorithm for computing +// betweeness centrality, using push-pull optimization. + +// This is an Advanced algorithm (G->AT is required). + + +//------------------------------------------------------------------------------ + +#define LG_FREE_WORK \ +{ \ + GrB_free (&frontier) ; \ + GrB_free (&paths) ; \ + GrB_free (&bc_update) ; \ + GrB_free (&W) ; \ + if (S != NULL) \ + { \ + for (int64_t i = 0 ; i < n ; i++) \ + { \ + if (S [i] == NULL) break ; \ + GrB_free (&(S [i])) ; \ + } \ + LAGraph_Free ((void **) &S, NULL) ; \ + } \ +} + +#define LG_FREE_ALL \ +{ \ + LG_FREE_WORK ; \ + GrB_free (centrality) ; \ +} + +#include "LG_internal.h" +#include + +GrB_Info add_one_divide(double *z, const double *x, const double *y) { + *z = (1 + *x) / *y; // Operation (1 + x) / y + return GrB_SUCCESS; +} + +//------------------------------------------------------------------------------ +// LAGr_EdgeBetweennessCentrality: edge betweenness-centrality +//------------------------------------------------------------------------------ + +int LAGr_EdgeBetweennessCentrality +( + // output: + GrB_Vector *centrality, // centrality(i): betweeness centrality of i + // input: + LAGraph_Graph G, // input graph + char *msg +) +{ + + //-------------------------------------------------------------------------- + // check inputs + //-------------------------------------------------------------------------- + + LG_CLEAR_MSG ; + + // Array of BFS search matrices. + // S [i] is a sparse matrix that stores the depth at which each vertex is + // first seen thus far in each BFS at the current depth i. Each column + // corresponds to a BFS traversal starting from a source node. + GrB_Vector *S = NULL ; + + // Frontier matrix, a sparse matrix. + // Stores # of shortest paths to vertices at current BFS depth + GrB_Vector frontier = NULL ; + + // Paths matrix holds the number of shortest paths for each node and + // starting node discovered so far. A dense matrix that is updated with + // sparse updates, and also used as a mask. + GrB_Matrix paths = NULL ; + + // Update matrix for betweenness centrality, values for each node for + // each starting node. A dense matrix. + GrB_Matrix bc_update = NULL ; + + // Temporary workspace matrix (sparse). + GrB_Matrix W = NULL ; + + GrB_Index n = 0 ; // # nodes in the graph + + LG_ASSERT (centrality != NULL && sources != NULL, GrB_NULL_POINTER) ; + (*centrality) = NULL ; + LG_TRY (LAGraph_CheckGraph (G, msg)) ; + + GrB_Matrix A = G->A ; + GrB_Matrix AT ; + if (G->kind == LAGraph_ADJACENCY_UNDIRECTED || + G->is_symmetric_structure == LAGraph_TRUE) + { + // A and A' have the same structure + AT = A ; + } + else + { + // A and A' differ + AT = G->AT ; + LG_ASSERT_MSG (AT != NULL, LAGRAPH_NOT_CACHED, "G->AT is required") ; + } + + // ========================================================================= + // === initialization ===================================================== + // ========================================================================= + + // Initialize paths and frontier with source notes + GRB_TRY (GrB_Matrix_nrows (&n, A)) ; + GRB_TRY (GrB_Matrix_new (&paths, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; // todo: change to bool? + GRB_TRY (LG_SET_FORMAT_HINT (paths, LG_BITMAP + LG_FULL)) ; + + // TOOO: change this to just set everything to 1 instead of looping + for (GrB_Index i = 0 ; i < n ; i++) + { + // paths (i,s(i)) = 1 + // frontier (i,s(i)) = 1 + double one = 1 ; + GrB_Index src = sources [i] ; + GRB_TRY (GrB_Matrix_setElement (paths, one, i, src)) ; + GRB_TRY (GrB_Matrix_setElement (frontier, one, i, src)) ; + } + + // Initial frontier: frontier= frontier*A + GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, + frontier, A, GrB_DESC_RSC)) ; + + // Allocate memory for the array of S matrices + LG_TRY (LAGraph_Malloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; + S [0] = NULL ; + + // ========================================================================= + // === Breadth-first search stage ========================================== + // ========================================================================= + + bool last_was_pull = false ; + GrB_Index frontier_size, last_frontier_size = 0 ; + GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; + + int64_t depth ; + for (depth = 0 ; frontier_size > 0 && depth < n ; depth++) + { + + //---------------------------------------------------------------------- + // S [depth] = structure of frontier + //---------------------------------------------------------------------- + + S [depth+1] = NULL ; + LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; + + //---------------------------------------------------------------------- + // Accumulate path counts: paths += frontier + //---------------------------------------------------------------------- + + GRB_TRY (GrB_assign (paths, NULL, GrB_PLUS_FP64, frontier, GrB_ALL, n, + GrB_ALL, n, NULL)) ; + + //---------------------------------------------------------------------- + // Update frontier: frontier = frontier*A + //---------------------------------------------------------------------- + + // pull if frontier is more than 10% dense, + // or > 6% dense and last step was pull + double frontier_denity = ((double) frontier_size) / (double) (n*n) ; + bool do_pull = frontier_denity > (last_was_pull ? 0.06 : 0.10 ) ; + + if (do_pull) + { + // frontier = frontier*AT' + GRB_TRY (LG_SET_FORMAT_HINT (frontier, LG_BITMAP)) ; + GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, + frontier, AT, GrB_DESC_RSCT1)) ; + } + else // push + { + // frontier = frontier*A + GRB_TRY (LG_SET_FORMAT_HINT (frontier, LG_SPARSE)) ; + GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, + frontier, A, GrB_DESC_RSC)) ; + } + + //---------------------------------------------------------------------- + // Get size of current frontier: frontier_size = nvals(frontier) + //---------------------------------------------------------------------- + + last_frontier_size = frontier_size ; + last_was_pull = do_pull ; + GRB_TRY (GrB_Matrix_nvals (&frontier_size, frontier)) ; + } + + GRB_TRY (GrB_free (&frontier)) ; + + // ========================================================================= + // === Betweenness centrality computation phase ============================ + // ========================================================================= + + // bc_update = ones (n, n) ; a full matrix (and stays full) + GRB_TRY (GrB_Matrix_new (&bc_update, GrB_FP64, n, n)) ; + GRB_TRY (GrB_assign (bc_update, NULL, NULL, 1, GrB_ALL, n, GrB_ALL, n, + NULL)) ; + // W: empty n-by-n array, as workspace + GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; + + // Backtrack through the BFS and compute centrality updates for each vertex + for (int64_t d = depth-1 ; d > 0 ; d--) + { + GrB_Vector f_d = S[d] ; + GrB_Vector f_d1 = S[d - 1] ; + + // 18 w = S(d, :) ÷ p × v + S(d, :) + // 19 U = A .× w + // 20 w = S(d − 1, :) × p + // 21 U = w .× U + + // make J Matrix + + GrB_Vector J_vec; + GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)); + + GrB_Vector bc_update_col, paths_col; + GRB_TRY(GrB_Vector_new(&bc_update_col, GrB_FP64, rows)); + GRB_TRY(GrB_Vector_new(&paths_col, GrB_FP64, rows)); + GRB_TRY(GrB_extract(bc_update_col, f_d, GrB_NULL, bc_update, d)); + GRB_TRY(GrB_extract(paths_col, f_d, GrB_NULL, paths, d)); + + GRB_TRY(GrB_eWiseAdd(J_vec, f_d, NULL, add_one_divide, bc_update_col, paths_col, GrB_DESC_R)); + + GrB_Matrix J_matrix; + GRB_TRY(GrB_Matrix_diag(&J_matrix, J_vec, 0)); + + + // make I matrix + + GrB_Vector I_vec; + GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_extract (I_vec, f_d1, GrB_NULL, paths, d-1)) ; + + GrB_Matrix I_matrix; + GRB_TRY(GrB_Matrix_diag(&I_matrix, I_vec, 0)); + + + // combine + + // intermediate matrix for Fd1 * A + GrB_Matrix Fd1A; + GrB_Matrix_new(&Fd1A, GrB_FP64, n, n); + GRB_TRY(GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, J_matrix, A, NULL)); + + GrB_Matrix update; + GrB_Matrix_new(update, GrB_FP64, n, n); + GRB_TRY(GrB_eWiseMult(*update, NULL, NULL, GrB_TIMES_FP64, Fd1A, I_matrix, NULL)); + + // free intermediate matrix + GrB_Matrix_free(&Fd1A); + + + // 22 B = B + U + GRB_TRY(GrB_eWiseAdd(centrality, NULL, NULL, GrB_PLUS_FP64, centrality, update, NULL)); + + // 23 v = U +. + GrB_Vector temp_update; + GrB_Vector_new(&temp_update, GrB_FP64, n); // Create a temporary vector + + // Reduce "update" matrix to a vector (sum each column) + GRB_TRY(GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, update, NULL)); + GRB_TRY(GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)); + + GrB_Vector_free(&temp_update); + + // 24 d = d − 1 + } + + // ========================================================================= + // === finalize the centrality ============================================= + // ========================================================================= + + // Initialize the centrality array with -n to avoid counting + // zero length paths + GRB_TRY (GrB_Vector_new (centrality, GrB_FP64, n)) ; + GRB_TRY (GrB_assign (*centrality, NULL, NULL, -n, GrB_ALL, n, NULL)) ; + + // centrality (i) += sum (bc_update (:,i)) for all nodes i + GRB_TRY (GrB_reduce (*centrality, NULL, GrB_PLUS_FP64, GrB_PLUS_MONOID_FP64, + bc_update, GrB_DESC_T0)) ; + + LG_FREE_WORK ; + return (GrB_SUCCESS) ; +} diff --git a/include/LAGraphX.h b/include/LAGraphX.h index e02214dffa..b099c6ab1d 100644 --- a/include/LAGraphX.h +++ b/include/LAGraphX.h @@ -1276,6 +1276,20 @@ int LAGr_HITS char *msg ) ; +//------------------------------------------------------------------------------ +// edge betweenness centrality +//------------------------------------------------------------------------------ + +LAGRAPHX_PUBLIC +int LAGr_EdgeBetweennessCentrality +( + // output: + GrB_Vector *centrality, // centrality(i): betweeness centrality of i + // input: + LAGraph_Graph G, // input graph + char *msg +) + //------------------------------------------------------------------------------ // graph clustering with quality metrics //------------------------------------------------------------------------------ From 287bd07bb1ff92027953221d0ebd21170cef574f Mon Sep 17 00:00:00 2001 From: peicasey Date: Tue, 25 Feb 2025 01:43:44 -0600 Subject: [PATCH 02/10] initial parallel ebc --- .../LAGr_EdgeBetweennessCentrality.c | 238 ++++++++++-------- .../test/LG_check_edgeBetweennessCentrality.c | 30 +-- .../test/test_edgeBetweennessCentrality.c | 5 +- include/LAGraphX.h | 4 +- 4 files changed, 151 insertions(+), 126 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 244b35d4aa..2e512174e2 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -29,7 +29,8 @@ GrB_free (&frontier) ; \ GrB_free (&paths) ; \ GrB_free (&bc_update) ; \ - GrB_free (&W) ; \ + GrB_free (&v) ; \ + GrB_free (&U) ; \ if (S != NULL) \ { \ for (int64_t i = 0 ; i < n ; i++) \ @@ -50,11 +51,25 @@ #include "LG_internal.h" #include -GrB_Info add_one_divide(double *z, const double *x, const double *y) { - *z = (1 + *x) / *y; // Operation (1 + x) / y - return GrB_SUCCESS; +//------------------------------------------------------------------------------ +// (1+x)/y function for double: z = (1 + x) / y +//------------------------------------------------------------------------------ + +void add_one_divide_function (void *z, const void *x, const void *y) +{ + double a = (*((double *) x)) ; + double b = (*((double *) y)) ; + (*((double *) z)) = (1 + a) / b ; } +#define ADD_ONE_DIVIDE_FUNCTION_DEFN \ +"void add_one_divide_function (void *z, const void *x, const void *y) \n" \ +"{ \n" \ +" double a = (*((double *) x)) ; \n" \ +" double b = (*((double *) y)) ; \n" \ +" (*((double *) z)) = (1 + a) / b ; \n" \ +"}" + //------------------------------------------------------------------------------ // LAGr_EdgeBetweennessCentrality: edge betweenness-centrality //------------------------------------------------------------------------------ @@ -62,7 +77,7 @@ GrB_Info add_one_divide(double *z, const double *x, const double *y) { int LAGr_EdgeBetweennessCentrality ( // output: - GrB_Vector *centrality, // centrality(i): betweeness centrality of i + GrB_Matrix *centrality, // centrality(i): betweeness centrality of i // input: LAGraph_Graph G, // input graph char *msg @@ -88,18 +103,26 @@ int LAGr_EdgeBetweennessCentrality // Paths matrix holds the number of shortest paths for each node and // starting node discovered so far. A dense matrix that is updated with // sparse updates, and also used as a mask. - GrB_Matrix paths = NULL ; + GrB_Vector paths = NULL ; + + // the delta vector for each node for each starting node. A dense matrix. + GrB_Vector bc_update = NULL ; // Update matrix for betweenness centrality, values for each node for // each starting node. A dense matrix. - GrB_Matrix bc_update = NULL ; + GrB_Matrix U = NULL ; + + GrB_Vector v = NULL ; + + GrB_BinaryOp Add_One_Divide = NULL ; + // Temporary workspace matrix (sparse). - GrB_Matrix W = NULL ; + // GrB_Matrix W = NULL ; GrB_Index n = 0 ; // # nodes in the graph - LG_ASSERT (centrality != NULL && sources != NULL, GrB_NULL_POINTER) ; + LG_ASSERT (centrality != NULL, GrB_NULL_POINTER) ; (*centrality) = NULL ; LG_TRY (LAGraph_CheckGraph (G, msg)) ; @@ -122,30 +145,32 @@ int LAGr_EdgeBetweennessCentrality // === initialization ===================================================== // ========================================================================= + GRB_TRY (GxB_BinaryOp_new (&Add_One_Divide, add_one_divide_function, + GrB_FP64, GrB_FP64, GrB_FP64, + "add_one_divide_function", ADD_ONE_DIVIDE_FUNCTION_DEFN)) ; + // Initialize paths and frontier with source notes GRB_TRY (GrB_Matrix_nrows (&n, A)) ; - GRB_TRY (GrB_Matrix_new (&paths, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new (&paths, GrB_FP64, n)) ; GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; // todo: change to bool? - GRB_TRY (LG_SET_FORMAT_HINT (paths, LG_BITMAP + LG_FULL)) ; + // GRB_TRY (LG_SET_FORMAT_HINT (paths, LG_BITMAP + LG_FULL)) ; + + GRB_TRY (GrB_Matrix_new (&U, GrB_FP64, n, n)) ; + + GRB_TRY (GrB_Vector_new (&v, GrB_FP64, n)) ; + + GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; - // TOOO: change this to just set everything to 1 instead of looping - for (GrB_Index i = 0 ; i < n ; i++) - { - // paths (i,s(i)) = 1 - // frontier (i,s(i)) = 1 - double one = 1 ; - GrB_Index src = sources [i] ; - GRB_TRY (GrB_Matrix_setElement (paths, one, i, src)) ; - GRB_TRY (GrB_Matrix_setElement (frontier, one, i, src)) ; - } + + // Initialize centrality matrix with zeros using A as structural mask + GRB_TRY (GrB_assign (centrality, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, NULL)) ; // Initial frontier: frontier= frontier*A - GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, - frontier, A, GrB_DESC_RSC)) ; + // GRB_TRY (GrB_vxv (frontier, paths, NULL, LAGraph_plus_first_fp64, + // frontier, A, GrB_DESC_RSC)) ; - // Allocate memory for the array of S matrices + // Allocate memory for the array of S vectors LG_TRY (LAGraph_Malloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; - S [0] = NULL ; // ========================================================================= // === Breadth-first search stage ========================================== @@ -155,55 +180,57 @@ int LAGr_EdgeBetweennessCentrality GrB_Index frontier_size, last_frontier_size = 0 ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; - int64_t depth ; - for (depth = 0 ; frontier_size > 0 && depth < n ; depth++) + int64_t depth, root ; + for (root = 1 ; root <= n ; root++) { - //---------------------------------------------------------------------- - // S [depth] = structure of frontier - //---------------------------------------------------------------------- - - S [depth+1] = NULL ; - LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; + depth = 0 ; + S [root] = NULL ; + LG_TRY (LAGraph_Vector_Structure (&(S [root]), frontier, msg)) ; - //---------------------------------------------------------------------- - // Accumulate path counts: paths += frontier - //---------------------------------------------------------------------- + GRB_TRY (GrB_Vector_clear (paths)) ; + GRB_TRY (GrB_Vector_setElement (paths, 1.0, root)) ; - GRB_TRY (GrB_assign (paths, NULL, GrB_PLUS_FP64, frontier, GrB_ALL, n, - GrB_ALL, n, NULL)) ; + GRB_TRY (GrB_Matrix_clear (U)) ; - //---------------------------------------------------------------------- - // Update frontier: frontier = frontier*A - //---------------------------------------------------------------------- + GRB_TRY (GrB_Vector_clear (v)) ; - // pull if frontier is more than 10% dense, - // or > 6% dense and last step was pull - double frontier_denity = ((double) frontier_size) / (double) (n*n) ; - bool do_pull = frontier_denity > (last_was_pull ? 0.06 : 0.10 ) ; + // Extract row root from A into frontier vector: frontier = A(root,:) + GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, NULL)) ; - if (do_pull) - { - // frontier = frontier*AT' - GRB_TRY (LG_SET_FORMAT_HINT (frontier, LG_BITMAP)) ; - GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, - frontier, AT, GrB_DESC_RSCT1)) ; - } - else // push + while (frontier_size != 0) { - // frontier = frontier*A + depth++ ; + + //---------------------------------------------------------------------- + // Accumulate path counts: paths += frontier + //---------------------------------------------------------------------- + + GRB_TRY (GrB_assign (paths, NULL, GrB_PLUS_FP64, frontier, GrB_ALL, n, + NULL)) ; + + //---------------------------------------------------------------------- + // Add frontier to S: S(depth, :) = frontier + //---------------------------------------------------------------------- + + S [depth] = NULL ; + LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; + + //---------------------------------------------------------------------- + // Update frontier: frontier = frontier*A x !paths + //---------------------------------------------------------------------- + GRB_TRY (LG_SET_FORMAT_HINT (frontier, LG_SPARSE)) ; - GRB_TRY (GrB_mxm (frontier, paths, NULL, LAGraph_plus_first_fp64, - frontier, A, GrB_DESC_RSC)) ; - } + GRB_TRY (GrB_vxm (frontier, paths, NULL, GxB_PLUS_FIRST_FP64, frontier, + A, GrB_DESC_RSC )) ; - //---------------------------------------------------------------------- - // Get size of current frontier: frontier_size = nvals(frontier) - //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // Get size of current frontier: frontier_size = nvals(frontier) + //---------------------------------------------------------------------- - last_frontier_size = frontier_size ; - last_was_pull = do_pull ; - GRB_TRY (GrB_Matrix_nvals (&frontier_size, frontier)) ; + last_frontier_size = frontier_size ; + GRB_TRY (GrB_Matrix_nvals (&frontier_size, frontier)) ; + } } GRB_TRY (GrB_free (&frontier)) ; @@ -213,17 +240,17 @@ int LAGr_EdgeBetweennessCentrality // ========================================================================= // bc_update = ones (n, n) ; a full matrix (and stays full) - GRB_TRY (GrB_Matrix_new (&bc_update, GrB_FP64, n, n)) ; - GRB_TRY (GrB_assign (bc_update, NULL, NULL, 1, GrB_ALL, n, GrB_ALL, n, - NULL)) ; - // W: empty n-by-n array, as workspace - GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; + // GRB_TRY (GrB_Matrix_new (&bc_update, GrB_FP64, n, n)) ; + // GRB_TRY (GrB_assign (bc_update, NULL, NULL, 1, GrB_ALL, n, GrB_ALL, n, + // NULL)) ; + // // W: empty n-by-n array, as workspace + // GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; // Backtrack through the BFS and compute centrality updates for each vertex - for (int64_t d = depth-1 ; d > 0 ; d--) - { - GrB_Vector f_d = S[d] ; - GrB_Vector f_d1 = S[d - 1] ; + while (depth >= 2) + { + GrB_Vector f_d = S[depth] ; + GrB_Vector f_d1 = S[depth - 1] ; // 18 w = S(d, :) ÷ p × v + S(d, :) // 19 U = A .× w @@ -232,56 +259,51 @@ int LAGr_EdgeBetweennessCentrality // make J Matrix - GrB_Vector J_vec; - GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)); - - GrB_Vector bc_update_col, paths_col; - GRB_TRY(GrB_Vector_new(&bc_update_col, GrB_FP64, rows)); - GRB_TRY(GrB_Vector_new(&paths_col, GrB_FP64, rows)); - GRB_TRY(GrB_extract(bc_update_col, f_d, GrB_NULL, bc_update, d)); - GRB_TRY(GrB_extract(paths_col, f_d, GrB_NULL, paths, d)); - - GRB_TRY(GrB_eWiseAdd(J_vec, f_d, NULL, add_one_divide, bc_update_col, paths_col, GrB_DESC_R)); - - GrB_Matrix J_matrix; - GRB_TRY(GrB_Matrix_diag(&J_matrix, J_vec, 0)); + GrB_Vector J_vec ; + GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; + + GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_R)) ; + + GrB_Matrix J_matrix ; + GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; // make I matrix - GrB_Vector I_vec; + GrB_Vector I_vec ; GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; - GRB_TRY (GrB_extract (I_vec, f_d1, GrB_NULL, paths, d-1)) ; - GrB_Matrix I_matrix; - GRB_TRY(GrB_Matrix_diag(&I_matrix, I_vec, 0)); + GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, depth-1, 1, GrB_DESC_R)) ; + + GrB_Matrix I_matrix ; + GRB_TRY (GrB_Matrix_diag(&I_matrix, I_vec, 0)) ; // combine // intermediate matrix for Fd1 * A - GrB_Matrix Fd1A; - GrB_Matrix_new(&Fd1A, GrB_FP64, n, n); - GRB_TRY(GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, J_matrix, A, NULL)); + GrB_Matrix Fd1A ; + GrB_Matrix_new (&Fd1A, GrB_FP64, n, n) ; + GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, J_matrix, A, NULL)) ; - GrB_Matrix update; - GrB_Matrix_new(update, GrB_FP64, n, n); - GRB_TRY(GrB_eWiseMult(*update, NULL, NULL, GrB_TIMES_FP64, Fd1A, I_matrix, NULL)); + GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, I_matrix, NULL)) ; // free intermediate matrix - GrB_Matrix_free(&Fd1A); + GrB_Matrix_free(&Fd1A) ; // 22 B = B + U - GRB_TRY(GrB_eWiseAdd(centrality, NULL, NULL, GrB_PLUS_FP64, centrality, update, NULL)); - + GRB_TRY (GrB_assign(centrality, centrality, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; + // 23 v = U +. - GrB_Vector temp_update; - GrB_Vector_new(&temp_update, GrB_FP64, n); // Create a temporary vector + GrB_Vector temp_update ; + GrB_Vector_new(&temp_update, GrB_FP64, n) ; // Create a temporary vector // Reduce "update" matrix to a vector (sum each column) - GRB_TRY(GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, update, NULL)); - GRB_TRY(GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)); + GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, U, NULL)) ; + GRB_TRY (GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)) ; + + // Grb_reduce_monoid GrB_Vector_free(&temp_update); @@ -292,14 +314,16 @@ int LAGr_EdgeBetweennessCentrality // === finalize the centrality ============================================= // ========================================================================= + GxB_print(*centrality, GxB_COMPLETE) ; + // Initialize the centrality array with -n to avoid counting // zero length paths - GRB_TRY (GrB_Vector_new (centrality, GrB_FP64, n)) ; - GRB_TRY (GrB_assign (*centrality, NULL, NULL, -n, GrB_ALL, n, NULL)) ; + // GRB_TRY (GrB_Vector_new (centrality, GrB_FP64, n)) ; + // GRB_TRY (GrB_assign (*centrality, NULL, NULL, -n, GrB_ALL, n, NULL)) ; - // centrality (i) += sum (bc_update (:,i)) for all nodes i - GRB_TRY (GrB_reduce (*centrality, NULL, GrB_PLUS_FP64, GrB_PLUS_MONOID_FP64, - bc_update, GrB_DESC_T0)) ; + // // centrality (i) += sum (bc_update (:,i)) for all nodes i + // GRB_TRY (GrB_reduce (*centrality, NULL, GrB_PLUS_FP64, GrB_PLUS_MONOID_FP64, + // bc_update, GrB_DESC_T0)) ; LG_FREE_WORK ; return (GrB_SUCCESS) ; diff --git a/experimental/test/LG_check_edgeBetweennessCentrality.c b/experimental/test/LG_check_edgeBetweennessCentrality.c index aa89061d4a..f61c6045e9 100644 --- a/experimental/test/LG_check_edgeBetweennessCentrality.c +++ b/experimental/test/LG_check_edgeBetweennessCentrality.c @@ -286,20 +286,20 @@ int LG_check_edgeBetweennessCentrality // printf("\n"); } - if (s < 10) { + // if (s < 10) { - printf("==========================================\n"); + // printf("==========================================\n"); - for (int64_t w = 0; w < n; w++) { - printf("%ld's: ", w); - for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { - printf("%ld ", Pj [p]) ; - } - printf("\n"); - } - printf("\n"); + // for (int64_t w = 0; w < n; w++) { + // printf("%ld's: ", w); + // for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { + // printf("%ld ", Pj [p]) ; + // } + // printf("\n"); + // } + // printf("\n"); - } + // } // Set dependency score δ[v] ← 0 // 24. δ[v] ← 0, ∀v ∈ V @@ -348,17 +348,17 @@ int LG_check_edgeBetweennessCentrality // 27. w ← pop(S) int64_t w = S [--sp] ; - if (s < 10) printf("w: %ld\n", w); + // if (s < 10) printf("w: %ld\n", w); // 28. for v ∈ P [w] for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { int64_t v = Pj [p] ; - if (s < 10) printf(" v: %ld\n", v); + // if (s < 10) printf(" v: %ld\n", v); // Update dependency and centrality values // 30. δ[v] ← δ[v] + σ[v] × ( δ[w]/σ[w] + 1) - if (s < 10) printf(" %g = %g * (%g + 1)/%g\n", sigma [v] * ((delta [w] + 1) / sigma [w]), sigma [v], delta [w], sigma [w]) ; + // if (s < 10) printf(" %g = %g * (%g + 1)/%g\n", sigma [v] * ((delta [w] + 1) / sigma [w]), sigma [v], delta [w], sigma [w]) ; // if (v == w) { printf ("Ack!!\n") ; fflush (stdout) ; abort ( ) ; } if (v == w) { @@ -372,7 +372,7 @@ int LG_check_edgeBetweennessCentrality // 31. result [(v, w)] ← result [(v, w)] + σ[v] × ( δ[w]/σ[w] + 1) result [INDEX (v,w)] += centrality; // result [INDEX (w,v)] += centrality; - if (s < 10) printf(" result: %g\n", result[INDEX(v,w)]); + // if (s < 10) printf(" result: %g\n", result[INDEX(v,w)]); // if (result [INDEX (v,w)] == 0) { // result [INDEX (w,v)] += centrality; diff --git a/experimental/test/test_edgeBetweennessCentrality.c b/experimental/test/test_edgeBetweennessCentrality.c index 2a11dcba0b..f2ff6ed833 100644 --- a/experimental/test/test_edgeBetweennessCentrality.c +++ b/experimental/test/test_edgeBetweennessCentrality.c @@ -152,7 +152,8 @@ void test_diamonds_ebc (void) TEST_CHECK (A == NULL) ; // A has been moved into G->A // compute its betweenness centrality - OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; + OK (LAGr_EdgeBetweennessCentrality (¢rality, G, msg)) ; + // OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; // compare with GAP: double err = difference(centrality, &diamonds_ebc[0][0], 8, 8) ; @@ -205,6 +206,6 @@ void test_karate_ebc (void) TEST_LIST = { {"test_diamonds_ebc", test_diamonds_ebc}, - {"test_karate_ebc", test_karate_ebc}, + // {"test_karate_ebc", test_karate_ebc}, {NULL, NULL} }; diff --git a/include/LAGraphX.h b/include/LAGraphX.h index b099c6ab1d..148c47007c 100644 --- a/include/LAGraphX.h +++ b/include/LAGraphX.h @@ -1284,11 +1284,11 @@ LAGRAPHX_PUBLIC int LAGr_EdgeBetweennessCentrality ( // output: - GrB_Vector *centrality, // centrality(i): betweeness centrality of i + GrB_Matrix *centrality, // centrality(i): betweeness centrality of i // input: LAGraph_Graph G, // input graph char *msg -) +); //------------------------------------------------------------------------------ // graph clustering with quality metrics From a27483f0edea3db5a5814d59a62a61ac07fa88d1 Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 26 Feb 2025 11:01:00 -0600 Subject: [PATCH 03/10] before 2/26 meeting --- .../LAGr_EdgeBetweennessCentrality.c | 31 +++++++++++++------ .../test/test_edgeBetweennessCentrality.c | 14 ++++++++- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 2e512174e2..4635afc9fb 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -116,6 +116,7 @@ int LAGr_EdgeBetweennessCentrality GrB_BinaryOp Add_One_Divide = NULL ; + GrB_Matrix centrality_temp = NULL; // Temporary workspace matrix (sparse). // GrB_Matrix W = NULL ; @@ -162,8 +163,9 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; - // Initialize centrality matrix with zeros using A as structural mask - GRB_TRY (GrB_assign (centrality, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, NULL)) ; + // Initialize centrality_temp matrix with zeros using A as structural mask + LG_TRY (GrB_Matrix_new(¢rality_temp, GrB_FP64, n, n)) ; + GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, NULL)) ; // Initial frontier: frontier= frontier*A // GRB_TRY (GrB_vxv (frontier, paths, NULL, LAGraph_plus_first_fp64, @@ -176,14 +178,13 @@ int LAGr_EdgeBetweennessCentrality // === Breadth-first search stage ========================================== // ========================================================================= - bool last_was_pull = false ; GrB_Index frontier_size, last_frontier_size = 0 ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; int64_t depth, root ; - for (root = 1 ; root <= n ; root++) + for (root = 0 ; root < n ; root++) { - + printf("root: %ld \n", root) ; depth = 0 ; S [root] = NULL ; LG_TRY (LAGraph_Vector_Structure (&(S [root]), frontier, msg)) ; @@ -197,6 +198,9 @@ int LAGr_EdgeBetweennessCentrality // Extract row root from A into frontier vector: frontier = A(root,:) GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, NULL)) ; + GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; + + GxB_print(frontier, 5) ; while (frontier_size != 0) { @@ -229,10 +233,13 @@ int LAGr_EdgeBetweennessCentrality //---------------------------------------------------------------------- last_frontier_size = frontier_size ; - GRB_TRY (GrB_Matrix_nvals (&frontier_size, frontier)) ; + GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; } } + printf(" after:\n") ; + GxB_print(frontier, 5) ; + GRB_TRY (GrB_free (&frontier)) ; // ========================================================================= @@ -273,7 +280,9 @@ int LAGr_EdgeBetweennessCentrality GrB_Vector I_vec ; GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; - GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, depth-1, 1, GrB_DESC_R)) ; + GrB_Index idx[1]; + idx[0] = depth-1; + GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, idx, 1, NULL)) ; GrB_Matrix I_matrix ; GRB_TRY (GrB_Matrix_diag(&I_matrix, I_vec, 0)) ; @@ -293,7 +302,9 @@ int LAGr_EdgeBetweennessCentrality // 22 B = B + U - GRB_TRY (GrB_assign(centrality, centrality, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; + GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; + // GRB_TRY (GrB_eWiseAdd (*centrality_temp, NULL, GrB_PLUS_FP64, U, *centrality, NULL)) ; + // 23 v = U +. GrB_Vector temp_update ; @@ -314,7 +325,9 @@ int LAGr_EdgeBetweennessCentrality // === finalize the centrality ============================================= // ========================================================================= - GxB_print(*centrality, GxB_COMPLETE) ; + GxB_print(centrality_temp, GxB_COMPLETE) ; + + *centrality = centrality_temp; // Initialize the centrality array with -n to avoid counting // zero length paths diff --git a/experimental/test/test_edgeBetweennessCentrality.c b/experimental/test/test_edgeBetweennessCentrality.c index f2ff6ed833..5595f92f06 100644 --- a/experimental/test/test_edgeBetweennessCentrality.c +++ b/experimental/test/test_edgeBetweennessCentrality.c @@ -139,8 +139,10 @@ void test_diamonds_ebc (void) { LAGraph_Init (msg) ; GrB_Matrix A = NULL ; + GrB_Matrix AT = NULL ; GrB_Matrix centrality = NULL ; int niters = 0 ; + LAGraph_Kind kind = LAGraph_ADJACENCY_DIRECTED ; // create the karate graph snprintf (filename, LEN, LG_DATA_DIR "%s", "diamonds.mtx") ; @@ -148,9 +150,19 @@ void test_diamonds_ebc (void) TEST_CHECK (f != NULL) ; OK (LAGraph_MMRead (&A, f, msg)) ; OK (fclose (f)) ; - OK (LAGraph_New (&G, &A, LAGraph_ADJACENCY_DIRECTED, msg)) ; + OK (LAGraph_New (&G, &A, kind, msg)) ; TEST_CHECK (A == NULL) ; // A has been moved into G->A + OK (GrB_transpose(AT, NULL, NULL, A, GrB_DESC_R)) ; + G->AT = AT; + + // check that AT is cached + int ok_result = (kind == LAGraph_ADJACENCY_UNDIRECTED) ? + LAGRAPH_CACHE_NOT_NEEDED : GrB_SUCCESS ; + int result = LAGraph_Cached_AT (G, msg) ; + TEST_CHECK (result == ok_result) ; + + // compute its betweenness centrality OK (LAGr_EdgeBetweennessCentrality (¢rality, G, msg)) ; // OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; From 40d3a25088e4141631d1a8713213e05035ac57b3 Mon Sep 17 00:00:00 2001 From: Tim Davis Date: Wed, 26 Feb 2025 12:09:13 -0600 Subject: [PATCH 04/10] updates from Feb 26 meeting --- .../LAGr_EdgeBetweennessCentrality.c | 97 +++++++++++++------ .../test/test_edgeBetweennessCentrality.c | 3 - 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 4635afc9fb..9b8a5168f3 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -27,15 +27,21 @@ #define LG_FREE_WORK \ { \ GrB_free (&frontier) ; \ + GrB_free (&J_vec) ; \ + GrB_free (&I_vec) ; \ + GrB_free (&J_matrix) ; \ + GrB_free (&I_matrix) ; \ + GrB_free (&Fd1A) ; \ GrB_free (&paths) ; \ GrB_free (&bc_update) ; \ + GrB_free (&temp_update) ; \ + GrB_free (&Add_One_Divide) ; \ GrB_free (&v) ; \ GrB_free (&U) ; \ if (S != NULL) \ { \ for (int64_t i = 0 ; i < n ; i++) \ { \ - if (S [i] == NULL) break ; \ GrB_free (&(S [i])) ; \ } \ LAGraph_Free ((void **) &S, NULL) ; \ @@ -45,12 +51,35 @@ #define LG_FREE_ALL \ { \ LG_FREE_WORK ; \ + GrB_free (¢rality_temp) ; \ GrB_free (centrality) ; \ } #include "LG_internal.h" #include +#undef LAGRAPH_CATCH +#define LAGRAPH_CATCH(status) \ +{ \ + print ("LAGraph failure (file %s, line %d): status: %d", \ + __FILE__, __LINE__, status) ; \ + LG_ERROR_MSG ("LAGraph failure (file %s, line %d): status: %d", \ + __FILE__, __LINE__, status) ; \ + LG_FREE_ALL ; \ + return (status) ; \ +} + +#undef GRB_CATCH +#define GRB_CATCH(info) \ +{ \ + printf ("GraphBLAS failure (file %s, line %d): info: %d", \ + __FILE__, __LINE__, info) ; \ + LG_ERROR_MSG ("GraphBLAS failure (file %s, line %d): info: %d", \ + __FILE__, __LINE__, info) ; \ + LG_FREE_ALL ; \ + return (info) ; \ +} + //------------------------------------------------------------------------------ // (1+x)/y function for double: z = (1 + x) / y //------------------------------------------------------------------------------ @@ -118,6 +147,13 @@ int LAGr_EdgeBetweennessCentrality GrB_Matrix centrality_temp = NULL; + GrB_Vector J_vec = NULL ; + GrB_Vector I_vec = NULL ; + GrB_Matrix I_matrix = NULL ; + GrB_Matrix J_matrix = NULL ; + GrB_Matrix Fd1A = NULL ; + GrB_Vector temp_update = NULL ; + // Temporary workspace matrix (sparse). // GrB_Matrix W = NULL ; @@ -142,6 +178,9 @@ int LAGr_EdgeBetweennessCentrality LG_ASSERT_MSG (AT != NULL, LAGRAPH_NOT_CACHED, "G->AT is required") ; } + printf ("G->A is:\n") ;GxB_print (A, 5) ; + printf ("G->AT is:\n") ;GxB_print (AT, 5) ; + // ========================================================================= // === initialization ===================================================== // ========================================================================= @@ -165,14 +204,14 @@ int LAGr_EdgeBetweennessCentrality // Initialize centrality_temp matrix with zeros using A as structural mask LG_TRY (GrB_Matrix_new(¢rality_temp, GrB_FP64, n, n)) ; - GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, NULL)) ; + GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ; // Initial frontier: frontier= frontier*A // GRB_TRY (GrB_vxv (frontier, paths, NULL, LAGraph_plus_first_fp64, // frontier, A, GrB_DESC_RSC)) ; // Allocate memory for the array of S vectors - LG_TRY (LAGraph_Malloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; + LG_TRY (LAGraph_Calloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; // ========================================================================= // === Breadth-first search stage ========================================== @@ -186,8 +225,8 @@ int LAGr_EdgeBetweennessCentrality { printf("root: %ld \n", root) ; depth = 0 ; - S [root] = NULL ; - LG_TRY (LAGraph_Vector_Structure (&(S [root]), frontier, msg)) ; +// GrB_free (&(S [0])) ; +// LG_TRY (LAGraph_Vector_Structure (&(S [0]), frontier, msg)) ; GRB_TRY (GrB_Vector_clear (paths)) ; GRB_TRY (GrB_Vector_setElement (paths, 1.0, root)) ; @@ -197,7 +236,8 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_clear (v)) ; // Extract row root from A into frontier vector: frontier = A(root,:) - GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, NULL)) ; + GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, + GrB_DESC_T0)) ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; GxB_print(frontier, 5) ; @@ -217,7 +257,7 @@ int LAGr_EdgeBetweennessCentrality // Add frontier to S: S(depth, :) = frontier //---------------------------------------------------------------------- - S [depth] = NULL ; + GrB_free (&(S [depth])) ; LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; //---------------------------------------------------------------------- @@ -235,6 +275,13 @@ int LAGr_EdgeBetweennessCentrality last_frontier_size = frontier_size ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; } + + printf ("depth: %ld\n", depth) ; + for (int64_t d = 1 ; d <= depth ; d++) + { + printf ("------------------- S [%ld]\n", d) ; + GxB_print (S [d], 5) ; + } } printf(" after:\n") ; @@ -253,9 +300,15 @@ int LAGr_EdgeBetweennessCentrality // // W: empty n-by-n array, as workspace // GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_Matrix_new (&Fd1A, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new(&temp_update, GrB_FP64, n)) ; // Create a temporary vector + // Backtrack through the BFS and compute centrality updates for each vertex while (depth >= 2) { + printf ("backtrack depth %ld\n", depth) ; GrB_Vector f_d = S[depth] ; GrB_Vector f_d1 = S[depth - 1] ; @@ -266,49 +319,31 @@ int LAGr_EdgeBetweennessCentrality // make J Matrix - GrB_Vector J_vec ; - GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; - - GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_R)) ; - - GrB_Matrix J_matrix ; - GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; + GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_RS)) ; + GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; + GxB_print (J_matrix, 5) ; // make I matrix - GrB_Vector I_vec ; - GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, GrB_ALL, n, GrB_DESC_RS)) ; - GrB_Index idx[1]; - idx[0] = depth-1; - GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, idx, 1, NULL)) ; - - GrB_Matrix I_matrix ; GRB_TRY (GrB_Matrix_diag(&I_matrix, I_vec, 0)) ; - + GxB_print (J_matrix, 5) ; // combine // intermediate matrix for Fd1 * A - GrB_Matrix Fd1A ; - GrB_Matrix_new (&Fd1A, GrB_FP64, n, n) ; GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, J_matrix, A, NULL)) ; GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, I_matrix, NULL)) ; - // free intermediate matrix - GrB_Matrix_free(&Fd1A) ; - - // 22 B = B + U GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; // GRB_TRY (GrB_eWiseAdd (*centrality_temp, NULL, GrB_PLUS_FP64, U, *centrality, NULL)) ; // 23 v = U +. - GrB_Vector temp_update ; - GrB_Vector_new(&temp_update, GrB_FP64, n) ; // Create a temporary vector // Reduce "update" matrix to a vector (sum each column) GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, U, NULL)) ; @@ -316,8 +351,6 @@ int LAGr_EdgeBetweennessCentrality // Grb_reduce_monoid - GrB_Vector_free(&temp_update); - // 24 d = d − 1 } diff --git a/experimental/test/test_edgeBetweennessCentrality.c b/experimental/test/test_edgeBetweennessCentrality.c index 5595f92f06..2fd07b8f87 100644 --- a/experimental/test/test_edgeBetweennessCentrality.c +++ b/experimental/test/test_edgeBetweennessCentrality.c @@ -153,9 +153,6 @@ void test_diamonds_ebc (void) OK (LAGraph_New (&G, &A, kind, msg)) ; TEST_CHECK (A == NULL) ; // A has been moved into G->A - OK (GrB_transpose(AT, NULL, NULL, A, GrB_DESC_R)) ; - G->AT = AT; - // check that AT is cached int ok_result = (kind == LAGraph_ADJACENCY_UNDIRECTED) ? LAGRAPH_CACHE_NOT_NEEDED : GrB_SUCCESS ; From 6bd49170460d70dfe6be96c5207f9a22d952f7aa Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 5 Mar 2025 10:27:51 -0600 Subject: [PATCH 05/10] before meeting 3/5 --- .../LAGr_EdgeBetweennessCentrality.c | 181 +++++++++++------- 1 file changed, 108 insertions(+), 73 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 9b8a5168f3..354324b1fb 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -11,13 +11,13 @@ // funding and support from the U.S. Government (see Acknowledgments.txt file). // DM22-0790 -// Contributed by Casey and Tim Davis, Texas A&M University; +// Contributed by Casey Pei and Tim Davis, Texas A&M University; // Adapted and revised from GraphBLAS C API Spec, Appendix B.4. //------------------------------------------------------------------------------ -// LAGr_EdgeBetweennessCentrality: Batch algorithm for computing -// betweeness centrality, using push-pull optimization. +// LAGr_EdgeBetweennessCentrality: Exact algorithm for computing +// betweeness centrality. // This is an Advanced algorithm (G->AT is required). @@ -223,6 +223,7 @@ int LAGr_EdgeBetweennessCentrality int64_t depth, root ; for (root = 0 ; root < n ; root++) { + printf("----\n"); printf("root: %ld \n", root) ; depth = 0 ; // GrB_free (&(S [0])) ; @@ -235,9 +236,11 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_clear (v)) ; - // Extract row root from A into frontier vector: frontier = A(root,:) - GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, - GrB_DESC_T0)) ; + // Extract row root from A into frontier vector: frontier = AT(root,:) + // GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, + // GrB_DESC_T0)) ; + GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, AT, GrB_ALL, n, root, + NULL)) ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; GxB_print(frontier, 5) ; @@ -276,84 +279,116 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; } - printf ("depth: %ld\n", depth) ; - for (int64_t d = 1 ; d <= depth ; d++) - { - printf ("------------------- S [%ld]\n", d) ; - GxB_print (S [d], 5) ; - } - } - - printf(" after:\n") ; - GxB_print(frontier, 5) ; - - GRB_TRY (GrB_free (&frontier)) ; - - // ========================================================================= - // === Betweenness centrality computation phase ============================ - // ========================================================================= - - // bc_update = ones (n, n) ; a full matrix (and stays full) - // GRB_TRY (GrB_Matrix_new (&bc_update, GrB_FP64, n, n)) ; - // GRB_TRY (GrB_assign (bc_update, NULL, NULL, 1, GrB_ALL, n, GrB_ALL, n, - // NULL)) ; - // // W: empty n-by-n array, as workspace - // GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; - - GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; - GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; - GRB_TRY (GrB_Matrix_new (&Fd1A, GrB_FP64, n, n)) ; - GRB_TRY (GrB_Vector_new(&temp_update, GrB_FP64, n)) ; // Create a temporary vector - - // Backtrack through the BFS and compute centrality updates for each vertex - while (depth >= 2) - { - printf ("backtrack depth %ld\n", depth) ; - GrB_Vector f_d = S[depth] ; - GrB_Vector f_d1 = S[depth - 1] ; - - // 18 w = S(d, :) ÷ p × v + S(d, :) - // 19 U = A .× w - // 20 w = S(d − 1, :) × p - // 21 U = w .× U - - // make J Matrix - - GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_RS)) ; - - GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; - GxB_print (J_matrix, 5) ; - - // make I matrix - - GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, GrB_ALL, n, GrB_DESC_RS)) ; - - GRB_TRY (GrB_Matrix_diag(&I_matrix, I_vec, 0)) ; - GxB_print (J_matrix, 5) ; + // printf ("depth: %ld\n", depth) ; + // for (int64_t d = 1 ; d <= depth ; d++) + // { + // printf ("------------------- S [%ld]\n", d) ; + // GxB_print (S [d], 5) ; + // } + + // printf(" after:\n") ; + // GxB_print(frontier, 5) ; + + // GRB_TRY (GrB_free (&frontier)) ; + + + // ========================================================================= + // === Betweenness centrality computation phase ============================ + // ========================================================================= + + // bc_update = ones (n, n) ; a full matrix (and stays full) + GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; + GRB_TRY (GrB_assign(bc_update, NULL, NULL, 0.0, GrB_ALL, n, NULL)) ; + // // W: empty n-by-n array, as workspace + // GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; + + // GxB_print (bc_update, 5) ; + + + GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; + GRB_TRY (GrB_Matrix_new (&Fd1A, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new(&temp_update, GrB_FP64, n)) ; // Create a temporary vector + + // Backtrack through the BFS and compute centrality updates for each vertex + // GrB_Index fd1_size; + while (depth >= 1) + { + printf ("backtrack depth %ld\n", depth) ; + GrB_Vector f_d = S[depth] ; + GrB_Vector f_d1 = S[depth - 1] ; + + // GRB_TRY (GrB_Vector_nvals (&fd1_size, f_d1)) ; + if (f_d1 == NULL) { + GRB_TRY (GrB_Vector_new(&f_d1, GrB_FP64, n)) ; + GRB_TRY (GrB_Vector_setElement_FP64(f_d1, 0, 0)) ; + } + + printf("#####################################\n") ; + printf("predecessors (frontier):\n") ; + GxB_print (f_d, 5) ; + GxB_print (f_d1, 5) ; + + // 18 w = S(d, :) ÷ p × v + S(d, :) + // 19 U = A .× w + // 20 w = S(d − 1, :) × p + // 21 U = w .× U + + // make J Matrix + GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_RS)) ; + // GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, GrB_PLUS_FP64, bc_update, paths, GrB_DESC_RS)) ; + GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; + + // make I matrix + GRB_TRY (GrB_Vector_extract (I_vec, f_d1, NULL, paths, GrB_ALL, n, GrB_DESC_RS)) ; + GRB_TRY (GrB_Matrix_diag(&I_matrix, I_vec, 0)) ; + + // combine + + // intermediate matrix for Fd1 * A + // GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, I_matrix, AT, NULL)) ; + GRB_TRY(GrB_mxm(Fd1A, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP32, + I_matrix, A, NULL)) ; + // GxB_print (Fd1A, 5) ; + + // GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, J_matrix, NULL)) ; + GRB_TRY(GrB_mxm(U, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP32, + Fd1A, J_matrix, NULL)) ; + GxB_print (U, 5) ; + - // combine + // GxB_print (centrality_temp, 5) ; - // intermediate matrix for Fd1 * A - GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, J_matrix, A, NULL)) ; + // 22 B = B + U + // GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; + GRB_TRY (GrB_eWiseAdd (centrality_temp, NULL, NULL, GrB_PLUS_FP64, centrality_temp, U, NULL)) ; - GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, I_matrix, NULL)) ; - // 22 B = B + U - GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; - // GRB_TRY (GrB_eWiseAdd (*centrality_temp, NULL, GrB_PLUS_FP64, U, *centrality, NULL)) ; + // 23 v = U +. + // Reduce "update" matrix to a vector (sum each column) + GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, U, NULL)) ; + // GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GxB_ANY_FP64_MONOID, U, NULL)) ; + GRB_TRY (GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)) ; - // 23 v = U +. + printf("#####################################\n sigma:\n") ; + GxB_print (paths, 5) ; + printf("delta:\n") ; + GxB_print (bc_update, 5) ; + printf("betweenness:\n") ; + GxB_print (centrality_temp, 5) ; + printf("#####################################\n") ; - // Reduce "update" matrix to a vector (sum each column) - GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, U, NULL)) ; - GRB_TRY (GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)) ; + // Grb_reduce_monoid - // Grb_reduce_monoid + // 24 d = d − 1 + depth-- ; + } - // 24 d = d − 1 + } + // ========================================================================= // === finalize the centrality ============================================= // ========================================================================= From 1f080775d654ebf453fc4bb29731b8b687a5883b Mon Sep 17 00:00:00 2001 From: Tim Davis Date: Wed, 5 Mar 2025 12:09:13 -0600 Subject: [PATCH 06/10] in meeting, Mar 5 --- .../LAGr_EdgeBetweennessCentrality.c | 26 ++++++------ .../test/test_edgeBetweennessCentrality.c | 40 ++++++++++++------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 354324b1fb..8244ee3527 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -192,7 +192,7 @@ int LAGr_EdgeBetweennessCentrality // Initialize paths and frontier with source notes GRB_TRY (GrB_Matrix_nrows (&n, A)) ; GRB_TRY (GrB_Vector_new (&paths, GrB_FP64, n)) ; - GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; // todo: change to bool? + GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; // GRB_TRY (LG_SET_FORMAT_HINT (paths, LG_BITMAP + LG_FULL)) ; GRB_TRY (GrB_Matrix_new (&U, GrB_FP64, n, n)) ; @@ -202,6 +202,7 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; + // FIXME: rename this: // Initialize centrality_temp matrix with zeros using A as structural mask LG_TRY (GrB_Matrix_new(¢rality_temp, GrB_FP64, n, n)) ; GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ; @@ -229,8 +230,14 @@ int LAGr_EdgeBetweennessCentrality // GrB_free (&(S [0])) ; // LG_TRY (LAGraph_Vector_Structure (&(S [0]), frontier, msg)) ; + // root frontier: S [0](root) = true + GrB_free (&(S [0])) ; + GRB_TRY (GrB_Vector_new(&(S [0]), GrB_BOOL, n)) ; + GRB_TRY (GrB_Vector_setElement_BOOL(S [0], (bool) true, root)) ; + + // clear paths, and then set paths (root) = 1 GRB_TRY (GrB_Vector_clear (paths)) ; - GRB_TRY (GrB_Vector_setElement (paths, 1.0, root)) ; + GRB_TRY (GrB_Vector_setElement (paths, (double) 1.0, root)) ; GRB_TRY (GrB_Matrix_clear (U)) ; @@ -264,7 +271,7 @@ int LAGr_EdgeBetweennessCentrality LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; //---------------------------------------------------------------------- - // Update frontier: frontier = frontier*A x !paths + // Update frontier: frontier = frontier*A //---------------------------------------------------------------------- GRB_TRY (LG_SET_FORMAT_HINT (frontier, LG_SPARSE)) ; @@ -318,12 +325,6 @@ int LAGr_EdgeBetweennessCentrality GrB_Vector f_d = S[depth] ; GrB_Vector f_d1 = S[depth - 1] ; - // GRB_TRY (GrB_Vector_nvals (&fd1_size, f_d1)) ; - if (f_d1 == NULL) { - GRB_TRY (GrB_Vector_new(&f_d1, GrB_FP64, n)) ; - GRB_TRY (GrB_Vector_setElement_FP64(f_d1, 0, 0)) ; - } - printf("#####################################\n") ; printf("predecessors (frontier):\n") ; GxB_print (f_d, 5) ; @@ -347,12 +348,12 @@ int LAGr_EdgeBetweennessCentrality // intermediate matrix for Fd1 * A // GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, I_matrix, AT, NULL)) ; - GRB_TRY(GrB_mxm(Fd1A, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP32, + GRB_TRY(GrB_mxm(Fd1A, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, I_matrix, A, NULL)) ; // GxB_print (Fd1A, 5) ; // GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, J_matrix, NULL)) ; - GRB_TRY(GrB_mxm(U, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP32, + GRB_TRY(GrB_mxm(U, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, Fd1A, J_matrix, NULL)) ; GxB_print (U, 5) ; @@ -360,7 +361,8 @@ int LAGr_EdgeBetweennessCentrality // GxB_print (centrality_temp, 5) ; // 22 B = B + U - // GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, NULL)) ; + // GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, + // GrB_DESC_S)) ; GRB_TRY (GrB_eWiseAdd (centrality_temp, NULL, NULL, GrB_PLUS_FP64, centrality_temp, U, NULL)) ; diff --git a/experimental/test/test_edgeBetweennessCentrality.c b/experimental/test/test_edgeBetweennessCentrality.c index 2fd07b8f87..acec3cced8 100644 --- a/experimental/test/test_edgeBetweennessCentrality.c +++ b/experimental/test/test_edgeBetweennessCentrality.c @@ -56,7 +56,7 @@ double difference(GrB_Matrix bc, double* gap_result, GrB_Index rows, GrB_Index c // GxB_print (diff, 5) ; OK(GrB_apply(diff, NULL, NULL, GrB_ABS_FP64, diff, NULL)); - float err = 0; + double err = 0; OK(GrB_reduce(&err, NULL, GrB_MAX_MONOID_FP64, diff, NULL)); OK(GrB_free(&diff)); @@ -159,20 +159,22 @@ void test_diamonds_ebc (void) int result = LAGraph_Cached_AT (G, msg) ; TEST_CHECK (result == ok_result) ; + // compute its betweenness centrality with C version + OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; + double err = difference(centrality, &diamonds_ebc[0][0], 8, 8) ; + printf ("diamonds: err: %e (C version)\n", err) ; + TEST_CHECK (err < 1e-4) ; + OK (GrB_free (¢rality)) ; - // compute its betweenness centrality + // compute its betweenness centrality with GraphBLAS version OK (LAGr_EdgeBetweennessCentrality (¢rality, G, msg)) ; - // OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; - - // compare with GAP: - double err = difference(centrality, &diamonds_ebc[0][0], 8, 8) ; - printf ("diamonds: err: %e\n", err) ; + err = difference(centrality, &diamonds_ebc[0][0], 8, 8) ; + printf ("diamonds: err: %e (pure GraphBLAS)\n", err) ; TEST_CHECK (err < 1e-4) ; OK (GrB_free (¢rality)) ; - OK (LAGraph_Delete (&G, msg)) ; + OK (LAGraph_Delete (&G, msg)) ; LAGraph_Finalize (msg) ; - } //------------------------------------------------------------------------------ @@ -195,16 +197,21 @@ void test_karate_ebc (void) OK (LAGraph_New (&G, &A, LAGraph_ADJACENCY_UNDIRECTED, msg)) ; TEST_CHECK (A == NULL) ; // A has been moved into G->A - // compute its betweenness centrality + // compute its betweenness centrality (C version) OK (LG_check_edgeBetweennessCentrality (¢rality, G, msg)) ; + double err = difference(centrality, &karate_ebc[0][0], 34, 34) ; + printf ("karate: err: %e (C version)\n", err) ; + TEST_CHECK (err < 1e-4) ; + OK (GrB_free (¢rality)) ; - // compare with GAP: - float err = difference(centrality, &karate_ebc[0][0], 34, 34) ; - printf ("karate: err: %e\n", err) ; + // compute its betweenness centrality (GraphBLAS version) + OK (LAGr_EdgeBetweennessCentrality (¢rality, G, msg)) ; + err = difference(centrality, &karate_ebc[0][0], 34, 34) ; + printf ("karate: err: %e (GraphBLAS version)\n", err) ; TEST_CHECK (err < 1e-4) ; OK (GrB_free (¢rality)) ; - OK (LAGraph_Delete (&G, msg)) ; + OK (LAGraph_Delete (&G, msg)) ; LAGraph_Finalize (msg) ; } @@ -213,8 +220,11 @@ void test_karate_ebc (void) // list of tests //------------------------------------------------------------------------------ +// FIXME: add more matrices + TEST_LIST = { {"test_diamonds_ebc", test_diamonds_ebc}, - // {"test_karate_ebc", test_karate_ebc}, + {"test_karate_ebc", test_karate_ebc}, +// {"test_many", test_many}, FIXME ADD THIS {NULL, NULL} }; From 2766a949b9f3ac5e1d50ea0117022fa7ac1f278e Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 19 Mar 2025 09:54:52 -0500 Subject: [PATCH 07/10] remove commented print statements on check_ebc --- .../test/LG_check_edgeBetweennessCentrality.c | 142 +----------------- 1 file changed, 1 insertion(+), 141 deletions(-) diff --git a/experimental/test/LG_check_edgeBetweennessCentrality.c b/experimental/test/LG_check_edgeBetweennessCentrality.c index f61c6045e9..35e81050fb 100644 --- a/experimental/test/LG_check_edgeBetweennessCentrality.c +++ b/experimental/test/LG_check_edgeBetweennessCentrality.c @@ -114,25 +114,7 @@ int LG_check_edgeBetweennessCentrality LG_ASSERT_MSG (AT != NULL, LAGRAPH_NOT_CACHED, "G->AT is required") ; } - // better: as basic algo - /* - GrB_Matrix A_temp = NULL - if nself_edges is unknown - compute it - if any self edges - copy G->A into A_temp - remove self edges from A_temp - A = A_temp - now A has no self edges - when done: free A_temp - */ - - // hack: - // G->nself_edges = LAGRAPH_UNKNOWN ; <=== overkill - - // GRB_TRY (LAGraph_Graph_Print (G, 500, stdout, msg)) ; - // GxB_print (A, 5) ; - // GxB_print (AT, 5) ; + //-------------------------------------------------------------------------- LG_CLEAR_MSG ; @@ -162,7 +144,6 @@ int LG_check_edgeBetweennessCentrality // Initialize centrality matrix result to 0 // 1. result [(v, w)] ← 0, ∀(v, w) ∈ E - // TODO make this a copy of A except with 1 = 0 // A temporary result centrality matrix initialized to 0 for all vertice, // -- further changes would need to be made to make it a dictionary of edges. GrB_Index result_size = n * n ; @@ -186,11 +167,6 @@ int LG_check_edgeBetweennessCentrality Phead = ATp ; - // for (size_t i = 0; i < Aj_size; i++) { - // printf("%ld ", Aj[i]); - // } - // printf("\n"); - //-------------------------------------------------------------------------- LG_TRY(LAGraph_Malloc((void **)&Pj, nvals, sizeof(GrB_Index), msg)); @@ -204,7 +180,6 @@ int LG_check_edgeBetweennessCentrality size_t sp = 0; // Initialize predecessors list P[w] to empty - // TODO // 5. P [w] ← empty queue, ∀w ∈ V memcpy (Ptail, ATp, n * sizeof (GrB_Index)) ; @@ -237,16 +212,11 @@ int LG_check_edgeBetweennessCentrality // 13. push(S, v) S [sp++] = v; - // if (s < 10) printf("v: %ld\n", v); - // TODO // traverse all entries in A(v,:) for (int64_t p = Ap [v] ; p < Ap [v+1] ; p++) { int64_t w = Aj [p] ; - // if (s < 10) printf(" w: %ld\n", w); - - // printf(" %ld - d[w] (%ld) < 0?\n", w, d [w]); // 16. if d[w] < 0 if (d [w] < 0) { // Update depth and enqueue @@ -254,17 +224,12 @@ int LG_check_edgeBetweennessCentrality queue [qt++] = w ; // 19. d[w] ← d[v] + 1 d [w] = d [v] + 1 ; - // printf(" changed d[w] (%ld) = d[v] (%ld) + 1\n", d [w], d [v] ); - } - // printf(" %ld - d[w] (%ld) == d[v] (%ld) + 1?\n", w, d [w], d [v]); - // 20. if d[w] = d[v] + 1 if (d [w] == d [v] + 1) { // Update shortest path count and add predecessor // 22. σ[w] ← σ[w] + σ[v] - // printf(" sigma[w] (%g) = sigma[w] (%g) + sigma[v] (%g)\n", sigma[w]+sigma[v], sigma[w], sigma[v]); sigma [w] = sigma [w] + sigma [v] ; // 23. append(P [w], v) if (Ptail [w] >= Phead [w+1] || Ptail [w] < Phead [w]) @@ -274,93 +239,29 @@ int LG_check_edgeBetweennessCentrality fflush (stdout) ; abort ( ) ; } Pj [Ptail [w]++] = v ; - // printf(" added\n Pj: "); - - // for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { - // printf("%ld ", Pj [p]) ; - // } - // printf("\n"); - } } - // printf("\n"); } - // if (s < 10) { - - // printf("==========================================\n"); - - // for (int64_t w = 0; w < n; w++) { - // printf("%ld's: ", w); - // for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { - // printf("%ld ", Pj [p]) ; - // } - // printf("\n"); - // } - // printf("\n"); - - // } - // Set dependency score δ[v] ← 0 // 24. δ[v] ← 0, ∀v ∈ V for (size_t v = 0; v < n; v++) { delta [v] = 0 ; } - - // PRINT OUT STUFF - // printf("==========================================\n"); - // printf("d:\n"); - // for (size_t i = 0; i < n; i++) { - // printf("(%ld, %ld) ", i, d[i]); - // } - // printf("\n"); - - // printf("delta:\n"); - // for (size_t i = 0; i < n; i++) { - // printf("(%ld, %g) ", i, delta[i]); - // } - // printf("\n"); - - // printf("S:\n"); - // for (size_t i = 0; i < n; i++) { - // printf("(%ld, %ld) ", i, S[i]); - // } - // printf("\n"); - - // printf("queue:\n"); - // for (size_t i = 0; i < n; i++) { - // printf("(%ld, %ld) ", i, queue[i]); - // } - // printf("\n"); - - // printf("sigma:\n"); - // for (size_t i = 0; i < n; i++) { - // printf("(%ld, %g) ", i, sigma[i]); - // } - // printf("\n==========================================\n"); - // printf("\n"); - - // Process stack S // 25. while ¬empty(S) while (sp > 0) { // 27. w ← pop(S) int64_t w = S [--sp] ; - // if (s < 10) printf("w: %ld\n", w); - // 28. for v ∈ P [w] for (int64_t p = Phead [w] ; p < Ptail [w] ; p++) { int64_t v = Pj [p] ; - // if (s < 10) printf(" v: %ld\n", v); // Update dependency and centrality values // 30. δ[v] ← δ[v] + σ[v] × ( δ[w]/σ[w] + 1) - // if (s < 10) printf(" %g = %g * (%g + 1)/%g\n", sigma [v] * ((delta [w] + 1) / sigma [w]), sigma [v], delta [w], sigma [w]) ; - - // if (v == w) { printf ("Ack!!\n") ; fflush (stdout) ; abort ( ) ; } if (v == w) { printf (" Ack!!\n") ; fflush (stdout) ; abort ( ) ; continue; @@ -371,34 +272,7 @@ int LG_check_edgeBetweennessCentrality // 31. result [(v, w)] ← result [(v, w)] + σ[v] × ( δ[w]/σ[w] + 1) result [INDEX (v,w)] += centrality; - // result [INDEX (w,v)] += centrality; - // if (s < 10) printf(" result: %g\n", result[INDEX(v,w)]); - - // if (result [INDEX (v,w)] == 0) { - // result [INDEX (w,v)] += centrality; - // if (s < 10) printf(" result: %g\n", result[INDEX(w,v)]); - - // } - // else { - // result [INDEX (v,w)] += centrality; - // if (s < 10) printf(" result: %g\n", result[INDEX(v,w)]); - // } - - // if (s < 10) { - // printf(" delta:\n "); - // for (size_t i = 0; i < n; i++) { - // printf(" (%ld, %g)", i, delta[i]); - // } - // printf("\n"); - // printf(" sigma:\n "); - // for (size_t i = 0; i < n; i++) { - // printf(" (%ld, %g)", i, sigma[i]); - // } - // printf("\n"); - // } - } - // if (s < 10) printf("\n"); } @@ -422,20 +296,6 @@ int LG_check_edgeBetweennessCentrality &ATp, &ATj, &ATx, ATp_size, ATj_size, ATx_size, AT_iso, false, NULL)) ; #endif - // printf("result: \n") ; - // for (int64_t i = 0 ; i < n ; i++) - // { - // printf ("row: %ld\n", i) ; - // for (int64_t j = 0 ; j < n ; j++) - // { - // int64_t p = INDEX (i,j) ; - // double aij = result [p] ; - // printf(" C(%ld,%ld) = %g\n", i, j, aij) ; - // // numerical value of A(i,j) - // } - // printf("\n") ; - // } - #if 0 GrB_Info GxB_Matrix_pack_FullR // pack a full matrix, held by row ( From 1c67847605f0c669d82d4ba832baf3aad61ae881 Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 19 Mar 2025 10:02:01 -0500 Subject: [PATCH 08/10] remove print statements --- .../LAGr_EdgeBetweennessCentrality.c | 74 ------------------- .../test/LG_check_edgeBetweennessCentrality.c | 2 - 2 files changed, 76 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index 8244ee3527..e843e7e910 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -36,7 +36,6 @@ GrB_free (&bc_update) ; \ GrB_free (&temp_update) ; \ GrB_free (&Add_One_Divide) ; \ - GrB_free (&v) ; \ GrB_free (&U) ; \ if (S != NULL) \ { \ @@ -141,8 +140,6 @@ int LAGr_EdgeBetweennessCentrality // each starting node. A dense matrix. GrB_Matrix U = NULL ; - GrB_Vector v = NULL ; - GrB_BinaryOp Add_One_Divide = NULL ; GrB_Matrix centrality_temp = NULL; @@ -154,9 +151,6 @@ int LAGr_EdgeBetweennessCentrality GrB_Matrix Fd1A = NULL ; GrB_Vector temp_update = NULL ; - // Temporary workspace matrix (sparse). - // GrB_Matrix W = NULL ; - GrB_Index n = 0 ; // # nodes in the graph LG_ASSERT (centrality != NULL, GrB_NULL_POINTER) ; @@ -178,9 +172,6 @@ int LAGr_EdgeBetweennessCentrality LG_ASSERT_MSG (AT != NULL, LAGRAPH_NOT_CACHED, "G->AT is required") ; } - printf ("G->A is:\n") ;GxB_print (A, 5) ; - printf ("G->AT is:\n") ;GxB_print (AT, 5) ; - // ========================================================================= // === initialization ===================================================== // ========================================================================= @@ -193,12 +184,9 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Matrix_nrows (&n, A)) ; GRB_TRY (GrB_Vector_new (&paths, GrB_FP64, n)) ; GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; - // GRB_TRY (LG_SET_FORMAT_HINT (paths, LG_BITMAP + LG_FULL)) ; GRB_TRY (GrB_Matrix_new (&U, GrB_FP64, n, n)) ; - GRB_TRY (GrB_Vector_new (&v, GrB_FP64, n)) ; - GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; @@ -207,10 +195,6 @@ int LAGr_EdgeBetweennessCentrality LG_TRY (GrB_Matrix_new(¢rality_temp, GrB_FP64, n, n)) ; GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ; - // Initial frontier: frontier= frontier*A - // GRB_TRY (GrB_vxv (frontier, paths, NULL, LAGraph_plus_first_fp64, - // frontier, A, GrB_DESC_RSC)) ; - // Allocate memory for the array of S vectors LG_TRY (LAGraph_Calloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; @@ -224,11 +208,7 @@ int LAGr_EdgeBetweennessCentrality int64_t depth, root ; for (root = 0 ; root < n ; root++) { - printf("----\n"); - printf("root: %ld \n", root) ; depth = 0 ; -// GrB_free (&(S [0])) ; -// LG_TRY (LAGraph_Vector_Structure (&(S [0]), frontier, msg)) ; // root frontier: S [0](root) = true GrB_free (&(S [0])) ; @@ -241,17 +221,11 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Matrix_clear (U)) ; - GRB_TRY (GrB_Vector_clear (v)) ; - // Extract row root from A into frontier vector: frontier = AT(root,:) - // GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, A, GrB_ALL, n, root, - // GrB_DESC_T0)) ; GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, AT, GrB_ALL, n, root, NULL)) ; GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; - GxB_print(frontier, 5) ; - while (frontier_size != 0) { depth++ ; @@ -286,18 +260,6 @@ int LAGr_EdgeBetweennessCentrality GRB_TRY (GrB_Vector_nvals (&frontier_size, frontier)) ; } - // printf ("depth: %ld\n", depth) ; - // for (int64_t d = 1 ; d <= depth ; d++) - // { - // printf ("------------------- S [%ld]\n", d) ; - // GxB_print (S [d], 5) ; - // } - - // printf(" after:\n") ; - // GxB_print(frontier, 5) ; - - // GRB_TRY (GrB_free (&frontier)) ; - // ========================================================================= // === Betweenness centrality computation phase ============================ @@ -306,11 +268,6 @@ int LAGr_EdgeBetweennessCentrality // bc_update = ones (n, n) ; a full matrix (and stays full) GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; GRB_TRY (GrB_assign(bc_update, NULL, NULL, 0.0, GrB_ALL, n, NULL)) ; - // // W: empty n-by-n array, as workspace - // GRB_TRY (GrB_Matrix_new (&W, GrB_FP64, n, n)) ; - - // GxB_print (bc_update, 5) ; - GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; @@ -321,15 +278,9 @@ int LAGr_EdgeBetweennessCentrality // GrB_Index fd1_size; while (depth >= 1) { - printf ("backtrack depth %ld\n", depth) ; GrB_Vector f_d = S[depth] ; GrB_Vector f_d1 = S[depth - 1] ; - printf("#####################################\n") ; - printf("predecessors (frontier):\n") ; - GxB_print (f_d, 5) ; - GxB_print (f_d1, 5) ; - // 18 w = S(d, :) ÷ p × v + S(d, :) // 19 U = A .× w // 20 w = S(d − 1, :) × p @@ -350,15 +301,11 @@ int LAGr_EdgeBetweennessCentrality // GRB_TRY (GrB_eWiseMult(Fd1A, NULL, NULL, GrB_TIMES_FP64, I_matrix, AT, NULL)) ; GRB_TRY(GrB_mxm(Fd1A, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, I_matrix, A, NULL)) ; - // GxB_print (Fd1A, 5) ; // GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, J_matrix, NULL)) ; GRB_TRY(GrB_mxm(U, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, Fd1A, J_matrix, NULL)) ; - GxB_print (U, 5) ; - - // GxB_print (centrality_temp, 5) ; // 22 B = B + U // GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, @@ -373,16 +320,6 @@ int LAGr_EdgeBetweennessCentrality // GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GxB_ANY_FP64_MONOID, U, NULL)) ; GRB_TRY (GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)) ; - printf("#####################################\n sigma:\n") ; - GxB_print (paths, 5) ; - printf("delta:\n") ; - GxB_print (bc_update, 5) ; - printf("betweenness:\n") ; - GxB_print (centrality_temp, 5) ; - printf("#####################################\n") ; - - // Grb_reduce_monoid - // 24 d = d − 1 depth-- ; } @@ -395,19 +332,8 @@ int LAGr_EdgeBetweennessCentrality // === finalize the centrality ============================================= // ========================================================================= - GxB_print(centrality_temp, GxB_COMPLETE) ; - *centrality = centrality_temp; - // Initialize the centrality array with -n to avoid counting - // zero length paths - // GRB_TRY (GrB_Vector_new (centrality, GrB_FP64, n)) ; - // GRB_TRY (GrB_assign (*centrality, NULL, NULL, -n, GrB_ALL, n, NULL)) ; - - // // centrality (i) += sum (bc_update (:,i)) for all nodes i - // GRB_TRY (GrB_reduce (*centrality, NULL, GrB_PLUS_FP64, GrB_PLUS_MONOID_FP64, - // bc_update, GrB_DESC_T0)) ; - LG_FREE_WORK ; return (GrB_SUCCESS) ; } diff --git a/experimental/test/LG_check_edgeBetweennessCentrality.c b/experimental/test/LG_check_edgeBetweennessCentrality.c index 35e81050fb..a1eae228c2 100644 --- a/experimental/test/LG_check_edgeBetweennessCentrality.c +++ b/experimental/test/LG_check_edgeBetweennessCentrality.c @@ -314,8 +314,6 @@ GrB_Info GxB_Matrix_pack_FullR // pack a full matrix, held by row LG_TRY (GrB_assign(C_temp, A, NULL, C_temp, GrB_ALL, n, GrB_ALL, n, GrB_DESC_RS)) ; - GxB_print(C_temp, GxB_COMPLETE) ; - *C = C_temp; //-------------------------------------------------------------------------- From 938c0a001240e8098157848087d6a85ca6328897 Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 19 Mar 2025 10:17:47 -0500 Subject: [PATCH 09/10] rename variables --- .../LAGr_EdgeBetweennessCentrality.c | 97 +++++++++---------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c index e843e7e910..9fea4ae129 100644 --- a/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c +++ b/experimental/algorithm/LAGr_EdgeBetweennessCentrality.c @@ -33,24 +33,23 @@ GrB_free (&I_matrix) ; \ GrB_free (&Fd1A) ; \ GrB_free (&paths) ; \ - GrB_free (&bc_update) ; \ + GrB_free (&bc_vertex_flow) ; \ GrB_free (&temp_update) ; \ GrB_free (&Add_One_Divide) ; \ - GrB_free (&U) ; \ - if (S != NULL) \ + GrB_free (&Update) ; \ + if (Search != NULL) \ { \ for (int64_t i = 0 ; i < n ; i++) \ { \ - GrB_free (&(S [i])) ; \ + GrB_free (&(Search [i])) ; \ } \ - LAGraph_Free ((void **) &S, NULL) ; \ + LAGraph_Free ((void **) &Search, NULL) ; \ } \ } #define LG_FREE_ALL \ { \ LG_FREE_WORK ; \ - GrB_free (¢rality_temp) ; \ GrB_free (centrality) ; \ } @@ -119,12 +118,12 @@ int LAGr_EdgeBetweennessCentrality LG_CLEAR_MSG ; // Array of BFS search matrices. - // S [i] is a sparse matrix that stores the depth at which each vertex is + // Search [i] is a sparse matrix that stores the depth at which each vertex is // first seen thus far in each BFS at the current depth i. Each column // corresponds to a BFS traversal starting from a source node. - GrB_Vector *S = NULL ; + GrB_Vector *Search = NULL ; - // Frontier matrix, a sparse matrix. + // Frontier vector, a sparse matrix. // Stores # of shortest paths to vertices at current BFS depth GrB_Vector frontier = NULL ; @@ -133,17 +132,14 @@ int LAGr_EdgeBetweennessCentrality // sparse updates, and also used as a mask. GrB_Vector paths = NULL ; - // the delta vector for each node for each starting node. A dense matrix. - GrB_Vector bc_update = NULL ; + // The betweenness centrality each vertex. A dense vector. + GrB_Vector bc_vertex_flow = NULL ; - // Update matrix for betweenness centrality, values for each node for - // each starting node. A dense matrix. - GrB_Matrix U = NULL ; + // Update matrix for betweenness centrality for each edge. A sparse matrix. + GrB_Matrix Update = NULL ; GrB_BinaryOp Add_One_Divide = NULL ; - GrB_Matrix centrality_temp = NULL; - GrB_Vector J_vec = NULL ; GrB_Vector I_vec = NULL ; GrB_Matrix I_matrix = NULL ; @@ -180,23 +176,20 @@ int LAGr_EdgeBetweennessCentrality GrB_FP64, GrB_FP64, GrB_FP64, "add_one_divide_function", ADD_ONE_DIVIDE_FUNCTION_DEFN)) ; - // Initialize paths and frontier with source notes + // Initialize the frontier, paths, Update, and bc_vertex_flow GRB_TRY (GrB_Matrix_nrows (&n, A)) ; GRB_TRY (GrB_Vector_new (&paths, GrB_FP64, n)) ; GRB_TRY (GrB_Vector_new (&frontier, GrB_FP64, n)) ; + GRB_TRY (GrB_Matrix_new (&Update, GrB_FP64, n, n)) ; + GRB_TRY (GrB_Vector_new (&bc_vertex_flow, GrB_FP64, n)) ; - GRB_TRY (GrB_Matrix_new (&U, GrB_FP64, n, n)) ; - - GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; - - - // FIXME: rename this: - // Initialize centrality_temp matrix with zeros using A as structural mask - LG_TRY (GrB_Matrix_new(¢rality_temp, GrB_FP64, n, n)) ; - GRB_TRY (GrB_assign (centrality_temp, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ; + + // Initialize centrality matrix with zeros using A as structural mask + LG_TRY (GrB_Matrix_new(centrality, GrB_FP64, n, n)) ; + GRB_TRY (GrB_assign (*centrality, A, NULL, 0.0, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ; // Allocate memory for the array of S vectors - LG_TRY (LAGraph_Calloc ((void **) &S, n+1, sizeof (GrB_Vector), msg)) ; + LG_TRY (LAGraph_Calloc ((void **) &Search, n+1, sizeof (GrB_Vector), msg)) ; // ========================================================================= // === Breadth-first search stage ========================================== @@ -210,16 +203,16 @@ int LAGr_EdgeBetweennessCentrality { depth = 0 ; - // root frontier: S [0](root) = true - GrB_free (&(S [0])) ; - GRB_TRY (GrB_Vector_new(&(S [0]), GrB_BOOL, n)) ; - GRB_TRY (GrB_Vector_setElement_BOOL(S [0], (bool) true, root)) ; + // root frontier: Search [0](root) = true + GrB_free (&(Search [0])) ; + GRB_TRY (GrB_Vector_new(&(Search [0]), GrB_BOOL, n)) ; + GRB_TRY (GrB_Vector_setElement_BOOL(Search [0], (bool) true, root)) ; // clear paths, and then set paths (root) = 1 GRB_TRY (GrB_Vector_clear (paths)) ; GRB_TRY (GrB_Vector_setElement (paths, (double) 1.0, root)) ; - GRB_TRY (GrB_Matrix_clear (U)) ; + GRB_TRY (GrB_Matrix_clear (Update)) ; // Extract row root from A into frontier vector: frontier = AT(root,:) GRB_TRY (GrB_Col_extract (frontier, NULL, NULL, AT, GrB_ALL, n, root, @@ -241,8 +234,8 @@ int LAGr_EdgeBetweennessCentrality // Add frontier to S: S(depth, :) = frontier //---------------------------------------------------------------------- - GrB_free (&(S [depth])) ; - LG_TRY (LAGraph_Vector_Structure (&(S [depth]), frontier, msg)) ; + GrB_free (&(Search [depth])) ; + LG_TRY (LAGraph_Vector_Structure (&(Search [depth]), frontier, msg)) ; //---------------------------------------------------------------------- // Update frontier: frontier = frontier*A @@ -265,9 +258,9 @@ int LAGr_EdgeBetweennessCentrality // === Betweenness centrality computation phase ============================ // ========================================================================= - // bc_update = ones (n, n) ; a full matrix (and stays full) - GRB_TRY (GrB_Vector_new (&bc_update, GrB_FP64, n)) ; - GRB_TRY (GrB_assign(bc_update, NULL, NULL, 0.0, GrB_ALL, n, NULL)) ; + // bc_vertex_flow = ones (n, n) ; a full matrix (and stays full) + GRB_TRY (GrB_Vector_new (&bc_vertex_flow, GrB_FP64, n)) ; + GRB_TRY (GrB_assign(bc_vertex_flow, NULL, NULL, 0.0, GrB_ALL, n, NULL)) ; GRB_TRY (GrB_Vector_new(&J_vec, GrB_FP64, n)) ; GRB_TRY (GrB_Vector_new (&I_vec, GrB_FP64, n)) ; @@ -278,17 +271,17 @@ int LAGr_EdgeBetweennessCentrality // GrB_Index fd1_size; while (depth >= 1) { - GrB_Vector f_d = S[depth] ; - GrB_Vector f_d1 = S[depth - 1] ; + GrB_Vector f_d = Search [depth] ; + GrB_Vector f_d1 = Search [depth - 1] ; // 18 w = S(d, :) ÷ p × v + S(d, :) - // 19 U = A .× w + // 19 Update = A .× w // 20 w = S(d − 1, :) × p - // 21 U = w .× U + // 21 Update = w .× U // make J Matrix - GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_update, paths, GrB_DESC_RS)) ; - // GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, GrB_PLUS_FP64, bc_update, paths, GrB_DESC_RS)) ; + GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, Add_One_Divide, bc_vertex_flow, paths, GrB_DESC_RS)) ; + // GRB_TRY (GrB_eWiseMult(J_vec, f_d, NULL, GrB_PLUS_FP64, bc_vertex_flow, paths, GrB_DESC_RS)) ; GRB_TRY (GrB_Matrix_diag(&J_matrix, J_vec, 0)) ; // make I matrix @@ -303,22 +296,22 @@ int LAGr_EdgeBetweennessCentrality I_matrix, A, NULL)) ; // GRB_TRY (GrB_eWiseMult(U, NULL, NULL, GrB_TIMES_FP64, Fd1A, J_matrix, NULL)) ; - GRB_TRY(GrB_mxm(U, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, + GRB_TRY(GrB_mxm(Update, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, Fd1A, J_matrix, NULL)) ; - // 22 B = B + U - // GRB_TRY (GrB_assign(centrality_temp, centrality_temp, GrB_PLUS_FP64, U, GrB_ALL, n, GrB_ALL, n, + // 22 centrality = centrality + Update + // GRB_TRY (GrB_assign(centrality, centrality, GrB_PLUS_FP64, Update, GrB_ALL, n, GrB_ALL, n, // GrB_DESC_S)) ; - GRB_TRY (GrB_eWiseAdd (centrality_temp, NULL, NULL, GrB_PLUS_FP64, centrality_temp, U, NULL)) ; + GRB_TRY (GrB_eWiseAdd (*centrality, NULL, NULL, GrB_PLUS_FP64, *centrality, Update, NULL)) ; - // 23 v = U +. + // 23 v = Update +. // Reduce "update" matrix to a vector (sum each column) - GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, U, NULL)) ; - // GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GxB_ANY_FP64_MONOID, U, NULL)) ; - GRB_TRY (GrB_eWiseAdd(bc_update, NULL, NULL, GrB_PLUS_FP64, bc_update, temp_update, NULL)) ; + GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GrB_PLUS_MONOID_FP64, Update, NULL)) ; + // GRB_TRY (GrB_reduce(temp_update, NULL, NULL, GxB_ANY_FP64_MONOID, Update, NULL)) ; + GRB_TRY (GrB_eWiseAdd(bc_vertex_flow, NULL, NULL, GrB_PLUS_FP64, bc_vertex_flow, temp_update, NULL)) ; // 24 d = d − 1 depth-- ; @@ -332,8 +325,6 @@ int LAGr_EdgeBetweennessCentrality // === finalize the centrality ============================================= // ========================================================================= - *centrality = centrality_temp; - LG_FREE_WORK ; return (GrB_SUCCESS) ; } From 971fb5a83bb2c587fa6b0cb5bfca716f6950749e Mon Sep 17 00:00:00 2001 From: peicasey Date: Wed, 19 Mar 2025 10:27:54 -0500 Subject: [PATCH 10/10] rename variables in check ebc --- .../test/LG_check_edgeBetweennessCentrality.c | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/experimental/test/LG_check_edgeBetweennessCentrality.c b/experimental/test/LG_check_edgeBetweennessCentrality.c index a1eae228c2..602df6c09a 100644 --- a/experimental/test/LG_check_edgeBetweennessCentrality.c +++ b/experimental/test/LG_check_edgeBetweennessCentrality.c @@ -19,10 +19,10 @@ #define LG_FREE_WORK \ { \ LAGraph_Free ((void **) &queue, NULL) ; \ - LAGraph_Free ((void **) &d, NULL) ; \ - LAGraph_Free ((void **) &delta, NULL) ; \ + LAGraph_Free ((void **) &depth, NULL) ; \ + LAGraph_Free ((void **) &bc_vertex_flow, NULL) ; \ LAGraph_Free ((void **) &S, NULL) ; \ - LAGraph_Free ((void **) &sigma, NULL) ; \ + LAGraph_Free ((void **) &paths, NULL) ; \ LAGraph_Free ((void **) &Pj, NULL) ; \ LAGraph_Free ((void **) &Ptail, NULL) ; \ } @@ -63,10 +63,10 @@ int LG_check_edgeBetweennessCentrality double* result ; // Holds the distances (depth levels) from the source vertex. - int64_t *d = NULL ; + int64_t *depth = NULL ; - // Stores dependency scores for each vertex. - double *delta = NULL ; + // Stores the betweenness centrality for each vertex. + double *bc_vertex_flow = NULL ; // Stack used for backtracking phase int64_t *S = NULL ; @@ -78,7 +78,8 @@ int LG_check_edgeBetweennessCentrality GrB_Index *Ptail = NULL ; GrB_Index *Phead = NULL ; - double *sigma = NULL ; + // Holds the number of shortest paths for current node + double *paths = NULL ; //-------------------------------------------------------------------------- // check inputs @@ -123,9 +124,9 @@ int LG_check_edgeBetweennessCentrality // allocate workspace //-------------------------------------------------------------------------- - LG_TRY(LAGraph_Malloc((void **)&d, n, sizeof(int64_t), msg)); + LG_TRY(LAGraph_Malloc((void **)&depth, n, sizeof(int64_t), msg)); - LG_TRY(LAGraph_Calloc((void **)&delta, n, sizeof(double), msg)); + LG_TRY(LAGraph_Calloc((void **)&bc_vertex_flow, n, sizeof(double), msg)); LG_TRY(LAGraph_Malloc((void **)&S, n, sizeof(int64_t), msg)); @@ -172,7 +173,7 @@ int LG_check_edgeBetweennessCentrality LG_TRY(LAGraph_Malloc((void **)&Pj, nvals, sizeof(GrB_Index), msg)); LG_TRY(LAGraph_Malloc((void **)&Ptail, n, sizeof(GrB_Index), msg)); // might need to be + 1 - LAGraph_Calloc ((void **) &sigma, n, sizeof (double), msg) ; + LAGraph_Calloc ((void **) &paths, n, sizeof (double), msg) ; // 2. for ∀s ∈ V for (int64_t s = 0; s < n; s++) { @@ -183,19 +184,19 @@ int LG_check_edgeBetweennessCentrality // 5. P [w] ← empty queue, ∀w ∈ V memcpy (Ptail, ATp, n * sizeof (GrB_Index)) ; - // Initialize sigma[t], d[t] for all t + // Initialize paths[t], d[t] for all t // 6. σ[t] ← 0, ∀t ∈ V , σ[s] ← 1 // Keeps track of the number of shortest paths for each vertex. for (int64_t i = 0; i < n; i++) { - sigma [i] = 0 ; + paths [i] = 0 ; } - sigma [s] = 1 ; + paths [s] = 1 ; // 7. d[t] ← −1, ∀t ∈ V , d[s] ← 0 for (size_t t = 0; t < n; t++) { - d [t] = -1; + depth [t] = -1; } - d [s] = 0; + depth [s] = 0; // Initialize queue and enqueue starting node s // 8. Q ← empty queue @@ -218,19 +219,19 @@ int LG_check_edgeBetweennessCentrality int64_t w = Aj [p] ; // 16. if d[w] < 0 - if (d [w] < 0) { + if (depth [w] < 0) { // Update depth and enqueue // 18. enqueue(Q, w) queue [qt++] = w ; // 19. d[w] ← d[v] + 1 - d [w] = d [v] + 1 ; + depth [w] = depth [v] + 1 ; } // 20. if d[w] = d[v] + 1 - if (d [w] == d [v] + 1) { + if (depth [w] == depth [v] + 1) { // Update shortest path count and add predecessor // 22. σ[w] ← σ[w] + σ[v] - sigma [w] = sigma [w] + sigma [v] ; + paths [w] = paths [w] + paths [v] ; // 23. append(P [w], v) if (Ptail [w] >= Phead [w+1] || Ptail [w] < Phead [w]) { @@ -246,7 +247,7 @@ int LG_check_edgeBetweennessCentrality // Set dependency score δ[v] ← 0 // 24. δ[v] ← 0, ∀v ∈ V for (size_t v = 0; v < n; v++) { - delta [v] = 0 ; + bc_vertex_flow [v] = 0 ; } // Process stack S @@ -267,8 +268,8 @@ int LG_check_edgeBetweennessCentrality continue; } - double centrality = sigma [v] * ((delta [w] + 1) / sigma [w]) ; - delta [v] += centrality ; + double centrality = paths [v] * ((bc_vertex_flow [w] + 1) / paths [w]) ; + bc_vertex_flow [v] += centrality ; // 31. result [(v, w)] ← result [(v, w)] + σ[v] × ( δ[w]/σ[w] + 1) result [INDEX (v,w)] += centrality;