Skip to content

Commit ef81062

Browse files
committed
fix: correct L and R kleene stars
In previous versions there was a logic mistakes in processing of L and R kleene stars. Now they are correct. Also provide a docs. Signed-off-by: Rodion Suvorov <rodion.suvorov.94@mail.ru>
1 parent 27a2d8a commit ef81062

File tree

1 file changed

+106
-76
lines changed

1 file changed

+106
-76
lines changed

experimental/algorithm/LAGraph_RPQMatrix.c

Lines changed: 106 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -300,142 +300,172 @@ static GrB_Info LAGraph_RPQMatrixKleene(RPQMatrixPlan *plan, char *msg)
300300
return (GrB_SUCCESS);
301301
}
302302

303+
// this function need to handle special case where some optimization
304+
// are available.
305+
//
306+
// consider following AST:
307+
// ┌─┐
308+
// │/|
309+
// └┬┘
310+
// ┌─┬─┴─┬─┐
311+
// │*│ │b│
312+
// └┬┘ └─┘
313+
// ┌┴┐
314+
// │a│
315+
// └─┘
316+
// If matrix B is sparse and A is dense, then instead of naive
317+
// way:
318+
//
319+
// (I + A + A x A + ...) x B
320+
//
321+
// we can do:
322+
//
323+
// (B + A x B + A x A x B + ...)
324+
//
325+
// and AST should be rewritten in the following way:
326+
// ┌───┐
327+
// │L^*│
328+
// └─┬─┘
329+
// ┌─┬─┴─┬─┐
330+
// │a│ │b│
331+
// └─┘ └─┘
303332
static GrB_Info LAGraph_RPQMatrixKleene_L(RPQMatrixPlan *plan, char *msg)
304333
{
305334
LG_ASSERT(plan != NULL, GrB_NULL_POINTER);
306335
LG_ASSERT(plan->op == RPQ_MATRIX_OP_KLEENE, GrB_INVALID_VALUE);
307336
LG_ASSERT(plan->res_mat == NULL, GrB_INVALID_VALUE);
308337

309-
RPQMatrixPlan *lhs = plan->lhs;
310-
RPQMatrixPlan *rhs = plan->rhs;
338+
RPQMatrixPlan *lhs = plan->lhs; // A
339+
RPQMatrixPlan *rhs = plan->rhs; // B
311340

312-
LG_ASSERT(lhs == NULL, GrB_NULL_POINTER);
313-
LG_ASSERT(rhs == NULL, GrB_NULL_POINTER);
341+
LG_ASSERT(lhs != NULL, GrB_NULL_POINTER);
342+
LG_ASSERT(rhs != NULL, GrB_NULL_POINTER);
314343

315-
OK(LAGraph_RPQMatrix_solver(rhs, msg));
316344
OK(LAGraph_RPQMatrix_solver(lhs, msg));
345+
OK(LAGraph_RPQMatrix_solver(rhs, msg));
317346

318-
GrB_Matrix B = rhs->res_mat;
319347
GrB_Matrix A = lhs->res_mat;
348+
GrB_Matrix B = rhs->res_mat;
320349

321-
// Creating identity matrix.
322350
GrB_Index n;
323-
GRB_TRY(GrB_Matrix_nrows(&n, B));
324-
GrB_Matrix E;
325-
GRB_TRY(GrB_Matrix_new(&E, GrB_BOOL, n, n));
326-
327-
GrB_Vector v;
328-
GRB_TRY(GrB_Vector_new(&v, GrB_BOOL, n));
329-
GRB_TRY(GrB_Vector_assign_BOOL(v, NULL, NULL, true, GrB_ALL, n, NULL));
330-
331-
GRB_TRY(GrB_Matrix_diag(&E, v, 0));
351+
GRB_TRY(GrB_Matrix_nrows(&n, A));
332352

333-
GRB_TRY(GrB_Vector_free(&v));
334-
335-
GrB_Matrix BPE;
336-
GRB_TRY(GrB_Matrix_new(&BPE, GrB_BOOL, n, n));
337-
GRB_TRY(GrB_eWiseAdd(BPE, GrB_NULL, GrB_NULL,
338-
op, B, E, GrB_DESC_R));
353+
// S <- B
339354
GrB_Matrix S, T;
340-
GRB_TRY(GrB_Matrix_dup(&S, A));
355+
GRB_TRY(GrB_Matrix_dup(&S, B));
356+
GRB_TRY(GrB_Matrix_new(&T, GrB_BOOL, n, n));
341357

342358
bool changed = true;
343-
GrB_Index nnz_S = n, nnz_T = 0;
359+
GrB_Index nnz_S = 0, nnz_T = 0;
344360

345361
while (changed)
346362
{
347-
GRB_TRY(GrB_Matrix_new(&T, GrB_BOOL, n, n));
348-
GRB_TRY(GrB_mxm(T, GrB_NULL, GrB_NULL,
349-
sr, S, BPE, GrB_DESC_R));
363+
// T <- A x S
364+
GRB_TRY(GrB_mxm(T, NULL, NULL, sr, A, S, NULL));
350365

351-
GRB_TRY(GrB_Matrix_nvals(&nnz_T, T));
352-
if (nnz_T != nnz_S)
366+
// S <- S + T
367+
GRB_TRY(GrB_eWiseAdd(S, NULL, NULL, op, S, T, NULL));
368+
369+
GRB_TRY(GrB_Matrix_nvals(&nnz_S, S));
370+
if (nnz_S == nnz_T)
353371
{
354-
changed = true;
355-
nnz_S = nnz_T;
356-
GRB_TRY(GrB_Matrix_free(&S));
357-
S = T;
372+
changed = false;
358373
}
359374
else
360375
{
361-
changed = false;
362-
GRB_TRY(GrB_Matrix_free(&T));
376+
changed = true;
377+
nnz_T = nnz_S;
378+
363379
}
364380
}
365-
plan->res_mat = S;
366381

367-
GRB_TRY(GrB_Matrix_free(&E));
368-
GRB_TRY(GrB_Matrix_free(&BPE));
369-
return (GrB_SUCCESS);
382+
plan->res_mat = S;
383+
GRB_TRY(GrB_Matrix_free(&T));
384+
return GrB_SUCCESS;
370385
}
371386

