Skip to content

Fix regular path query test coverage #299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/rpq_data/3_a.mtx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%%MatrixMarket matrix coordinate pattern general
%%MatrixMarket matrix coordinate pattern symmetric
%%GraphBLAS type bool
2 2 1
1 1
2 changes: 1 addition & 1 deletion data/rpq_data/3_b.mtx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%%MatrixMarket matrix coordinate pattern general
%%MatrixMarket matrix coordinate pattern symmetric
%%GraphBLAS type bool
2 2 1
1 1
7 changes: 0 additions & 7 deletions experimental/algorithm/LAGraph_RegularPathQuery.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@
// Performance considerations: the best performance is shown when the algorithm
// receives a minimal deterministic finite automaton as an input.

// FIXME: some of the code below is not covered by the test suite, "make cov".
// See the FIXMEs below.

#define LG_FREE_WORK \
{ \
GrB_free (&frontier) ; \
Expand Down Expand Up @@ -200,8 +197,6 @@ int LAGraph_RegularPathQuery
B[i] = R[i]->A ;
if (R[i]->is_symmetric_structure == LAGraph_TRUE)
{
// FIXME: this case is not tested
// by experimental/test/test_RegularPathQuery.c
BT[i] = B[i] ;
}
else
Expand Down Expand Up @@ -326,8 +321,6 @@ int LAGraph_RegularPathQuery
}
else
{
// FIXME: this case is not tested
// by experimental/test/test_RegularPathQuery.c
GRB_TRY (GrB_mxm (symbol_frontier, GrB_NULL, GrB_NULL,
GrB_LOR_LAND_SEMIRING_BOOL, B[i], frontier, GrB_DESC_RT0)) ;
}
Expand Down
229 changes: 119 additions & 110 deletions experimental/test/test_RegularPathQuery.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,143 +70,152 @@ void test_RegularPathQueryBasic (void)
snprintf (testcase_name, LEN, "basic regular path query %s", files[k].name) ;
TEST_CASE (testcase_name) ;

