#define LG_FREE_WORK \
{ \
GrB_free (&d1) ; \
GrB_free (&d) ; \
GrB_free (&t) ; \
GrB_free (&w) ; \
}
#define LG_FREE_ALL \
{ \
LG_FREE_WORK ; \
GrB_free (&r) ; \
}
#include "LG_internal.h"
int LAGr_PageRankGAP
(
GrB_Vector *centrality, int *iters, const LAGraph_Graph G, float damping, float tol, int itermax, char *msg
)
{
LG_CLEAR_MSG ;
GrB_Vector r = NULL, d = NULL, t = NULL, w = NULL, d1 = NULL ;
LG_ASSERT (centrality != NULL, GrB_NULL_POINTER) ;
LG_TRY (LAGraph_CheckGraph (G, msg)) ;
GrB_Matrix AT ;
if (G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
G->is_symmetric_structure == LAGraph_TRUE)
{
AT = G->A ;
}
else
{
AT = G->AT ;
LG_ASSERT_MSG (AT != NULL,
LAGRAPH_NOT_CACHED, "G->AT is required") ;
}
GrB_Vector d_out = G->out_degree ;
LG_ASSERT_MSG (d_out != NULL,
LAGRAPH_NOT_CACHED, "G->out_degree is required") ;
GrB_Index n ;
(*centrality) = NULL ;
GRB_TRY (GrB_Matrix_nrows (&n, AT)) ;
const float scaled_damping = (1 - damping) / n ;
const float teleport = scaled_damping ; float rdiff = 1 ;
GRB_TRY (GrB_Vector_new (&t, GrB_FP32, n)) ;
GRB_TRY (GrB_Vector_new (&r, GrB_FP32, n)) ;
GRB_TRY (GrB_Vector_new (&w, GrB_FP32, n)) ;
GRB_TRY (GrB_assign (r, NULL, NULL, (float) (1.0 / n), GrB_ALL, n, NULL)) ;
GRB_TRY (GrB_Vector_new (&d, GrB_FP32, n)) ;
GRB_TRY (GrB_apply (d, NULL, NULL, GrB_DIV_FP32, d_out, damping, NULL)) ;
float dmin = 1.0 / damping ;
GRB_TRY (GrB_Vector_new (&d1, GrB_FP32, n)) ;
GRB_TRY (GrB_assign (d1, NULL, NULL, dmin, GrB_ALL, n, NULL)) ;
GRB_TRY (GrB_eWiseAdd (d, NULL, NULL, GrB_MAX_FP32, d1, d, NULL)) ;
GrB_free (&d1) ;
for ((*iters) = 0 ; (*iters) < itermax && rdiff > tol ; (*iters)++)
{
GrB_Vector temp = t ; t = r ; r = temp ;
GRB_TRY (GrB_eWiseMult (w, NULL, NULL, GrB_DIV_FP32, t, d, NULL)) ;
GRB_TRY (GrB_assign (r, NULL, NULL, teleport, GrB_ALL, n, NULL)) ;
GRB_TRY (GrB_mxv (r, NULL, GrB_PLUS_FP32, LAGraph_plus_second_fp32,
AT, w, NULL)) ;
GRB_TRY (GrB_assign (t, NULL, GrB_MINUS_FP32, r, GrB_ALL, n, NULL)) ;
GRB_TRY (GrB_apply (t, NULL, NULL, GrB_ABS_FP32, t, NULL)) ;
GRB_TRY (GrB_reduce (&rdiff, NULL, GrB_PLUS_MONOID_FP32, t, NULL)) ;
}
(*centrality) = r ;
LG_FREE_WORK ;
return (GrB_SUCCESS) ;
}