Path: blob/devel/elmergrid/src/metis-5.1.0/GKlib/rw.c
3206 views
/*!1* \file2*3* \brief Various routines that perform random-walk based operations4on graphs stored as gk_csr_t matrices.5*6* \author George Karypis7* \version\verbatim $Id: rw.c 11078 2011-11-12 00:20:44Z karypis $ \endverbatim8*/910#include <GKlib.h>111213/*************************************************************************/14/*! Computes the (personalized) page-rank of the vertices in a graph.1516\param mat is the matrix storing the graph.17\param lamda is the restart probability.18\param eps is the error tolerance for convergance.19\param max_niter is the maximum number of allowed iterations.20\param pr on entry stores the restart distribution of the vertices.21This allows for the computation of personalized page-rank scores22by appropriately setting that parameter.23On return, pr stores the computed page ranks.2425\returns the number of iterations that were performed.26*/27/**************************************************************************/28int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr)29{30ssize_t i, j, k, iter, nrows;31double *rscale, *prold, *prnew, *prtmp;32double fromsinks, error;33ssize_t *rowptr;34int *rowind;35float *rowval;3637nrows = mat->nrows;38rowptr = mat->rowptr;39rowind = mat->rowind;40rowval = mat->rowval;4142prold = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prnew");43prnew = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prold");44rscale = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: rscale");4546/* compute the scaling factors to get adjacency weights into transition47probabilities */48for (i=0; i<nrows; i++) {49for (j=rowptr[i]; j<rowptr[i+1]; j++)50rscale[i] += rowval[j];51if (rscale[i] > 0)52rscale[i] = 1.0/rscale[i];53}5455/* the restart distribution is the initial pr scores */56for (i=0; i<nrows; i++)57prnew[i] = pr[i];5859/* get into the PR iteration */60for (iter=0; iter<max_niter; iter++) {61gk_SWAP(prnew, prold, prtmp);62gk_dset(nrows, 0.0, prnew);6364/* determine the total current PR score of the sinks so that you65can distribute them to all nodes according to the restart66distribution. */67for (fromsinks=0.0, i=0; i<nrows; i++) {68if (rscale[i] == 0)69fromsinks += prold[i];70}7172/* push random-walk scores to the outlinks */73for (i=0; i<nrows; i++) {74for (j=rowptr[i]; j<rowptr[i+1]; j++)75prnew[rowind[j]] += prold[i]*rscale[i]*rowval[j];76}7778/* apply the restart conditions */79for (i=0; i<nrows; i++) {80prnew[i] = lamda*(fromsinks*pr[i]+prnew[i]) + (1.0-lamda)*pr[i];81}8283/* compute the error */84for (error=0.0, i=0; i<nrows; i++)85error = (fabs(prnew[i]-prold[i]) > error ? fabs(prnew[i]-prold[i]) : error);8687//printf("nrm1: %le maxfabserr: %le\n", gk_dsum(nrows, prnew, 1), error);8889if (error < eps)90break;91}9293/* store the computed pr scores into pr for output */94for (i=0; i<nrows; i++)95pr[i] = prnew[i];9697gk_free((void **)&prnew, &prold, &rscale, LTERM);9899return (int)(iter+1);100101}102103104105