Commit ba2aee8a authored by Tiago Peixoto's avatar Tiago Peixoto

* add support for betweenness centrality

* change from HashedDescriptorMap to vector_property_map in several
  algorithms to save memory and increase speed in the most common
  case, where the graph is unfiltered.




git-svn-id: https://svn.forked.de/graph-tool/trunk@102 d4600afd-f417-0410-95de-beed9576f240
parent d199d4bb
This diff is collapsed.
#! /usr/bin/env python
# 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
......@@ -111,6 +113,7 @@ statistics.add_option("--average-edge-property", action="callback", callback=pus
statistics.add_option("--reciprocity", action="callback", callback=push_option, type="string", metavar="FILE", help="get the edge reciprocity")
statistics.add_option("--minimum-spanning-tree", action="callback", callback=push_option, type="string", metavar="[WEIGHT|]PROPERTY", help="mark the minimum spanning tree edges in PROPERTY")
statistics.add_option("--line-graph", action="callback", callback=push_option, type="string", metavar="FILE[|FORMAT]", help="save the corresponding line graph to FILE")
statistics.add_option("--betweenness-centrality", action="callback", callback=push_option, type="string", metavar="VERTEX_BETWEENESS[EDGE_BETWEENESS]", help="calculate and store the vertex and/or edge betweenness centrality")
correlations = parser.add_option_group("Correlations")
correlations.add_option("--average-combined-vertex-correlation", action="callback", callback=push_option, type="string", metavar="DEGREE1|DEGREE2|FILE", help="get the average of DEGREE2 in function of DEGREE1. Scalar properties are also accepted as DEGREE1 or DEGREE2")
......@@ -503,6 +506,22 @@ def parse_option(opt, just_file=False):
else:
format = ""
graph.GetLineGraph(values[0], format)
elif opt.name == "betweenness-centrality":
values = parse_values(opt.value)
if len(values) < 1 or len(values) > 3:
raise OptionError(opt.name, "invalid value '%s'" % opt.value)
if just_file:
return None
vertex_centrality = values[0]
if len(values) > 1:
edge_centrality = values[1]
else:
edge_centrality = ""
if len(values) > 2:
weight = values[2]
else:
weight = ""
graph.GetBetweenness(weight, vertex_centrality, edge_centrality)
elif opt.name == "vertex-correlation-histogram":
values = parse_values(opt.value)
if len(values) < 3 or len(values) > 4:
......
......@@ -40,6 +40,7 @@ libgraph_tool_la_SOURCES = \
graph_community.cc\
graph_community_network.cc\
graph_line_graph.cc\
graph_betweenness.cc\
graph_io.cc\
graph_bind.cc\
graphml.cpp\
......
......@@ -97,6 +97,7 @@ public:
double GetReciprocity() const;
void GetMinimumSpanningTree(std::string weight, std::string property);
void GetLineGraph(std::string out_file, std::string format);
void GetBetweenness(std::string weight, std::string edge_betweenness, std::string vertex_betweenness);
// community structure
enum comm_corr_t
......
......@@ -357,6 +357,9 @@ struct graph_traits< UndirectedAdaptor<Graph> > {
static vertex_descriptor null_vertex() {return graph_traits<Graph>::null_vertex();}
};
template <class Graph>
struct graph_traits< const UndirectedAdaptor<Graph> >: public graph_traits< UndirectedAdaptor<Graph> > {};
//==============================================================================
// Nonmember functions
// these provide manipulation to the graph
......
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/mpl/for_each.hpp>
#include "graph.hh"
#include "histogram.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include "graph_adaptor.hh"
#include <boost/graph/betweenness_centrality.hpp>
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
struct get_betweenness
{
template <class Graph, class VertexIndexMap, class EdgeBetweenness, class VertexBetweenness>
void operator()(Graph& g, VertexIndexMap index_map, EdgeBetweenness edge_betweenness, VertexBetweenness vertex_betweenness) const
{
brandes_betweenness_centrality(g, vertex_index_map(index_map).edge_centrality_map(edge_betweenness).centrality_map(vertex_betweenness));
}
};
template <class Graph, class VertexIndexMap, class EdgeIndexMap, class EdgeBetweenness, class VertexBetweenness>
struct get_weighted_betweenness
{
get_weighted_betweenness(Graph& g, VertexIndexMap vertex_index, EdgeIndexMap edge_index, string& weight, dynamic_properties& dp,
EdgeBetweenness edge_betweenness, VertexBetweenness vertex_betweenness, bool& found)
:_g(g), _vertex_index(vertex_index), _edge_index(edge_index), _weight(weight), _dp(dp), _edge_betweenness(edge_betweenness), _vertex_betweenness(vertex_betweenness), _found(found) {}
template <class WeightType>
void operator()(WeightType)
{
try
{
typedef vector_property_map<WeightType, EdgeIndexMap> weight_map_t;
weight_map_t weight_map(_edge_index);
weight_map = get_static_property_map<weight_map_t>(find_property_map(_dp, _weight, typeid(graph_traits<typename GraphInterface::multigraph_t>::edge_descriptor)));
brandes_betweenness_centrality(_g, vertex_index_map(_vertex_index).weight_map(weight_map).edge_centrality_map(_edge_betweenness).centrality_map(_vertex_betweenness));
_found = true;
}
catch (property_not_found) {}
catch (bad_cast) {}
}
Graph& _g;
VertexIndexMap _vertex_index;
EdgeIndexMap _edge_index;
string& _weight;
dynamic_properties& _dp;
EdgeBetweenness _edge_betweenness;
VertexBetweenness _vertex_betweenness;
bool& _found;
};
struct choose_weight_map
{
template <class Graph, class VertexIndexMap, class EdgeIndexMap, class EdgeBetweenness, class VertexBetweenness>
void operator()(Graph& g, VertexIndexMap vertex_index, EdgeIndexMap edge_index, string& weight, dynamic_properties& dp,
EdgeBetweenness edge_betweenness, VertexBetweenness vertex_betweenness, bool& found) const
{
mpl::for_each<scalar_types>(get_weighted_betweenness<Graph,VertexIndexMap,EdgeIndexMap,EdgeBetweenness,VertexBetweenness>
(g, vertex_index, edge_index, weight, dp, edge_betweenness, vertex_betweenness, found));
}
};
void GraphInterface::GetBetweenness(string weight, string edge_betweenness, string vertex_betweenness)
{
typedef vector_property_map<double, vertex_index_map_t> vertex_betweenness_map_t;
vertex_betweenness_map_t vertex_betweenness_map(_vertex_index);
typedef vector_property_map<double, edge_index_map_t> edge_betweenness_map_t;
edge_betweenness_map_t edge_betweenness_map(_edge_index);
if (vertex_betweenness != "" && edge_betweenness != "")
{
if (weight != "")
{
bool found = false;
check_filter(*this, bind<void>(choose_weight_map(), _1, var(_vertex_index), var(_edge_index), var(weight), var(_properties), var(edge_betweenness_map), var(vertex_betweenness_map), var(found)), reverse_check(), directed_check());
if (!found)
throw GraphException("error getting scalar property: " + weight);
}
else
{
check_filter(*this, bind<void>(get_betweenness(), _1, var(_vertex_index), var(edge_betweenness_map), var(vertex_betweenness_map)), reverse_check(), directed_check());
}
}
else if (vertex_betweenness != "")
{
if (weight != "")
{
bool found = false;
check_filter(*this, bind<void>(choose_weight_map(), _1, var(_vertex_index), var(_edge_index), var(weight), var(_properties), var(edge_betweenness_map), dummy_property_map(), var(found)), reverse_check(), directed_check());
if (!found)
throw GraphException("error getting scalar property: " + weight);
}
else
{
check_filter(*this, bind<void>(get_betweenness(), _1, var(_vertex_index), var(edge_betweenness_map), dummy_property_map()), reverse_check(), directed_check());
}
}
else
{
if (weight != "")
{
bool found = false;
check_filter(*this, bind<void>(choose_weight_map(), _1, var(_vertex_index), var(_edge_index), var(weight), var(_properties), dummy_property_map(), var(vertex_betweenness_map), var(found)), reverse_check(), directed_check());
if (!found)
throw GraphException("error getting scalar property: " + weight);
}
else
{
check_filter(*this, bind<void>(get_betweenness(), _1, var(_vertex_index), dummy_property_map(), var(vertex_betweenness_map)), reverse_check(), directed_check());
}
}
if (vertex_betweenness != "")
{
try
{
find_property_map(_properties, vertex_betweenness, typeid(graph_traits<multigraph_t>::vertex_descriptor));
RemoveVertexProperty(vertex_betweenness);
}
catch (property_not_found) {}
_properties.property(vertex_betweenness, vertex_betweenness_map);
}
if (edge_betweenness != "")
{
try
{
find_property_map(_properties, edge_betweenness, typeid(graph_traits<multigraph_t>::edge_descriptor));
RemoveEdgeProperty(edge_betweenness);
}
catch (property_not_found) {}
_properties.property(edge_betweenness, edge_betweenness_map);
}
}
......@@ -239,6 +239,7 @@ BOOST_PYTHON_MODULE(libgraph_tool)
.def("GetReciprocity", &GraphInterfaceWrap::GetReciprocity)
.def("GetMinimumSpanningTree", &GraphInterfaceWrap::GetMinimumSpanningTree)
.def("GetLineGraph", &GraphInterfaceWrap::GetLineGraph)
.def("GetBetweenness", &GraphInterfaceWrap::GetBetweenness)
.def("GetCommunityStructure", &GraphInterfaceWrap::GetCommunityStructure)
.def("GetCommunityNetwork", &GraphInterfaceWrap::GetCommunityNetwork)
.def("GetModularity", &GraphInterfaceWrap::GetModularity)
......
......@@ -197,7 +197,7 @@ struct set_clustering_to_property
void GraphInterface::SetLocalClusteringToProperty(string property)
{
typedef HashedDescriptorMap<vertex_index_map_t,double> clust_map_t;
typedef vector_property_map<double,vertex_index_map_t> clust_map_t;
clust_map_t clust_map(_vertex_index);
bool directed = _directed;
......
......@@ -651,7 +651,7 @@ struct copy_spins
void GraphInterface::GetCommunityStructure(double gamma, comm_corr_t corr, size_t n_iter, double Tmin, double Tmax, size_t Nspins, size_t seed, bool verbose, string history_file, string weight, string property)
{
typedef HashedDescriptorMap<vertex_index_map_t,size_t> comm_map_t;
typedef vector_property_map<size_t,vertex_index_map_t> comm_map_t;
comm_map_t comm_map(_vertex_index);
bool new_spins = true;
......
......@@ -158,7 +158,7 @@ struct get_extended_clustering
void GraphInterface::SetExtendedClusteringToProperty(string property_prefix, size_t max_depth)
{
typedef HashedDescriptorMap<vertex_index_map_t,double> cmap_t;
typedef vector_property_map<double, vertex_index_map_t> cmap_t;
vector<cmap_t> cmaps(max_depth);
for (size_t i = 0; i < cmaps.size(); ++i)
cmaps[i] = cmap_t(_vertex_index);
......
......@@ -40,6 +40,36 @@
#include "graph_python_filtering.hh"
#endif
// some additional functions...
namespace boost
{
//==============================================================================
// vertex(i, filtered_graph<G>)
//==============================================================================
template <class Graph, class EdgePredicate, class VertexPredicate>
typename graph_traits<filtered_graph<Graph,EdgePredicate,VertexPredicate> >::vertex_descriptor
vertex(size_t i, const filtered_graph<Graph,EdgePredicate,VertexPredicate>& g)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g.m_g);
if (g.m_vertex_pred(v))
return v;
else
return graph_traits<Graph>::null_vertex();
}
//==============================================================================
// vertex(i, reverse_graph<G>)
//==============================================================================
template <class Graph>
typename graph_traits<reverse_graph<Graph> >::vertex_descriptor
vertex(size_t i, const reverse_graph<Graph>& g)
{
return vertex(i, g.m_g);
}
} // namespace boost
namespace graph_tool
{
using namespace boost;
......@@ -96,32 +126,6 @@ struct SoftNumEdges
size_t operator()(const Graph &g) const { return num_edges(g); }
};
//==============================================================================
// vertex(i, filtered_graph<G>)
//==============================================================================
template <class Graph, class EdgePredicate, class VertexPredicate>
typename graph_traits<filtered_graph<Graph,EdgePredicate,VertexPredicate> >::vertex_descriptor
vertex(size_t i, const filtered_graph<Graph,EdgePredicate,VertexPredicate>& g)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g.m_g);
if (g.m_vertex_pred(v))
return v;
else
return graph_traits<Graph>::null_vertex();
}
//==============================================================================
// vertex(i, reverse_graph<G>)
//==============================================================================
template <class Graph>
typename graph_traits<reverse_graph<Graph> >::vertex_descriptor
vertex(size_t i, const reverse_graph<Graph>& g)
{
return vertex(i, g.m_g);
}
//==============================================================================
// RangeFilter
//==============================================================================
......
......@@ -66,8 +66,6 @@ struct check_value_type
// generate the corresponding property map, depending on the value type
//==============================================================================
typedef mpl::vector<bool, int, long, float, double, string> value_types;
template <class VertexIndexMap, class EdgeIndexMap>
struct create_dynamic_map
{
......
......@@ -55,7 +55,7 @@ struct get_kruskal_min_span_tree
void GraphInterface::GetMinimumSpanningTree(string weight, string property)
{
typedef HashedDescriptorMap<edge_index_map_t,size_t> tree_map_t;
typedef vector_property_map<size_t, edge_index_map_t> tree_map_t;
tree_map_t tree_map(_edge_index);
bool directed = _directed;
......
......@@ -34,9 +34,14 @@ using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
typedef mpl::vector<bool, int, long, size_t, float, double, std::string> value_types;
namespace graph_tool
{
// global property types
const char* type_names[] = {"boolean", "int", "long", "long", "float", "double", "string"};
// scalar types
const char* scalar_names[] = {"boolean", "int", "long", "long", "float", "double"};
}
//==============================================================================
// find_property_map(dp,name,key_type)
......
......@@ -31,6 +31,16 @@
namespace graph_tool
{
// global property types
typedef boost::mpl::vector<bool, int, long, size_t, float, double, std::string> value_types;
extern const char* type_names[];
// scalar types
typedef boost::mpl::vector<bool, int, long, size_t, float, double> scalar_types;
extern const char* scalar_names[];
//==============================================================================
// Property Map Utility Functions
//==============================================================================
......
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