LCOV - code coverage report
Current view: top level - src/test - LG_check_tri.c (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: cc56ed4. Current time (UTC): 2024-08-30T17:14:30Z Lines: 35 35 100.0 %
Date: 2024-08-30 17:16:41 Functions: 1 1 100.0 %

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LG_check_tri: compute the number of triangles in 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 triangle count using a parallel dot-product method.
      19             : // Computes the sum(sum((A'*A).*A)), in MATLAB notation, where A is symmetric
      20             : // and treated as binary (only the structure is used).  Diagonal entries are
      21             : // ignored.  In GraphBLAS notation, C{A} = A'*A followed by reduce(C) to scalar.
      22             : // This method is for testing only, to check the result of other, faster
      23             : // methods.  Do not benchmark this method; it is slow and simple by design.
      24             : 
      25             : #define LG_FREE_ALL                         \
      26             : {                                           \
      27             :     LAGraph_Free ((void **) &Ap, NULL) ;    \
      28             :     LAGraph_Free ((void **) &Aj, NULL) ;    \
      29             :     LAGraph_Free ((void **) &Ax, NULL) ;    \
      30             : }
      31             : 
      32             : #include "LG_internal.h"
      33             : #include "LG_test.h"
      34             : 
      35             : //------------------------------------------------------------------------------
      36             : // LG_check_tri
      37             : //------------------------------------------------------------------------------
      38             : 
      39             : // Since this method does not modify G->A, it can be tested with LG_BRUTAL.
      40             : // See test_TriangleCount for a brutal memory test of this method.
      41             : 
      42         143 : int LG_check_tri        // -1 if out of memory, 0 if successful
      43             : (
      44             :     // output
      45             :     uint64_t *ntri,     // # of triangles in A
      46             :     // input
      47             :     LAGraph_Graph G,    // the structure of G->A must be symmetric
      48             :     char *msg
      49             : )
      50             : {
      51             : 
      52             :     //--------------------------------------------------------------------------
      53             :     // check inputs
      54             :     //--------------------------------------------------------------------------
      55             : 
      56         143 :     LG_CLEAR_MSG ;
      57             : 
      58         143 :     GrB_Index *Ap = NULL, *Aj = NULL, *Ai = NULL ;
      59         143 :     void *Ax = NULL ;
      60             :     GrB_Index Ap_size, Aj_size, Ax_size, n, ncols, Ap_len, Aj_len, Ax_len ;
      61         143 :     LG_ASSERT (ntri != NULL, GrB_NULL_POINTER) ;
      62         143 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
      63         143 :     LG_ASSERT (G->nself_edges == 0, LAGRAPH_NO_SELF_EDGES_ALLOWED) ;
      64         143 :     LG_ASSERT_MSG ((G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
      65             :        (G->kind == LAGraph_ADJACENCY_DIRECTED &&
      66             :         G->is_symmetric_structure == LAGraph_TRUE)),
      67             :         LAGRAPH_SYMMETRIC_STRUCTURE_REQUIRED,
      68             :         "G->A must be known to be symmetric") ;
      69         143 :     GRB_TRY (GrB_Matrix_nrows (&n, G->A)) ;
      70         143 :     GRB_TRY (GrB_Matrix_ncols (&ncols, G->A)) ;
      71             : 
      72             :     //--------------------------------------------------------------------------
      73             :     // export the matrix in CSR form
      74             :     //--------------------------------------------------------------------------
      75             : 
      76             :     size_t typesize ;
      77         143 :     LG_TRY (LG_check_export (G, &Ap, &Aj, &Ax, &Ap_len, &Aj_len, &Ax_len,
      78             :         &typesize, msg)) ;
      79             : 
      80             :     //--------------------------------------------------------------------------
      81             :     // compute the # of triangles (each triangle counted 6 times)
      82             :     //--------------------------------------------------------------------------
      83             : 
      84          37 :     int64_t ntriangles = 0 ;
      85          37 :     Ai = Aj ;       // pretend A is symmetric and in CSC format instead
      86             : 
      87             :     // masked dot-product method
      88             :     int64_t j;
      89             :     #if !defined ( COVERAGE )
      90             :     #pragma omp parallel for reduction(+:ntriangles) schedule(dynamic,1024)
      91             :     #endif
      92       12987 :     for (j = 0 ; j < n ; j++)
      93             :     {
      94             :         // for each entry in the lower triangular part of A
      95      367098 :         for (int64_t p = Ap [j] ; p < Ap [j+1] ; p++)
      96             :         {
      97      354148 :             const int64_t i = Ai [p] ;
      98      354148 :             if (i > j)
      99             :             {
     100             :                 // ntriangles += A(:,i)' * A(:,j)
     101      177074 :                 int64_t p1 = Ap [i] ;
     102      177074 :                 int64_t p1_end = Ap [i+1] ;
     103      177074 :                 int64_t p2 = Ap [j] ;
     104      177074 :                 int64_t p2_end = Ap [j+1] ;
     105    11681606 :                 while (p1 < p1_end && p2 < p2_end)
     106             :                 {
     107    11504532 :                     int64_t i1 = Ai [p1] ;
     108    11504532 :                     int64_t i2 = Ai [p2] ;
     109    11504532 :                     if (i1 < i2)
     110             :                     {
     111             :                         // A(i1,i) appears before A(i2,j)
     112     3055392 :                         p1++ ;
     113             :                     }
     114     8449140 :                     else if (i2 < i1)
     115             :                     {
     116             :                         // A(i2,j) appears before A(i1,i)
     117     4316361 :                         p2++ ;
     118             :                     }
     119             :                     else // i1 == i2 == k
     120             :                     {
     121             :                         // A(k,i) and A(k,j) are the next entries to merge
     122     4132779 :                         ntriangles++ ;
     123     4132779 :                         p1++ ;
     124     4132779 :                         p2++ ;
     125             :                     }
     126             :                 }
     127             :             }
     128             :         }
     129             :     }
     130          37 :     ntriangles = ntriangles / 3 ;
     131             : 
     132             :     //--------------------------------------------------------------------------
     133             :     // free workspace and return result
     134             :     //--------------------------------------------------------------------------
     135             : 
     136          37 :     LG_FREE_ALL ;
     137          37 :     (*ntri) = ntriangles ;
     138          37 :     return (GrB_SUCCESS) ;
     139             : }

Generated by: LCOV version 1.14