@@ -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+ // └─┘ └─┘
303332static 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+
372417static 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
441471GrB_Info LAGraph_RPQMatrix_solver (RPQMatrixPlan * plan , char * msg )
0 commit comments