387+
388+
// this function need to handle special case where some optimization
389+
// are available.
390+
// consider following AST:
391+
// ┌─┐
392+
// │/|
393+
// └┬┘
394+
// ┌─┬─┴─┬─┐
395+
// │a│ │*│
396+
// └─┘ └┬┘
397+
// ┌┴┐
398+
// │b│
399+
// └─┘
400+
// If matrix A is sparse and B is dense, then instead of naive
401+
// way:
402+
//
403+
// A x (I + B + B x B + ...)
404+
//
405+
// we can do:
406+
//
407+
// (A + A x B + A x B x B + ...)
408+
//
409+
// and AST should be rewritten in the following way:
410+
// ┌───┐
411+
// │R^*│
412+
// └─┬─┘
413+
// ┌─┬─┴─┬─┐
414+
// │a│ │b│
415+
// └─┘ └─┘
416+
372417
static GrB_Info LAGraph_RPQMatrixKleene_R(RPQMatrixPlan *plan, char *msg)
373418
{
374419
LG_ASSERT(plan != NULL, GrB_NULL_POINTER);
375420
LG_ASSERT(plan->op == RPQ_MATRIX_OP_KLEENE, GrB_INVALID_VALUE);
376421
LG_ASSERT(plan->res_mat == NULL, GrB_INVALID_VALUE);
377422

378-
RPQMatrixPlan *lhs = plan->lhs;
379-
RPQMatrixPlan *rhs = plan->rhs;
423+
RPQMatrixPlan *lhs = plan->lhs; // A
424+
RPQMatrixPlan *rhs = plan->rhs; // B
380425

381426
LG_ASSERT(lhs != NULL, GrB_NULL_POINTER);
382427
LG_ASSERT(rhs != NULL, GrB_NULL_POINTER);
383428

384-
OK(LAGraph_RPQMatrix_solver(rhs, msg));
385429
OK(LAGraph_RPQMatrix_solver(lhs, msg));
430+
OK(LAGraph_RPQMatrix_solver(rhs, msg));
386431

387-
GrB_Matrix B = lhs->res_mat;
388-
GrB_Matrix A = rhs->res_mat;
432+
GrB_Matrix A = lhs->res_mat;
433+
GrB_Matrix B = rhs->res_mat;
389434

390-
// Creating identity matrix.
391435
GrB_Index n;
392-
GRB_TRY(GrB_Matrix_nrows(&n, B));
393-
GrB_Matrix E;
394-
GRB_TRY(GrB_Matrix_new(&E, GrB_BOOL, n, n));
395-
396-
GrB_Vector v;
397-
GRB_TRY(GrB_Vector_new(&v, GrB_BOOL, n));
398-
GRB_TRY(GrB_Vector_assign_BOOL(v, NULL, NULL, true, GrB_ALL, n, NULL));
436+
GRB_TRY(GrB_Matrix_nrows(&n, A));
399437

400-
GRB_TRY(GrB_Matrix_diag(&E, v, 0));
401-
402-
GRB_TRY(GrB_Vector_free(&v));
403-
404-
GrB_Matrix BPE;
405-
GRB_TRY(GrB_Matrix_new(&BPE, GrB_BOOL, n, n));
406-
GRB_TRY(GrB_eWiseAdd(BPE, GrB_NULL, GrB_NULL,
407-
GrB_LOR, B, E, GrB_DESC_R));
438+
// S <- A
408439
GrB_Matrix S, T;
409440
GRB_TRY(GrB_Matrix_dup(&S, A));
441+
GRB_TRY(GrB_Matrix_new(&T, GrB_BOOL, n, n));
410442

411443
bool changed = true;
412-
GrB_Index nnz_S = n, nnz_T = 0;
444+
GrB_Index nnz_S = 0, nnz_T = 0;
413445

414446
while (changed)
415447
{
416-
GRB_TRY(GrB_Matrix_new(&T, GrB_BOOL, n, n));
417-
GRB_TRY(GrB_mxm(T, GrB_NULL, GrB_NULL,
418-
sr, BPE, S, GrB_DESC_R));
448+
// T <- S × B
449+
GRB_TRY(GrB_mxm(T, NULL, NULL, sr, S, B, NULL));
419450

420-
GRB_TRY(GrB_Matrix_nvals(&nnz_T, T));
421-
if (nnz_T != nnz_S)
451+
// S <- S + T
452+
GRB_TRY(GrB_eWiseAdd(S, NULL, NULL, op, S, T, NULL));
453+
454+
GRB_TRY(GrB_Matrix_nvals(&nnz_S, S));
455+
if (nnz_S == nnz_T)
422456
{
423-
changed = true;
424-
nnz_S = nnz_T;
425-
GRB_TRY(GrB_Matrix_free(&S));
426-
S = T;
457+
changed = false;
427458
}
428459
else
429460
{
430-
changed = false;
431-
GRB_TRY(GrB_Matrix_free(&T));
461+
changed = true;
462+
nnz_T = nnz_S;
432463
}
433464
}
434-
plan->res_mat = S;
435465

436-
GRB_TRY(GrB_Matrix_free(&E));
437-
GRB_TRY(GrB_Matrix_free(&BPE));
438-
return (GrB_SUCCESS);
466+
plan->res_mat = S;
467+
GRB_TRY(GrB_Matrix_free(&T));
468+
return GrB_SUCCESS;
439469
}
440470

441471
GrB_Info LAGraph_RPQMatrix_solver(RPQMatrixPlan *plan, char *msg)

0 commit comments

Comments
 (0)