Commit 00a53d62 authored by Tiago Peixoto's avatar Tiago Peixoto

Modify and rename absolute_trust()

absolute_trust() is now called trust_transitivity(), and the whole
trust matrix can now be efficiently calculated.
parent 82b11daf
......@@ -18,11 +18,11 @@ libgraph_tool_centrality_la_SOURCES = \
graph_betweenness.cc \
graph_pagerank.cc \
graph_eigentrust.cc \
graph_absolute_trust.cc \
graph_trust_transitivity.cc \
graph_centrality_bind.cc
libgraph_tool_centrality_la_include_HEADERS = \
graph_pagerank.hh \
graph_eigentrust.hh \
graph_absolute_trust.hh \
graph_trust_transitivity.hh \
minmax.hh
......@@ -21,13 +21,13 @@ using namespace boost;
void export_betweenness();
void export_eigentrust();
void export_absolute_trust();
void export_trust_transitivity();
void export_pagerank();
BOOST_PYTHON_MODULE(libgraph_tool_centrality)
{
export_betweenness();
export_eigentrust();
export_absolute_trust();
export_trust_transitivity();
export_pagerank();
}
......@@ -22,30 +22,30 @@
#include "graph.hh"
#include "graph_selectors.hh"
#include "graph_absolute_trust.hh"
#include "graph_trust_transitivity.hh"
using namespace std;
using namespace boost;
using namespace graph_tool;
void absolute_trust(GraphInterface& g, int64_t source, int64_t target,
void trust_transitivity(GraphInterface& g, int64_t source, int64_t target,
boost::any c, boost::any t)
{
if (!belongs<edge_floating_properties>()(c))
throw ValueException("edge property must be of floating point value type");
if (!belongs<vertex_floating_properties>()(t))
throw ValueException("vertex property must be of floating point value type");
if (!belongs<vertex_floating_vector_properties>()(t))
throw ValueException("vertex property must be of floating point valued vector type");
run_action<>()(g,
bind<void>(get_absolute_trust(), _1, g.GetVertexIndex(),
bind<void>(get_trust_transitivity(), _1, g.GetVertexIndex(),
g.GetEdgeIndex(), g.GetMaxEdgeIndex(), source,
target, _2, _3),
edge_floating_properties(),
vertex_floating_properties())(c,t);
vertex_floating_vector_properties())(c,t);
}
void export_absolute_trust()
void export_trust_transitivity()
{
using namespace boost::python;
def("get_absolute_trust", &absolute_trust);
def("get_trust_transitivity", &trust_transitivity);
}
......@@ -15,8 +15,8 @@
// 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
#ifndef GRAPH_TRUST_TRANSITIVITY_HH
#define GRAPH_TRUST_TRANSITIVITY_HH
#include "graph.hh"
#include "graph_filtering.hh"
......@@ -94,27 +94,32 @@ struct filter_vertex_pred
size_t _v;
};
struct get_absolute_trust
struct get_trust_transitivity
{
template <class Graph, class VertexIndex, class EdgeIndex, class TrustMap,
class InferredTrustMap>
void operator()(Graph& g, VertexIndex vertex_index, EdgeIndex edge_index,
size_t max_edge_index, int64_t source, int64_t target,
TrustMap c, InferredTrustMap t) const
TrustMap c, InferredTrustMap t)
const
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename property_traits<TrustMap>::value_type c_type;
typedef typename property_traits<InferredTrustMap>::value_type t_type;
typedef typename
property_traits<InferredTrustMap>::value_type::value_type t_type;
vertex_t v = vertex(source, g);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = 0; i < N; ++i)
t[vertex(i, g)].resize((source == -1 && target == -1) ? N : 1);
int i, N = (target == -1) ? num_vertices(g) : target + 1;
N = (target == -1) ? num_vertices(g) : target + 1;
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = (target == -1) ? 0 : target; i < N; ++i)
{
vertex_t w = vertex(i, g);
vertex_t tgt = vertex(i, g);
// mark the sources
typedef unchecked_vector_property_map<uint8_t, VertexIndex>
......@@ -122,47 +127,103 @@ struct get_absolute_trust
source_map_t source_map(vertex_index, num_vertices(g));
typename in_edge_iteratorS<Graph>::type e, e_end;
for (tie(e, e_end) = in_edge_iteratorS<Graph>::get_edges(w, g);
for (tie(e, e_end) = in_edge_iteratorS<Graph>::get_edges(tgt, g);
e != e_end; ++e)
source_map[boost::source(*e,g)] = true;
// filter vertex w out of the graph
filtered_graph<Graph, boost::keep_all, filter_vertex_pred>
fg(g, boost::keep_all(), filter_vertex_pred(w));
typedef filtered_graph<Graph, boost::keep_all, filter_vertex_pred>
fg_t;
fg_t fg(g, boost::keep_all(), filter_vertex_pred(tgt));
// distance map (target weight map)
typedef unchecked_vector_property_map<t_type, VertexIndex>
dist_map_t;
dist_map_t dist_map(vertex_index, num_vertices(g));
// compute the targets weights
try
if (source != -1)
{
size_t k = in_degreeS()(w,g);
source_counter<source_map_t,dist_map_t>
visitor(source_map, dist_map, k);
dijkstra_shortest_paths(fg, v, weight_map(c).
vertex_index_map(vertex_index).
distance_map(dist_map).
distance_compare(dist_compare()).
distance_combine(dist_combine()).
distance_inf(t_type(0)).
distance_zero(t_type(1)).
visitor(visitor));
vertex_t src = vertex(source, g);
// compute the targets weights
try
{
size_t k = in_degreeS()(tgt, g);
source_counter<source_map_t,dist_map_t>
visitor(source_map, dist_map, k);
dijkstra_shortest_paths(fg, src, weight_map(c).
vertex_index_map(vertex_index).
distance_map(dist_map).
distance_compare(dist_compare()).
distance_combine(dist_combine()).
distance_inf(t_type(0)).
distance_zero(t_type(1)).
visitor(visitor));
}
catch (const stop_search&) {}
// compute the target's trust
t_type sum_w = 0, avg = 0;
for (tie(e, e_end) =
in_edge_iteratorS<Graph>::get_edges(tgt, g);
e != e_end; ++e)
{
t_type weight = dist_map[boost::source(*e,g)];
sum_w += weight;
avg += c[*e]*weight*weight;
}
if (sum_w > 0)
t[tgt][0] = avg/sum_w;
if (tgt == src)
t[tgt][0] = 1.0;
}
catch (const stop_search&) {}
// compute the target's trust
t_type sum_w = 0, avg = 0;
for (tie(e, e_end) = in_edge_iteratorS<Graph>::get_edges(w, g);
e != e_end; ++e)
else
{
t_type weight = dist_map[boost::source(*e,g)];
sum_w += weight;
avg += c[*e]*weight*weight;
typedef typename
mpl::if_<typename is_directed::apply<Graph>::type,
reverse_graph<fg_t>,
fg_t>::type rg_t;
rg_t rg(fg);
dist_map_t sum_w(vertex_index, num_vertices(g));
int j, N2 = num_vertices(g);
for (tie(e, e_end) =
in_edge_iteratorS<Graph>::get_edges(tgt, g);
e != e_end; ++e)
{
// compute the weights to all sources
dijkstra_shortest_paths
(rg, boost::source(*e, g), weight_map(c).
vertex_index_map(vertex_index).
distance_map(dist_map).
distance_compare(dist_compare()).
distance_combine(dist_combine()).
distance_inf(t_type(0)).
distance_zero(t_type(1)));
#pragma omp parallel for default(shared) private(j) \
schedule(dynamic)
for (j = 0; j < N2; ++j)
{
vertex_t src = vertex(j, g);
t_type weight = dist_map[src];
sum_w[src] += weight;
size_t tidx = (target == -1) ? vertex_index[tgt] : 0;
t[src][tidx] += c[*e]*weight*weight;
}
}
#pragma omp parallel for default(shared) private(j) \
schedule(dynamic)
for (j = 0; j < N2; ++j)
{
vertex_t src = vertex(j, g);
size_t tidx = (target == -1) ? vertex_index[tgt] : 0;
if (sum_w[src] > 0)
t[src][tidx] /= sum_w[src];
if (src == tgt)
t[src][tidx] = 1.0;
}
}
if (sum_w > 0)
t[w] = avg/sum_w;
}
}
};
......
......@@ -34,7 +34,7 @@ Summary
betweenness
central_point_dominance
eigentrust
absolute_trust
trust_transitivity
Contents
++++++++
......@@ -43,12 +43,12 @@ Contents
from .. dl_import import dl_import
dl_import("import libgraph_tool_centrality")
from .. core import _prop
from .. core import _prop, ungroup_vector_property
import sys
import numpy
__all__ = ["pagerank", "betweenness", "central_point_dominance", "eigentrust",
"absolute_trust"]
"trust_transitivity"]
def pagerank(g, damping=0.8, prop=None, epslon=1e-6, max_iter=None,
......@@ -81,7 +81,7 @@ def pagerank(g, damping=0.8, prop=None, epslon=1e-6, max_iter=None,
--------
betweenness: betweenness centrality
eigentrust: eigentrust centrality
absolute_trust: absolute trust centrality
trust_transitivity: pervasive trust transitivity
Notes
-----
......@@ -177,7 +177,7 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True):
central_point_dominance: central point dominance of the graph
pagerank: PageRank centrality
eigentrust: eigentrust centrality
absolute_trust: absolute trust centrality
trust_transitivity: pervasive trust transitivity
Notes
-----
......@@ -342,7 +342,7 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0,
--------
betweenness: betweenness centrality
pagerank: PageRank centrality
absolute_trust: absolute trust centrality
trust_transitivity: pervasive trust transitivity
Notes
-----
......@@ -413,10 +413,10 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0,
return vprop
def absolute_trust(g, trust_map, source, target=None, vprop=None):
def trust_transitivity(g, trust_map, source=None, target=None, vprop=None):
r"""
Calculate the absolute trust centrality of each vertex in the graph, from a
given source.
Calculate the pervasive trust transitivity between chosen (or all) vertices
in the graph.
Parameters
----------
......@@ -425,22 +425,26 @@ def absolute_trust(g, trust_map, source, target=None, vprop=None):
trust_map : :class:`~graph_tool.PropertyMap`
Edge property map with the values of trust associated with each
edge. The values must lie in the range [0,1].
source : Vertex
source : Vertex (optional, default: None)
Source vertex. All trust values are computed relative to this vertex.
If left unspecified, the trust values for all sources are computed.
target : Vertex (optional, default: None)
The only target for which the trust value will be calculated. If left
unspecified, the trust values for all targets are computed.
vprop : :class:`~graph_tool.PropertyMap` (optional, default: None)
A vertex property map where the values of trust for each source
must be stored.
A vertex property map where the values of transitive trust must be
stored.
Returns
-------
absolute_trust : :class:`~graph_tool.PropertyMap` or float
A vertex property map containing the absolute trust vector from the
source vertex to the rest of the network. If `target` is specified, the
result is a single float, with the corresponding trust value for the
target.
trust_transitivity : :class:`~graph_tool.PropertyMap` or float
A vertex vector property map containing, for each source vertex, a
vector with the trust values for the other vertices. If only one of
`source` or `target` is specified, this will be a single-valued vertex
property map containing the trust vector from/to the source/target
vertex to/from the rest of the network. If both `source` and `target`
are specified, the result is a single float, with the corresponding
trust value for the target.
See Also
--------
......@@ -465,12 +469,16 @@ def absolute_trust(g, trust_map, source, target=None, vprop=None):
w_G(i\to j) = \prod_{e\in i\to j} c_e.
The algorithm measures the absolute trust by finding the paths with maximum
weight, using Dijkstra's algorithm, to all in-neighbours of a given
The algorithm measures the transitive trust by finding the paths with
maximum weight, using Dijkstra's algorithm, to all in-neighbours of a given
target. This search needs to be performed repeatedly for every target, since
it needs to be removed from the graph first. The resulting complexity is
therefore :math:`O(N^2\log N)` for all targets, and :math:`O(N\log N)` for a
single target.
it needs to be removed from the graph first. For each given source, the
resulting complexity is therefore :math:`O(N^2\log N)` for all targets, and
:math:`O(N\log N)` for a single target. For a given target, the complexity
for obtaining the trust from all given sources is :math:`O(kN\log N)`, where
:math:`k` is the in-degree of the target. Thus, the complexity for obtaining
the complete trust matrix is :math:`O(EN\log N)`, where :math:`E` is the
number of edges in the network.
If enabled during compilation, this algorithm runs in parallel.
......@@ -481,7 +489,7 @@ def absolute_trust(g, trust_map, source, target=None, vprop=None):
>>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)))
>>> trust = g.new_edge_property("double")
>>> trust.a = random(g.num_edges())
>>> t = gt.absolute_trust(g, trust, source=g.vertex(0))
>>> t = gt.trust_transitivity(g, trust, source=g.vertex(0))
>>> print t.a
[ 0.04096112 0.15271582 0.07130332 0.10597708 0. 0.58940763
0.04233924 0.03619048 0.04137002 0.05926363 0.06584407 0.06315985
......@@ -503,18 +511,24 @@ def absolute_trust(g, trust_map, source, target=None, vprop=None):
"""
if vprop == None:
vprop = g.new_vertex_property("double")
source = g.vertex_index[source]
vprop = g.new_vertex_property("vector<double>")
if target == None:
target = -1
else:
target = g.vertex_index[target]
if source == None:
source = -1
else:
source = g.vertex_index[source]
libgraph_tool_centrality.\
get_absolute_trust(g._Graph__graph, source, target,
_prop("e", g, trust_map), _prop("v", g, vprop))
if target != -1:
get_trust_transitivity(g._Graph__graph, source, target,
_prop("e", g, trust_map),
_prop("v", g, vprop))
if target != -1 or source != -1:
vprop = ungroup_vector_property(g, vprop, [0])[0]
if target != -1 and source != -1:
return vprop.a[target]
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