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 cd186a61 authored by Tiago Peixoto's avatar Tiago Peixoto

inference: Refactor multicanonical_sweep based on mcmc_loop.hh

parent 87abb56d
......@@ -29,6 +29,7 @@ libgraph_tool_inference_la_SOURCES = \
graph_blockmodel_layers_mcmc.cc \
graph_blockmodel_layers_merge.cc \
graph_blockmodel_layers_multicanonical.cc \
graph_blockmodel_layers_multicanonical_multiflip.cc \
graph_blockmodel_layers_multiflip_mcmc.cc \
graph_blockmodel_layers_overlap.cc \
graph_blockmodel_layers_overlap_exhaustive.cc \
......@@ -37,10 +38,12 @@ libgraph_tool_inference_la_SOURCES = \
graph_blockmodel_layers_overlap_multiflip_mcmc.cc \
graph_blockmodel_layers_overlap_gibbs.cc \
graph_blockmodel_layers_overlap_multicanonical.cc \
graph_blockmodel_layers_overlap_multicanonical_multiflip.cc \
graph_blockmodel_layers_overlap_vacate.cc \
graph_blockmodel_marginals.cc \
graph_blockmodel_mcmc.cc \
graph_blockmodel_multicanonical.cc \
graph_blockmodel_multicanonical_multiflip.cc \
graph_blockmodel_multiflip_mcmc.cc \
graph_blockmodel_merge.cc \
graph_blockmodel_overlap.cc \
......@@ -49,6 +52,7 @@ libgraph_tool_inference_la_SOURCES = \
graph_blockmodel_overlap_mcmc.cc \
graph_blockmodel_overlap_mcmc_bundled.cc \
graph_blockmodel_overlap_multicanonical.cc \
graph_blockmodel_overlap_multicanonical_multiflip.cc \
graph_blockmodel_overlap_multiflip_mcmc.cc \
graph_blockmodel_overlap_vacate.cc \
graph_modularity.cc \
......@@ -81,7 +85,6 @@ libgraph_tool_inference_la_include_HEADERS = \
graph_state.hh \
mcmc_loop.hh \
merge_loop.hh \
multicanonical_loop.hh \
parallel_rng.hh \
int_part.hh \
util.hh
......@@ -24,18 +24,24 @@
#include "graph_blockmodel.hh"
#define BASE_STATE_params BLOCK_STATE_params
#include "graph_blockmodel_layers.hh"
#include "graph_blockmodel_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "multicanonical_loop.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(block_state, BlockState, BLOCK_STATE_params)
template <class BaseState>
GEN_DISPATCH(layered_block_state, Layers<BaseState>::template LayeredBlockState,
LAYERED_BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
......@@ -58,13 +64,22 @@ python::object multicanonical_layered_sweep(python::object omulticanonical_state
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
multicanonical_block_state<layered_state_t>::make_dispatch
mcmc_block_state<layered_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& s)
[&](auto& mcmc_state)
{
auto ret_ = multicanonical_sweep(s, rng);
ret = python::make_tuple(ret_.first, ret_.second,
s._f, s._time, s._refine);
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
},
false);
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2017 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_tool.hh"
#include "random.hh"
#include <boost/python.hpp>
#include "graph_blockmodel_util.hh"
#include "graph_blockmodel.hh"
#define BASE_STATE_params BLOCK_STATE_params
#include "graph_blockmodel_layers.hh"
#include "graph_blockmodel_multiflip_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(block_state, BlockState, BLOCK_STATE_params)
template <class BaseState>
GEN_DISPATCH(layered_block_state, Layers<BaseState>::template LayeredBlockState,
LAYERED_BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
MULTICANONICAL_BLOCK_STATE_params(State))
python::object multicanonical_layered_multiflip_sweep(python::object omulticanonical_state,
python::object olayered_state,
rng_t& rng)
{
python::object ret;
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(olayered_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
mcmc_block_state<layered_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mcmc_state)
{
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
},
false);
};
block_state::dispatch(dispatch);
return ret;
}
void export_layered_blockmodel_multicanonical_multiflip()
{
using namespace boost::python;
def("multicanonical_layered_multiflip_sweep", &multicanonical_layered_multiflip_sweep);
}
......@@ -24,8 +24,9 @@
#include "graph_blockmodel_overlap.hh"
#define BASE_STATE_params OVERLAP_BLOCK_STATE_params ((eweight,,,0))
#include "graph_blockmodel_layers.hh"
#include "graph_blockmodel_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "multicanonical_loop.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
......@@ -36,6 +37,10 @@ template <class BaseState>
GEN_DISPATCH(layered_block_state, Layers<BaseState>::template LayeredBlockState,
LAYERED_BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
......@@ -59,13 +64,22 @@ multicanonical_layered_overlap_sweep(python::object omulticanonical_state,
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
multicanonical_block_state<layered_state_t>::make_dispatch
mcmc_block_state<layered_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& s)
[&](auto& mcmc_state)
{
auto ret_ = multicanonical_sweep(s, rng);
ret = python::make_tuple(ret_.first, ret_.second,
s._f, s._time, s._refine);
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
},
false);
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2017 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_tool.hh"
#include "random.hh"
#include <boost/python.hpp>
#include "graph_blockmodel_overlap_util.hh"
#include "graph_blockmodel_overlap.hh"
#define BASE_STATE_params OVERLAP_BLOCK_STATE_params ((eweight,,,0))
#include "graph_blockmodel_layers.hh"
#include "graph_blockmodel_multiflip_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(overlap_block_state, OverlapBlockState, OVERLAP_BLOCK_STATE_params)
template <class BaseState>
GEN_DISPATCH(layered_block_state, Layers<BaseState>::template LayeredBlockState,
LAYERED_BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
MULTICANONICAL_BLOCK_STATE_params(State))
python::object
multicanonical_layered_overlap_multiflip_sweep(python::object omulticanonical_state,
python::object olayered_state,
rng_t& rng)
{
python::object ret;
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(olayered_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
mcmc_block_state<layered_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mcmc_state)
{
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
},
false);
};
overlap_block_state::dispatch(dispatch);
return ret;
}
void export_layered_overlap_blockmodel_multicanonical_multiflip()
{
using namespace boost::python;
def("multicanonical_layered_overlap_multiflip_sweep",
&multicanonical_layered_overlap_multiflip_sweep);
}
......@@ -133,6 +133,35 @@ struct MCMC
{
_state.move_vertex(v, nr);
}
bool is_deterministic()
{
return _deterministic;
}
bool is_sequential()
{
return _sequential;
}
auto& get_vlist()
{
return _vlist;
}
double get_beta()
{
return _beta;
}
size_t get_niter()
{
return _niter;
}
void step(size_t, size_t)
{
}
};
};
......
......@@ -22,14 +22,19 @@
#include "graph_blockmodel_util.hh"
#include "graph_blockmodel.hh"
#include "graph_blockmodel_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "multicanonical_loop.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(block_state, BlockState, BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
......@@ -45,14 +50,23 @@ python::object do_multicanonical_sweep(python::object omulticanonical_state,
typedef typename std::remove_reference<decltype(block_state)>::type
state_t;
multicanonical_block_state<state_t>::make_dispatch
(omulticanonical_state,
[&](auto& s)
{
auto ret_ = multicanonical_sweep(s, rng);
ret = python::make_tuple(ret_.first, ret_.second, s._f,
s._time);
});
mcmc_block_state<state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mcmc_state)
{
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
};
block_state::dispatch(oblock_state, dispatch);
return ret;
......
......@@ -40,18 +40,9 @@ using namespace std;
((S_min, , double, 0)) \
((S_max, , double, 0)) \
((f, , double, 0)) \
((time, , double, 0)) \
((refine, , bool, 0)) \
((S, , double, 0)) \
((E,, size_t, 0)) \
((vlist,&, std::vector<size_t>&, 0)) \
((c,, double, 0)) \
((d,, double, 0)) \
((entropy_args,, entropy_args_t, 0)) \
((allow_vacate,, bool, 0)) \
((verbose,, bool, 0)) \
((target_bin,, int, 0)) \
((niter,, size_t, 0))
((verbose,, bool, 0))
template <class State>
......@@ -74,15 +65,12 @@ struct Multicanonical
sizeof...(Ts)>* = nullptr>
MulticanonicalBlockState(ATs&&... as)
: MulticanonicalBlockStateBase<Ts...>(as...),
_g(_state._g)
_i(get_bin(_S))
{
_state.init_mcmc(_c,
(_entropy_args.partition_dl ||
_entropy_args.degree_dl ||
_entropy_args.edges_dl));
}
typename state_t::g_t& _g;
int _i;
double _dS;
int get_bin(double S)
{
......@@ -90,9 +78,14 @@ struct Multicanonical
((S - _S_min) / (_S_max - _S_min)));
};
bool skip_node(size_t v)
{
return _state.skip_node(v);
}
size_t node_state(size_t v)
{
return _state._b[v];
return _state.node_state(v);
}
size_t node_weight(size_t v)
......@@ -103,33 +96,62 @@ struct Multicanonical
template <class RNG>
size_t move_proposal(size_t v, RNG& rng)
{
auto r = _state._b[v];
return _state.move_proposal(v, rng);
}
size_t s = _state.sample_block(v, _c, _d, rng);
auto virtual_move_dS(size_t v, size_t nr)
{
auto dS = _state.virtual_move_dS(v, nr);
double nS = _S + get<0>(dS);
if (nS < _S_min || nS >= _S_max)
{
get<0>(dS) = numeric_limits<double>::infinity();
}
else
{
int j = get_bin(nS);
get<1>(dS) += _dens[_i] - _dens[j];
}
_dS = get<0>(dS);
return dS;
}
void perform_move(size_t v, size_t nr)
{
_state.perform_move(v, nr);
_S += _dS;
_i = get_bin(_S);
}
if (!_state.allow_move(r, s))
return r;
bool is_deterministic()
{
return _state.is_deterministic();
}
if (!_allow_vacate && _state.virtual_remove_size(v) == 0)
return r;
bool is_sequential()
{
return _state.is_sequential();
}
return s;
auto& get_vlist()
{
return _state.get_vlist();
}
std::pair<double, double> virtual_move_dS(size_t v, size_t nr)
double get_beta()
{
double dS = _state.virtual_move(v, _state._b[v], nr, _entropy_args);
return 1;
}
size_t r = _state._b[v];
double pf = _state.get_move_prob(v, r, nr, _c, _d, false);
double pb = _state.get_move_prob(v, nr, r, _c, _d, true);
double a = log(pb) - log(pf);
return make_pair(dS, a);
size_t get_niter()
{
return _state.get_niter();
}
void perform_move(size_t v, size_t nr)
void step(size_t, size_t)
{
_state.move_vertex(v, nr);
_hist[_i]++;
_dens[_i] += _f;
}
};
};
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2017 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_tool.hh"
#include "random.hh"
#include <boost/python.hpp>
#include "graph_blockmodel_util.hh"
#include "graph_blockmodel.hh"
#include "graph_blockmodel_multiflip_mcmc.hh"
#include "graph_blockmodel_multicanonical.hh"
#include "mcmc_loop.hh"
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(block_state, BlockState, BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(mcmc_block_state, MCMC<State>::template MCMCBlockState,
MCMC_BLOCK_STATE_params(State))
template <class State>
GEN_DISPATCH(multicanonical_block_state,
Multicanonical<State>::template MulticanonicalBlockState,
MULTICANONICAL_BLOCK_STATE_params(State))
python::object do_multicanonical_multiflip_sweep(python::object omulticanonical_state,
python::object oblock_state,
rng_t& rng)
{
python::object ret;
auto dispatch = [&](auto& block_state)
{
typedef typename std::remove_reference<decltype(block_state)>::type
state_t;
mcmc_block_state<state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mcmc_state)
{
typedef typename std::remove_reference<decltype(mcmc_state)>::type
mcmc_state_t;
omulticanonical_state.attr("state") = boost::any(mcmc_state);
multicanonical_block_state<mcmc_state_t>::make_dispatch
(omulticanonical_state,
[&](auto& mc_state)
{
auto ret_ = mcmc_sweep(mc_state, rng);
ret = python::make_tuple(ret_.first, ret_.second);
});
});
};
block_state::dispatch(oblock_state, dispatch);
return ret;
}
void export_blockmodel_multicanonical_multiflip()
{
using namespace boost::python;
def("multicanonical_multiflip_sweep", &do_multicanonical_multiflip_sweep);
}
......@@ -256,6 +256,35 @@ struct MCMC
if (_state._wr[r] == 0)
remove_element(_vlist, _rpos, r);
}
bool is_deterministic()
{
return _deterministic;
}
bool is_sequential()
{
return _sequential;
}
auto& get_vlist()
{
return _vlist;
}
double get_beta()
{
return _beta;
}
size_t get_niter()
{
return _niter;
}
void step(size_t, size_t)
{
}
};
};
......
......@@ -176,6 +176,36 @@ struct MCMC
for (auto v : _bundles[i])
_state.move_vertex(v, nr);
}
bool is_deterministic()
{
return _deterministic;
}
bool is_sequential()
{
return _sequential;