If you want to fork this repository to propose merge requests, please send an email to tiago@skewed.de, and your project limit will be raised.

Commit ed204f5e authored by Tiago Peixoto's avatar Tiago Peixoto

Resurrect modularity() function

parent 98c6c2b9
......@@ -49,6 +49,7 @@ libgraph_tool_inference_la_SOURCES = \
graph_blockmodel_overlap_multicanonical.cc \
graph_blockmodel_overlap_multiflip_mcmc.cc \
graph_blockmodel_overlap_vacate.cc \
graph_modularity.cc \
graph_inference.cc \
int_part.cc \
spence.cc
......@@ -73,6 +74,7 @@ libgraph_tool_inference_la_include_HEADERS = \
graph_blockmodel_overlap_util.hh \
graph_blockmodel_overlap_vacate.hh \
graph_blockmodel_util.hh \
graph_modularity.hh \
graph_neighbour_sampler.hh \
graph_state.hh \
mcmc_loop.hh \
......
......@@ -101,6 +101,7 @@ extern void export_overlap_blockmodel_exhaustive();
extern void export_layered_blockmodel_exhaustive();
extern void export_layered_overlap_blockmodel_exhaustive();
extern void export_marginals();
extern void export_modularity();
BOOST_PYTHON_MODULE(libgraph_tool_inference)
{
......@@ -137,6 +138,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_inference)
export_layered_blockmodel_exhaustive();
export_layered_overlap_blockmodel_exhaustive();
export_marginals();
export_modularity();
def("vector_map", vector_map<int32_t>);
def("vector_map64", vector_map<int64_t>);
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2016 Tiago de Paula Peixoto <tiago@skewed.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/>.
#include "graph_modularity.hh"
#include <boost/mpl/push_back.hpp>
#include <boost/python.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
double modularity(GraphInterface& gi, boost::any weight, boost::any property)
{
double Q = 0;
typedef UnityPropertyMap<int, GraphInterface::edge_t> weight_map_t;
typedef boost::mpl::push_back<edge_scalar_properties, weight_map_t>::type
edge_props_t;
if(weight.empty())
weight = weight_map_t();
run_action<>()
(gi, [&](auto& g, auto& w, auto& b){ Q = get_modularity(g, w, b);},
edge_props_t(), vertex_scalar_properties())
(weight, property);
return Q;
}
using namespace boost::python;
void export_modularity()
{
def("modularity", &modularity);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2016 Tiago de Paula Peixoto <tiago@skewed.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/>.
#ifndef GRAPH_MODULARITY_HH
#define GRAPH_MODULARITY_HH
#include <tuple>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "graph_tool.hh"
#include "hash_map_wrap.hh"
namespace graph_tool
{
using namespace std;
using namespace boost;
// get Newman's modularity of a given community partition
template <class Graph, class WeightMap, class CommunityMap>
double get_modularity(const Graph& g, WeightMap weights, CommunityMap b)
{
size_t B = 0;
for (auto v : vertices_range(g))
{
auto r = get(b, v);
if (r < 0)
throw ValueException("invalid community label: negative value!");
B = std::max(size_t(r) + 1, B);
}
vector<double> er(B), err(B);
double W = 0;
for (auto e : edges_range(g))
{
size_t r = get(b, source(e, g));
size_t s = get(b, target(e, g));
auto w = get(weights, e);
W += 2 * w;
er[r] += w;
er[s] += w;
if (r == s)
err[r] += 2 * w;
}
double Q = 0;
for (size_t r = 0; r < B; ++r)
Q += err[r] - (er[r] * er[r]) / W;
Q /= W;
return Q;
};
} // graph_tool namespace
#endif //GRAPH_MODULARITY_HH
......@@ -73,6 +73,7 @@ graph_tool_inference_PYTHON = \
inference/overlap_blockmodel.py \
inference/mcmc.py \
inference/minimize.py \
inference/modularity.py \
inference/util.py
graph_tool_inferencedir = $(MOD_DIR)/inference
......
......@@ -109,7 +109,13 @@ Expectation-maximization Inference
em_infer
Large-scale descriptors
+++++++++++++++++++++++
.. autosummary::
:nosignatures:
modularity
Contents
++++++++
......@@ -145,7 +151,8 @@ __all__ = ["minimize_blockmodel_dl",
"BlockPairHist",
"half_edge_graph",
"get_block_edge_gradient",
"get_hierarchy_tree"]
"get_hierarchy_tree",
"modularity"]
from . blockmodel import *
from . overlap_blockmodel import *
......@@ -156,3 +163,4 @@ from . bisection import *
from . minimize import *
from . blockmodel_em import *
from . util import *
from . modularity import *
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# graph_tool -- a general graph manipulation python module
#
# Copyright (C) 2006-2016 Tiago de Paula Peixoto <tiago@skewed.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/>.
from .. import _prop, perfect_prop_hash
from .. dl_import import dl_import
dl_import("from . import libgraph_tool_inference as libinference")
def modularity(g, b, weight=None):
r"""
Calculate Newman's modularity of a network partition.
Parameters
----------
g : :class:`~graph_tool.Graph`
Graph to be used.
b : :class:`~graph_tool.PropertyMap`
Vertex property map with the community partition.
weight : :class:`~graph_tool.PropertyMap` (optional, default: None)
Edge property map with the optional edge weights.
Returns
-------
Q : float
Newman's modularity.
Notes
-----
Given a specific graph partition specified by `prop`, Newman's modularity
[newman-modularity-2006]_ is defined as:
.. math::
Q = \frac{1}{2E} \sum_r e_{rr}- \frac{e_r^2}{2E}
where :math:`e_{rs}` is the number of edges which fall between
vertices in communities s and r, or twice that number if :math:`r = s`, and
:math:`e_r = \sum_s e_{rs}`.
If weights are provided, the matrix :math:`e_{rs}` corresponds to the sum
of edge weights instead of number of edges, and the value of :math:`E`
becomes the total sum of edge weights.
Examples
--------
>>> g = gt.collection.data["football"]
>>> modularity(g, g.vp.value_tsevans)
0.5744393497...
References
----------
.. [newman-modularity-2006] M. E. J. Newman, "Modularity and community
structure in networks", Proc. Natl. Acad. Sci. USA 103, 8577-8582 (2006),
:doi:`10.1073/pnas.0601602103`, :arxiv:`physics/0602124`
"""
if b.value_type() not in ["bool", "int16_t", "int32_t", "int64_t",
"unsigned long"]:
b = perfect_prop_hash([b])[0]
Q = libinference.modularity(g._Graph__graph,
_prop("e", g, weight),
_prop("v", g, b))
return Q
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