Commit 4d7eb88e authored by Tiago Peixoto's avatar Tiago Peixoto

Fix bug in katz() and introduce optional normalization

parent 5c45cb3a
...@@ -39,19 +39,19 @@ void katz(GraphInterface& g, boost::any w, boost::any c, boost::any beta, ...@@ -39,19 +39,19 @@ void katz(GraphInterface& g, boost::any w, boost::any c, boost::any beta,
throw ValueException("personalization vertex property must be of floating point" throw ValueException("personalization vertex property must be of floating point"
" value type"); " value type");
typedef ConstantPropertyMap<int, GraphInterface::edge_t> weight_map_t; typedef ConstantPropertyMap<double, GraphInterface::edge_t> weight_map_t;
typedef mpl::push_back<writable_edge_scalar_properties, weight_map_t>::type typedef mpl::push_back<writable_edge_scalar_properties, weight_map_t>::type
weight_props_t; weight_props_t;
if(w.empty()) if(w.empty())
w = weight_map_t(1); w = weight_map_t(1.);
typedef ConstantPropertyMap<int, GraphInterface::vertex_t> beta_map_t; typedef ConstantPropertyMap<double, GraphInterface::vertex_t> beta_map_t;
typedef mpl::push_back<vertex_floating_properties, beta_map_t>::type typedef mpl::push_back<vertex_floating_properties, beta_map_t>::type
beta_props_t; beta_props_t;
if(beta.empty()) if(beta.empty())
beta = beta_map_t(1); beta = beta_map_t(1.);
run_action<>()(g, bind<void> run_action<>()(g, bind<void>
(get_katz(), _1, g.GetVertexIndex(), _2, (get_katz(), _1, g.GetVertexIndex(), _2,
......
...@@ -44,14 +44,12 @@ struct get_katz ...@@ -44,14 +44,12 @@ struct get_katz
CentralityMap c_temp(vertex_index, num_vertices(g)); CentralityMap c_temp(vertex_index, num_vertices(g));
t_type delta = epsilon + 1; t_type delta = epsilon + 1;
t_type norm = 0;
size_t iter = 0; size_t iter = 0;
int i, N = num_vertices(g); int i, N = num_vertices(g);
while (delta >= epsilon) while (delta >= epsilon)
{ {
norm = 0;
#pragma omp parallel for default(shared) private(i) \ #pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:norm) schedule(static) if (N > 100)
for (i = 0; i < N; ++i) for (i = 0; i < N; ++i)
{ {
typename graph_traits<Graph>::vertex_descriptor v = typename graph_traits<Graph>::vertex_descriptor v =
...@@ -66,14 +64,12 @@ struct get_katz ...@@ -66,14 +64,12 @@ struct get_katz
{ {
typename graph_traits<Graph>::vertex_descriptor s; typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value) if (is_directed::apply<Graph>::type::value)
s = source(*e,g); s = source(*e, g);
else else
s = target(*e,g); s = target(*e, g);
c_temp[v] += alpha * get(w, *e) * c[s]; c_temp[v] += alpha * get(w, *e) * c[s];
} }
norm += power(c_temp[v], 2);
} }
norm = sqrt(norm);
delta = 0; delta = 0;
#pragma omp parallel for default(shared) private(i) \ #pragma omp parallel for default(shared) private(i) \
...@@ -84,13 +80,12 @@ struct get_katz ...@@ -84,13 +80,12 @@ struct get_katz
vertex(i, g); vertex(i, g);
if (v == graph_traits<Graph>::null_vertex()) if (v == graph_traits<Graph>::null_vertex())
continue; continue;
c_temp[v] /= norm;
delta += abs(c_temp[v] - c[v]); delta += abs(c_temp[v] - c[v]);
} }
swap(c_temp, c); swap(c_temp, c);
++iter; ++iter;
if (max_iter > 0 && iter== max_iter) if (max_iter > 0 && iter == max_iter)
break; break;
} }
...@@ -104,7 +99,7 @@ struct get_katz ...@@ -104,7 +99,7 @@ struct get_katz
vertex(i, g); vertex(i, g);
if (v == graph_traits<Graph>::null_vertex()) if (v == graph_traits<Graph>::null_vertex())
continue; continue;
c[v] = c_temp[v]; c_temp[v] = c[v];
} }
} }
} }
......
...@@ -53,6 +53,7 @@ from .. import _prop, ungroup_vector_property ...@@ -53,6 +53,7 @@ from .. import _prop, ungroup_vector_property
from .. topology import shortest_distance from .. topology import shortest_distance
import sys import sys
import numpy import numpy
import numpy.linalg
__all__ = ["pagerank", "betweenness", "central_point_dominance", "closeness", __all__ = ["pagerank", "betweenness", "central_point_dominance", "closeness",
"eigentrust", "eigenvector", "katz", "hits", "trust_transitivity"] "eigentrust", "eigenvector", "katz", "hits", "trust_transitivity"]
...@@ -622,7 +623,8 @@ def eigenvector(g, weight=None, vprop=None, epsilon=1e-6, max_iter=None): ...@@ -622,7 +623,8 @@ def eigenvector(g, weight=None, vprop=None, epsilon=1e-6, max_iter=None):
return ee, vprop return ee, vprop
def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6, max_iter=None): def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6,
max_iter=None, norm=True):
r""" r"""
Calculate the Katz centrality of each vertex in the graph. Calculate the Katz centrality of each vertex in the graph.
...@@ -646,6 +648,8 @@ def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6, max_it ...@@ -646,6 +648,8 @@ def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6, max_it
vertices are below this value. vertices are below this value.
max_iter : int, optional (default: ``None``) max_iter : int, optional (default: ``None``)
If supplied, this will limit the total number of iterations. If supplied, this will limit the total number of iterations.
norm : bool, optional (default: ``True``)
Whether or not the centrality values should be normalized.
Returns Returns
------- -------
...@@ -723,15 +727,15 @@ def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6, max_it ...@@ -723,15 +727,15 @@ def katz(g, alpha=0.01, beta=None, weight=None, vprop=None, epsilon=1e-6, max_it
Weblogging Ecosystem (2005). :DOI:`10.1145/1134271.1134277` Weblogging Ecosystem (2005). :DOI:`10.1145/1134271.1134277`
""" """
if vprop == None: if vprop is None:
vprop = g.new_vertex_property("double") vprop = g.new_vertex_property("double")
N = len(vprop.a)
vprop.a = beta.a[:N] if beta is not None else 1.
if max_iter is None: if max_iter is None:
max_iter = 0 max_iter = 0
ee = libgraph_tool_centrality.\ libgraph_tool_centrality.\
get_katz(g._Graph__graph, _prop("e", g, weight), _prop("v", g, vprop), get_katz(g._Graph__graph, _prop("e", g, weight), _prop("v", g, vprop),
_prop("v", beta, vprop), float(alpha), epsilon, max_iter) _prop("v", g, beta), float(alpha), epsilon, max_iter)
if norm:
vprop.fa = vprop.fa / numpy.linalg.norm(vprop.fa)
return vprop return vprop
......
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