Commit ef1ed6c4 authored by Tiago Peixoto's avatar Tiago Peixoto

pagerank(): Fix problem with sink nodes

Nodes with out-degree zero are now assumed to connect to every other
node.
parent 3f7ca407
......@@ -41,12 +41,14 @@ struct get_pagerank
RankMap deg(vertex_index, num_vertices(g));
// init degs
parallel_vertex_loop
(g,
[&](auto v)
{
put(deg, v, out_degreeS()(v, g, weight));
});
std::vector<size_t> sinks;
for (auto v : vertices_range(g))
{
auto k = out_degreeS()(v, g, weight);
put(deg, v, k);
if (k == 0)
sinks.push_back(v);
}
rank_type delta = epsilon + 1;
rank_type d = damping;
......@@ -54,13 +56,21 @@ struct get_pagerank
while (delta >= epsilon)
{
delta = 0;
#pragma omp parallel if (num_vertices(g) > OPENMP_MIN_THRESH) \
double p_sink = 0;
#pragma omp parallel if (sinks.size() > OPENMP_MIN_THRESH) \
reduction(+:p_sink)
parallel_loop_no_spawn
(sinks,
[&](auto, auto v){ p_sink += get(rank, v); });
#pragma omp parallel if (num_vertices(g) > OPENMP_MIN_THRESH) \
reduction(+:delta)
parallel_vertex_loop_no_spawn
(g,
[&](auto v)
{
rank_type r = 0;
rank_type r = p_sink * get(pers, v);
for (const auto& e : in_or_out_edges_range(v, g))
{
auto s = source(e, g);
......
......@@ -61,8 +61,7 @@ __all__ = ["pagerank", "betweenness", "central_point_dominance", "closeness",
def pagerank(g, damping=0.85, pers=None, weight=None, prop=None, epsilon=1e-6,
max_iter=None, ret_iter=False):
r"""
Calculate the PageRank of each vertex.
r"""Calculate the PageRank of each vertex.
Parameters
----------
......@@ -109,8 +108,8 @@ def pagerank(g, damping=0.85, pers=None, weight=None, prop=None, epsilon=1e-6,
PR(v) = \frac{1-d}{N} + d \sum_{u \in \Gamma^{-}(v)}
\frac{PR (u)}{d^{+}(u)}
where :math:`\Gamma^{-}(v)` are the in-neighbors of v, :math:`d^{+}(w)` is
the out-degree of w, and d is a damping factor.
where :math:`\Gamma^{-}(v)` are the in-neighbors of v, :math:`d^{+}(u)` is
the out-degree of u, and d is a damping factor.
If a personalization property :math:`p(v)` is given, the definition becomes:
......@@ -129,6 +128,10 @@ def pagerank(g, damping=0.85, pers=None, weight=None, prop=None, epsilon=1e-6,
where :math:`d^{+}(u)=\sum_{y}A_{u,y}w_{u\to y}` is redefined to be the sum
of the weights of the out-going edges from u.
If a node has out-degree zero, it is assumed to connect to every other node
with a weight proportional to :math:`p(v)` or a constant if no
personalization is given.
The implemented algorithm progressively iterates the above equations, until
it no longer changes, according to the parameter epsilon. It has a
topology-dependent running time.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment