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

          Line data    Source code
       1             : #include <stdio.h>
       2             : #include <acutest.h>
       3             : #include <LG_Xtest.h>
       4             : #include <LG_test.h>
       5             : #include <LAGraphX.h>
       6             : #include <LAGraph_test.h>
       7             : 
       8             : #define LEN 512
       9             : #define MAX_LABELS 3
      10             : #define MAX_RESULTS 2000000
      11             : 
      12             : char msg [LAGRAPH_MSG_LEN] ;
      13             : LAGraph_Graph G[MAX_LABELS] ;
      14             : LAGraph_Graph R[MAX_LABELS] ;
      15             : GrB_Matrix A ;
      16             : 
      17             : char testcase_name [LEN+1] ;
      18             : char filename [LEN+1] ;
      19             : 
      20             : typedef struct
      21             : {
      22             :     const char* name ;
      23             :     const char* graphs[MAX_LABELS] ;
      24             :     const char* fas[MAX_LABELS] ;
      25             :     const char* fa_meta ;
      26             :     const char* sources ;
      27             :     const GrB_Index expected[MAX_RESULTS] ;
      28             :     const size_t expected_count ;
      29             : }
      30             : matrix_info ;
      31             : 
      32             : const matrix_info files [ ] =
      33             : {
      34             :     {"simple 1 or more",
      35             :      {"rpq_data/a.mtx",   "rpq_data/b.mtx",   NULL},
      36             :      {"rpq_data/1_a.mtx", NULL },                    // Regex: a+
      37             :      "rpq_data/1_meta.txt",
      38             :      "rpq_data/1_sources.txt",
      39             :      {2, 4, 6, 7}, 4},
      40             :     {"simple kleene star",
      41             :      {"rpq_data/a.mtx",   "rpq_data/b.mtx",   NULL},
      42             :      {"rpq_data/2_a.mtx", "rpq_data/2_b.mtx", NULL}, // Regex: (a b)*
      43             :      "rpq_data/2_meta.txt",
      44             :      "rpq_data/2_sources.txt",
      45             :      {2, 6, 8}, 3},
      46             :     {"kleene star of the conjunction",
      47             :      {"rpq_data/a.mtx",   "rpq_data/b.mtx",   NULL},
      48             :      {"rpq_data/3_a.mtx", "rpq_data/3_b.mtx", NULL}, // Regex: (a | b)*
      49             :      "rpq_data/3_meta.txt",
      50             :      "rpq_data/3_sources.txt",
      51             :      {3, 6}, 2},
      52             :     {"simple repeat from n to m times",
      53             :      {"rpq_data/a.mtx",   "rpq_data/b.mtx",   NULL},
      54             :      {"",                 "rpq_data/4_b.mtx", NULL}, // Regex: b b b (b b)?
      55             :      "rpq_data/4_meta.txt",
      56             :      "rpq_data/4_sources.txt",
      57             :      {3, 4, 6}, 3},
      58             :     {NULL, NULL, NULL, NULL},
      59             : } ;
      60             : 
      61             : //****************************************************************************
      62           1 : void test_RegularPathQueryBasic (void)
      63             : {
      64           1 :     LAGraph_Init (msg) ;
      65             : 
      66           5 :     for (int k = 0 ; ; k++)
      67             :     {
      68           5 :         if (files[k].sources == NULL) break ;
      69             : 
      70           4 :         snprintf (testcase_name, LEN, "basic regular path query %s", files[k].name) ;
      71           4 :         TEST_CASE (testcase_name) ;
      72             : 
      73          12 :         for (int check_symmetry = 0 ; check_symmetry <= 1 ; check_symmetry++)
      74             :         {
      75             :             // Load graph from MTX files representing its adjacency matrix
      76             :             // decomposition
      77           8 :             for (int i = 0 ; ; i++)
      78          16 :             {
      79          24 :                 const char *name = files[k].graphs[i] ;
      80             : 
      81          24 :                 if (name == NULL) break ;
      82          16 :                 if (strlen(name) == 0) continue ;
      83             : 
      84          16 :                 snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
      85          16 :                 FILE *f = fopen (filename, "r") ;
      86          16 :                 TEST_CHECK (f != NULL) ;
      87          16 :                 OK (LAGraph_MMRead (&A, f, msg)) ;
      88          16 :                 OK (fclose (f));
      89             : 
      90          16 :                 OK (LAGraph_New (&(G[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
      91             : 
      92          16 :                 TEST_CHECK (A == NULL) ;
      93             :             }
      94             : 
      95             :             // Load NFA from MTX files representing its adjacency matrix
      96             :             // decomposition
      97           8 :             for (int i = 0 ; ; i++)
      98          14 :             {
      99          22 :                 const char *name = files[k].fas[i] ;
     100             : 
     101          22 :                 if (name == NULL) break ;
     102          14 :                 if (strlen(name) == 0) continue ;
     103             : 
     104          12 :                 snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
     105          12 :                 FILE *f = fopen (filename, "r") ;
     106          12 :                 TEST_CHECK (f != NULL) ;
     107          12 :                 OK (LAGraph_MMRead (&A, f, msg)) ;
     108          12 :                 OK (fclose (f)) ;
     109             : 
     110          12 :                 OK (LAGraph_New (&(R[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
     111             : 
     112          12 :                 if (check_symmetry)
     113             :                 {
     114             :                     // Check if the pattern is symmetric - if it isn't make it.
     115             :                     // Note this also computes R[i]->AT
     116           6 :                     OK (LAGraph_Cached_IsSymmetricStructure (R[i], msg)) ;
     117             :                 }
     118             : 
     119          12 :                 TEST_CHECK (A == NULL) ;
     120             :             }
     121             : 
     122             :             // Note the matrix rows/cols are enumerated from 0 to n-1.
     123             :             // Meanwhile, in MTX format they are enumerated from 1 to n. Thus,
     124             :             // when loading/comparing the results these values should be
     125             :             // decremented/incremented correspondingly.
     126             : 
     127             :             // Load graph source nodes from the sources file
     128             :             GrB_Index s ;
     129             :             GrB_Index S[16] ;
     130           8 :             size_t ns = 0 ;
     131             : 
     132           8 :             const char *name = files[k].sources ;
     133           8 :             snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
     134           8 :             FILE *f = fopen (filename, "r") ;
     135           8 :             TEST_CHECK (f != NULL) ;
     136             : 
     137          20 :             while (fscanf(f, "%" PRIu64, &s) != EOF)
     138             :             {
     139          12 :                 S[ns++] = s - 1 ;
     140             :             }
     141             : 
     142           8 :             OK (fclose(f)) ;
     143             : 
     144             :             // Load NFA starting states from the meta file
     145             :             GrB_Index qs ;
     146             :             GrB_Index QS[16] ;
     147           8 :             size_t nqs = 0 ;
     148             : 
     149           8 :             name = files[k].fa_meta ;
     150           8 :             snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
     151           8 :             f = fopen (filename, "r") ;
     152           8 :             TEST_CHECK (f != NULL) ;
     153             : 
     154           8 :             uint64_t nqs64 = 0 ;
     155           8 :             TEST_CHECK (fscanf(f, "%" PRIu64, &nqs64) != EOF) ;
     156           8 :             nqs = (size_t) nqs64 ;
     157             : 
     158          18 :             for (uint64_t i = 0; i < nqs; i++) {
     159          10 :                 TEST_CHECK (fscanf(f, "%" PRIu64, &qs) != EOF) ;
     160          10 :                 QS[i] = qs - 1 ;
     161             :             }
     162             : 
     163             :             // Load NFA final states from the same file
     164             :             uint64_t qf ;
     165             :             uint64_t QF[16] ;
     166           8 :             size_t nqf = 0 ;
     167           8 :             uint64_t  nqf64 = 0 ;
     168             : 
     169           8 :             TEST_CHECK (fscanf(f, "%" PRIu64, &nqf64) != EOF) ;
     170           8 :             nqf = (size_t) nqf64 ;
     171             : 
     172          16 :             for (uint64_t i = 0; i < nqf; i++) {
     173           8 :                 TEST_CHECK (fscanf(f, "%" PRIu64, &qf) != EOF) ;
     174           8 :                 QF[i] = qf - 1 ;
     175             :             }
     176             : 
     177           8 :             OK (fclose(f)) ;
     178             : 
     179             :             // Evaluate the algorithm
     180           8 :             GrB_Vector r = NULL ;
     181             : 
     182           8 :             OK (LAGraph_RegularPathQuery (&r, R, MAX_LABELS, QS, nqs,
     183             :                                              QF, nqf, G, S, ns, msg)) ;
     184             : 
     185             :             // Extract results from the output vector
     186             :             GrB_Index *reachable ;
     187             :             bool *values ;
     188             : 
     189             :             GrB_Index nvals ;
     190           8 :             GrB_Vector_nvals (&nvals, r) ;
     191             : 
     192           8 :             OK (LAGraph_Malloc ((void **) &reachable, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
     193           8 :             OK (LAGraph_Malloc ((void **) &values, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
     194             : 
     195           8 :             GrB_Vector_extractTuples (reachable, values, &nvals, r) ;
     196             : 
     197             :             // Compare the results with expected values
     198           8 :             TEST_CHECK (nvals == files[k].expected_count) ;
     199          32 :             for (uint64_t i = 0 ; i < nvals ; i++)
     200          24 :                 TEST_CHECK (reachable[i] + 1 == files[k].expected[i]) ;
     201             : 
     202             :             // Cleanup
     203           8 :             OK (LAGraph_Free ((void **) &values, NULL)) ;
     204           8 :             OK (LAGraph_Free ((void **) &reachable, NULL)) ;
     205             : 
     206           8 :             OK (GrB_free (&r)) ;
     207             : 
     208          32 :             for (uint64_t i = 0 ; i < MAX_LABELS ; i++)
     209             :             {
     210          24 :                 if (G[i] == NULL) continue ;
     211          16 :                 OK (LAGraph_Delete (&(G[i]), msg)) ;
     212             :             }
     213             : 
     214          32 :             for (uint64_t i = 0 ; i < MAX_LABELS ; i++ )
     215             :             {
     216          24 :                 if (R[i] == NULL) continue ;
     217          12 :                 OK (LAGraph_Delete (&(R[i]), msg)) ;
     218             :             }
     219             :         }
     220             :     }
     221             : 
     222           1 :     LAGraph_Finalize (msg) ;
     223           1 : }
     224             : 
     225             : 
     226             : TEST_LIST = {
     227             :     {"RegularPathQueryBasic", test_RegularPathQueryBasic},
     228             :     {NULL, NULL}
     229             : };

Generated by: LCOV version 1.14