LCOV - code coverage report
Current view: top level - src/test - LG_check_cc.c (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: 3b461aa. Current time (UTC): 2024-01-25T16:04:32Z Lines: 63 63 100.0 %
Date: 2024-01-25 16:05:28 Functions: 1 1 100.0 %

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LAGraph/src/test/LG_check_cc: stand-alone test for CC
       3             : //------------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2019-2022 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 Timothy A. Davis, Texas A&M University
      15             : 
      16             : //------------------------------------------------------------------------------
      17             : 
      18             : #define LG_FREE_WORK                                \
      19             : {                                                   \
      20             :     LAGraph_Free ((void **) &queue, NULL) ;         \
      21             :     LAGraph_Free ((void **) &component_in, NULL) ;  \
      22             :     LAGraph_Free ((void **) &visited, NULL) ;       \
      23             :     LAGraph_Free ((void **) &neighbors, NULL) ;     \
      24             :     GrB_free (&Row) ;                               \
      25             : }
      26             : 
      27             : #define LG_FREE_ALL                                 \
      28             : {                                                   \
      29             :     LG_FREE_WORK ;                                  \
      30             :     LAGraph_Free ((void **) &Ap, NULL) ;            \
      31             :     LAGraph_Free ((void **) &Aj, NULL) ;            \
      32             :     LAGraph_Free ((void **) &Ax, NULL) ;            \
      33             : }
      34             : 
      35             : #include "LG_internal.h"
      36             : #include "LG_test.h"
      37             : 
      38             : // The output of LAGr_ConnectedComponents is a vector Component, where
      39             : // Component(i)=s if node i is in the connected compononent whose
      40             : // representative node is node s.  If s is a representative, then
      41             : // Component(s)=s.  The number of connected components in the graph G is the
      42             : // number of representatives.
      43             : 
      44             : //------------------------------------------------------------------------------
      45             : // test the results from LAGr_ConnectedComponents
      46             : //------------------------------------------------------------------------------
      47             : 
      48             : // Because this method does on GxB_unpack on G->A, it should not be used in a
      49             : // brutal memory test, unless the caller is prepared to reconstruct G->A
      50             : // when the brutal test causes this method to return early.
      51             : 
      52          97 : int LG_check_cc
      53             : (
      54             :     // input
      55             :     GrB_Vector Component,   // Component(i)=s if node is in Component s
      56             :     LAGraph_Graph G,
      57             :     char *msg
      58             : )
      59             : {
      60             : 
      61             :     //--------------------------------------------------------------------------
      62             :     // check inputs
      63             :     //--------------------------------------------------------------------------
      64             : 
      65          97 :     double tt = LAGraph_WallClockTime ( ) ;
      66          97 :     GrB_Vector Row = NULL ;
      67          97 :     GrB_Index *Ap = NULL, *Aj = NULL, *neighbors = NULL ;
      68          97 :     void *Ax = NULL ;
      69             :     GrB_Index Ap_size, Aj_size, Ax_size, n, ncols ;
      70          97 :     int64_t *queue = NULL, *component_in = NULL ;
      71          97 :     bool *visited = NULL ;
      72          97 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
      73          97 :     GRB_TRY (GrB_Matrix_nrows (&n, G->A)) ;
      74          97 :     GRB_TRY (GrB_Matrix_ncols (&ncols, G->A)) ;
      75          97 :     LG_ASSERT (Component != NULL, GrB_NULL_POINTER) ;
      76             : 
      77          97 :     LG_ASSERT_MSG ((G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
      78             :        (G->kind == LAGraph_ADJACENCY_DIRECTED &&
      79             :         G->is_symmetric_structure == LAGraph_TRUE)),
      80             :         LAGRAPH_SYMMETRIC_STRUCTURE_REQUIRED,
      81             :         "G->A must be known to be symmetric") ;
      82             : 
      83             :     //--------------------------------------------------------------------------
      84             :     // allocate workspace
      85             :     //--------------------------------------------------------------------------
      86             : 
      87          97 :     LG_TRY (LAGraph_Calloc ((void **) &queue, n, sizeof (int64_t), msg)) ;
      88             : 
      89             :     //--------------------------------------------------------------------------
      90             :     // get the contents of the Component vector
      91             :     //--------------------------------------------------------------------------
      92             : 
      93          97 :     LG_TRY (LAGraph_Malloc ((void **) &component_in, n, sizeof (int64_t), msg)) ;
      94          97 :     LG_TRY (LG_check_vector (component_in, Component, n, -1)) ;
      95             : 
      96             :     //--------------------------------------------------------------------------
      97             :     // find the # of connected components, according to Component vector
      98             :     //--------------------------------------------------------------------------
      99             : 
     100          97 :     int64_t *count = queue ;        // use queue as workspace
     101          97 :     int64_t ncomp_in = 0 ;
     102       65165 :     for (int64_t i = 0 ; i < n ; i++)
     103             :     {
     104       65068 :         int64_t comp = component_in [i] ;
     105       65068 :         LG_ASSERT (comp >= 0 && comp < n, -2000) ;
     106       65068 :         count [comp]++ ;
     107       65068 :         if (comp == i)
     108             :         {
     109             :             // this is the representative of its component
     110       27182 :             ncomp_in++ ;
     111             :         }
     112             :     }
     113          97 :     printf ("# of components: %g\n", (double) ncomp_in) ;
     114             : 
     115          97 :     if (n < 1000)
     116             :     {
     117        1021 :         for (int64_t i = 0 ; i < n ; i++)
     118             :         {
     119         956 :             if (component_in [i] == i)
     120             :             {
     121         126 :                 printf ("Component %g, size %g\n", (double) i,
     122         126 :                     (double) count [i]) ;
     123             :             }
     124             :         }
     125             :     }
     126             : 
     127             :     //--------------------------------------------------------------------------
     128             :     // unpack the matrix in CSR form for SuiteSparse:GraphBLAS
     129             :     //--------------------------------------------------------------------------
     130             : 
     131             :     #if LAGRAPH_SUITESPARSE
     132             :     bool iso, jumbled ;
     133          97 :     GRB_TRY (GxB_Matrix_unpack_CSR (G->A,
     134             :         &Ap, &Aj, &Ax, &Ap_size, &Aj_size, &Ax_size, &iso, &jumbled, NULL)) ;
     135             :     #endif
     136             : 
     137             :     //--------------------------------------------------------------------------
     138             :     // find the connected components via repeated BFS
     139             :     //--------------------------------------------------------------------------
     140             : 
     141          97 :     tt = LAGraph_WallClockTime ( ) - tt ;
     142          97 :     printf ("LG_check_cc init  time: %g sec\n", tt) ;
     143          97 :     tt = LAGraph_WallClockTime ( ) ;
     144             : 
     145          97 :     LG_TRY (LAGraph_Calloc ((void **) &visited, n, sizeof (bool), msg)) ;
     146             : 
     147             :     #if !LAGRAPH_SUITESPARSE
     148             :     GRB_TRY (GrB_Vector_new (&Row, GrB_BOOL, n)) ;
     149             :     LG_TRY (LAGraph_Malloc ((void **) &neighbors, n, sizeof (GrB_Index), msg)) ;
     150             :     #endif
     151             : 
     152          97 :     int64_t ncomp = 0 ;
     153             : 
     154       65165 :     for (int64_t src = 0 ; src < n ; src++)
     155             :     {
     156             :         // skip this node if already visited
     157       65068 :         if (visited [src]) continue ;
     158             : 
     159             :         // src node is part of a new connected component, comp
     160       27182 :         int64_t comp = component_in [src] ;
     161       27182 :         ncomp++ ;
     162       27182 :         LG_ASSERT_MSG (ncomp <= ncomp_in, -2001, "wrong # of components") ;
     163             : 
     164       27182 :         queue [0] = src ;
     165       27182 :         int64_t head = 0 ;
     166       27182 :         int64_t tail = 1 ;
     167       27182 :         visited [src] = true ;      // src is visited
     168             : 
     169       92250 :         while (head < tail)
     170             :         {
     171             :             // dequeue the node at the head of the queue
     172       65068 :             int64_t u = queue [head++] ;
     173             : 
     174             :             #if LAGRAPH_SUITESPARSE
     175             :             // directly access the indices of entries in A(u,:)
     176       65068 :             GrB_Index degree = Ap [u+1] - Ap [u] ;
     177       65068 :             GrB_Index *node_u_adjacency_list = Aj + Ap [u] ;
     178             :             #else
     179             :             // extract the indices of entries in A(u,:)
     180             :             GrB_Index degree = n ;
     181             :             GRB_TRY (GrB_Col_extract (Row, NULL, NULL, G->A, GrB_ALL, n, u,
     182             :                 GrB_DESC_T0)) ;
     183             :             GRB_TRY (GrB_Vector_extractTuples_BOOL (neighbors, NULL, &degree,
     184             :                 Row)) ;
     185             :             GrB_Index *node_u_adjacency_list = neighbors ;
     186             :             #endif
     187             : 
     188             :             // traverse all entries in A(u,:)
     189     1017016 :             for (int64_t k = 0 ; k < degree ; k++)
     190             :             {
     191             :                 // consider edge (u,v)
     192      951948 :                 int64_t v = node_u_adjacency_list [k] ;
     193             :                 // ensure v is in the same connected component as the src node
     194      951948 :                 LG_ASSERT (comp == component_in [u], -2002) ;
     195             :                 // printf ("    seen: %ld\n", v) ;
     196      951948 :                 if (!visited [v])
     197             :                 {
     198             :                     // node v is not yet visited; set its level and add to the
     199             :                     // end of the queue
     200       37886 :                     visited [v] = true ;
     201       37886 :                     queue [tail++] = v ;
     202             :                 }
     203             :             }
     204             :         }
     205             :     }
     206             : 
     207          97 :     LG_ASSERT_MSG (ncomp == ncomp_in, -2001, "wrong # of components") ;
     208             : 
     209          97 :     tt = LAGraph_WallClockTime ( ) - tt ;
     210          97 :     printf ("LG_check_cc component time: %g sec\n", tt) ;
     211          97 :     tt = LAGraph_WallClockTime ( ) ;
     212             : 
     213             :     //--------------------------------------------------------------------------
     214             :     // repack the matrix in CSR form for SuiteSparse:GraphBLAS
     215             :     //--------------------------------------------------------------------------
     216             : 
     217             :     #if LAGRAPH_SUITESPARSE
     218          97 :     GRB_TRY (GxB_Matrix_pack_CSR (G->A,
     219             :         &Ap, &Aj, &Ax, Ap_size, Aj_size, Ax_size, iso, jumbled, NULL)) ;
     220             :     #endif
     221             : 
     222          97 :     LG_FREE_WORK ;
     223             : 
     224          97 :     tt = LAGraph_WallClockTime ( ) - tt ;
     225          97 :     printf ("LG_check_cc check time: %g sec\n", tt) ;
     226             : 
     227          97 :     return (GrB_SUCCESS) ;
     228             : }

Generated by: LCOV version 1.14