diff --git a/configure.ac b/configure.ac index c8d1932d8257b74def14029e20d048b861383454..d9c83669e7acb8e031cf2f111a2693a33de860dc 100644 --- a/configure.ac +++ b/configure.ac @@ -273,6 +273,7 @@ src/graph/correlations/Makefile src/graph/generation/Makefile src/graph/stats/Makefile src/graph/clustering/Makefile +src/graph/community/Makefile src/graph/util/Makefile src/graph/misc/Makefile src/graph_tool/Makefile diff --git a/src/graph/Makefile.am b/src/graph/Makefile.am index eb373d77f0304996d5ec107f0f11146ad2951d1b..7e86c04b11c594068918a387092b8bedaf47579c 100644 --- a/src/graph/Makefile.am +++ b/src/graph/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = generation correlations stats clustering util misc +SUBDIRS = generation correlations stats clustering community util misc AM_CPPFLAGS =\ -I$(srcdir)/.. \ diff --git a/src/graph/community/Makefile.am b/src/graph/community/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..24f7f2324ec4ba501fa74865b2b3d989c0f266f7 --- /dev/null +++ b/src/graph/community/Makefile.am @@ -0,0 +1,18 @@ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = $(MOD_CPPFLAGS) + +AM_CFLAGS=$(AM_CXXFLAGS) + +libgraph_tool_communitydir = $(pythondir)/graph_tool/community + +libgraph_tool_community_LTLIBRARIES = libgraph_tool_community.la + +libgraph_tool_community_la_includedir = $(pythondir)/graph_tool/include + +libgraph_tool_community_la_LIBADD = $(MOD_LIBADD) + +libgraph_tool_community_la_LDFLAGS = $(MOD_LDFLAGS) + +libgraph_tool_community_la_SOURCES = \ + graph_community.cc diff --git a/src/graph/community/graph_community.cc b/src/graph/community/graph_community.cc index 37208549809997e208c4dbee835251035bc9b3ed..5d742c0c52a975108d257d70c6b0dac1d98d8c29 100644 --- a/src/graph/community/graph_community.cc +++ b/src/graph/community/graph_community.cc @@ -22,125 +22,98 @@ #include #include +#include #include "graph_community.hh" using namespace std; 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, - string property) + +void community_structure(GraphInterface& g, double gamma, string corr_name, + size_t n_iter, double Tmin, double Tmax, size_t Nspins, + bool new_spins, size_t seed, bool verbose, string history_file, + boost::any weight, boost::any property) { + using boost::lambda::bind; + using boost::lambda::_1; + using boost::lambda::_2; + using boost::lambda::_3; + typedef property_map_types::apply, - vertex_index_map_t, + GraphInterface::vertex_index_map_t, mpl::bool_ >::type allowed_spin_properties; - boost::any vertex_prop; - bool new_spins; - try - { - find_property_map(_properties, property, typeid(vertex_t)); - vertex_prop = prop(property, _vertex_index, _properties); - if (!belongs()(vertex_prop)) - throw GraphException("vertex property " + property + - " is not of integer type int32_t or int64_t"); - new_spins = false; - } - catch (property_not_found) - { - typedef vector_property_map comm_map_t; - comm_map_t comm_map(_vertex_index); - _properties.property(property, comm_map); - vertex_prop = comm_map; - new_spins = true; - } - - boost::any edge_prop; - typedef DynamicPropertyMapWrap weight_map_t; - typedef ConstantPropertyMap no_weight_map_t; + if (!belongs()(property)) + throw GraphException("vertex property is not of integer type int32_t " + "or int64_t"); + + typedef DynamicPropertyMapWrap weight_map_t; + typedef ConstantPropertyMap no_weight_map_t; typedef mpl::vector weight_properties; - if(weight != "") - { - try - { - weight_map_t wrap(find_property_map(_properties, weight, - typeid(edge_t))); - edge_prop = wrap; - } - catch (property_not_found) - { - throw GraphException("edge property " + weight + " not found"); - } - } + if (weight.empty()) + weight = no_weight_map_t(1.0); + else + weight = weight_map_t(weight, edge_scalar_properties()); + + comm_corr_t corr; + if (corr_name == "erdos") + corr = ERDOS_REYNI; + else if (corr_name == "uncorrelated") + corr = UNCORRELATED; + else if (corr_name == "correlated") + corr = CORRELATED; else - { - edge_prop = no_weight_map_t(1.0); - } - - bool directed = _directed; - _directed = false; - try - { - run_action() - (*this, bind(get_communities_selector(corr), - _1, _2, _3, gamma, n_iter, - make_pair(Tmin, Tmax), - make_pair(Nspins, new_spins), - seed, make_pair(verbose,history_file)), - weight_properties(), allowed_spin_properties()) - (edge_prop, vertex_prop); - } - catch (property_not_found& e) - { - _directed = directed; - throw GraphException("error getting scalar property: " + - string(e.what())); - } - _directed = directed; + throw GraphException("invalid correlation type: " + corr_name); + + bool directed = g.GetDirected(); + g.SetDirected(false); + run_action() + (g, bind(get_communities_selector(corr), + _1, _2, _3, gamma, n_iter, + make_pair(Tmin, Tmax), + make_pair(Nspins, new_spins), + seed, make_pair(verbose,history_file)), + weight_properties(), allowed_spin_properties()) + (weight, property); + g.SetDirected(directed); } -double GraphInterface::GetModularity(string weight, string property) +double modularity(GraphInterface& g, boost::any weight, boost::any property) { + using boost::lambda::bind; + using boost::lambda::_1; + using boost::lambda::_2; + using boost::lambda::_3; + double modularity = 0; - boost::any vertex_prop = prop(property, _vertex_index, _properties); + typedef ConstantPropertyMap weight_map_t; - boost::any edge_prop; - typedef ConstantPropertyMap weight_map_t; + if(weight.empty()) + weight = weight_map_t(1); - if(weight != "") - edge_prop = prop(weight, _edge_index, _properties); - else - edge_prop = weight_map_t(1); - - typedef mpl::push_back::type - weight_properties; - - bool directed = _directed; - _directed = false; - try - { - run_action() - (*this, bind(get_modularity(), _1, _2, _3, var(modularity)), - weight_properties(), vertex_scalar_properties()) - (edge_prop, vertex_prop); - } - catch (property_not_found& e) - { - _directed = directed; - throw GraphException("error getting scalar property: " + - string(e.what())); - } - _directed = directed; + bool directed = g.GetDirected(); + g.SetDirected(false); + run_action() + (g, bind(get_modularity(), _1, _2, _3, var(modularity)), + edge_scalar_properties(), vertex_scalar_properties()) + (weight, property); + g.SetDirected(directed); return modularity; } + +using namespace boost::python; + +BOOST_PYTHON_MODULE(libgraph_tool_community) +{ + def("community_structure", &community_structure); + def("modularity", &modularity); +} diff --git a/src/graph/community/graph_community.hh b/src/graph/community/graph_community.hh index 056622e2590fd105404d9923b42b76aeff11f3a9..9e9f34b408d1f0bf14862c9448f79ad7c730addd 100644 --- a/src/graph/community/graph_community.hh +++ b/src/graph/community/graph_community.hh @@ -670,11 +670,17 @@ private: unordered_map > _NNks; }; +enum comm_corr_t +{ + ERDOS_REYNI, + UNCORRELATED, + CORRELATED +}; struct get_communities_selector { - get_communities_selector(GraphInterface::comm_corr_t corr):_corr(corr) {} - GraphInterface::comm_corr_t _corr; + get_communities_selector(comm_corr_t corr):_corr(corr) {} + comm_corr_t _corr; template void operator()(const Graph* gp, WeightMap weights, CommunityMap s, double gamma, @@ -686,15 +692,15 @@ struct get_communities_selector switch (_corr) { - case GraphInterface::ERDOS_REYNI: + case ERDOS_REYNI: get_communities()(g, weights, s, gamma, n_iter, Tinterval, Nspins, seed, verbose); break; - case GraphInterface::UNCORRELATED: + case UNCORRELATED: get_communities()(g, weights, s, gamma, n_iter, Tinterval, Nspins, seed, verbose); break; - case GraphInterface::CORRELATED: + case CORRELATED: get_communities()(g, weights, s, gamma, n_iter, Tinterval, Nspins, seed, verbose); break; diff --git a/src/graph_tool/Makefile.am b/src/graph_tool/Makefile.am index 4b7b13bb3924ffd1224bd3eb7f8329591492128f..561b979b9f192754bca3ce2f62ac64c7457261a1 100644 --- a/src/graph_tool/Makefile.am +++ b/src/graph_tool/Makefile.am @@ -38,6 +38,10 @@ graph_tool_clustering_PYTHON = \ clustering/__init__.py graph_tool_clusteringdir = $(MOD_DIR)/clustering +graph_tool_community_PYTHON = \ + community/__init__.py +graph_tool_communitydir = $(MOD_DIR)/community + graph_tool_draw_PYTHON = \ draw/__init__.py graph_tool_drawdir = $(MOD_DIR)/draw diff --git a/src/graph_tool/all.py b/src/graph_tool/all.py index 85ecc59707358b5040499796caea1ec7760a422a..bf8e0ffd7db2114115816e48e162e3a70ee838bd 100644 --- a/src/graph_tool/all.py +++ b/src/graph_tool/all.py @@ -39,6 +39,8 @@ from graph_tool.stats import * import graph_tool.stats from graph_tool.clustering import * import graph_tool.clustering +from graph_tool.community import * +import graph_tool.community from graph_tool.run_action import * graph_tool.run_action from graph_tool.misc import * diff --git a/src/graph_tool/community/__init__.py b/src/graph_tool/community/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1742a77c5ea33c1182e62383d3ded2e851f4e6e2 --- /dev/null +++ b/src/graph_tool/community/__init__.py @@ -0,0 +1,48 @@ +#! /usr/bin/env python +# graph_tool.py -- a general graph manipulation python module +# +# Copyright (C) 2007 Tiago de Paula Peixoto +# +# 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 . + +from .. dl_import import dl_import +dl_import("import libgraph_tool_community") + +from .. core import _degree, _prop +import random, sys + +__all__ = ["community_structure", "modularity"] + + +def community_structure(g, gamma=1.0, corr="erdos", spins=None, + weights=None, max_iter=0, t_range=(100.0,0.01), + n_spins=0, verbose=False, history_file="", seed=0): + if spins == None: + spins = g.new_vertex_property("int32_t") + new_spins = True + else: + new_spins = False + if seed != 0: + seed = random.randint(0, sys.maxint) + libgraph_tool_community.community_structure(g._Graph__graph, gamma, corr, + max_iter, t_range[1], + t_range[0], n_spins, new_spins, + seed, verbose, history_file, + _prop("e", g, weights), + _prop("v", g, spins)) + return spins + +def modularity(g): + c = libgraph_tool_clustering.global_clustering(g._Graph__graph) + return c