Commit 96b9c5e7 authored by Tiago Peixoto's avatar Tiago Peixoto

Add centrality module

This adds the centrality module, which supports betweenness, eigentrust,
pagerank and absolute trust.
parent d0a73fff
......@@ -293,6 +293,7 @@ src/graph/Makefile
src/graph/correlations/Makefile
src/graph/generation/Makefile
src/graph/stats/Makefile
src/graph/centrality/Makefile
src/graph/clustering/Makefile
src/graph/community/Makefile
src/graph/util/Makefile
......
## Process this file with automake to produce Makefile.in
SUBDIRS = generation correlations stats clustering community util misc
SUBDIRS = generation stats clustering community util misc centrality correlations
AM_CPPFLAGS =\
-I$(srcdir)/.. \
......
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = $(MOD_CPPFLAGS)
AM_CFLAGS=$(AM_CXXFLAGS)
libgraph_tool_centralitydir = $(MOD_DIR)/centrality
libgraph_tool_centrality_LTLIBRARIES = libgraph_tool_centrality.la
libgraph_tool_centrality_la_includedir = $(MOD_DIR)/include
libgraph_tool_centrality_la_LIBADD = $(MOD_LIBADD)
libgraph_tool_centrality_la_LDFLAGS = $(MOD_LDFLAGS)
libgraph_tool_centrality_la_SOURCES = \
graph_betweenness.cc \
graph_pagerank.cc \
graph_eigentrust.cc \
graph_absolute_trust.cc \
graph_centrality_bind.cc
libgraph_tool_centrality_la_include_HEADERS =
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include <boost/python.hpp>
#include <boost/lambda/bind.hpp>
#include "graph.hh"
#include "graph_selectors.hh"
#include <boost/random.hpp>
typedef boost::mt19937 rng_t;
#include "graph_absolute_trust.hh"
using namespace std;
using namespace boost;
using namespace graph_tool;
void absolute_trust(GraphInterface& g, boost::any c, boost::any t,
double epslon, size_t max_iter, size_t seed)
{
rng_t rng(static_cast<rng_t::result_type>(seed));
if (!belongs<edge_floating_properties>()(c))
throw GraphException("edge property must be of floating point value type");
if (!belongs<vertex_floating_vector_properties>()(t))
throw GraphException("vertex property must be of floating point vector value type");
run_action<>()
(g, bind<void>
(get_eigentrust(),
_1, g.GetVertexIndex(), g.GetEdgeIndex(), _2,
_3, epslon, max_iter, ref(rng)),
edge_floating_properties(),
vertex_floating_vector_properties())(c,t);
}
void export_absolute_trust()
{
using namespace boost::python;
def("get_absolute_trust", &absolute_trust);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_ABSOLUTE_TRUST_HH
#define GRAPH_ABSOLUTE_TRUST_HH
#include "graph.hh"
#include "graph_filtering.hh"
#include "graph_util.hh"
#include <boost/random/uniform_int.hpp>
namespace graph_tool
{
using namespace std;
using namespace boost;
struct get_eigentrust
{
template <class Graph, class VertexIndex, class EdgeIndex, class TrustMap,
class InferredTrustMap>
void operator()(Graph* gp, VertexIndex vertex_index, EdgeIndex edge_index,
TrustMap c, InferredTrustMap t, double epslon,
size_t max_iter, rng_t& rng)
const
{
Graph& g = *gp;
typedef typename property_traits<TrustMap>::value_type c_type;
typedef typename property_traits<InferredTrustMap>::value_type
::value_type t_type;
unchecked_vector_property_map<vector<size_t>, VertexIndex>
t_count(vertex_index, num_vertices(g));
unchecked_vector_property_map<vector<size_t>, VertexIndex>
v_mark(vertex_index, num_vertices(g));
// init inferred trust t
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
t[v].resize(N);
t_count[v].resize(N,0);
v_mark[v].resize(N,0);
}
t_type delta = 2*epslon;
size_t iter = 0;
while (delta >= epslon)
{
delta = 0;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
typename graph_traits<Graph>::vertex_descriptor pos = v;
t_type pos_t = 1.0;
v_mark[v][vertex_index[v]] = iter+1;
// start a self-avoiding walk from vertex v
vector<typename graph_traits<Graph>::edge_descriptor> out_es;
vector<t_type> out_prob;
do
{
out_es.clear();
out_prob.clear();
// obtain list of candidate edges to follow
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(pos, g); e != e_end; ++e)
{
typename graph_traits<Graph>::vertex_descriptor t =
target(*e,g);
if (v_mark[v][vertex_index[t]] <= iter)
{
out_es.push_back(*e);
if (out_prob.empty())
out_prob.push_back(c[*e]);
else
out_prob.push_back(out_prob.back()+c[*e]);
}
}
if (!out_es.empty())
{
// select edge according to its probability
typename graph_traits<Graph>::edge_descriptor e;
uniform_real<t_type> random(0,out_prob.back());
t_type u;
{
#pragma omp critical
u = random(rng);
}
e = out_es[lower_bound(out_prob.begin(),
out_prob.end(), u) -
out_prob.begin()];
pos = target(e,g);
size_t posi = vertex_index[pos];
//update current path trust, and update new vertex
pos_t *= c[e];
t_type old = 0;
if (t_count[v][posi] > 0)
old = t[v][posi]/t_count[v][posi];
t[v][posi] += pos_t;
t_count[v][posi]++;
delta += abs(old - t[v][posi]/t_count[v][posi]);
v_mark[v][posi] = iter+1; // mark vertex
}
}
while (!out_es.empty());
}
++iter;
if (max_iter > 0 && iter == max_iter)
break;
}
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
for (size_t j = 0; j < N; ++j)
if (t_count[v][j] > 0)
t[v][j] /= t_count[v][j];
}
}
};
}
#endif
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <boost/python.hpp>
using namespace boost;
void export_betweenness();
void export_eigentrust();
void export_absolute_trust();
void export_pagerank();
BOOST_PYTHON_MODULE(libgraph_tool_centrality)
{
export_betweenness();
export_eigentrust();
export_absolute_trust();
export_pagerank();
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include <boost/python.hpp>
#include <boost/lambda/bind.hpp>
#include "graph.hh"
#include "graph_selectors.hh"
#include "graph_eigentrust.hh"
using namespace std;
using namespace boost;
using namespace graph_tool;
void eigentrust(GraphInterface& g, boost::any c, boost::any t,
double epslon, size_t max_iter)
{
if (!belongs<writable_edge_scalar_properties>()(c))
throw GraphException("edge property must be writable");
if (!belongs<vertex_floating_vector_properties>()(t))
throw GraphException("vertex property must be of floating point value type");
run_action<>()
(g, bind<void>
(get_eigentrust(),
_1, g.GetVertexIndex(), g.GetEdgeIndex(), _2,
_3, epslon, max_iter),
writable_edge_scalar_properties(),
vertex_floating_properties())(c,t);
}
void export_eigentrust()
{
using namespace boost::python;
def("get_eigentrust", &eigentrust);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_TRUST_HH
#define GRAPH_TRUST_HH
#include "graph.hh"
#include "graph_filtering.hh"
#include "graph_util.hh"
namespace graph_tool
{
using namespace std;
using namespace boost;
struct get_eigentrust
{
template <class Graph, class VertexIndex, class EdgeIndex, class TrustMap,
class InferredTrustMap>
void operator()(Graph* gp, VertexIndex vertex_index,
EdgeIndex edge_index, TrustMap c, InferredTrustMap t,
double epslon, size_t max_iter)
const
{
Graph& g = *gp;
typedef typename property_traits<TrustMap>::value_type c_type;
typedef typename property_traits<InferredTrustMap>::value_type t_type;
InferredTrustMap t_temp(vertex_index, num_vertices(g));
// Norm c values
InferredTrustMap c_sum(vertex_index);
if (typename is_directed::apply<Graph>::type())
{
TrustMap c_temp(edge_index, c.get_storage().size());
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
c_type sum = 0;
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(v, g); e != e_end; ++e)
sum += get(c, *e);
if (sum > 0)
for (tie(e, e_end) = out_edges(v, g); e != e_end; ++e)
put(c_temp, *e, get(c, *e)/sum);
}
c = c_temp;
}
else
{
c_sum.reserve(num_vertices(g));
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
c_sum[v] = 0;
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(v, g); e != e_end; ++e)
c_sum[v] += c[*e];
}
}
// init inferred trust t
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
t[v] = 1.0/N;
}
t_type delta = 2*epslon;
size_t iter = 0;
while (delta >= epslon)
{
delta = 0;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
t_temp[v] = 0;
typename in_edge_iteratorS<Graph>::type e, e_end;
for (tie(e, e_end) = in_edge_iteratorS<Graph>::get_edges(v, g);
e != e_end; ++e)
{
typename graph_traits<Graph>::vertex_descriptor s =
source(*e,g);
if (!typename is_directed::apply<Graph>::type())
t_temp[v] += get(c, *e)*t[s]/abs(c_sum[s]);
else
t_temp[v] += get(c, *e)*t[s];
}
delta += abs(t_temp[v] - t[v]);
}
swap(t_temp, t);
++iter;
if (max_iter > 0 && iter== max_iter)
break;
}
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (int i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
t[v] = t_temp[v];
}
}
}
};
}
#endif
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include <boost/python.hpp>
#include <boost/lambda/bind.hpp>
#include "graph.hh"
#include "graph_selectors.hh"
#include "graph_pagerank.hh"
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
size_t pagerank(GraphInterface& g, boost::any rank, double d, double epslon,
size_t max_iter)
{
if (!belongs<writable_vertex_scalar_properties>()(rank))
throw GraphException("vertex property must be of writable");
size_t iter;
run_action<>()
(g, lambda::bind<void>(get_pagerank(),
lambda::_1, g.GetVertexIndex(), lambda::_2, d,
epslon, max_iter, lambda::var(iter)),
writable_vertex_scalar_properties())(rank);
return iter;
}
void export_pagerank()
{
using namespace boost::python;
def("get_pagerank", &pagerank);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_PAGERANK_HH
#define GRAPH_PAGERANK_HH
#include "graph.hh"
#include "graph_filtering.hh"
#include "graph_util.hh"
namespace graph_tool
{
using namespace std;
using namespace boost;
struct get_pagerank
{
template <class Graph, class VertexIndex, class RankMap>
void operator()(Graph* gp, VertexIndex vertex_index, RankMap rank,
double damping, double epslon, size_t max_iter,
size_t& iter) const
{
Graph& g = *gp;
typedef typename property_traits<RankMap>::value_type rank_type;
RankMap r_temp(vertex_index,num_vertices(g));
// init ranks
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
rank[v] = 1.0/N;
}
rank_type delta = 2*epslon;
rank_type d = damping;
iter = 0;
while (delta >= epslon)
{
delta = 0;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(dynamic) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;