Commit 3cfff0cb authored by Tiago Peixoto's avatar Tiago Peixoto

Split libgraph_tool into sub-modules and add test cases

This commit splits libraph_tool into different libraries:
 
   - libgraph_tool_core
   - libgraph_tool_clustering (*)
   - libgraph_tool_community (*)
   - libgraph_tool_correlations (*)
   - libgraph_tool_distance (*)
   - libgraph_tool_generation (*)
   - libgraph_tool_layout (*)
   - libgraph_tool_misc (*)
   - libgraph_tool_stats (*)

It also adds the python sub-module 'test', which provides extensive unit
testing of the core functionality. The core library is fully functional
and all test pass successfully.

(*) -> module needs to be ported to new refactoring, and does not yet build
parent 0b66e272
......@@ -12,7 +12,7 @@ graphtooldoc_DATA = \
TODO
EXTRA_DIST = $(graphtooldoc_DATA)
EXTRA_DIST = $(graphtooldoc_DATA)
# Copy all the spec files. Of cource, only one is actually used.
dist-hook:
......
......@@ -204,6 +204,7 @@ AC_OUTPUT([
Makefile
src/Makefile
src/graph/Makefile
src/graph/correlations/Makefile
src/graph_tool/Makefile
])
......@@ -60,13 +60,13 @@ namespace boost {
}
const Set* m_s;
};
namespace detail {
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
struct out_edge_predicate {
out_edge_predicate() { }
out_edge_predicate(EdgePredicate ep, VertexPredicate vp,
out_edge_predicate(EdgePredicate ep, VertexPredicate vp,
const Graph& g)
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
......@@ -82,7 +82,7 @@ namespace boost {
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
struct in_edge_predicate {
in_edge_predicate() { }
in_edge_predicate(EdgePredicate ep, VertexPredicate vp,
in_edge_predicate(EdgePredicate ep, VertexPredicate vp,
const Graph& g)
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
......@@ -98,7 +98,7 @@ namespace boost {
template <typename EdgePredicate, typename VertexPredicate, typename Graph>
struct edge_predicate {
edge_predicate() { }
edge_predicate(EdgePredicate ep, VertexPredicate vp,
edge_predicate(EdgePredicate ep, VertexPredicate vp,
const Graph& g)
: m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { }
......@@ -134,7 +134,7 @@ namespace boost {
const G& m_g;
};
template <typename Graph,
template <typename Graph,
typename EdgePredicate,
typename VertexPredicate = keep_all>
class filtered_graph : public filtered_graph_base<Graph> {
......@@ -143,11 +143,11 @@ namespace boost {
typedef filtered_graph self;
public:
typedef Graph graph_type;
typedef detail::out_edge_predicate<EdgePredicate,
typedef detail::out_edge_predicate<EdgePredicate,
VertexPredicate, self> OutEdgePred;
typedef detail::in_edge_predicate<EdgePredicate,
typedef detail::in_edge_predicate<EdgePredicate,
VertexPredicate, self> InEdgePred;
typedef detail::edge_predicate<EdgePredicate,
typedef detail::edge_predicate<EdgePredicate,
VertexPredicate, self> EdgePred;
// Constructors
......@@ -168,7 +168,7 @@ namespace boost {
typedef filter_iterator<
OutEdgePred, typename Traits::out_edge_iterator
> out_edge_iterator;
typedef typename Traits::degree_size_type degree_size_type;
// AdjacencyGraph requirements
......@@ -221,13 +221,13 @@ namespace boost {
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template<typename Graph, typename EdgePredicate, typename VertexPredicate>
struct vertex_bundle_type<filtered_graph<Graph, EdgePredicate,
VertexPredicate> >
struct vertex_bundle_type<filtered_graph<Graph, EdgePredicate,
VertexPredicate> >
: vertex_bundle_type<Graph> { };
template<typename Graph, typename EdgePredicate, typename VertexPredicate>
struct edge_bundle_type<filtered_graph<Graph, EdgePredicate,
VertexPredicate> >
struct edge_bundle_type<filtered_graph<Graph, EdgePredicate,
VertexPredicate> >
: edge_bundle_type<Graph> { };
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
......@@ -251,11 +251,11 @@ namespace boost {
typename filtered_graph<G, EP, VP>::vertex_iterator>
vertices(const filtered_graph<G, EP, VP>& g)
{
typedef filtered_graph<G, EP, VP> Graph;
typedef filtered_graph<G, EP, VP> Graph;
typename graph_traits<G>::vertex_iterator f, l;
tie(f, l) = vertices(g.m_g);
typedef typename Graph::vertex_iterator iter;
return std::make_pair(iter(g.m_vertex_pred, f, l),
return std::make_pair(iter(g.m_vertex_pred, f, l),
iter(g.m_vertex_pred, l, l));
}
......@@ -285,18 +285,18 @@ namespace boost {
// tie(vi, viend) = vertices(g);
// assert(std::distance(vi, viend) == num_vertices(g));
template <typename G, typename EP, typename VP>
template <typename G, typename EP, typename VP>
typename filtered_graph<G, EP, VP>::vertices_size_type
num_vertices(const filtered_graph<G, EP, VP>& g) {
return num_vertices(g.m_g);
}
template <typename G, typename EP, typename VP>
template <typename G, typename EP, typename VP>
typename filtered_graph<G, EP, VP>::edges_size_type
num_edges(const filtered_graph<G, EP, VP>& g) {
return num_edges(g.m_g);
}
template <typename G>
typename filtered_graph_base<G>::vertex_descriptor
source(typename filtered_graph_base<G>::edge_descriptor e,
......@@ -352,7 +352,7 @@ namespace boost {
return std::make_pair(adjacency_iterator(f, const_cast<Graph*>(&g)),
adjacency_iterator(l, const_cast<Graph*>(&g)));
}
template <typename G, typename EP, typename VP>
std::pair<typename filtered_graph<G, EP, VP>::in_edge_iterator,
typename filtered_graph<G, EP, VP>::in_edge_iterator>
......@@ -426,14 +426,14 @@ namespace boost {
typedef typename Map::type type;
typedef typename Map::const_type const_type;
};
};
};
} // namespace detail
template <>
template <>
struct vertex_property_selector<filtered_graph_tag> {
typedef detail::filtered_graph_property_selector type;
};
template <>
template <>
struct edge_property_selector<filtered_graph_tag> {
typedef detail::filtered_graph_property_selector type;
};
......@@ -460,7 +460,7 @@ namespace boost {
return get(p, (const G&)g.m_g, k);
}
template <typename G, typename EP, typename VP, typename Property,
template <typename G, typename EP, typename VP, typename Property,
typename Key, typename Value>
void
put(Property p, const filtered_graph<G, EP, VP>& g, const Key& k,
......
......@@ -74,7 +74,7 @@ struct all_force_pairs
{
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#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);
......@@ -119,7 +119,7 @@ struct grid_force_pairs
buckets_t buckets(rows * columns);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#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);
......@@ -137,7 +137,7 @@ struct grid_force_pairs
}
N = rows * columns;
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = 0; i < N; ++i)
{
std::size_t row = i / rows;
......@@ -158,11 +158,11 @@ struct grid_force_pairs
std::size_t adj_end_column = column == columns - 1? column : column + 1;
for (std::size_t other_row = adj_start_row; other_row <= adj_end_row;
++other_row)
for (std::size_t other_column = adj_start_column;
for (std::size_t other_column = adj_start_column;
other_column <= adj_end_column; ++other_column)
if (other_row != row || other_column != column) {
// Repulse vertices in this bucket
bucket_t& other_bucket
bucket_t& other_bucket
= buckets[other_row * columns + other_column];
for (v = other_bucket.begin(); v != other_bucket.end(); ++v)
apply_force(*u, *v);
......@@ -300,14 +300,14 @@ fruchterman_reingold_force_directed_layout
std::vector<edge_descriptor> edge_list;
edge_list.reserve(num_edges(g));
edge_iterator e, e_end;
for (tie(e, e_end) = edges(g); e != e_end; ++e)
for (tie(e, e_end) = edges(g); e != e_end; ++e)
edge_list.push_back(*e);
Dim temp = cool();
if (temp) do {
// Calculate repulsive forces
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#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);
......@@ -320,7 +320,7 @@ fruchterman_reingold_force_directed_layout
// Calculate attractive forces
N = edge_list.size();
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = 0; i < N; ++i)
{
edge_descriptor e = edge_list[i];
......@@ -339,7 +339,7 @@ fruchterman_reingold_force_directed_layout
// Update positions
N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
#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);
......@@ -350,17 +350,17 @@ fruchterman_reingold_force_directed_layout
BOOST_USING_STD_MAX();
Dim disp_size = sqrt(displacement[v].x * displacement[v].x
+ displacement[v].y * displacement[v].y);
position[v].x += displacement[v].x / disp_size
position[v].x += displacement[v].x / disp_size
* min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp);
position[v].y += displacement[v].y / disp_size
position[v].y += displacement[v].y / disp_size
* min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp);
position[v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION
(width / 2,
max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2,
position[v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION
(width / 2,
max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2,
position[v].x));
position[v].y = min BOOST_PREVENT_MACRO_SUBSTITUTION
(height / 2,
max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2,
(height / 2,
max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2,
position[v].y));
}
} while ( (temp = cool()) );
......
## Process this file with automake to produce Makefile.in
SUBDIRS = correlations
AM_CPPFLAGS =\
-I. -I.. \
-I../boost-workaround \
......@@ -12,78 +14,33 @@ AM_CXXFLAGS =\
AM_CFLAGS=$(AM_CXXFLAGS)
libgraph_tooldir = $(pythondir)/graph_tool
libgraph_tool_coredir = $(pythondir)/graph_tool
libgraph_tool_LTLIBRARIES = libgraph_tool.la
libgraph_tool_core_LTLIBRARIES = libgraph_tool_core.la
libgraph_tool_la_includedir = $(pythondir)/graph_tool/include
libgraph_tool_core_la_includedir = $(pythondir)/graph_tool/include
libgraph_tool_la_SOURCES = \
graph_assortativity.cc \
graph_betweenness.cc \
libgraph_tool_core_la_SOURCES = \
graph_bind.cc \
graph.cc \
graph_clustering.cc \
graph_community.cc \
graph_community_network.cc \
graph_correlations.cc \
graph_correlations_combined.cc \
graph_correlations_combined_corr.cc \
graph_correlations_imp1.cc \
graph_correlations_imp2.cc \
graph_correlations_imp3.cc \
graph_correlations_neighbours.cc \
graph_correlations_neighbours_imp1.cc \
graph_correlations_neighbours_imp2.cc \
graph_correlations_neighbours_imp3.cc \
graph_correlations_neighbours_imp4.cc \
graph_correlations_neighbours_imp5.cc \
graph_correlations_neighbours_imp6.cc \
graph_distance.cc \
graph_distance_sampled.cc \
graph_edge_correlations.cc \
graph_edge_correlations_imp1.cc \
graph_edge_correlations_imp2.cc \
graph_edge_correlations_imp3.cc \
graph_edge_correlations_imp4.cc \
graph_edge_correlations_imp5.cc \
graph_extended_clustering.cc \
graph_copy.cc \
graph_filtering.cc \
graph_generation.cc \
graph_io.cc \
graph_layout.cc \
graph_line_graph.cc \
graph_minimum_spanning_tree.cc \
graph_properties.cc \
graph_python_interface.cc \
graph_python_interface_export.cc \
graph_reciprocity.cc \
graph_rewiring.cc \
graph_selectors.cc \
graphml.cpp\
read_graphviz_spirit.cpp\
../boost-workaround/boost/graph/filtered_graph.hpp\
../boost-workaround/boost/graph/fruchterman_reingold.hpp\
../boost-workaround/boost/graph/graphml.hpp
libgraph_tool_la_include_HEADERS = \
libgraph_tool_core_la_include_HEADERS = \
graph_adaptor.hh \
graph_assortativity.hh \
graph_clustering.hh \
graph_community.hh \
graph_community_network.hh \
graph_correlations_combined.hh \
graph_correlations.hh \
graph_correlations_neighbours.hh \
graph_distance.hh \
graph_distance_sampled.hh \
graph_edge_correlations.hh \
graph_extended_clustering.hh \
graph_filtering.hh \
graph.hh \
graph_properties.hh \
graph_python_interface.hh \
graph_rewiring.hh \
graph_selectors.hh \
graph_util.hh \
histogram.hh \
......@@ -91,19 +48,20 @@ libgraph_tool_la_include_HEADERS = \
shared_map.hh \
../../config.h
BUILT_SOURCES = \
graph_filtering.hh.gch
# leave out precompiled headers for now, since it doesn't seem to help much
# BUILT_SOURCES = \
# graph_filtering.hh.gch
## Header precompilation
## FIXME: need a better way to convince libtool to let us do this.
$(libgraph_tool_la_include_HEADERS):
# ## Header precompilation
# ## FIXME: need a better way to convince libtool to let us do this.
# $(libgraph_tool_la_include_HEADERS):
$(BUILT_SOURCES):
$(CXXCOMPILE) $(CXXFLAGS) $(AM_CXXFLAGS) $(AM_CPPFLAGS) -fPIC -DPIC -x c++-header `basename $@ .gch`
mostlyclean-local:
-rm -f *.gch
# $(BUILT_SOURCES):
# $(CXXCOMPILE) $(CXXFLAGS) $(AM_CXXFLAGS) $(AM_CPPFLAGS) -fPIC -DPIC -x c++-header `basename $@ .gch`
# mostlyclean-local:
# -rm -f *.gch
libgraph_tool_la_LIBADD = \
libgraph_tool_core_la_LIBADD = \
$(PYTHON_LDFLAGS) \
$(BOOST_LDFLAGS) \
$(OPENMP_LDFLAGS) \
......@@ -113,7 +71,7 @@ libgraph_tool_la_LIBADD = \
# needed for typeinfo objects to work across DSO boundaries.
# see http://gcc.gnu.org/faq.html#dso
libgraph_tool_la_LDFLAGS = \
libgraph_tool_core_la_LDFLAGS = \
-module \
-avoid-version \
-export-dynamic \
......
......@@ -35,7 +35,7 @@ GraphInterface::GetGlobalClustering()
bool directed = _directed;
_directed = false;
run_action<detail::never_directed>()
(*this, bind<void>(get_global_clustering(), _1, var(c), var(c_err)))();
(*this, bind<void>(get_global_clustering(), _1, var(c), var(c_err)))();
_directed = directed;
return make_pair(c,c_err);
}
......@@ -49,7 +49,7 @@ void GraphInterface::SetLocalClusteringToProperty(string property)
find_property_map(_properties, property, typeid(vertex_t));
vertex_prop = prop(property, _vertex_index, _properties);
if (!belongs<vertex_floating_properties>()(vertex_prop))
throw GraphException("vertex property " + property +
throw GraphException("vertex property " + property +
" is not of floating type");
}
catch (property_not_found)
......@@ -63,6 +63,6 @@ void GraphInterface::SetLocalClusteringToProperty(string property)
bool directed = _directed;
_directed = false;
run_action<detail::never_directed>()
(*this, bind<void>(set_clustering_to_property(), _1, _2))(vertex_prop);
(*this, bind<void>(set_clustering_to_property(), _1, _2))(vertex_prop);
_directed = directed;
}
......@@ -27,14 +27,14 @@ using namespace boost;
// calculates the number of triangles to which v belongs
template <class Graph>
pair<int,int>
pair<int,int>
get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g)
{
tr1::unordered_set<typename graph_traits<Graph>::vertex_descriptor>
tr1::unordered_set<typename graph_traits<Graph>::vertex_descriptor>
neighbour_set1, neighbour_set2, neighbour_set3;
size_t triangles = 0, k = 0;
typename graph_traits<Graph>::adjacency_iterator n1_begin, n1_end, n1;
tie(n1_begin, n1_end) = adjacent_vertices(v, g);
for (n1 = n1_begin; n1 != n1_end; ++n1)
......@@ -45,7 +45,7 @@ get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g)
continue;
else
neighbour_set1.insert(*n1);
typename graph_traits<Graph>::adjacency_iterator n2_begin, n2_end, n2;
tie(n2_begin, n2_end) = adjacent_vertices(*n1, g);
for (n2 = n2_begin; n2 != n2_end; ++n2)
......@@ -56,8 +56,8 @@ get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g)
continue;
else
neighbour_set2.insert(*n2);
typename graph_traits<Graph>::adjacency_iterator
typename graph_traits<Graph>::adjacency_iterator
n3_begin, n3_end, n3;
tie(n3_begin, n3_end) = adjacent_vertices(*n2, g);
for (n3 = n3_begin; n3 != n3_end; ++n3)
......@@ -68,9 +68,9 @@ get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g)
continue;
else
neighbour_set3.insert(*n3);
if (*n3 == v) //found a triangle
triangles++;
triangles++;
}
neighbour_set3.clear();
}
......@@ -103,14 +103,14 @@ struct get_global_clustering
continue;
temp = get_triangles(v, g);
triangles += temp.first;
triangles += temp.first;
n += temp.second;
}
c = double(triangles)/n;
// "jackknife" variance
c_err = 0.0;
#pragma omp parallel for default(shared) private(i,temp) \
schedule(dynamic) reduction(+|c_err)
for (i = 0; i < N; ++i)
......@@ -122,7 +122,7 @@ struct get_global_clustering
temp = get_triangles(v, g);
double cl = double(triangles - temp.first)/(n - temp.second);
c_err += (c - cl)*(c - cl);
c_err += (c - cl)*(c - cl);
}
c_err = sqrt(c_err);
}
......@@ -138,26 +138,26 @@ struct set_clustering_to_property
const Graph& g = *gp;
typename get_undirected_graph<Graph>::type ug(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;
pair<size_t,size_t> triangles = get_triangles(v,ug); // get from ug
double clustering = (triangles.second > 0) ?
double(triangles.first)/triangles.second :
0.0;
#pragma omp critical
{
clust_map[v] = clustering;
}
}
}
template <class Graph>
struct get_undirected_graph
{
......@@ -169,6 +169,6 @@ struct set_clustering_to_property
};
};
} //graph-tool namespace
} //graph-tool namespace
#endif // GRAPH_CLUSTERING_HH
......@@ -34,7 +34,7 @@ using namespace graph_tool;
template <class PropertySequence>
struct prop_vector
{
{
boost::any operator()(const vector<boost::any>& props, bool& found) const
{
boost::any prop_vec;
......@@ -49,7 +49,7 @@ struct prop_vector
template <class Property>
void operator()(Property, const vector<boost::any>& props,
boost::any& prop_vec, bool& found) const
{
{
if (typeid(Property) == props[0].type())
{
try
......@@ -100,18 +100,18 @@ void GraphInterface::SetExtendedClusteringToProperty(string property_prefix,
}
}
typedef mpl::transform<vertex_floating_properties,
typedef mpl::transform<vertex_floating_properties,
get_property_vector_type>::type
property_vectors;
bool found = false;
run_action<>()
(*this, bind<void>(get_extended_clustering(), _1, _vertex_index,_2),
(*this, bind<void>(get_extended_clustering(), _1, _vertex_index,_2),
property_vectors())
(prop_vector<vertex_scalar_properties>()(cmaps, found));
if (!found)
throw GraphException("All vertex properties " + property_prefix +
throw GraphException("All vertex properties " + property_prefix +
"* must be of the same floating point type!");
}
......@@ -30,16 +30,16 @@ using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
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,
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 property_map_types::apply<mpl::vector<int32_t,int64_t>,
vertex_index_map_t,
mpl::bool_<false> >::type