modifying brandes_betweenness_centrality_impl
Hello all,
Im trying to modify the brandes centrality in order to analyse only a subset
of the graph based on a cutoff distance calculated by some
other edge weight than the one used for the brandes call.
What I have done so far is to add a shortest path search call before the
main
path search inside brandes_betweenness_centrality_impl.
The first search uses the edge::m_metric_weight and constructs the distance
map
from 's' based on that weight.
Then I feed the metric distance map in the 'brandes special visitor' and I
check inside visitor's examine_vertex. Reminder that the brandes
call uses the m_special_weight.
While this works as a principle I have no idea how people with experience
would do it!
A problem with this is that while the metric cutoff can be small you still
run
both searches to the max (as if there is no cutoff).
Any help on how to change the first 'dijkstra_shortest_paths' so that after
reaching the cutoff the search stops gracefully and leaves the
rest of the 'distance_map' to infinity?
Thanks a lot and please let me know if something need more clarification.
###############
struct EdgeProperties
{
double m_special_weight;
double m_metric_distance_weight;
};
typedef boost::adjacency_list
Anyone with boost graph experience that might at least point me to the
right direction?
Any information missing from my previus post that might help?
Thanks
On Wed, Dec 3, 2014 at 2:38 PM, The Maschine wrote: Hello all, Im trying to modify the brandes centrality in order to analyse only a
subset
of the graph based on a cutoff distance calculated by some
other edge weight than the one used for the brandes call. What I have done so far is to add a shortest path search call before the
main
path search inside brandes_betweenness_centrality_impl.
The first search uses the edge::m_metric_weight and constructs the
distance map
from 's' based on that weight. Then I feed the metric distance map in the 'brandes special visitor' and I
check inside visitor's examine_vertex. Reminder that the brandes
call uses the m_special_weight. While this works as a principle I have no idea how people with experience
would do it!
A problem with this is that while the metric cutoff can be small you still
run
both searches to the max (as if there is no cutoff).
Any help on how to change the first 'dijkstra_shortest_paths' so that after
reaching the cutoff the search stops gracefully and leaves the
rest of the 'distance_map' to infinity? Thanks a lot and please let me know if something need more clarification. ############### struct EdgeProperties
{
double m_special_weight;
double m_metric_distance_weight;
}; typedef boost::adjacency_list // test my_brandes_dijkstra_visitor //
template my_brandes_dijkstra_visitor(std::stack /**
* Whenever an edge e = (v, w) is relaxed, the incoming edge list
* for w is set to {(v, w)} and the shortest path count of w is set to
* the number of paths that reach {v}.
*/
void edge_relaxed(edge_descriptor e, const Graph& g)
{
vertex_descriptor v = source(e, g), w = target(e, g);
incoming[w].clear();
incoming[w].push_back(e);
put(path_count, w, get(path_count, v));
} /**
* If an edge e = (v, w) was not relaxed, it may still be the case
* that we've found more equally-short paths, so include {(v, w)} in
the
* incoming edges of w and add all of the shortest paths to v to the
* shortest path count of w.
*/
void edge_not_relaxed(edge_descriptor e, const Graph& g)
{
typedef typename property_traits<WeightMap>::value_type weight_type;
typedef typename property_traits<DistanceMap>::value_type
distance_type;
vertex_descriptor v = source(e, g), w = target(e, g);
distance_type d_v = get(distance, v), d_w = get(distance, w);
weight_type w_e = get(weight, e); closed_plus /// Keep track of vertices as they are reached
void examine_vertex(vertex_descriptor w, const Graph&)
{
// add only if this is within the 'cutoff'. cutoff_dists holds
// the metric distances from s.
if( cutoff_dists[w] < cutoff ) ordered_vertices.push(w);
} private:
std::stack std::vector<float> cutoff_dists;
float cutoff;
}; //////////////////////////////////////////////////////////////////// template<typename WeightMap>
struct my_brandes_dijkstra_shortest_paths
{
my_brandes_dijkstra_shortest_paths(WeightMap iweight_map)
: weight_map(iweight_map) { } template visitor_type visitor(ov, weight_map, incoming, distance,
path_count,c_dists,coff); // modified cutoff vector and value dijkstra_shortest_paths(g, s,
boost::weight_map(weight_map)
.vertex_index_map(vertex_index)
.distance_map(distance)
.visitor(visitor));
} private:
WeightMap weight_map;
}; ////////////////////////////// template // Initialize centrality
init_centrality_map(vertices(g), centrality);
init_centrality_map(edges(g), edge_centrality_map); 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 s = vertex(i, g);
if (s == graph_traits<Graph>::null_vertex())
continue; // First we build a map of all distances from 's' based
// on m_metric_distance_weight.
typedef typename boost::property_map < Graph,
boost::vertex_index_t >::type CIndexMap;
typedef typename boost::iterator_property_map <
vertex_descriptor*,
CIndexMap, vertex_descriptor, vertex_descriptor& > CPredecessorMap;
typedef typename boost::iterator_property_map < float*,
CIndexMap,
float, float& > CDistanceMap;
float co = 2200.0f; std::vector // Local storage for OpenMP
std::stack // Initialize for this iteration
vertex_iterator w, w_end;
for (tie(w, w_end) = vertices(g); w != w_end; ++w) {
incoming[*w].clear();
put(path_count, *w, 0);
put(dependency, *w, 0);
}
put(path_count, s, 1); // co - cutoff added. b_centrality is calculated based on
// Edge::m_special_weight while we are testing
// to be inside the 'cutoff' that is based on the
// Edge::m_metric_weight.
shortest_paths(g, s, ordered_vertices, incoming, distance,
path_count, vertex_index, cut_distances, co); while (!ordered_vertices.empty())
{
vertex_descriptor u = ordered_vertices.top();
ordered_vertices.pop(); typedef typename property_traits<IncomingMap>::value_type
incoming_type;
typedef typename incoming_type::iterator incoming_iterator;
typedef typename property_traits<DependencyMap>::value_type
dependency_type; for (incoming_iterator vw = incoming[u].begin();
vw != incoming[u].end(); ++vw) {
vertex_descriptor v = source(*vw, g);
dependency_type factor = dependency_type(get(path_count,
v))
/ dependency_type(get(path_count, u));
factor *= (dependency_type(1) + get(dependency, u));
put(dependency, v, get(dependency, v) + factor);
update_centrality(edge_centrality_map, *vw, factor);
} if (u != s) {
#pragma omp critical(globalupdate)
{
update_centrality(centrality, u, get(dependency, u));
}
}
}
} typedef typename graph_traits<Graph>::directed_category
directed_category;
const bool is_undirected =
is_convertible
participants (1)
-
The Maschine