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

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LAGraph_ExactDiameter: Graph Diameter Computation
       3             : //------------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2021 by The LAGraph Contributors, All Rights Reserved.
       6             : // SPDX-License-Identifier: BSD-2-Clause
       7             : // See additional acknowledgments in the LICENSE file,
       8             : // or contact permission@sei.cmu.edu for the full terms.
       9             : 
      10             : // Contributed by Alexandra Goff
      11             : 
      12             : //------------------------------------------------------------------------------
      13             : 
      14             : // TODO: almost ready for src; says it's not vanilla but should be OK
      15             : 
      16             : // Takes in a graph and finds the diameter 
      17             : // and optionally also the peripheral nodes of the graph
      18             : 
      19             : // Outputs: 
      20             : // Diameter returns the diameter of the graph
      21             : // If not set to NULL, peripheral will be a vector with n elements
      22             : // index i of peripheral is the diameter if it's a peripheral node or nothing if not
      23             : // If not set to NULL, eccentricity will be a vector with the eccentricity of each 
      24             : // node in the graph
      25             : 
      26             : // Inputs:
      27             : // G is the graph to be analyzed
      28             : // k is the number of nodes in each batch of the BFS, 
      29             : // higher k value allows for more parallelization at the cost of more space used
      30             : // msg is a buffer for error messages
      31             : 
      32             : #define LG_FREE_WORK        \
      33             : {                           \
      34             :     GrB_free (&srcEcc) ;    \
      35             :     GrB_free (&ecc) ;       \
      36             :     GrB_free (&level) ;     \
      37             :     GrB_free (&srcs) ;      \
      38             :     LAGraph_Free((void**) &sources, NULL);  \
      39             : }
      40             : 
      41             : #define LG_FREE_ALL             \
      42             : {                               \
      43             :     LG_FREE_WORK ;              \
      44             :     GrB_free (eccentricity) ;   \
      45             :     GrB_free (&peri) ;          \
      46             : }
      47             : 
      48             : #include "LG_internal.h"
      49             : #include "LAGraphX.h"
      50             : 
      51          10 : int LAGraph_ExactDiameter
      52             : (
      53             :     // outputs:
      54             :     GrB_Index    *diameter,
      55             :     GrB_Vector    *peripheral,
      56             :     GrB_Vector    *eccentricity,
      57             :     // inputs:
      58             :     const LAGraph_Graph G,
      59             :     GrB_Index      k,
      60             :     char          *msg
      61             : )
      62             : {
      63             : #if LAGRAPH_SUITESPARSE
      64             : 
      65             :     //--------------------------------------------------------------------------
      66             :     // check inputs
      67             :     //--------------------------------------------------------------------------
      68             : 
      69          10 :     LG_CLEAR_MSG ;
      70          10 :     GrB_Vector ecc = NULL ;           // the eccentricity of the nodes
      71          10 :     GrB_Vector peri = NULL ;          // vector to store peripheral node status in
      72          10 :     GrB_Vector srcEcc = NULL ;        // work vector to store each iteration's eccentricity in temporarily
      73          10 :     GrB_Matrix level = NULL;          // work matrix for storing msbfs level info
      74             :     GrB_Index d ;                     // diameter
      75          10 :     GrB_Vector srcs = NULL ;
      76          10 :     GrB_Index *sources = NULL ;
      77             : 
      78          10 :     bool compute_periphery  = (peripheral != NULL) ;
      79          10 :     if (compute_periphery ) (*peripheral) = NULL ;
      80          10 :     bool compute_eccentricity  = (eccentricity != NULL) ;
      81          10 :     if (compute_eccentricity ) (*eccentricity) = NULL ;
      82          10 :     bool compute_diameter  = (diameter != NULL) ;
      83          10 :     LG_ASSERT_MSG (compute_diameter, GrB_NULL_POINTER,
      84             :         "Diameter destination must be non-NULL") ;
      85             : 
      86          10 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
      87             : 
      88             :     //--------------------------------------------------------------------------
      89             :     // get the problem size and cached properties
      90             :     //--------------------------------------------------------------------------
      91             : 
      92          10 :     GrB_Matrix A = G->A ;
      93             :     
      94             :     GrB_Index n;        // number of nodes in the graph
      95          10 :     GRB_TRY (GrB_Matrix_nrows (&n, A)) ;
      96             : 
      97          10 :     GrB_Type int_type = (n > INT32_MAX) ? GrB_INT64 : GrB_INT32 ;
      98          10 :     GRB_TRY (GrB_Vector_new (&ecc, int_type, n)) ;
      99             : 
     100             :     //--------------------------------------------------------------------------
     101             :     // get eccentricity, k nodes at a time
     102             :     //--------------------------------------------------------------------------
     103             : 
     104          10 :     int64_t setStart = 0;
     105          20 :     GrB_Monoid max = (n > INT32_MAX) ?
     106          10 :             GrB_MAX_MONOID_INT64 : GrB_MAX_MONOID_INT32 ;
     107         428 :     while (setStart < n){
     108             :         // set up the sources for this iteration
     109             :         int64_t nsrcs;
     110         418 :         if ((setStart + k) <= n){
     111         409 :             nsrcs = k;
     112             :         } else {
     113           9 :             nsrcs = n - setStart;
     114             :         }
     115         418 :         GRB_TRY (GrB_Vector_new (&srcs, int_type, nsrcs)) ;
     116         418 :         GRB_TRY (LAGraph_Calloc((void **) &sources, nsrcs, sizeof(GrB_Index), msg)) ;
     117        3712 :         for (int64_t i = 0; i < nsrcs; i++){
     118        3294 :             GRB_TRY (GrB_Vector_setElement (srcs, setStart+i, i)) ;
     119        3294 :             sources[i] = setStart+i;
     120             :         }
     121             : 
     122             :         // run bfs to get level matrix for the sources
     123         418 :         GrB_free (&level) ;
     124         418 :         LAGRAPH_TRY (LAGraph_MultiSourceBFS (&level, NULL, G, srcs, msg)) ;
     125         418 :         GrB_free (&srcs) ;
     126             : 
     127             :         // populate setStart to setStart+nsrcs of ecc with the max level for each src
     128         418 :         GRB_TRY (GrB_Vector_new (&srcEcc, int_type, nsrcs)) ;
     129         418 :         GRB_TRY (GrB_reduce(srcEcc, NULL, NULL, max, level, GrB_NULL)) ;
     130         418 :         LAGRAPH_TRY (GrB_assign(ecc, NULL, NULL, srcEcc, sources,  nsrcs, GrB_NULL)) ;
     131         418 :         GrB_free (&level) ;
     132         418 :         GrB_free (&srcEcc) ;
     133             : 
     134         418 :         LAGraph_Free((void**) &sources, NULL);
     135             : 
     136             :         // adjust setStart for next iteration
     137         418 :         setStart = setStart + nsrcs;
     138             :     }
     139             : 
     140             : 
     141             :     //--------------------------------------------------------------------------
     142             :     // determine diameter from eccentricity list
     143             :     //--------------------------------------------------------------------------
     144             :     
     145          10 :     GRB_TRY (GrB_reduce(&d, NULL, max, ecc, GrB_NULL)) ;
     146             : 
     147             :     //--------------------------------------------------------------------------
     148             :     // get peripheral nodes, if applicable
     149             :     //--------------------------------------------------------------------------
     150             : 
     151          10 :     if (compute_periphery){
     152          20 :         GrB_IndexUnaryOp eqOp = (n > INT32_MAX) ?
     153          10 :             GrB_VALUEEQ_INT64 : GrB_VALUEEQ_INT32 ;
     154          10 :         GRB_TRY (GrB_Vector_new (&peri, int_type, n)) ;
     155          10 :         GRB_TRY (GrB_select(peri, NULL, NULL, eqOp, ecc, d, NULL)) ;
     156             :     }
     157             : 
     158             :     //--------------------------------------------------------------------------
     159             :     // free workspace and return result
     160             :     //--------------------------------------------------------------------------
     161             : 
     162          10 :     if (compute_periphery)
     163             :     {
     164          10 :         (*peripheral) = peri ;
     165          10 :         peri = NULL ;
     166             :     }
     167          10 :     if (compute_eccentricity)
     168             :     {
     169          10 :         (*eccentricity) = ecc ;
     170          10 :         ecc = NULL; // makes sure eccentricity vector doesn't get freed if the user wants it
     171             :     } 
     172          10 :     (*diameter) = d;
     173          10 :     LG_FREE_WORK ;
     174          10 :     return (GrB_SUCCESS) ;
     175             : #else
     176             :     return (GrB_NOT_IMPLEMENTED) ;
     177             : #endif
     178             : }

Generated by: LCOV version 1.14