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

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LG_check_ktruss: construct the ktruss of a graph (simple method)
       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             : // A very slow, bare-bones ktruss method.  This method is for testing only, to
      19             : // check the result of other, faster methods.  Do not benchmark this method; it
      20             : // is slow and simple by design.  G->A must be symmetric, with no entries on
      21             : // its diagonal.
      22             : 
      23             : #define LG_FREE_WORK                            \
      24             : {                                               \
      25             :     LAGraph_Free ((void **) &Cp, NULL) ;        \
      26             :     LAGraph_Free ((void **) &Cj, NULL) ;        \
      27             :     LAGraph_Free ((void **) &Cx, NULL) ;        \
      28             :     LAGraph_Free ((void **) &Ax, NULL) ;        \
      29             : }
      30             : 
      31             : #define LG_FREE_ALL                             \
      32             : {                                               \
      33             :     LG_FREE_WORK ;                              \
      34             :     GrB_free (&C) ;                             \
      35             : }
      36             : 
      37             : #include "LG_internal.h"
      38             : #include "LG_test.h"
      39             : 
      40          30 : int LG_check_ktruss
      41             : (
      42             :     // output
      43             :     GrB_Matrix *C_handle,   // the ktruss of G->A, of type GrB_UINT32
      44             :     // input
      45             :     LAGraph_Graph G,        // the structure of G->A must be symmetric
      46             :     uint32_t k,
      47             :     char *msg
      48             : )
      49             : {
      50             : 
      51             :     //--------------------------------------------------------------------------
      52             :     // check inputs
      53             :     //--------------------------------------------------------------------------
      54             : 
      55          30 :     LG_CLEAR_MSG ;
      56             : 
      57          30 :     GrB_Matrix C = NULL ;
      58          30 :     GrB_Index *Cp = NULL, *Cj = NULL ;
      59          30 :     uint32_t *Cx = NULL ;
      60          30 :     void *Ax = NULL ;
      61             :     GrB_Index n, ncols, Cp_len, Cj_len, Cx_len, nvals1, nvals2 ;
      62          30 :     LG_ASSERT (C_handle != NULL, GrB_NULL_POINTER) ;
      63          30 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
      64          30 :     LG_ASSERT_MSG (G->nself_edges == 0, -104, "G->nself_edges must be zero") ;
      65          30 :     if (G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
      66           9 :        (G->kind == LAGraph_ADJACENCY_DIRECTED &&
      67           9 :         G->is_symmetric_structure == LAGraph_TRUE))
      68             :     {
      69             :         // the structure of A is known to be symmetric
      70             :         ;
      71             :     }
      72             :     else
      73             :     {
      74             :         // A is not known to be symmetric
      75           1 :         LG_ASSERT_MSG (false, -1005, "G->A must be symmetric") ;
      76             :     }
      77          29 :     GRB_TRY (GrB_Matrix_nrows (&n, G->A)) ;
      78          29 :     GRB_TRY (GrB_Matrix_ncols (&ncols, G->A)) ;
      79          29 :     LG_ASSERT_MSG (n == ncols, -1001, "A must be square") ;
      80             : 
      81             :     //--------------------------------------------------------------------------
      82             :     // export G->A in CSR form and discard its values
      83             :     //--------------------------------------------------------------------------
      84             : 
      85             :     size_t typesize ;
      86          29 :     LG_TRY (LG_check_export (G, &Cp, &Cj, &Ax, &Cp_len, &Cj_len, &Cx_len,
      87             :         &typesize, msg)) ;
      88          29 :     LAGraph_Free ((void **) &Ax, NULL) ;
      89             : 
      90             :     //--------------------------------------------------------------------------
      91             :     // allocate Cx
      92             :     //--------------------------------------------------------------------------
      93             : 
      94          29 :     LG_TRY (LAGraph_Malloc ((void **) &Cx, Cx_len, sizeof (uint32_t), msg)) ;
      95             : 
      96             :     //--------------------------------------------------------------------------
      97             :     // construct the k-truss of G->A
      98             :     //--------------------------------------------------------------------------
      99             : 
     100             :     while (true)
     101          47 :     {
     102             : 
     103             :         //----------------------------------------------------------------------
     104             :         // compute the # of triangles incident on each edge of C
     105             :         //----------------------------------------------------------------------
     106             : 
     107             :         // masked dot-product method: C{C}=C*C' using the PLUS_ONE semiring
     108             :         int64_t i;
     109             :         #if !defined ( COVERAGE )
     110             :         #pragma omp parallel for schedule(dynamic,1024)
     111             :         #endif
     112       19130 :         for (i = 0 ; i < n ; i++)
     113             :         {
     114             :             // for each entry in C(i,:)
     115       63472 :             for (int64_t p = Cp [i] ; p < Cp [i+1] ; p++)
     116             :             {
     117       44418 :                 const int64_t j = Cj [p] ;
     118       44418 :                 uint32_t cij = 0 ;
     119             :                 // cij += C(i,:) * C(j,:)'
     120       44418 :                 int64_t p1 = Cp [i] ;
     121       44418 :                 int64_t p1_end = Cp [i+1] ;
     122       44418 :                 int64_t p2 = Cp [j] ;
     123       44418 :                 int64_t p2_end = Cp [j+1] ;
     124      391970 :                 while (p1 < p1_end && p2 < p2_end)
     125             :                 {
     126      347552 :                     int64_t j1 = Cj [p1] ;
     127      347552 :                     int64_t j2 = Cj [p2] ;
     128      347552 :                     if (j1 < j2)
     129             :                     {
     130             :                         // C(i,j1) appears before C(j,j2)
     131      133513 :                         p1++ ;
     132             :                     }
     133      214039 :                     else if (j2 < j1)
     134             :                     {
     135             :                         // C(j,j2) appears before C(i,j1)
     136      133513 :                         p2++ ;
     137             :                     }
     138             :                     else // j1 == j2
     139             :                     {
     140             :                         // C(i,j1) and C(j,j1) are the next entries to merge
     141       80526 :                         cij++ ;
     142       80526 :                         p1++ ;
     143       80526 :                         p2++ ;
     144             :                     }
     145             :                 }
     146       44418 :                 Cx [p] = cij ;
     147             :             }
     148             :         }
     149             : 
     150             :         //----------------------------------------------------------------------
     151             :         // import C in CSR form
     152             :         //----------------------------------------------------------------------
     153             : 
     154          76 :         GRB_TRY (GrB_Matrix_import_UINT32 (&C, GrB_UINT32, n, n,
     155             :             Cp, Cj, Cx, Cp_len, Cj_len, Cx_len, GrB_CSR_FORMAT)) ;
     156          76 :         GRB_TRY (GrB_Matrix_nvals (&nvals1, C)) ;
     157             : 
     158             :         //----------------------------------------------------------------------
     159             :         // keep entries >= k-2 and check for convergence
     160             :         //----------------------------------------------------------------------
     161             : 
     162          76 :         GRB_TRY (GrB_select (C, NULL, NULL, GrB_VALUEGE_UINT32, C, k-2, NULL)) ;
     163          76 :         GRB_TRY (GrB_Matrix_nvals (&nvals2, C)) ;
     164          76 :         if (nvals1 == nvals2)
     165             :         {
     166             :             // C is now the k-truss of G->A
     167          29 :             LG_FREE_WORK ;
     168          29 :             (*C_handle) = C ;
     169          29 :             return (GrB_SUCCESS) ;
     170             :         }
     171             : 
     172             :         //----------------------------------------------------------------------
     173             :         // export C in CSR form for the next iteration and free it
     174             :         //----------------------------------------------------------------------
     175             : 
     176          47 :         GRB_TRY (GrB_Matrix_export_UINT32 (Cp, Cj, Cx,
     177             :             &Cp_len, &Cj_len, &Cx_len, GrB_CSR_FORMAT, C)) ;
     178          47 :         GRB_TRY (GrB_free (&C)) ;
     179             :     }
     180             : }

Generated by: LCOV version 1.14