Commit 28610ba6 authored by Tiago Peixoto's avatar Tiago Peixoto

Remove redundant random_move parameter from mcmc_sweep() and related functions

To specify fully random moves, one should set the parameter "c" to
"float(inf)", as explained in the docstring.
parent 0abe5a7c
......@@ -709,10 +709,8 @@ struct build_egroups
VEprop etgtpos, Eprop eweight, Graph& g,
VertexIndex vertex_index, bool weighted, bool empty) const
{
if (empty)
return;
egroups_manage::build(b, oegroups, esrcpos, etgtpos, eweight, g,
vertex_index, weighted);
vertex_index, weighted, empty);
}
};
......
......@@ -995,7 +995,7 @@ struct egroups_manage
template <class Eprop, class Vprop, class VEprop, class Graph, class VertexIndex>
static void build(Vprop b, boost::any& oegroups, VEprop esrcpos,
VEprop etgtpos, Eprop eweight, Graph& g,
VertexIndex vertex_index, bool weighted)
VertexIndex vertex_index, bool weighted, bool empty)
{
if (weighted)
{
......@@ -1004,6 +1004,8 @@ struct egroups_manage
VertexIndex>::type vemap_t;
vemap_t egroups_checked(vertex_index);
oegroups = egroups_checked;
if (empty)
return;
build_dispatch(b, egroups_checked.get_unchecked(num_vertices(g)),
esrcpos, etgtpos, eweight, g, vertex_index,
mpl::true_());
......@@ -1015,6 +1017,8 @@ struct egroups_manage
VertexIndex>::type vemap_t;
vemap_t egroups_checked(vertex_index);
oegroups = egroups_checked;
if (empty)
return;
build_dispatch(b, egroups_checked.get_unchecked(num_vertices(g)),
esrcpos, etgtpos, eweight, g, vertex_index,
mpl::true_());
......
......@@ -715,9 +715,8 @@ def get_akc(B, I, N=float("inf"), directed=False):
ak /= 2
return ak
def mcmc_sweep(state, beta=1., random_move=False, c=1., dense=False,
multigraph=False, sequential=True, vertices=None,
verbose=False):
def mcmc_sweep(state, beta=1., c=1., dense=False, multigraph=False,
sequential=True, vertices=None, verbose=False):
r"""Performs a Markov chain Monte Carlo sweep on the network, to sample the block partition according to a probability :math:`\propto e^{-\beta \mathcal{S}_{t/c}}`, where :math:`\mathcal{S}_{t/c}` is the blockmodel entropy.
Parameters
......@@ -726,11 +725,6 @@ def mcmc_sweep(state, beta=1., random_move=False, c=1., dense=False,
The block state.
beta : ``float`` (optional, default: `1.0`)
The inverse temperature parameter :math:`\beta`.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``1.0``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -867,6 +861,8 @@ def mcmc_sweep(state, beta=1., random_move=False, c=1., dense=False,
vertices.a = state.g.vertex_index.copy("int").fa
state.sweep_vertices = vertices
random_move = c == float("inf")
if random_move:
state._BlockState__build_egroups(empty=True)
elif state.egroups is None:
......@@ -985,8 +981,8 @@ def greedy_shrink(state, B, nsweeps=10, adaptive_sweeps=True, nmerge_sweeps=None
adaptive_sweeps=adaptive_sweeps,
epsilon=epsilon, r=r, greedy=greedy,
anneal=anneal, c=c, dense=dense,
multigraph=multigraph, random_move=random_move,
sequential=sequential, verbose=verbose)
multigraph=multigraph, sequential=sequential,
verbose=verbose)
bm = bg_state.b
libcommunity.vector_map(state.b.a, bm.a)
......@@ -1013,9 +1009,8 @@ class MinimizeState(object):
def multilevel_minimize(state, B, nsweeps=10, adaptive_sweeps=True, epsilon=0,
anneal=(1., 1.), r=2., nmerge_sweeps=10, greedy=True,
random_move=False, c=1., dense=False, multigraph=False,
sequential=True, checkpoint=None,
minimize_state=None, verbose=False):
c=1., dense=False, multigraph=False, sequential=True,
checkpoint=None, minimize_state=None, verbose=False):
r"""Performs an agglomerative heuristic, which progressively merges blocks together (while allowing individual node moves) to achieve a good partition in ``B`` blocks.
Parameters
......@@ -1049,11 +1044,6 @@ def multilevel_minimize(state, B, nsweeps=10, adaptive_sweeps=True, epsilon=0,
If ``True``, the value of ``beta`` of the MCMC steps are kept at
infinity for all steps. Otherwise they change according to the ``anneal``
parameter.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``1.0``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -1220,8 +1210,7 @@ def multilevel_minimize(state, B, nsweeps=10, adaptive_sweeps=True, epsilon=0,
beta = float("inf")
delta, nmoves = mcmc_sweep(state, beta=beta, c=c,
dense=dense, multigraph=multigraph,
sequential=sequential,
random_move=random_move)
sequential=sequential)
S += delta
niter += 1
checkpoint_state[Bi]["S"] = S
......@@ -1268,8 +1257,7 @@ def multilevel_minimize(state, B, nsweeps=10, adaptive_sweeps=True, epsilon=0,
delta, nmoves = mcmc_sweep(state, beta=beta, c=c,
dense=dense, multigraph=multigraph,
sequential=sequential,
random_move=random_move)
sequential=sequential)
S += delta
niter += 1
total_nmoves += nmoves
......@@ -1313,8 +1301,7 @@ def multilevel_minimize(state, B, nsweeps=10, adaptive_sweeps=True, epsilon=0,
while count <= nsweeps:
delta, nmoves = mcmc_sweep(state, beta=float("inf"), c=c,
dense=dense, multigraph=multigraph,
sequential=sequential,
random_move=random_move)
sequential=sequential)
S += delta
niter += 1
total_nmoves += nmoves
......@@ -1368,7 +1355,7 @@ def get_state_dl(state, dense, nested_dl, clabel=None):
return dl
def get_b_dl(g, vweight, eweight, B, nsweeps, adaptive_sweeps, c, random_move,
def get_b_dl(g, vweight, eweight, B, nsweeps, adaptive_sweeps, c,
sequential, shrink, r, anneal, greedy, epsilon, nmerge_sweeps, clabel,
deg_corr, dense, sparse_heuristic, checkpoint, minimize_state,
max_BE, nested_dl, verbose):
......@@ -1428,8 +1415,7 @@ def get_b_dl(g, vweight, eweight, B, nsweeps, adaptive_sweeps, c, random_move,
adaptive_sweeps=adaptive_sweeps,
epsilon=epsilon, r=r, greedy=greedy,
nmerge_sweeps=nmerge_sweeps, anneal=anneal,
c=c, random_move=random_move,
dense=dense and not sparse_heuristic,
c=c, dense=dense and not sparse_heuristic,
multigraph=dense,
sequential=sequential,
minimize_state=minimize_state,
......@@ -1468,7 +1454,7 @@ def is_fibo(x):
return fibo(fibo_n_floor(x)) == x
def minimize_blockmodel_dl(g, eweight=None, vweight=None, deg_corr=True, dense=False,
sparse_heuristic=False, random_move=False, c=0, nsweeps=100,
sparse_heuristic=False, c=0, nsweeps=100,
adaptive_sweeps=True, epsilon=0., anneal=(1., 1.),
greedy_cooling=True, sequential=True, r=2,
nmerge_sweeps=10, max_B=None, min_B=1, mid_B=None,
......@@ -1496,11 +1482,6 @@ def minimize_blockmodel_dl(g, eweight=None, vweight=None, deg_corr=True, dense=F
If ``True``, the sparse entropy will be used to find the best partition,
but the dense entropy will be used to compare different partitions. This
has an effect only if ``dense == True``.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``1.0``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -1716,7 +1697,6 @@ def minimize_blockmodel_dl(g, eweight=None, vweight=None, deg_corr=True, dense=F
anneal=anneal, c=c,
dense=dense and not sparse_heuristic,
multigraph=dense,
random_move=random_move,
sequential=sequential,
nmerge_sweeps=nmerge_sweeps,
epsilon=epsilon,
......@@ -1746,7 +1726,7 @@ def minimize_blockmodel_dl(g, eweight=None, vweight=None, deg_corr=True, dense=F
args = dict(g=g, vweight=vweight, eweight=eweight, nsweeps=nsweeps,
adaptive_sweeps=adaptive_sweeps, c=c, random_move=random_move,
adaptive_sweeps=adaptive_sweeps, c=c,
sequential=sequential, shrink=shrink, r=r, anneal=anneal,
greedy=greedy, epsilon=epsilon, nmerge_sweeps=nmerge_sweeps,
clabel=clabel, deg_corr=deg_corr, dense=dense,
......
......@@ -265,8 +265,7 @@ class NestedBlockState(object):
return b
def nested_mcmc_sweep(state, beta=1., random_move=False, c=1., sequential=True,
verbose=False):
def nested_mcmc_sweep(state, beta=1., c=1., sequential=True, verbose=False):
r"""Performs a Markov chain Monte Carlo sweep on all levels of the hierarchy.
Parameters
......@@ -275,11 +274,6 @@ def nested_mcmc_sweep(state, beta=1., random_move=False, c=1., sequential=True,
The nested block state.
beta : `float` (optional, default: `1.0`)
The inverse temperature parameter :math:`\beta`.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``1.0``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -341,8 +335,7 @@ def nested_mcmc_sweep(state, beta=1., random_move=False, c=1., sequential=True,
print("Level:", l, "N:", bstate.N, "B:", bstate.B)
ret = mcmc_sweep(bstate, beta=beta, c=c, dense = l > 0,
multigraph = l > 0,
sequential=sequential,
random_move=random_move, verbose=verbose)
sequential=sequential, verbose=verbose)
if l + 1 < len(state.levels):
state._NestedBlockState__rebuild_level(l + 1)
rets.append(ret)
......@@ -350,9 +343,9 @@ def nested_mcmc_sweep(state, beta=1., random_move=False, c=1., sequential=True,
def replace_level(l, state, nsweeps=10, nmerge_sweeps=10, r=2,
c=0, epsilon=0., sequential=True, random_move=False,
dense=False, sparse_thresh=100, verbose=False,
checkpoint=None, minimize_state=None):
c=0, epsilon=0., sequential=True, dense=False,
sparse_thresh=100, verbose=False, checkpoint=None,
minimize_state=None):
bstate = state.levels[l]
g = bstate.g
......@@ -376,7 +369,7 @@ def replace_level(l, state, nsweeps=10, nmerge_sweeps=10, r=2,
res = minimize_blockmodel_dl(g, eweight=bstate.eweight,
deg_corr=bstate.deg_corr, nsweeps=nsweeps,
c=c, random_move=random_move,
c=c,
sequential=sequential,
r=r,
adaptive_sweeps=True, greedy_cooling=True,
......@@ -477,8 +470,7 @@ class NestedMinimizeState(object):
self.minimize_state = MinimizeState()
def nested_tree_sweep(state, nsweeps=10, epsilon=0., r=2.,
nmerge_sweeps=10, random_move=False,
c=0, dense=False, sequential=True,
nmerge_sweeps=10, c=0, dense=False, sequential=True,
sparse_thresh=100, checkpoint=None,
minimize_state=None, verbose=False):
r"""Performs one greedy sweep in the entire hierarchy tree, attempting to
......@@ -500,11 +492,6 @@ def nested_tree_sweep(state, nsweeps=10, epsilon=0., r=2.,
nmerge_sweeps : `int` (optional, default: `10`)
The number of merge sweeps done, where in each sweep a better merge
candidate is searched for every block.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``1.0``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -584,7 +571,7 @@ def nested_tree_sweep(state, nsweeps=10, epsilon=0., r=2.,
mstate.sync(state)
args = dict(state=state, nsweeps=nsweeps, nmerge_sweeps=nmerge_sweeps, r=r,
c=c, epsilon=epsilon, sequential=sequential, random_move=random_move,
c=c, epsilon=epsilon, sequential=sequential,
dense=dense, sparse_thresh=sparse_thresh,
checkpoint=checkpoint, minimize_state=minimize_state)
......@@ -703,7 +690,7 @@ def nested_tree_sweep(state, nsweeps=10, epsilon=0., r=2.,
def init_nested_state(g, Bs, deg_corr=True, dense=False,
eweight=None, vweight=None,
nsweeps=10, epsilon=0., r=2,
nmerge_sweeps=10, random_move=False,
nmerge_sweeps=10,
c=0, sequential=True,
sparse_thresh=100, checkpoint=None,
minimize_state=None, max_BE=1000,
......@@ -737,11 +724,6 @@ def init_nested_state(g, Bs, deg_corr=True, dense=False,
nmerge_sweeps : `int` (optional, default: `10`)
The number of merge sweeps done, where in each sweep a better merge
candidate is searched for every block.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``0.``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......@@ -847,7 +829,6 @@ def init_nested_state(g, Bs, deg_corr=True, dense=False,
greedy=True, c=c,
dense=(l > 0 and g.num_vertices() < sparse_thresh) or dense,
multigraph=l > 0 or dense,
random_move=random_move,
sequential=sequential, verbose=verbose,
checkpoint=chkp,
minimize_state=minimize_state.minimize_state)
......@@ -868,7 +849,7 @@ def init_nested_state(g, Bs, deg_corr=True, dense=False,
def minimize_nested_blockmodel_dl(g, Bs=None, bs=None, deg_corr=True,
dense=False, eweight=None, vweight=None,
nsweeps=10, epsilon=0., random_move=False, c=0,
nsweeps=10, epsilon=0., c=0,
nmerge_sweeps=10, r=2, sparse_thresh=100,
sequential=True, verbose=False,
checkpoint=None, minimize_state=None):
......@@ -900,11 +881,6 @@ def minimize_nested_blockmodel_dl(g, Bs=None, bs=None, deg_corr=True,
The number of sweeps necessary for the local minimum will
be estimated to be enough so that no more than ``epsilon * N`` nodes
changes their states in the last ``nsweeps`` sweeps.
random_move : ``bool`` (optional, default: ``False``)
If ``True``, the proposed moves will attempt to place the vertices in
fully randomly-chosen blocks. If ``False``, the proposed moves will be
chosen with a probability depending on the membership of the neighbours
and the currently-inferred block structure.
c : ``float`` (optional, default: ``0.``)
This parameter specifies how often fully random moves are attempted,
instead of more likely moves based on the inferred block partition.
......
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