@@ -1080,6 +1080,7 @@ static int ensure_result_capacity
10801080 LAGraph_Free ((void **) &BT, NULL) ; \
10811081 LAGraph_Free ((void **) &X, NULL) ; \
10821082 LAGraph_Free ((void **) &I, NULL) ; \
1083+ LAGraph_Free ((void **) &J, NULL) ; \
10831084 temp_arena_destroy () ; \
10841085}
10851086
@@ -1111,6 +1112,7 @@ static int LAGraph_2Rpq
11111112 const GrB_Index * S , // source vertices to start searching paths
11121113 size_t ns , // number of source vertices
11131114 bool inverse , // inverse the whole query
1115+ bool ignore_visited , // use mask to avoid processing the same (q, v)
11141116 uint64_t limit , // maximum path count
11151117 char * msg , // LAGraph output message
11161118 GrB_IndexUnaryOp op // index unary op for a specific semantic
@@ -1129,6 +1131,7 @@ static int LAGraph_2Rpq
11291131 // specific label
11301132 GrB_Matrix next_frontier = NULL ; // frontier value on the next
11311133 // traversal step
1134+ GrB_Matrix visited = NULL ; // visited pairs (state, vertex)
11321135 GrB_Vector final_reducer = NULL ; // auxiliary vector for reducing the
11331136 // visited matrix to an answer
11341137
@@ -1150,6 +1153,7 @@ static int LAGraph_2Rpq
11501153
11511154 MultiplePaths * X = NULL ;
11521155 GrB_Index * I = NULL ;
1156+ GrB_Index * J = NULL ;
11531157 size_t result_capacity = 0 ;
11541158
11551159 if (paths == NULL || path_count == NULL || G == NULL || R == NULL ||
@@ -1314,6 +1318,11 @@ static int LAGraph_2Rpq
13141318
13151319 GRB_TRY (GrB_Matrix_new (& next_frontier , multiple_paths , nr , ng )) ;
13161320
1321+ if (ignore_visited )
1322+ {
1323+ GRB_TRY (GrB_Matrix_new (& visited , GrB_BOOL , nr , ng )) ;
1324+ }
1325+
13171326 // Initialize frontier with the source nodes
13181327
13191328 for (size_t i = 0 ; i < ns ; i ++ )
@@ -1339,6 +1348,11 @@ static int LAGraph_2Rpq
13391348 }
13401349 }
13411350
1351+ if (ignore_visited )
1352+ {
1353+ GrB_assign (visited , NULL , NULL , true, QS , nqs , S , ns , NULL ) ;
1354+ }
1355+
13421356 // Initialize a few utility matrices
13431357 GRB_TRY (GrB_Matrix_new (& frontier , multiple_paths , nr , ng )) ;
13441358 GRB_TRY (GrB_Matrix_new (& symbol_frontier , multiple_paths , nr , ng )) ;
@@ -1354,9 +1368,10 @@ static int LAGraph_2Rpq
13541368
13551369 LG_TRY (LAGraph_Calloc ((void * * ) & X , nvals , sizeof (MultiplePaths ), msg )) ;
13561370 LG_TRY (LAGraph_Calloc ((void * * ) & I , nvals , sizeof (GrB_Index ), msg )) ;
1371+ LG_TRY (LAGraph_Calloc ((void * * ) & J , nvals , sizeof (GrB_Index ), msg )) ;
13571372
13581373 // TODO: Change to a generic call.
1359- GRB_TRY (GrB_Matrix_extractTuples_UDT (I , GrB_NULL , (void * * ) X , & nvals , next_frontier )) ;
1374+ GRB_TRY (GrB_Matrix_extractTuples_UDT (I , J , (void * * ) X , & nvals , next_frontier )) ;
13601375 //printf("Next frontier with %d entries\n", nvals);
13611376
13621377 for (size_t i = 0 ; i < nvals ; i ++ )
@@ -1383,6 +1398,20 @@ static int LAGraph_2Rpq
13831398 }
13841399 //printf("Path at %ld final is %b", I[i], final) ;
13851400
1401+ // HACK: only for all_shortest_paths
1402+ if (ignore_visited ) {
1403+ GrB_Vector w ;
1404+ GRB_TRY (GrB_Vector_new (& w , GrB_BOOL , nr )) ;
1405+ GrB_Col_extract (w , GrB_NULL , GrB_NULL , visited , QF , nqf , J [i ], GrB_NULL );
1406+ GrB_Index col_nvals = 0 ;
1407+ GrB_Vector_nvals (& col_nvals , w ) ;
1408+ GrB_free (& w ) ;
1409+
1410+ if (col_nvals > 0 ) {
1411+ continue ;
1412+ }
1413+ }
1414+
13861415 if (!final )
13871416 {
13881417 continue ;
@@ -1414,8 +1443,16 @@ static int LAGraph_2Rpq
14141443 }
14151444 }
14161445
1446+ if (ignore_visited )
1447+ {
1448+ //GRB_TRY (GrB_assign (visited, visited, GrB_NULL, next_frontier,
1449+ // GrB_ALL, nr, GrB_ALL, ng, GrB_DESC_SC)) ;
1450+ GrB_assign (visited , next_frontier , GrB_NULL , true, GrB_ALL , nr , GrB_ALL , ng , GrB_DESC_S ) ;
1451+ }
1452+
14171453 LAGraph_Free ((void * * ) & X , NULL ) ;
14181454 LAGraph_Free ((void * * ) & I , NULL ) ;
1455+ LAGraph_Free ((void * * ) & J , NULL ) ;
14191456
14201457 if (!had_non_empty_path || (* path_count ) == limit )
14211458 {
@@ -1456,22 +1493,25 @@ static int LAGraph_2Rpq
14561493 GRB_TRY (GrB_Matrix_nvals (& symbol_nvals , symbol_frontier )) ;
14571494 if (symbol_nvals == 0 ) continue ;
14581495
1496+ GrB_Descriptor desc_forward = ignore_visited ? GrB_DESC_SC : GrB_NULL ;
1497+ GrB_Descriptor desc_backward = ignore_visited ? GrB_DESC_SCT1 : GrB_DESC_T1 ;
1498+
14591499 // Traverse the graph
14601500 if (!inverse_labels [i ]) {
14611501 if (!inverse ) {
1462- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , A [i ], GrB_NULL )) ;
1502+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , A [i ], desc_forward )) ;
14631503 } else if (AT [i ]) {
1464- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , AT [i ], GrB_NULL )) ;
1504+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , AT [i ], desc_forward )) ;
14651505 } else {
1466- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , A [i ], GrB_DESC_T1 )) ;
1506+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , A [i ], desc_backward )) ;
14671507 }
14681508 } else {
14691509 if (!inverse && AT [i ]) {
1470- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , AT [i ], GrB_NULL )) ;
1510+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , AT [i ], desc_forward )) ;
14711511 } else if (!inverse ) {
1472- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , A [i ], GrB_DESC_T1 )) ;
1512+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , A [i ], desc_backward )) ;
14731513 } else {
1474- GRB_TRY (GrB_mxm (next_frontier , GrB_NULL , acc , sr1 , symbol_frontier , A [i ], GrB_NULL )) ;
1514+ GRB_TRY (GrB_mxm (next_frontier , visited , acc , sr1 , symbol_frontier , A [i ], desc_forward )) ;
14751515 }
14761516 }
14771517
@@ -1524,7 +1564,7 @@ int LAGraph_2Rpq_AllSimple // All simple paths satisfying regular
15241564 char * msg // LAGraph output message
15251565)
15261566{
1527- return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , ULLONG_MAX , msg , extend_multiple_simple ) ;
1567+ return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , false, ULLONG_MAX , msg , extend_multiple_simple ) ;
15281568}
15291569
15301570LAGRAPHX_PUBLIC
@@ -1552,7 +1592,7 @@ int LAGraph_2Rpq_AllTrails // All trails satisfying regular expression.
15521592 char * msg // LAGraph output message
15531593)
15541594{
1555- return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , ULLONG_MAX , msg , extend_multiple_trails ) ;
1595+ return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , false, ULLONG_MAX , msg , extend_multiple_trails ) ;
15561596}
15571597
15581598int LAGraph_2Rpq_AllPaths // All paths satisfying regular expression
@@ -1579,7 +1619,33 @@ int LAGraph_2Rpq_AllPaths // All paths satisfying regular expression
15791619 char * msg // LAGraph output message
15801620 )
15811621{
1582- return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , limit , msg , extend_multiple_paths ) ;
1622+ return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , false, limit , msg , extend_multiple_paths ) ;
1623+ }
1624+
1625+ int LAGraph_2Rpq_AllShortestPaths // All shortest paths satisfying regular expression
1626+ (
1627+ // output:
1628+ Path * * paths , // paths from one of the starting nodes
1629+ // satisfying regular constraints
1630+ size_t * path_count , // resulting path count
1631+ // input:
1632+ LAGraph_Graph * R , // input non-deterministic finite automaton
1633+ // adjacency matrix decomposition
1634+ bool * inverse_labels , // inversed labels
1635+ size_t nl , // total label count, # of matrices graph and
1636+ // NFA adjacency matrix decomposition
1637+ const GrB_Index * QS , // starting states in NFA
1638+ size_t nqs , // number of starting states in NFA
1639+ const GrB_Index * QF , // final states in NFA
1640+ size_t nqf , // number of final states in NFA
1641+ LAGraph_Graph * G , // input graph adjacency matrix decomposition
1642+ const GrB_Index * S , // source vertices to start searching paths
1643+ size_t ns , // number of source vertices
1644+ bool inverse , // inverse the whole query
1645+ char * msg // LAGraph output message
1646+ )
1647+ {
1648+ return LAGraph_2Rpq (paths , path_count , R , inverse_labels , nl , QS , nqs , QF , nqf , G , S , ns , inverse , true, ULLONG_MAX , msg , extend_multiple_paths ) ;
15831649}
15841650
15851651// Required because returned Path objects may own heap-allocated PathExtra.
0 commit comments