Commit 003bd47f authored by Tiago Peixoto's avatar Tiago Peixoto

Port clustering algorithms to new interface

A new 'clustering' sub-module was created.
parent 242bfff7
......@@ -241,6 +241,7 @@ src/graph/Makefile
src/graph/correlations/Makefile
src/graph/generation/Makefile
src/graph/stats/Makefile
src/graph/clustering/Makefile
src/graph_tool/Makefile
])
## Process this file with automake to produce Makefile.in
SUBDIRS = generation correlations stats
SUBDIRS = generation correlations stats clustering
AM_CPPFLAGS =\
-I. -I.. \
......
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS =\
-I. -I.. \
-I../boost-workaround \
-DHAVE_CONFIG_H
AM_CFLAGS=$(AM_CXXFLAGS)
libgraph_tool_clusteringdir = $(pythondir)/graph_tool/clustering
libgraph_tool_clustering_LTLIBRARIES = libgraph_tool_clustering.la
libgraph_tool_clustering_la_includedir = $(pythondir)/graph_tool/include
libgraph_tool_clustering_la_SOURCES = \
graph_clustering.cc \
graph_extended_clustering.cc
libgraph_tool_clustering_la_include_HEADERS = \
graph_clustering.hh \
graph_extended_clustering.hh
libgraph_tool_clustering_la_LIBADD = \
$(PYTHON_LDFLAGS) \
$(BOOST_LDFLAGS) \
$(OPENMP_LDFLAGS) \
-lboost_python \
-lboost_iostreams \
-lexpat
# needed for typeinfo objects to work across DSO boundaries.
# see http://gcc.gnu.org/faq.html#dso
libgraph_tool_clustering_la_LDFLAGS = \
-module \
-avoid-version \
-export-dynamic \
-no-undefined \
-Wl,-E
......@@ -23,46 +23,43 @@
#include "graph_clustering.hh"
#include <boost/python.hpp>
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
pair<double,double>
GraphInterface::GetGlobalClustering()
python::tuple global_clustering(GraphInterface& g)
{
double c, c_err;
bool directed = _directed;
_directed = false;
run_action<detail::never_directed>()
(*this, bind<void>(get_global_clustering(), _1, var(c), var(c_err)))();
_directed = directed;
return make_pair(c,c_err);
bool directed = g.GetDirected();
g.SetDirected(false);
run_action<graph_tool::detail::never_directed>()
(g, lambda::bind<void>(get_global_clustering(), lambda::_1,
lambda::var(c), lambda::var(c_err)))();
g.SetDirected(directed);
return python::make_tuple(c, c_err);
}
void GraphInterface::SetLocalClusteringToProperty(string property)
void local_clustering(GraphInterface& g, boost::any prop)
{
boost::any vertex_prop;
bool directed = g.GetDirected();
g.SetDirected(false);
run_action<graph_tool::detail::never_directed>()
(g, lambda::bind<void>(set_clustering_to_property(), lambda::_1,
lambda::_2),
writable_vertex_scalar_properties())(prop);
g.SetDirected(directed);
}
try
{
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 +
" is not of floating type");
}
catch (property_not_found)
{
typedef vector_property_map<double,vertex_index_map_t> clust_map_t;
clust_map_t clust_map(num_vertices(_mg), _vertex_index);
_properties.property(property, clust_map);
vertex_prop = clust_map;
}
using namespace boost::python;
bool directed = _directed;
_directed = false;
run_action<detail::never_directed>()
(*this, bind<void>(set_clustering_to_property(), _1, _2))(vertex_prop);
_directed = directed;
void extended_clustering(GraphInterface& g, python::list props);
BOOST_PYTHON_MODULE(libgraph_tool_clustering)
{
def("global_clustering", &global_clustering);
def("local_clustering", &local_clustering);
def("extended_clustering", &extended_clustering);
}
......@@ -128,7 +128,6 @@ struct get_global_clustering
}
};
// sets the local clustering coefficient to a property
struct set_clustering_to_property
{
......
......@@ -18,15 +18,13 @@
// based on code written by Alexandre Hannud Abdo <abdo@member.fsf.org>
#include "graph_filtering.hh"
#include "graph.hh"
#include "histogram.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include <boost/graph/breadth_first_search.hpp>
#include "graph_extended_clustering.hh"
#include <boost/python.hpp>
using namespace std;
using namespace boost;
using namespace boost::lambda;
......@@ -35,20 +33,20 @@ using namespace graph_tool;
template <class PropertySequence>
struct prop_vector
{
boost::any operator()(const vector<boost::any>& props, bool& found) const
boost::any operator()(const vector<boost::any>& props) const
{
boost::any prop_vec;
mpl::for_each<PropertySequence>(bind<void>(get_prop_vector(), _1,
var(props), var(prop_vec),
var(found)));
mpl::for_each<PropertySequence>
(lambda::bind<void>(get_prop_vector(), lambda::_1,
lambda::var(props), lambda::var(prop_vec)));
return prop_vec;
}
struct get_prop_vector
{
template <class Property>
void operator()(Property, const vector<boost::any>& props,
boost::any& prop_vec, bool& found) const
void operator()(Property, const vector<boost::any>& props,
boost::any& prop_vec) const
{
if (typeid(Property) == props[0].type())
{
......@@ -59,12 +57,8 @@ struct prop_vector
for (size_t i = 0; i < props.size(); ++i)
vec[i] = any_cast<Property>(props[i]);
prop_vec = vec;
found = true;
}
catch (bad_any_cast)
{
found = false;
}
catch (bad_any_cast){}
}
}
};
......@@ -80,38 +74,25 @@ struct get_property_vector_type
};
};
void GraphInterface::SetExtendedClusteringToProperty(string property_prefix,
size_t max_depth)
void extended_clustering(GraphInterface& g, python::list props)
{
typedef vector_property_map<double, vertex_index_map_t> cmap_t;
vector<any> cmaps(max_depth);
vector<any> cmaps(python::len(props));
for (size_t i = 0; i < cmaps.size(); ++i)
{
string name = property_prefix + lexical_cast<string>(i+1);
try
{
cmaps[i] = prop(name, _vertex_index, _properties);
}
catch (property_not_found)
{
cmap_t cmap(num_vertices(_mg), _vertex_index);
_properties.property(name, cmap);
cmaps[i] = cmap;
}
}
cmaps[i] = python::extract<boost::any>(props[i])();
typedef mpl::transform<vertex_floating_properties,
get_property_vector_type>::type
property_vectors;
boost::any vprop = prop_vector<vertex_scalar_properties>()(cmaps);
if (vprop.empty())
throw GraphException("all vertex properties must be of the same"
" floating point type");
bool found = false;
typedef mpl::transform<writable_vertex_scalar_properties,
get_property_vector_type>::type
properties_vector;
run_action<>()
(*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 +
"* must be of the same floating point type!");
(g, lambda::bind<void>(get_extended_clustering(), lambda::_1,
any_cast<GraphInterface::vertex_index_map_t>
(g.GetVertexIndex()), lambda::_2),
properties_vector()) (vprop);
}
#! /usr/bin/env python
# graph_tool.py -- a general graph manipulation python module
#
# 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, see <http://www.gnu.org/licenses/>.
import sys
# RTLD_GLOBAL needs to be set in dlopen() if we want typeinfo and friends to
# work properly across DSO boundaries. See http://gcc.gnu.org/faq.html#dso
# The "except" is because the dl module raises a system error on ia64 and x86_64
# systems because "int" and addresses are different sizes.
try:
from dl import RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL
except ImportError:
RTLD_LAZY = 1
RTLD_NOW = 2
RTLD_GLOBAL = 256
_orig_dlopen_flags = sys.getdlopenflags()
sys.setdlopenflags(RTLD_LAZY|RTLD_GLOBAL)
import libgraph_tool_clustering
sys.setdlopenflags(_orig_dlopen_flags) # reset it to normal case to avoid
# unnecessary symbol collision
from .. core import _degree, _prop
from numpy import *
__all__ = ["local_clustering", "global_clustering", "extended_clustering"]
def local_clustering(g, prop=None):
if prop == None:
prop = g.new_vertex_property("double")
libgraph_tool_clustering.extended_clustering(g.underlying_graph(),
[_prop("v", g, prop)])
return prop
def global_clustering(g):
c = libgraph_tool_clustering.global_clustering(g.underlying_graph())
return c
def extended_clustering(g, props=None, max_depth=3):
if props == None:
props = []
for i in xrange(0, max_depth):
props.append(g.new_vertex_property("double"))
libgraph_tool_clustering.extended_clustering(g.underlying_graph(),
[_prop("v", g, p) for p in props])
return props
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