Skip to content

Commit 1dbeedc

Browse files
Fix regular path query test coverage
In GraphBLAS#261 an algorithm for evaluating regular path queries has been introduced. The algorithm uses NFAs for representing regular constraints and uses transpositions of their adjacency matrices. The implementation involved checks on whether the provided adjacency matrix is symmetric and its transpositions are cached though this behavior hasn't been tested and the coverage has been lower than 100%. This patch fixes it by varying whether to cache the matrix transpositions and compute the symmetry flags.
1 parent 8315558 commit 1dbeedc

File tree

4 files changed

+121
-119
lines changed

4 files changed

+121
-119
lines changed

data/rpq_data/3_a.mtx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
%%MatrixMarket matrix coordinate pattern general
1+
%%MatrixMarket matrix coordinate pattern symmetric
22
%%GraphBLAS type bool
33
2 2 1
44
1 1

data/rpq_data/3_b.mtx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
%%MatrixMarket matrix coordinate pattern general
1+
%%MatrixMarket matrix coordinate pattern symmetric
22
%%GraphBLAS type bool
33
2 2 1
44
1 1

experimental/algorithm/LAGraph_RegularPathQuery.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@
7575
// Performance considerations: the best performance is shown when the algorithm
7676
// receives a minimal deterministic finite automaton as an input.
7777

78-
// FIXME: some of the code below is not covered by the test suite, "make cov".
79-
// See the FIXMEs below.
80-
8178
#define LG_FREE_WORK \
8279
{ \
8380
GrB_free (&frontier) ; \
@@ -200,8 +197,6 @@ int LAGraph_RegularPathQuery
200197
B[i] = R[i]->A ;
201198
if (R[i]->is_symmetric_structure == LAGraph_TRUE)
202199
{
203-
// FIXME: this case is not tested
204-
// by experimental/test/test_RegularPathQuery.c
205200
BT[i] = B[i] ;
206201
}
207202
else
@@ -326,8 +321,6 @@ int LAGraph_RegularPathQuery
326321
}
327322
else
328323
{
329-
// FIXME: this case is not tested
330-
// by experimental/test/test_RegularPathQuery.c
331324
GRB_TRY (GrB_mxm (symbol_frontier, GrB_NULL, GrB_NULL,
332325
GrB_LOR_LAND_SEMIRING_BOOL, B[i], frontier, GrB_DESC_RT0)) ;
333326
}

experimental/test/test_RegularPathQuery.c

Lines changed: 119 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -70,143 +70,152 @@ void test_RegularPathQueryBasic (void)
7070
snprintf (testcase_name, LEN, "basic regular path query %s", files[k].name) ;
7171
TEST_CASE (testcase_name) ;
7272