// Load graph from MTX files representing its adjacency matrix
// decomposition
for (int i = 0 ; ; i++)
for (int check_symmetry = 0 ; check_symmetry <= 1 ; check_symmetry++)
{
const char *name = files[k].graphs[i] ;

if (name == NULL) break ;
if (strlen(name) == 0) continue ;

// Load graph from MTX files representing its adjacency matrix
// decomposition
for (int i = 0 ; ; i++)
{
const char *name = files[k].graphs[i] ;

if (name == NULL) break ;
if (strlen(name) == 0) continue ;

snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
FILE *f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
OK (LAGraph_MMRead (&A, f, msg)) ;
OK (fclose (f));

OK (LAGraph_New (&(G[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;

TEST_CHECK (A == NULL) ;
}

// Load NFA from MTX files representing its adjacency matrix
// decomposition
for (int i = 0 ; ; i++)
{
const char *name = files[k].fas[i] ;

if (name == NULL) break ;
if (strlen(name) == 0) continue ;

snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
FILE *f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
OK (LAGraph_MMRead (&A, f, msg)) ;
OK (fclose (f)) ;

OK (LAGraph_New (&(R[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;

if (check_symmetry)
{
// Check if the pattern is symmetric - if it isn't make it.
// Note this also computes R[i]->AT
OK (LAGraph_Cached_IsSymmetricStructure (R[i], msg)) ;
}

TEST_CHECK (A == NULL) ;
}

// Note the matrix rows/cols are enumerated from 0 to n-1.
// Meanwhile, in MTX format they are enumerated from 1 to n. Thus,
// when loading/comparing the results these values should be
// decremented/incremented correspondingly.

// Load graph source nodes from the sources file
GrB_Index s ;
GrB_Index S[16] ;
size_t ns = 0 ;

const char *name = files[k].sources ;
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
FILE *f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
OK (LAGraph_MMRead (&A, f, msg)) ;
OK (fclose (f));

OK (LAGraph_New (&(G[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;

TEST_CHECK (A == NULL) ;
}
while (fscanf(f, "%" PRIu64, &s) != EOF)
{
S[ns++] = s - 1 ;
}

// Load NFA from MTX files representing its adjacency matrix
// decomposition
for (int i = 0 ; ; i++)
{
const char *name = files[k].fas[i] ;
OK (fclose(f)) ;

if (name == NULL) break ;
if (strlen(name) == 0) continue ;
// Load NFA starting states from the meta file
GrB_Index qs ;
GrB_Index QS[16] ;
size_t nqs = 0 ;

name = files[k].fa_meta ;
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
FILE *f = fopen (filename, "r") ;
f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
OK (LAGraph_MMRead (&A, f, msg)) ;
OK (fclose (f)) ;

OK (LAGraph_New (&(R[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
OK (LAGraph_Cached_AT (R[i], msg)) ;
uint64_t nqs64 = 0 ;
TEST_CHECK (fscanf(f, "%" PRIu64, &nqs64) != EOF) ;
nqs = (size_t) nqs64 ;

TEST_CHECK (A == NULL) ;
}

// Note the matrix rows/cols are enumerated from 0 to n-1. Meanwhile, in
// MTX format they are enumerated from 1 to n. Thus, when
// loading/comparing the results these values should be
// decremented/incremented correspondingly.
for (uint64_t i = 0; i < nqs; i++) {
TEST_CHECK (fscanf(f, "%" PRIu64, &qs) != EOF) ;
QS[i] = qs - 1 ;
}

// Load graph source nodes from the sources file
GrB_Index s ;
GrB_Index S[16] ;
size_t ns = 0 ;
// Load NFA final states from the same file
uint64_t qf ;
uint64_t QF[16] ;
size_t nqf = 0 ;
uint64_t nqf64 = 0 ;

const char *name = files[k].sources ;
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
FILE *f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
TEST_CHECK (fscanf(f, "%" PRIu64, &nqf64) != EOF) ;
nqf = (size_t) nqf64 ;

while (fscanf(f, "%" PRIu64, &s) != EOF)
{
S[ns++] = s - 1 ;
}
for (uint64_t i = 0; i < nqf; i++) {
TEST_CHECK (fscanf(f, "%" PRIu64, &qf) != EOF) ;
QF[i] = qf - 1 ;
}

OK (fclose(f)) ;
OK (fclose(f)) ;

// Load NFA starting states from the meta file
GrB_Index qs ;
GrB_Index QS[16] ;
size_t nqs = 0 ;
// Evaluate the algorithm
GrB_Vector r = NULL ;

name = files[k].fa_meta ;
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
f = fopen (filename, "r") ;
TEST_CHECK (f != NULL) ;
OK (LAGraph_RegularPathQuery (&r, R, MAX_LABELS, QS, nqs,
QF, nqf, G, S, ns, msg)) ;

uint64_t nqs64 = 0 ;
TEST_CHECK (fscanf(f, "%" PRIu64, &nqs64) != EOF) ;
nqs = (size_t) nqs64 ;
// Extract results from the output vector
GrB_Index *reachable ;
bool *values ;

for (uint64_t i = 0; i < nqs; i++) {
TEST_CHECK (fscanf(f, "%" PRIu64, &qs) != EOF) ;
QS[i] = qs - 1 ;
}
GrB_Index nvals ;
GrB_Vector_nvals (&nvals, r) ;

// Load NFA final states from the same file
uint64_t qf ;
uint64_t QF[16] ;
size_t nqf = 0 ;
uint64_t nqf64 = 0 ;
OK (LAGraph_Malloc ((void **) &reachable, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
OK (LAGraph_Malloc ((void **) &values, MAX_RESULTS, sizeof (GrB_Index), msg)) ;

TEST_CHECK (fscanf(f, "%" PRIu64, &nqf64) != EOF) ;
nqf = (size_t) nqf64 ;
GrB_Vector_extractTuples (reachable, values, &nvals, r) ;

for (uint64_t i = 0; i < nqf; i++) {
TEST_CHECK (fscanf(f, "%" PRIu64, &qf) != EOF) ;
QF[i] = qf - 1 ;
}
// Compare the results with expected values
TEST_CHECK (nvals == files[k].expected_count) ;
for (uint64_t i = 0 ; i < nvals ; i++)
TEST_CHECK (reachable[i] + 1 == files[k].expected[i]) ;

OK (fclose(f)) ;
// Cleanup
OK (LAGraph_Free ((void **) &values, NULL)) ;
OK (LAGraph_Free ((void **) &reachable, NULL)) ;

// Evaluate the algorithm
GrB_Vector r = NULL ;
OK (GrB_free (&r)) ;

OK (LAGraph_RegularPathQuery (&r, R, MAX_LABELS, QS, nqs,
QF, nqf, G, S, ns, msg)) ;
for (uint64_t i = 0 ; i < MAX_LABELS ; i++)
{
if (G[i] == NULL) continue ;
OK (LAGraph_Delete (&(G[i]), msg)) ;
}

// Extract results from the output vector
GrB_Index *reachable ;
bool *values ;

GrB_Index nvals ;
GrB_Vector_nvals (&nvals, r) ;

OK (LAGraph_Malloc ((void **) &reachable, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
OK (LAGraph_Malloc ((void **) &values, MAX_RESULTS, sizeof (GrB_Index), msg)) ;

GrB_Vector_extractTuples (reachable, values, &nvals, r) ;

// Compare the results with expected values
TEST_CHECK (nvals == files[k].expected_count) ;
for (uint64_t i = 0 ; i < nvals ; i++)
TEST_CHECK (reachable[i] + 1 == files[k].expected[i]) ;

// Cleanup
OK (LAGraph_Free ((void **) &values, NULL)) ;
OK (LAGraph_Free ((void **) &reachable, NULL)) ;

OK (GrB_free (&r)) ;

for (uint64_t i = 0 ; i < MAX_LABELS ; i++)
{
if (G[i] == NULL) continue ;
OK (LAGraph_Delete (&(G[i]), msg)) ;
}

for (uint64_t i = 0 ; i < MAX_LABELS ; i++ )
{
if (R[i] == NULL) continue ;
OK (LAGraph_Delete (&(R[i]), msg)) ;
for (uint64_t i = 0 ; i < MAX_LABELS ; i++ )
{
if (R[i] == NULL) continue ;
OK (LAGraph_Delete (&(R[i]), msg)) ;
}
}
}

Expand Down
Loading