Commit 2e1d1a07 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Ignore self-loops when merging nodes in block graph

parent a7c6527b
......@@ -616,7 +616,7 @@ struct merge_sweep_dispatch
template <class Graph, class Eprop, class Vprop>
void operator()(Eprop mrs, Vprop mrp, Vprop mrm, Vprop wr, Vprop b,
Vprop clabel, Graph& bg, boost::any& aemat,
boost::any asampler) const
boost::any asampler, boost::any ansampler) const
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
......@@ -627,6 +627,7 @@ struct merge_sweep_dispatch
vindex_map_t>::type::unchecked_t
sampler_map_t;
sampler_map_t sampler = any_cast<sampler_map_t>(asampler);
sampler_map_t nsampler = any_cast<sampler_map_t>(ansampler);
try
{
......@@ -645,7 +646,7 @@ struct merge_sweep_dispatch
b.get_unchecked(num_vertices(bg)),
clabel.get_unchecked(num_vertices(bg)),
deg_corr, dense, multigraph,
bg, emat, sampler, nmerges, nsweeps,
bg, emat, sampler, nsampler, nmerges, nsweeps,
random_moves, verbose, rng, S, nmoves);
}
catch (bad_any_cast&)
......@@ -659,7 +660,7 @@ struct merge_sweep_dispatch
b.get_unchecked(num_vertices(bg)),
clabel.get_unchecked(num_vertices(bg)),
deg_corr, dense, multigraph, bg, emat, sampler,
nmerges, nsweeps, random_moves, verbose,
nsampler, nmerges, nsweeps, random_moves, verbose,
rng, S, nmoves);
}
}
......@@ -668,11 +669,13 @@ struct merge_sweep_dispatch
boost::python::object do_merge_sweep(GraphInterface& bgi, boost::any& emat,
boost::any sampler, boost::any omrs,
boost::any omrp, boost::any omrm, boost::any owr,
boost::any ob, boost::any oclabel, bool deg_corr,
bool dense, bool multigraph, size_t nsweeps,
size_t nmerges, bool random_moves, bool verbose,
boost::any sampler, boost::any nsampler,
boost::any omrs, boost::any omrp,
boost::any omrm, boost::any owr,
boost::any ob, boost::any oclabel,
bool deg_corr, bool dense, bool multigraph,
size_t nsweeps, size_t nmerges,
bool random_moves, bool verbose,
rng_t& rng)
{
typedef property_map_type::apply<int32_t,
......@@ -697,7 +700,7 @@ boost::python::object do_merge_sweep(GraphInterface& bgi, boost::any& emat,
random_moves, verbose,
bgi.GetGraph().get_last_index(), rng, S, nmoves),
mrs, mrp, mrm, wr, b, clabel, placeholders::_1,
std::ref(emat), sampler))();
std::ref(emat), sampler, nsampler))();
return boost::python::make_tuple(S, nmoves);
}
......@@ -745,7 +748,8 @@ boost::any do_build_egroups(GraphInterface& gi, GraphInterface& bgi,
return oegroups;
}
boost::any do_init_neighbour_sampler(GraphInterface& gi, boost::any oeweights)
boost::any do_init_neighbour_sampler(GraphInterface& gi, boost::any oeweights,
bool self_loops)
{
typedef property_map_type::apply<int32_t,
GraphInterface::edge_index_map_t>::type
......@@ -755,7 +759,7 @@ boost::any do_init_neighbour_sampler(GraphInterface& gi, boost::any oeweights)
boost::any osampler;
run_action<graph_tool::detail::all_graph_views, boost::mpl::true_>()
(gi, std::bind(init_neighbour_sampler(), placeholders::_1, eweights,
std::ref(osampler)))();
self_loops, std::ref(osampler)))();
return osampler;
}
......
......@@ -1406,7 +1406,8 @@ void move_sweep(EMprop mrs, Vprop mrp, Vprop mrm, Vprop wr, Vprop b,
template <class Vertex, class Graph, class Eprop, class SMap>
void build_neighbour_sampler(Vertex v, SMap sampler, Eprop eweight, Graph& g)
void build_neighbour_sampler(Vertex v, SMap sampler, Eprop eweight,
bool self_loops, Graph& g)
{
vector<Vertex> neighbours;
vector<double> probs;
......@@ -1420,19 +1421,27 @@ void build_neighbour_sampler(Vertex v, SMap sampler, Eprop eweight, Graph& g)
Vertex u = target(*e, g);
if (is_directed::apply<Graph>::type::value && u == v)
u = source(*e, g);
if (!self_loops && u == v)
continue;
neighbours.push_back(u);
probs.push_back(eweight[*e]); // Self-loops will be added twice, and
// hence will be sampled with probability
// 2 * eweight[e]
}
if (probs.empty())
{
neighbours.push_back(v);
probs.push_back(1.);
}
sampler[v] = Sampler<Vertex, mpl::false_>(neighbours, probs);
};
struct init_neighbour_sampler
{
template <class Graph, class Eprop>
void operator()(Graph& g, Eprop eweight, boost::any& asampler) const
void operator()(Graph& g, Eprop eweight, bool self_loops, boost::any& asampler) const
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
......@@ -1451,7 +1460,7 @@ struct init_neighbour_sampler
vertex_t v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
build_neighbour_sampler(v, sampler, eweight, g);
build_neighbour_sampler(v, sampler, eweight, self_loops, g);
}
}
};
......@@ -1551,6 +1560,7 @@ template <class BGraph, class Eprop, class Vprop, class EMat, class SamplerMap,
void merge_sweep(Eprop mrs, Vprop mrp, Vprop mrm, Vprop wr, Vprop b,
Vprop clabel, bool deg_corr, bool dense, bool multigraph,
BGraph& bg, EMat& emat, SamplerMap neighbour_sampler,
SamplerMap second_neighbour_sampler,
size_t nmerges, size_t nsweeps, bool random_moves,
bool verbose, RNG& rng, double& S, size_t& nmoves)
{
......@@ -1590,7 +1600,7 @@ void merge_sweep(Eprop mrs, Vprop mrp, Vprop mrm, Vprop wr, Vprop b,
else
{
vertex_t t = neighbour_sampler[r].sample(rng);
s = neighbour_sampler[t].sample(rng);
s = second_neighbour_sampler[t].sample(rng);
}
if (s == r)
......@@ -1718,10 +1728,8 @@ void merge_sweep(Eprop mrs, Vprop mrp, Vprop mrm, Vprop wr, Vprop b,
for (i = 0; i < N; ++i)
{
vertex_t r = vertex(i, bg);
if (total_degreeS()(r, bg) > 0)
build_neighbour_sampler(r, neighbour_sampler, mrs, bg);
else
neighbour_sampler[r] = Sampler<vertex_t, mpl::false_>();
build_neighbour_sampler(r, neighbour_sampler, mrs, false, bg);
build_neighbour_sampler(r, second_neighbour_sampler, mrs, true, bg);
}
}
}
......
......@@ -161,6 +161,7 @@ class BlockState(object):
# used by merge_sweep()
self.bnsampler = None
self.bnnsampler = None
libcommunity.init_safelog(int(2 * max(self.E, self.N)))
libcommunity.init_xlogx(int(2 * max(self.E, self.N)))
......@@ -191,10 +192,15 @@ class BlockState(object):
def __build_nsampler(self):
self.nsampler = libcommunity.init_neighbour_sampler(self.g._Graph__graph,
_prop("e", self.g, self.eweight))
_prop("e", self.g, self.eweight),
True)
def __build_bnsampler(self):
self.bnsampler = libcommunity.init_neighbour_sampler(self.bg._Graph__graph,
_prop("e", self.bg, self.mrs))
_prop("e", self.bg, self.mrs),
False)
self.bnnsampler = libcommunity.init_neighbour_sampler(self.bg._Graph__graph,
_prop("e", self.bg, self.mrs),
True)
def __cleanup_bg(self):
emask = self.bg.new_edge_property("bool")
......@@ -872,6 +878,7 @@ def mcmc_sweep(state, beta=1., c=1., dense=False, multigraph=False,
state._BlockState__build_nsampler()
state.bnsampler = None
state.bnnsampler = None
try:
dS, nmoves = libcommunity.move_sweep(state.g._Graph__graph,
......@@ -906,7 +913,7 @@ def merge_sweep(state, bm, nmerges, nsweeps=10, dense=False, multigraph=False,
if state.B == 1:
return 0., 0
if state.bnsampler is None:
if state.bnsampler is None or state.bnnsampler is None:
state._BlockState__build_bnsampler()
state.egroups = None
......@@ -915,6 +922,7 @@ def merge_sweep(state, bm, nmerges, nsweeps=10, dense=False, multigraph=False,
dS, nmoves = libcommunity.merge_sweep(state.bg._Graph__graph,
state._BlockState__get_emat(),
state.bnsampler,
state.bnnsampler,
_prop("e", state.bg, state.mrs),
_prop("v", state.bg, state.mrp),
_prop("v", state.bg, state.mrm),
......
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