LCOV - code coverage report
Current view: top level - experimental/test - LG_check_lcc.c (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: 7b9d2ee. Current time (UTC): 2025-06-03T21:57:17Z Lines: 88 88 100.0 %
Date: 2025-06-03 22:02:40 Functions: 3 3 100.0 %

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LG_check_lcc: compute local clustering coefficients of a graph (simple)
       3             : //------------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2023 by The LAGraph Contributors, All Rights Reserved.
       6             : // SPDX-License-Identifier: BSD-2-Clause
       7             : //
       8             : // For additional details (including references to third party source code and
       9             : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See
      10             : // Contributors.txt for a full list of contributors. Created, in part, with
      11             : // funding and support from the U.S. Government (see Acknowledgments.txt file).
      12             : // DM22-0790
      13             : 
      14             : // Contributed by Pascal Costanza, Intel, Belgium
      15             : 
      16             : //------------------------------------------------------------------------------
      17             : 
      18             : // An implementation of local clustering coefficient based on the descripion at
      19             : // https://en.wikipedia.org/wiki/Clustering_coefficient
      20             : // This method is for testing only, to check the result of other, faster methods.
      21             : // Do not benchmark this method; it is simple by design.
      22             : 
      23             : #define LG_FREE_ALL                         \
      24             : {                                           \
      25             :     GrB_free (&S) ;                         \
      26             :     GrB_free (&W) ;                         \
      27             :     GrB_free (&LCC) ;                       \
      28             :     LAGraph_Free ((void **) &Sp, msg) ;     \
      29             :     LAGraph_Free ((void **) &Si, msg) ;     \
      30             :     LAGraph_Free ((void **) &Tp, msg) ;     \
      31             :     LAGraph_Free ((void **) &Ti, msg) ;     \
      32             :     LAGraph_Free ((void **) &vb, msg) ;     \
      33             :     LAGraph_Free ((void **) &vx, msg) ;     \
      34             : }
      35             : 
      36             : #include <stdlib.h>
      37             : #include "LG_internal.h"
      38             : #include "LG_test.h"
      39             : #include "LG_test.h"
      40             : #include "LG_Xtest.h"
      41             : 
      42             : // assumes that the indices array is sorted
      43     2496168 : GrB_Index find(const GrB_Index* indices, GrB_Index n, GrB_Index index) {
      44     2496168 :     GrB_Index i = 0, j = n, h;
      45    14259134 :     while (i < j) {
      46    11762966 :         h = (i+j) >> 1;
      47    11762966 :         if (indices[h] < index) {
      48     1617048 :             i = h + 1;
      49             :         } else {
      50    10145918 :             j = h;
      51             :         }
      52             :     }
      53     2496168 :     return i;
      54             : }
      55             : 
      56             : // computes how many elements are in the intersection of both sets
      57             : // assumes that both arrays are sorted and don't have any duplicates
      58      178144 : GrB_Index intersection_size(
      59             :         GrB_Index* x, GrB_Index nx,
      60             :         GrB_Index* y, GrB_Index ny
      61             : ) {
      62      178144 :     GrB_Index n = 0;
      63     2497316 :     while ((nx > 0) && (ny > 0)) {
      64     2319172 :         if (y[0] > x[0]) {
      65      413706 :             GrB_Index* tmp = x; x = y; y = tmp;
      66      413706 :             GrB_Index ntmp = nx; nx = ny; ny = ntmp;
      67             :         }
      68     2319172 :         GrB_Index index = find(y, ny, x[0]);
      69     2319172 :         if ((index < ny) && (y[index] == x[0])) {
      70     2067108 :             n++;
      71     2067108 :             y += index+1;
      72     2067108 :             ny -= index+1;
      73             :         } else {
      74      252064 :             y += index;
      75      252064 :             ny -= index;
      76             :         }
      77     2319172 :         x += 1;
      78     2319172 :         nx -= 1;
      79             :     }
      80      178144 :     return n;
      81             : }
      82             : 
      83             : // This is a slow version.
      84          20 : int LG_check_lcc(
      85             :     // outputs:
      86             :     GrB_Vector *coefficients,     // the local clustering coefficients
      87             :     // inputs
      88             :     LAGraph_Graph G,        // input graph
      89             :     char *msg
      90             : )
      91             : {
      92             : #if LAGRAPH_SUITESPARSE
      93             : 
      94             :     //--------------------------------------------------------------------------
      95             :     // check inputs
      96             :     //--------------------------------------------------------------------------
      97             : 
      98          20 :     LG_CLEAR_MSG ;
      99             : 
     100          40 :     bool undirected = (G->kind == LAGraph_ADJACENCY_UNDIRECTED) ||
     101          20 :                       ((G->kind == LAGraph_ADJACENCY_DIRECTED) &&
     102          20 :                        (G->is_symmetric_structure == LAGraph_TRUE)) ;
     103          20 :     bool directed = !undirected ;
     104             : 
     105          20 :     GrB_Matrix S = NULL, T = NULL, W = NULL ;
     106          20 :     GrB_Index *Sp = NULL, *Si = NULL, *Tp = NULL, *Ti = NULL ;
     107          20 :     void *Sx = NULL , *Tx = NULL ;
     108          20 :     int8_t *vb = NULL ;
     109          20 :     double *vx = NULL ;
     110          20 :     GrB_Vector LCC = NULL ;
     111             :     GrB_Index n, ncols ;
     112          20 :     LG_ASSERT (coefficients != NULL, GrB_NULL_POINTER) ;
     113          20 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
     114          20 :     GRB_TRY (GrB_Matrix_nrows (&n, G->A)) ; //set n to number of rows
     115          20 :     GRB_TRY (GrB_Matrix_ncols (&ncols, G->A)) ;
     116          20 :     LG_ASSERT (n == ncols, GrB_INVALID_OBJECT) ;
     117             : 
     118          20 :     GRB_TRY (GrB_Vector_new (&LCC, GrB_FP64, n)) ;
     119             : 
     120          20 :     GrB_Matrix A = G->A ;
     121             : 
     122          20 :     GRB_TRY(GrB_Matrix_new(&S, GrB_BOOL, n, n)) ;
     123          20 :     GRB_TRY(GrB_assign(S, A, GrB_NULL, true, GrB_ALL, n, GrB_ALL, n, GrB_DESC_S)) ;
     124          20 :     if (G->nself_edges != 0) {
     125           6 :         GRB_TRY(GrB_select(S, GrB_NULL, GrB_NULL, GrB_OFFDIAG, S, 0, GrB_NULL)) ;
     126             :     }
     127             : 
     128          20 :     if (directed)
     129             :     {
     130           2 :         GRB_TRY(GrB_Matrix_new(&W, GrB_BOOL, n, n)) ;
     131           2 :         GRB_TRY(GrB_eWiseAdd(W, GrB_NULL, GrB_NULL, GrB_ONEB_BOOL, S, S, GrB_DESC_T1)) ;
     132           2 :         T = W ;
     133             :     } else {
     134          18 :         T = S ;
     135             :     }
     136             : 
     137             :     GrB_Index Sp_size, Si_size, Sx_size ;
     138             :     bool Siso ;
     139          20 :     GRB_TRY(GxB_Matrix_unpack_CSR(S, &Sp, &Si, &Sx, &Sp_size, &Si_size, &Sx_size, &Siso, NULL, GrB_NULL));
     140          20 :     LAGraph_Free (&Sx, msg) ;
     141             : 
     142             :     GrB_Index Tp_size, Ti_size, Tx_size ;
     143             :     bool Tiso ;
     144          20 :     if (directed) {
     145           2 :         GRB_TRY(GxB_Matrix_unpack_CSR(T, &Tp, &Ti, &Tx, &Tp_size, &Ti_size, &Tx_size, &Tiso, NULL, GrB_NULL));
     146           2 :         LAGraph_Free (&Tx, msg) ;
     147             :     } else {
     148          18 :         Tp = Sp; Tp_size = Sp_size;
     149          18 :         Ti = Si; Ti_size = Si_size;
     150             :     }
     151             : 
     152          20 :     LAGraph_Calloc ((void **) &vb, n, sizeof (int8_t), msg) ;
     153          20 :     LAGraph_Malloc ((void **) &vx, n, sizeof (double), msg) ;
     154             : 
     155             :     int64_t i;
     156          20 :     GrB_Index nvals = 0 ;
     157             : 
     158             : #pragma omp parallel for schedule(dynamic) reduction(+ : nvals)
     159        6608 :     for (i = 0; i < n; i++) {
     160        6588 :         GrB_Index *neighbors = Ti + Tp[i];
     161        6588 :         GrB_Index k = Tp[i + 1] - Tp[i];
     162        6588 :         if (k < 2) continue;
     163             : 
     164        6576 :         GrB_Index j, esum = 0;
     165      184720 :         for (j = 0; j < k; j++) {
     166      178144 :             GrB_Index e = neighbors[j];
     167      178144 :             GrB_Index *links = Si + Sp[e];
     168      178144 :             GrB_Index l = Sp[e + 1] - Sp[e];
     169      178144 :             if (l == 0) continue;
     170      178144 :             if (undirected) {
     171      176996 :                 l = find(links, l, e);
     172             :             }
     173      178144 :             esum += intersection_size(neighbors, k, links, l);
     174             :         }
     175             : 
     176        6576 :         if (esum == 0) continue;
     177             : 
     178        6558 :         if (undirected) {
     179        6428 :             esum *= 2;
     180             :         }
     181        6558 :         vb[i] = true;
     182        6558 :         vx[i] = ((double) esum) / ((double) (k * (k - 1)));
     183        6558 :         nvals++;
     184             :     }
     185             : 
     186          20 :     if (!directed)
     187             :     {
     188             :         // do not free these; they are aliases to Sp and Si:
     189          18 :         Tp = NULL ;
     190          18 :         Ti = NULL ;
     191             :     }
     192             : 
     193          20 :     GRB_TRY(GxB_Vector_pack_Bitmap(LCC, &vb, (void**)&vx, n*sizeof(int8_t), n*sizeof(double), false, nvals, GrB_NULL)) ;
     194             : 
     195          20 :     *coefficients = LCC ; LCC = NULL ;
     196          20 :     LG_FREE_ALL;
     197          20 :     return (GrB_SUCCESS);
     198             : #else
     199             :     return (GrB_NOT_IMPLEMENTED) ;
     200             : #endif
     201             : }

Generated by: LCOV version 1.14