Commit 8aefa447 authored by Tiago Peixoto's avatar Tiago Peixoto

Include support for keeping certain edges "pinned down" in random_rewire()

parent 9f0de17f
......@@ -63,7 +63,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[CXXFLAGS="${old_cxxflags} -std=gnu++0x"])
dnl set template depth
[CXXFLAGS="${CXXFLAGS} -ftemplate-depth-150"]
[CXXFLAGS="${CXXFLAGS} -ftemplate-depth-250"]
dnl disable deprecation warning, to silence some harmless BGL-related warnings
[CXXFLAGS="${CXXFLAGS} -Wno-deprecated -Wno-unknown-pragmas"]
......
......@@ -70,8 +70,8 @@ void generate_graph(GraphInterface& gi, size_t N, boost::python::object deg_samp
size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
bool no_sweep, bool self_loops, bool parallel_edges,
bool alias, bool traditional, bool persist,
boost::python::object corr_prob, boost::any block, bool cache,
rng_t& rng, bool verbose);
boost::python::object corr_prob, boost::any apin,
boost::any block, bool cache, rng_t& rng, bool verbose);
void predecessor_graph(GraphInterface& gi, GraphInterface& gpi,
boost::any pred_map);
void line_graph(GraphInterface& gi, GraphInterface& lgi,
......
......@@ -79,9 +79,10 @@ struct graph_rewire_block
bool alias;
bool traditional;
template <class Graph, class EdgeIndexMap, class CorrProb, class BlockProp>
template <class Graph, class EdgeIndexMap, class CorrProb, class PinMap,
class BlockProp>
void operator()(Graph& g, EdgeIndexMap edge_index, CorrProb corr_prob,
pair<bool, bool> rest, BlockProp block_prop,
PinMap pin, pair<bool, bool> rest, BlockProp block_prop,
pair<size_t, bool> iter_sweep,
std::tuple<bool, bool, bool> cache_verbose, size_t& pcount, rng_t& rng)
const
......@@ -89,18 +90,18 @@ struct graph_rewire_block
if (traditional)
{
graph_rewire<TradBlockRewireStrategy>()
(g, edge_index, corr_prob, rest.first, rest.second, iter_sweep,
(g, edge_index, corr_prob, pin, rest.first, rest.second, iter_sweep,
cache_verbose, pcount, rng, PropertyBlock<BlockProp>(block_prop));
}
else
{
if (alias)
graph_rewire<AliasProbabilisticRewireStrategy>()
(g, edge_index, corr_prob, rest.first, rest.second, iter_sweep,
(g, edge_index, corr_prob, pin, rest.first, rest.second, iter_sweep,
cache_verbose, pcount, rng, PropertyBlock<BlockProp>(block_prop));
else
graph_rewire<ProbabilisticRewireStrategy>()
(g, edge_index, corr_prob, rest.first, rest.second, iter_sweep,
(g, edge_index, corr_prob, pin, rest.first, rest.second, iter_sweep,
cache_verbose, pcount, rng, PropertyBlock<BlockProp>(block_prop));
}
}
......@@ -109,15 +110,16 @@ struct graph_rewire_block
struct graph_rewire_correlated
{
template <class Graph, class EdgeIndexMap, class CorrProb, class BlockProp>
template <class Graph, class EdgeIndexMap, class CorrProb, class PinMap,
class BlockProp>
void operator()(Graph& g, EdgeIndexMap edge_index, CorrProb corr_prob,
bool self_loops, bool parallel_edges,
PinMap pin, bool self_loops, bool parallel_edges,
pair<size_t, bool> iter_sweep,
std::tuple<bool, bool, bool> cache_verbose,
size_t& pcount, rng_t& rng, BlockProp block_prop) const
{
graph_rewire<CorrelatedRewireStrategy>()
(g, edge_index, corr_prob, self_loops, parallel_edges, iter_sweep,
(g, edge_index, corr_prob, pin, self_loops, parallel_edges, iter_sweep,
cache_verbose, pcount, rng, PropertyBlock<BlockProp>(block_prop));
}
};
......@@ -126,18 +128,26 @@ struct graph_rewire_correlated
size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
bool no_sweep, bool self_loops, bool parallel_edges,
bool alias, bool traditional, bool persist,
boost::python::object corr_prob, boost::any block, bool cache,
rng_t& rng, bool verbose)
boost::python::object corr_prob, boost::any apin,
boost::any block, bool cache, rng_t& rng, bool verbose)
{
PythonFuncWrap corr(corr_prob);
size_t pcount = 0;
typedef property_map_type::apply<uint8_t,
GraphInterface::edge_index_map_t>::type
emap_t;
emap_t::unchecked_t pin =
any_cast<emap_t>(apin).get_unchecked(gi.GetMaxEdgeIndex());
if (strat == "erdos")
{
run_action<graph_tool::detail::never_reversed>()
(gi, std::bind(graph_rewire<ErdosRewireStrategy>(),
placeholders::_1, gi.GetEdgeIndex(),
std::ref(corr),
std::ref(corr), pin,
self_loops, parallel_edges,
make_pair(niter, no_sweep),
std::make_tuple(persist, cache, verbose),
......@@ -148,7 +158,7 @@ size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
run_action<graph_tool::detail::never_reversed>()
(gi, std::bind(graph_rewire<RandomRewireStrategy>(),
placeholders::_1, gi.GetEdgeIndex(), std::ref(corr),
self_loops, parallel_edges,
pin, self_loops, parallel_edges,
make_pair(niter, no_sweep),
std::make_tuple(persist, cache, verbose),
std::ref(pcount), std::ref(rng)))();
......@@ -160,7 +170,7 @@ size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
run_action<graph_tool::detail::never_reversed>()
(gi, std::bind(graph_rewire<CorrelatedRewireStrategy>(),
placeholders::_1, gi.GetEdgeIndex(), std::ref(corr),
self_loops, parallel_edges,
pin, self_loops, parallel_edges,
make_pair(niter, no_sweep),
std::make_tuple(persist, cache, verbose),
std::ref(pcount), std::ref(rng)))();
......@@ -170,7 +180,7 @@ size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
run_action<graph_tool::detail::never_reversed>()
(gi, std::bind(graph_rewire_correlated(),
placeholders::_1, gi.GetEdgeIndex(), std::ref(corr),
self_loops, parallel_edges,
pin, self_loops, parallel_edges,
make_pair(niter, no_sweep),
std::make_tuple(persist, cache, verbose),
std::ref(pcount), std::ref(rng),
......@@ -183,7 +193,7 @@ size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
run_action<>()
(gi, std::bind(graph_rewire<ProbabilisticRewireStrategy>(),
placeholders::_1, gi.GetEdgeIndex(), std::ref(corr),
self_loops, parallel_edges,
pin, self_loops, parallel_edges,
make_pair(niter, no_sweep),
std::make_tuple(persist, cache, verbose),
std::ref(pcount), std::ref(rng)))();
......@@ -193,7 +203,7 @@ size_t random_rewire(GraphInterface& gi, string strat, size_t niter,
run_action<>()
(gi, std::bind(graph_rewire_block(alias, traditional),
placeholders::_1, gi.GetEdgeIndex(),
std::ref(corr),
std::ref(corr), pin,
make_pair(self_loops, parallel_edges),
placeholders::_2,
make_pair(niter, no_sweep),
......
......@@ -288,9 +288,9 @@ struct graph_rewire
{
template <class Graph, class EdgeIndexMap, class CorrProb,
class BlockDeg>
class BlockDeg, class PinMap>
void operator()(Graph& g, EdgeIndexMap edge_index, CorrProb corr_prob,
bool self_loops, bool parallel_edges,
PinMap pin, bool self_loops, bool parallel_edges,
pair<size_t, bool> iter_sweep,
std::tuple<bool, bool, bool> cache_verbose,
size_t& pcount, rng_t& rng, BlockDeg bd)
......@@ -306,6 +306,8 @@ struct graph_rewire
typename graph_traits<Graph>::edge_iterator e, e_end;
for (tie(e, e_end) = boost::edges(g); e != e_end; ++e)
{
if (pin[*e])
continue;
edges.push_back(*e);
edge_pos.push_back(edge_pos.size());
}
......@@ -357,15 +359,15 @@ struct graph_rewire
cout << endl;
}
template <class Graph, class EdgeIndexMap, class CorrProb>
template <class Graph, class EdgeIndexMap, class CorrProb, class PinMap>
void operator()(Graph& g, EdgeIndexMap edge_index, CorrProb corr_prob,
bool self_loops, bool parallel_edges,
PinMap pin, bool self_loops, bool parallel_edges,
pair<size_t, bool> iter_sweep,
std::tuple<bool, bool, bool> cache_verbose,
size_t& pcount, rng_t& rng)
const
{
operator()(g, edge_index, corr_prob, self_loops, parallel_edges,
operator()(g, edge_index, corr_prob, pin, self_loops, parallel_edges,
iter_sweep, cache_verbose, pcount, rng, DegreeBlock());
}
};
......
......@@ -432,7 +432,7 @@ def random_graph(N, deg_sampler, directed=True,
def random_rewire(g, model="uncorrelated", n_iter=1, edge_sweep=True,
parallel_edges=False, self_loops=False, vertex_corr=None,
block_membership=None, alias=True, cache_probs=True,
persist=False, ret_fail=False, verbose=False):
persist=False, pin=None, ret_fail=False, verbose=False):
r"""
Shuffle the graph in-place, following a variety of possible statistical
......@@ -544,6 +544,10 @@ def random_rewire(g, model="uncorrelated", n_iter=1, edge_sweep=True,
some probabilistic models, and should be sufficiently fast for sparse
graphs, but otherwise it may result in many repeated attempts for
certain corner-cases in which edges are difficult to swap.
pin : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
Edge property map which, if provided, specifies which edges are allowed
to be rewired. Edges for which the property value is ``1`` (or ``True``)
will be left unmodified in the graph.
verbose : bool (optional, default: ``False``)
If ``True``, verbose information is displayed.
......@@ -807,11 +811,19 @@ def random_rewire(g, model="uncorrelated", n_iter=1, edge_sweep=True,
model = "blockmodel"
traditional = True
if pin is None:
pin = g.new_edge_property("bool")
if pin.value_type() != "bool":
pin = pin.copy(value_type="bool")
pcount = libgraph_tool_generation.random_rewire(g._Graph__graph, model,
n_iter, not edge_sweep,
self_loops, parallel_edges,
alias, traditional, persist,
corr, _prop("v", g, block_membership),
corr,
_prop("e", g, pin),
_prop("v", g, block_membership),
cache_probs,
_get_rng(), verbose)
return pcount
......
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