Commit 8f787a13 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Limit the number of paths per vertex in absolute_trust()

This also adds the epsilon parameter, which drops paths with weight
below this value.
parent e0bd13c1
...@@ -29,7 +29,8 @@ using namespace boost; ...@@ -29,7 +29,8 @@ using namespace boost;
using namespace graph_tool; using namespace graph_tool;
void absolute_trust(GraphInterface& g, int64_t source, boost::any c, void absolute_trust(GraphInterface& g, int64_t source, boost::any c,
boost::any t, size_t n_paths, bool reversed) boost::any t, size_t n_paths, size_t n_paths_vertex,
double epsilon, bool reversed)
{ {
if (!belongs<edge_floating_properties>()(c)) if (!belongs<edge_floating_properties>()(c))
throw ValueException("edge property must be of floating point value type"); throw ValueException("edge property must be of floating point value type");
...@@ -38,9 +39,9 @@ void absolute_trust(GraphInterface& g, int64_t source, boost::any c, ...@@ -38,9 +39,9 @@ void absolute_trust(GraphInterface& g, int64_t source, boost::any c,
run_action<>()(g, run_action<>()(g,
bind<void>(get_absolute_trust(), _1, g.GetVertexIndex(), bind<void>(get_absolute_trust(), _1, g.GetVertexIndex(),
g.GetEdgeIndex(), g.GetMaxEdgeIndex(), g.GetEdgeIndex(), g.GetMaxEdgeIndex(), source, _2,
source, _2, _3, n_paths, reversed), _3, make_tuple(n_paths, n_paths_vertex, epsilon),
edge_floating_properties(), reversed), edge_floating_properties(),
vertex_floating_vector_properties())(c, t); vertex_floating_vector_properties())(c, t);
} }
......
...@@ -60,7 +60,8 @@ struct get_absolute_trust ...@@ -60,7 +60,8 @@ struct get_absolute_trust
class InferredTrustMap> class InferredTrustMap>
void operator()(Graph& g, VertexIndex vertex_index, EdgeIndex edge_index, void operator()(Graph& g, VertexIndex vertex_index, EdgeIndex edge_index,
size_t max_edge_index, int64_t source, TrustMap c, size_t max_edge_index, int64_t source, TrustMap c,
InferredTrustMap t, size_t n_paths, bool reversed) const InferredTrustMap t, boost::tuple<size_t, size_t,
double> path_limits, bool reversed) const
{ {
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t; typedef typename graph_traits<Graph>::edge_descriptor edge_t;
...@@ -68,6 +69,10 @@ struct get_absolute_trust ...@@ -68,6 +69,10 @@ struct get_absolute_trust
typedef typename property_traits<InferredTrustMap>::value_type:: typedef typename property_traits<InferredTrustMap>::value_type::
value_type t_type; value_type t_type;
size_t n_paths = get<0>(path_limits);
size_t n_paths_vertex = get<1>(path_limits);
t_type epsilon = get<2>(path_limits);
// the path type: the first value is the (trust,weight) pair, the second // the path type: the first value is the (trust,weight) pair, the second
// the set of vertices in the path and the third is the list of edges, // the set of vertices in the path and the third is the list of edges,
// in the path sequence. // in the path sequence.
...@@ -88,6 +93,7 @@ struct get_absolute_trust ...@@ -88,6 +93,7 @@ struct get_absolute_trust
get<0>(paths.back()).first = get<0>(paths.back()).second = 1; get<0>(paths.back()).first = get<0>(paths.back()).second = 1;
get<1>(paths.back()).insert(v); get<1>(paths.back()).insert(v);
queue.push(0); queue.push(0);
vector<size_t> free_paths; // free path indexes
// this is the actual queue of paths which will be used to compute // this is the actual queue of paths which will be used to compute
// the trust values // the trust values
...@@ -98,20 +104,31 @@ struct get_absolute_trust ...@@ -98,20 +104,31 @@ struct get_absolute_trust
VertexIndex> VertexIndex>
path_map(vertex_index, num_vertices(g)); path_map(vertex_index, num_vertices(g));
unchecked_vector_property_map<bool, VertexIndex>
saturated(vertex_index, num_vertices(g));
while (!queue.empty()) while (!queue.empty())
{ {
size_t pi = queue.top(); size_t pi = queue.top();
queue.pop_top(); queue.pop_top();
vertex_t w; vertex_t w;
// push queue top into final queue vertex_t ptarget;
if (get<2>(paths[pi]).size() > 0) if (get<2>(paths[pi]).size() > 0)
ptarget = target(get<2>(paths[pi]).back(),g);
// push queue top into final queue
if (get<2>(paths[pi]).size() > 0 &&
(n_paths_vertex == 0 || !saturated[ptarget]))
{ {
w = target(get<2>(paths[pi]).back(), g); w = target(get<2>(paths[pi]).back(), g);
final_queue.push(pi); final_queue.push(pi);
// augment path map // augment path map
path_map[target(get<2>(paths[pi]).back(),g)].insert(pi); path_map[ptarget].insert(pi);
if (path_map[ptarget].size() == n_paths_vertex)
saturated[ptarget] = true;
} }
else else
{ {
...@@ -122,14 +139,18 @@ struct get_absolute_trust ...@@ -122,14 +139,18 @@ struct get_absolute_trust
if ((n_paths > 0) && (final_queue.size() > n_paths)) if ((n_paths > 0) && (final_queue.size() > n_paths))
{ {
size_t bi = final_queue.bottom(); size_t bi = final_queue.bottom();
final_queue.pop_bottom(); ptarget = target(get<2>(paths[bi]).back(),g);
if (!saturated[ptarget])
{
final_queue.pop_bottom();
free_paths.push_back(bi);
// remove path from path map // remove path from path map
path_map[boost::target(get<2>(paths[bi]).back(),g)]. path_map[ptarget].erase(bi);
erase(bi);
if (bi == pi) if (bi == pi)
continue; continue;
}
} }
// augment paths and put them in the queue // augment paths and put them in the queue
...@@ -145,8 +166,18 @@ struct get_absolute_trust ...@@ -145,8 +166,18 @@ struct get_absolute_trust
get<1>(paths[pi]).size() == 1)) get<1>(paths[pi]).size() == 1))
{ {
size_t npi; size_t npi;
paths.push_back(paths[pi]); // clone last path // clone last path
npi = paths.size()-1; if (free_paths.empty())
{
paths.push_back(paths[pi]);
npi = paths.size()-1;
}
else
{
npi = free_paths.back();
free_paths.pop_back();
paths[npi] = paths[pi];
}
path_t& np = paths[npi]; // new path path_t& np = paths[npi]; // new path
...@@ -173,9 +204,18 @@ struct get_absolute_trust ...@@ -173,9 +204,18 @@ struct get_absolute_trust
(final_queue.size() == 0 || (final_queue.size() == 0 ||
(get<0>(np).second >= (get<0>(np).second >=
get<0>(paths[final_queue.bottom()]).second))) get<0>(paths[final_queue.bottom()]).second)))
queue.push(npi); {
// drop paths with weight smaller than epsilon
if (get<0>(np).second > epsilon)
queue.push(npi);
}
else else
paths.pop_back(); {
if (npi == paths.size() - 1)
paths.pop_back();
else
free_paths.push_back(npi);
}
} }
} }
} }
...@@ -204,33 +244,42 @@ struct get_absolute_trust ...@@ -204,33 +244,42 @@ struct get_absolute_trust
tr1::unordered_set<size_t> vlist; // all vertices involved tr1::unordered_set<size_t> vlist; // all vertices involved
// compute cumulative edge weight // compute cumulative edge weight
unchecked_vector_property_map tr1::unordered_map<size_t,
<tr1::unordered_map<vertex_t, t_type>, EdgeIndex> tr1::unordered_map<vertex_t, t_type> >
cum_weight(edge_index, max_edge_index+1); cum_weight;
for (typeof(apaths.begin()) iter = apaths.begin(); for (typeof(apaths.begin()) iter = apaths.begin();
iter != apaths.end(); ++iter) iter != apaths.end(); ++iter)
{ {
size_t path_size = get<2>(paths[*iter]).size(); path_t& path = paths[*iter];
vertex_t ptarget = target(get<2>(paths[*iter]).back(),g); size_t path_size = get<2>(path).size();
vertex_t ptarget = target(get<2>(path).back(),g);
t_type w = 1; t_type w = 1;
for (size_t j = 0; j < path_size; ++j) for (size_t j = 0; j < path_size; ++j)
{ {
edge_t e = get<2>(paths[*iter])[path_size - 1 - j]; edge_t e;
if (!reversed && j < path_size - 1) if (!reversed)
w *= c[e]; {
if (reversed && j > 0) e = get<2>(path)[path_size - 1 - j];
w *= c[e]; if (j < path_size - 1)
cum_weight[e][ptarget] += w; w *= c[e];
}
else
{
e = get<2>(path)[j];
if (j > 0)
w *= c[e];
}
cum_weight[edge_index[e]][ptarget] += w;
vlist.insert(target(e,g)); vlist.insert(target(e,g));
} }
vlist.insert(boost::source(get<2>(paths[*iter]).front(),g)); vlist.insert(boost::source(get<2>(paths[*iter]).front(),g));
} }
// compute out-weight // compute out-weight
unchecked_vector_property_map tr1::unordered_map<vertex_t,
<tr1::unordered_map<vertex_t, t_type>, VertexIndex> tr1::unordered_map<vertex_t, t_type> >
out_weight(vertex_index, num_vertices(g)); out_weight;
for (typeof(vlist.begin()) viter = vlist.begin(); for (typeof(vlist.begin()) viter = vlist.begin();
viter != vlist.end(); ++viter) viter != vlist.end(); ++viter)
{ {
...@@ -239,10 +288,13 @@ struct get_absolute_trust ...@@ -239,10 +288,13 @@ struct get_absolute_trust
{ {
typename graph_traits<Graph>::out_edge_iterator e,e_end; typename graph_traits<Graph>::out_edge_iterator e,e_end;
for (tie(e, e_end) = out_edges(u, g); e != e_end; ++e) for (tie(e, e_end) = out_edges(u, g); e != e_end; ++e)
for (typeof(cum_weight[*e].begin()) witer = {
cum_weight[*e].begin(); size_t ei = edge_index[*e];
witer != cum_weight[*e].end(); ++witer) for (typeof(cum_weight[ei].begin()) witer =
cum_weight[ei].begin();
witer != cum_weight[ei].end(); ++witer)
out_weight[u][witer->first] += witer->second; out_weight[u][witer->first] += witer->second;
}
} }
else else
{ {
...@@ -251,10 +303,13 @@ struct get_absolute_trust ...@@ -251,10 +303,13 @@ struct get_absolute_trust
for (tie(e, e_end) = for (tie(e, e_end) =
in_edge_iteratorS<Graph>::get_edges(v, g); in_edge_iteratorS<Graph>::get_edges(v, g);
e != e_end; ++e) e != e_end; ++e)
for (typeof(cum_weight[*e].begin()) witer = {
cum_weight[*e].begin(); size_t ei = edge_index[*e];
witer != cum_weight[*e].end(); ++witer) for (typeof(cum_weight[ei].begin()) witer =
cum_weight[ei].begin();
witer != cum_weight[ei].end(); ++witer)
out_weight[u][witer->first] += witer->second; out_weight[u][witer->first] += witer->second;
}
} }
} }
...@@ -276,7 +331,7 @@ struct get_absolute_trust ...@@ -276,7 +331,7 @@ struct get_absolute_trust
{ {
if ((!reversed && i < get<2>(p).size()-1) || if ((!reversed && i < get<2>(p).size()-1) ||
(reversed && i > 0)) (reversed && i > 0))
w *= c[e]*cum_weight[e][ptarget]/ w *= c[e]*cum_weight[edge_index[e]][ptarget]/
out_weight[u][ptarget]; out_weight[u][ptarget];
} }
val *= c[e]; val *= c[e];
......
...@@ -407,7 +407,7 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0, ...@@ -407,7 +407,7 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0,
return vprop return vprop
def absolute_trust(g, trust_map, source = None, vprop=None, n_paths=10000, def absolute_trust(g, trust_map, source = None, vprop=None, n_paths=10000,
reversed=False): n_paths_vertex=10, epsilon = 0, reversed=False):
r""" r"""
Calculate the absolute trust centrality of each vertex in the graph, from a Calculate the absolute trust centrality of each vertex in the graph, from a
given source. given source.
...@@ -540,7 +540,8 @@ def absolute_trust(g, trust_map, source = None, vprop=None, n_paths=10000, ...@@ -540,7 +540,8 @@ def absolute_trust(g, trust_map, source = None, vprop=None, n_paths=10000,
libgraph_tool_centrality.\ libgraph_tool_centrality.\
get_absolute_trust(g._Graph__graph, source, get_absolute_trust(g._Graph__graph, source,
_prop("e", g, trust_map), _prop("e", g, trust_map),
_prop("v", g, vprop), n_paths, reversed) _prop("v", g, vprop), n_paths,
n_paths_vertex, epsilon, reversed)
finally: finally:
if reversed: if reversed:
g.pop_filter(reversed=True) g.pop_filter(reversed=True)
......
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