73-
// Load graph from MTX files representing its adjacency matrix
74-
// decomposition
75-
for (int i = 0 ; ; i++)
73+
for (int check_symmetry = 0 ; check_symmetry <= 1 ; check_symmetry++)
7674
{
77-
const char *name = files[k].graphs[i] ;
78-
79-
if (name == NULL) break ;
80-
if (strlen(name) == 0) continue ;
81-
75+
// Load graph from MTX files representing its adjacency matrix
76+
// decomposition
77+
for (int i = 0 ; ; i++)
78+
{
79+
const char *name = files[k].graphs[i] ;
80+
81+
if (name == NULL) break ;
82+
if (strlen(name) == 0) continue ;
83+
84+
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
85+
FILE *f = fopen (filename, "r") ;
86+
TEST_CHECK (f != NULL) ;
87+
OK (LAGraph_MMRead (&A, f, msg)) ;
88+
OK (fclose (f));
89+
90+
OK (LAGraph_New (&(G[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
91+
92+
TEST_CHECK (A == NULL) ;
93+
}
94+
95+
// Load NFA from MTX files representing its adjacency matrix
96+
// decomposition
97+
for (int i = 0 ; ; i++)
98+
{
99+
const char *name = files[k].fas[i] ;
100+
101+
if (name == NULL) break ;
102+
if (strlen(name) == 0) continue ;
103+
104+
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
105+
FILE *f = fopen (filename, "r") ;
106+
TEST_CHECK (f != NULL) ;
107+
OK (LAGraph_MMRead (&A, f, msg)) ;
108+
OK (fclose (f)) ;
109+
110+
OK (LAGraph_New (&(R[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
111+
112+
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+
OK (LAGraph_Cached_IsSymmetricStructure (R[i], msg)) ;
117+
}
118+
119+
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+
size_t ns = 0 ;
131+
132+
const char *name = files[k].sources ;
82133
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
83134
FILE *f = fopen (filename, "r") ;
84135
TEST_CHECK (f != NULL) ;
85-
OK (LAGraph_MMRead (&A, f, msg)) ;
86-
OK (fclose (f));
87-
88-
OK (LAGraph_New (&(G[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
89136

90-
TEST_CHECK (A == NULL) ;
91-
}
137+
while (fscanf(f, "%" PRIu64, &s) != EOF)
138+
{
139+
S[ns++] = s - 1 ;
140+
}
92141

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

99-
if (name == NULL) break ;
100-
if (strlen(name) == 0) continue ;
144+
// Load NFA starting states from the meta file
145+
GrB_Index qs ;
146+
GrB_Index QS[16] ;
147+
size_t nqs = 0 ;
101148

149+
name = files[k].fa_meta ;
102150
snprintf (filename, LEN, LG_DATA_DIR "%s", name) ;
103-
FILE *f = fopen (filename, "r") ;
151+
f = fopen (filename, "r") ;
104152
TEST_CHECK (f != NULL) ;
105-
OK (LAGraph_MMRead (&A, f, msg)) ;
106-
OK (fclose (f)) ;
107153

108-
OK (LAGraph_New (&(R[i]), &A, LAGraph_ADJACENCY_DIRECTED, msg)) ;
109-
OK (LAGraph_Cached_AT (R[i], msg)) ;
154+
uint64_t nqs64 = 0 ;
155+
TEST_CHECK (fscanf(f, "%" PRIu64, &nqs64) != EOF) ;
156+
nqs = (size_t) nqs64 ;
110157

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

119-
// Load graph source nodes from the sources file
120-
GrB_Index s ;
121-
GrB_Index S[16] ;
122-
size_t ns = 0 ;
163+
// Load NFA final states from the same file
164+
uint64_t qf ;
165+
uint64_t QF[16] ;
166+
size_t nqf = 0 ;
167+
uint64_t nqf64 = 0 ;
123168

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

129-
while (fscanf(f, "%" PRIu64, &s) != EOF)
130-
{
131-
S[ns++] = s - 1 ;
132-
}
172+
for (uint64_t i = 0; i < nqf; i++) {
173+
TEST_CHECK (fscanf(f, "%" PRIu64, &qf) != EOF) ;
174+
QF[i] = qf - 1 ;
175+
}
133176

134-
OK (fclose(f)) ;
177+
OK (fclose(f)) ;
135178

136-
// Load NFA starting states from the meta file
137-
GrB_Index qs ;
138-
GrB_Index QS[16] ;
139-
size_t nqs = 0 ;
179+
// Evaluate the algorithm
180+
GrB_Vector r = NULL ;
140181

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

146-
uint64_t nqs64 = 0 ;
147-
TEST_CHECK (fscanf(f, "%" PRIu64, &nqs64) != EOF) ;
148-
nqs = (size_t) nqs64 ;
185+
// Extract results from the output vector
186+
GrB_Index *reachable ;
187+
bool *values ;
149188

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

155-
// Load NFA final states from the same file
156-
uint64_t qf ;
157-
uint64_t QF[16] ;
158-
size_t nqf = 0 ;
159-
uint64_t nqf64 = 0 ;
192+
OK (LAGraph_Malloc ((void **) &reachable, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
193+
OK (LAGraph_Malloc ((void **) &values, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
160194

161-
TEST_CHECK (fscanf(f, "%" PRIu64, &nqf64) != EOF) ;
162-
nqf = (size_t) nqf64 ;
195+
GrB_Vector_extractTuples (reachable, values, &nvals, r) ;
163196

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

169-
OK (fclose(f)) ;
202+
// Cleanup
203+
OK (LAGraph_Free ((void **) &values, NULL)) ;
204+
OK (LAGraph_Free ((void **) &reachable, NULL)) ;
170205

171-
// Evaluate the algorithm
172-
GrB_Vector r = NULL ;
206+
OK (GrB_free (&r)) ;
173207

174-
OK (LAGraph_RegularPathQuery (&r, R, MAX_LABELS, QS, nqs,
175-
QF, nqf, G, S, ns, msg)) ;
208+
for (uint64_t i = 0 ; i < MAX_LABELS ; i++)
209+
{
210+
if (G[i] == NULL) continue ;
211+
OK (LAGraph_Delete (&(G[i]), msg)) ;
212+
}
176213

177-
// Extract results from the output vector
178-
GrB_Index *reachable ;
179-
bool *values ;
180-
181-
GrB_Index nvals ;
182-
GrB_Vector_nvals (&nvals, r) ;
183-
184-
OK (LAGraph_Malloc ((void **) &reachable, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
185-
OK (LAGraph_Malloc ((void **) &values, MAX_RESULTS, sizeof (GrB_Index), msg)) ;
186-
187-
GrB_Vector_extractTuples (reachable, values, &nvals, r) ;
188-
189-
// Compare the results with expected values
190-
TEST_CHECK (nvals == files[k].expected_count) ;
191-
for (uint64_t i = 0 ; i < nvals ; i++)
192-
TEST_CHECK (reachable[i] + 1 == files[k].expected[i]) ;
193-
194-
// Cleanup
195-
OK (LAGraph_Free ((void **) &values, NULL)) ;
196-
OK (LAGraph_Free ((void **) &reachable, NULL)) ;
197-
198-
OK (GrB_free (&r)) ;
199-
200-
for (uint64_t i = 0 ; i < MAX_LABELS ; i++)
201-
{
202-
if (G[i] == NULL) continue ;
203-
OK (LAGraph_Delete (&(G[i]), msg)) ;
204-
}
205-
206-
for (uint64_t i = 0 ; i < MAX_LABELS ; i++ )
207-
{
208-
if (R[i] == NULL) continue ;
209-
OK (LAGraph_Delete (&(R[i]), msg)) ;
214+
for (uint64_t i = 0 ; i < MAX_LABELS ; i++ )
215+
{
216+
if (R[i] == NULL) continue ;
217+
OK (LAGraph_Delete (&(R[i]), msg)) ;
218+
}
210219
}
211220
}
212221

0 commit comments

Comments
 (0)