LCOV - code coverage report
Current view: top level - src/algorithm - LAGr_PageRankGAP.c (source / functions) Hit Total Coverage
Test: LAGraph code coverage report. Commit id: cc56ed4. Current time (UTC): 2024-08-30T17:14:30Z Lines: 39 39 100.0 %
Date: 2024-08-30 17:16:41 Functions: 1 1 100.0 %

          Line data    Source code
       1             : //------------------------------------------------------------------------------
       2             : // LAGr_PageRankGAP: pagerank for the GAP benchmark
       3             : //------------------------------------------------------------------------------
       4             : 
       5             : // LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
       6             : // SPDX-License-Identifier: BSD-2-Clause
       7             : //
       8             : // For additional details (including references to third party source code and
       9             : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See
      10             : // Contributors.txt for a full list of contributors. Created, in part, with
      11             : // funding and support from the U.S. Government (see Acknowledgments.txt file).
      12             : // DM22-0790
      13             : 
      14             : // Contributed by Timothy A. Davis and Mohsen Aznaveh, Texas A&M University
      15             : 
      16             : //------------------------------------------------------------------------------
      17             : 
      18             : // This is an Advanced algorithm (G->AT and G->out_degree are required).
      19             : 
      20             : // PageRank for the GAP benchmark (only).  Do not use in production.
      21             : 
      22             : // This algorithm follows the specification given in the GAP Benchmark Suite:
      23             : // https://arxiv.org/abs/1508.03619 which assumes that both A and A' are
      24             : // already available, as are the row and column degrees.  The GAP specification
      25             : // ignores dangling nodes (nodes with no outgoing edges, also called sinks),
      26             : // and thus shouldn't be used in production.  This method is for the GAP
      27             : // benchmark only.  See LAGr_PageRank for a method that
      28             : // handles sinks correctly.  This method does not return a centrality metric
      29             : // such that sum(centrality) is 1, if sinks are present.
      30             : 
      31             : // The G->AT and G->out_degree cached properties must be defined for this
      32             : // method.  If G is undirected or G->A is known to have a symmetric structure,
      33             : // then G->A is used instead of G->AT, however.
      34             : 
      35             : #define LG_FREE_WORK                \
      36             : {                                   \
      37             :     GrB_free (&d1) ;                \
      38             :     GrB_free (&d) ;                 \
      39             :     GrB_free (&t) ;                 \
      40             :     GrB_free (&w) ;                 \
      41             : }
      42             : 
      43             : #define LG_FREE_ALL                 \
      44             : {                                   \
      45             :     LG_FREE_WORK ;                  \
      46             :     GrB_free (&r) ;                 \
      47             : }
      48             : 
      49             : #include "LG_internal.h"
      50             : 
      51           3 : int LAGr_PageRankGAP
      52             : (
      53             :     // output:
      54             :     GrB_Vector *centrality, // centrality(i): GAP-style pagerank of node i
      55             :     int *iters,             // number of iterations taken
      56             :     // input:
      57             :     const LAGraph_Graph G,  // input graph
      58             :     float damping,          // damping factor (typically 0.85)
      59             :     float tol,              // stopping tolerance (typically 1e-4) ;
      60             :     int itermax,            // maximum number of iterations (typically 100)
      61             :     char *msg
      62             : )
      63             : {
      64             : 
      65             :     //--------------------------------------------------------------------------
      66             :     // check inputs
      67             :     //--------------------------------------------------------------------------
      68             : 
      69           3 :     LG_CLEAR_MSG ;
      70           3 :     GrB_Vector r = NULL, d = NULL, t = NULL, w = NULL, d1 = NULL ;
      71           3 :     LG_ASSERT (centrality != NULL, GrB_NULL_POINTER) ;
      72           3 :     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
      73             :     GrB_Matrix AT ;
      74           3 :     if (G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
      75           2 :         G->is_symmetric_structure == LAGraph_TRUE)
      76             :     {
      77             :         // A and A' have the same structure
      78           1 :         AT = G->A ;
      79             :     }
      80             :     else
      81             :     {
      82             :         // A and A' differ
      83           2 :         AT = G->AT ;
      84           2 :         LG_ASSERT_MSG (AT != NULL,
      85             :             LAGRAPH_NOT_CACHED, "G->AT is required") ;
      86             :     }
      87           3 :     GrB_Vector d_out = G->out_degree ;
      88           3 :     LG_ASSERT_MSG (d_out != NULL,
      89             :         LAGRAPH_NOT_CACHED, "G->out_degree is required") ;
      90             : 
      91             :     //--------------------------------------------------------------------------
      92             :     // initializations
      93             :     //--------------------------------------------------------------------------
      94             : 
      95             :     GrB_Index n ;
      96           3 :     (*centrality) = NULL ;
      97           3 :     GRB_TRY (GrB_Matrix_nrows (&n, AT)) ;
      98             : 
      99           3 :     const float scaled_damping = (1 - damping) / n ;
     100           3 :     const float teleport = scaled_damping ; // teleport = (1 - damping) / n
     101           3 :     float rdiff = 1 ;       // first iteration is always done
     102             : 
     103             :     // r = 1 / n
     104           3 :     GRB_TRY (GrB_Vector_new (&t, GrB_FP32, n)) ;
     105           3 :     GRB_TRY (GrB_Vector_new (&r, GrB_FP32, n)) ;
     106           3 :     GRB_TRY (GrB_Vector_new (&w, GrB_FP32, n)) ;
     107           3 :     GRB_TRY (GrB_assign (r, NULL, NULL, (float) (1.0 / n), GrB_ALL, n, NULL)) ;
     108             : 
     109             :     // prescale with damping factor, so it isn't done each iteration
     110             :     // d = d_out / damping ;
     111           3 :     GRB_TRY (GrB_Vector_new (&d, GrB_FP32, n)) ;
     112           3 :     GRB_TRY (GrB_apply (d, NULL, NULL, GrB_DIV_FP32, d_out, damping, NULL)) ;
     113             : 
     114             :     // d1 = 1 / damping
     115           3 :     float dmin = 1.0 / damping ;
     116           3 :     GRB_TRY (GrB_Vector_new (&d1, GrB_FP32, n)) ;
     117           3 :     GRB_TRY (GrB_assign (d1, NULL, NULL, dmin, GrB_ALL, n, NULL)) ;
     118             :     // d = max (d1, d)
     119           3 :     GRB_TRY (GrB_eWiseAdd (d, NULL, NULL, GrB_MAX_FP32, d1, d, NULL)) ;
     120           3 :     GrB_free (&d1) ;
     121             : 
     122             :     //--------------------------------------------------------------------------
     123             :     // pagerank iterations
     124             :     //--------------------------------------------------------------------------
     125             : 
     126          55 :     for ((*iters) = 0 ; (*iters) < itermax && rdiff > tol ; (*iters)++)
     127             :     {
     128             :         // swap t and r ; now t is the old score
     129          52 :         GrB_Vector temp = t ; t = r ; r = temp ;
     130             :         // w = t ./ d
     131          52 :         GRB_TRY (GrB_eWiseMult (w, NULL, NULL, GrB_DIV_FP32, t, d, NULL)) ;
     132             :         // r = teleport
     133          52 :         GRB_TRY (GrB_assign (r, NULL, NULL, teleport, GrB_ALL, n, NULL)) ;
     134             :         // r += A'*w
     135          52 :         GRB_TRY (GrB_mxv (r, NULL, GrB_PLUS_FP32, LAGraph_plus_second_fp32,
     136             :             AT, w, NULL)) ;
     137             :         // t -= r
     138          52 :         GRB_TRY (GrB_assign (t, NULL, GrB_MINUS_FP32, r, GrB_ALL, n, NULL)) ;
     139             :         // t = abs (t)
     140          52 :         GRB_TRY (GrB_apply (t, NULL, NULL, GrB_ABS_FP32, t, NULL)) ;
     141             :         // rdiff = sum (t)
     142          52 :         GRB_TRY (GrB_reduce (&rdiff, NULL, GrB_PLUS_MONOID_FP32, t, NULL)) ;
     143             :     }
     144             : 
     145             :     //--------------------------------------------------------------------------
     146             :     // free workspace and return result
     147             :     //--------------------------------------------------------------------------
     148             : 
     149           3 :     (*centrality) = r ;
     150           3 :     LG_FREE_WORK ;
     151           3 :     return (GrB_SUCCESS) ;
     152             : }

Generated by: LCOV version 1.14