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

Implement BlockState.exhaustive_sweep()

parent 30e6b8a0
......@@ -18,13 +18,16 @@ libgraph_tool_inference_la_SOURCES = \
cache.cc \
graph_blockmodel.cc \
graph_blockmodel_em.cc \
graph_blockmodel_exhaustive.cc \
graph_blockmodel_gibbs.cc \
graph_blockmodel_layers.cc \
graph_blockmodel_layers_exhaustive.cc \
graph_blockmodel_layers_gibbs.cc \
graph_blockmodel_layers_mcmc.cc \
graph_blockmodel_layers_merge.cc \
graph_blockmodel_layers_multicanonical.cc \
graph_blockmodel_layers_overlap.cc \
graph_blockmodel_layers_overlap_exhaustive.cc \
graph_blockmodel_layers_overlap_mcmc.cc \
graph_blockmodel_layers_overlap_mcmc_bundled.cc \
graph_blockmodel_layers_overlap_gibbs.cc \
......@@ -34,6 +37,7 @@ libgraph_tool_inference_la_SOURCES = \
graph_blockmodel_multicanonical.cc \
graph_blockmodel_merge.cc \
graph_blockmodel_overlap.cc \
graph_blockmodel_overlap_exhaustive.cc \
graph_blockmodel_overlap_gibbs.cc \
graph_blockmodel_overlap_mcmc.cc \
graph_blockmodel_overlap_mcmc_bundled.cc \
......@@ -45,9 +49,11 @@ libgraph_tool_inference_la_SOURCES = \
libgraph_tool_inference_la_include_HEADERS = \
bundled_vacate_loop.hh \
cache.hh \
exhaustive_loop.hh \
gibbs_loop.hh \
graph_blockmodel.hh \
graph_blockmodel_em.hh \
graph_blockmodel_exhaustive.hh \
graph_blockmodel_gibbs.hh \
graph_blockmodel_layers.hh \
graph_blockmodel_layers_util.hh \
......
// 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 EXHAUSTIVE_LOOP_HH
#define EXHAUSTIVE_LOOP_HH
#include "config.h"
namespace graph_tool
{
template <class ExhaustiveState, class Callback>
void exhaustive_sweep(ExhaustiveState& state, Callback&& callback)
{
auto& vlist = state._vlist;
double& S = state._S;
double& S_min = state._S_min;
size_t pos = 0;
size_t B = state.get_B();
size_t count = 0;
callback(state);
while (pos < vlist.size())
{
auto v = vlist[pos];
size_t r = state.node_state(v);
if (r < B - 1)
{
S += state.virtual_move_dS(pos, r + 1);
state.perform_move(pos, r + 1);
if (S < S_min)
{
S_min = S;
parallel_vertex_loop
(state._g,
[&](auto v){ state._b_min[v] = state.node_state(v); });
}
pos = 0;
callback(state);
count++;
if (count == state._max_iter)
break;
}
else
{
S += state.virtual_move_dS(pos, 0);
state.perform_move(pos, 0);
pos++;
}
}
}
} // graph_tool namespace
#endif //EXHAUSTIVE_LOOP_HH
// 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_tool.hh"
#include "random.hh"
#include <boost/python.hpp>
#include "graph_blockmodel_util.hh"
#include "graph_blockmodel.hh"
#include "graph_blockmodel_exhaustive.hh"
#include "exhaustive_loop.hh"
#include "numpy_bind.hh"
#ifdef HAVE_BOOST_COROUTINE
#include "graph_python_interface.hh"
#include <boost/coroutine/all.hpp>
#endif // HAVE_BOOST_COROUTINE
using namespace boost;
using namespace graph_tool;
GEN_DISPATCH(block_state, BlockState, BLOCK_STATE_params)
template <class State>
GEN_DISPATCH(exhaustive_block_state,
Exhaustive<State>::template ExhaustiveBlockState,
EXHAUSTIVE_BLOCK_STATE_params(State))
void do_exhaustive_sweep(python::object oexhaustive_state,
python::object oblock_state,
python::object callback)
{
auto dispatch = [&](auto& block_state)
{
typedef typename std::remove_reference<decltype(block_state)>::type
state_t;
exhaustive_block_state<state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
callback(state._S,
state._S_min);
});
});
};
block_state::dispatch(oblock_state, dispatch);
}
python::object do_exhaustive_sweep_iter(python::object oexhaustive_state,
python::object oblock_state)
{
#ifdef HAVE_BOOST_COROUTINE
auto coro_dispatch = [&](auto& yield)
{
auto dispatch = [&](auto& block_state)
{
typedef typename std::remove_reference<decltype(block_state)>::type
state_t;
exhaustive_block_state<state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep
(s,
[&](auto& state)
{
yield(python::make_tuple(state._S,
state._S_min));
});
});
};
block_state::dispatch(oblock_state, dispatch);
};
return python::object(CoroGenerator(coro_dispatch));
#else
throw GraphException("This functionality is not available because boost::coroutine was not found at compile-time");
#endif // HAVE_BOOST_COROUTINE
}
void do_exhaustive_dens(python::object oexhaustive_state,
python::object oblock_state,
double S_min, double S_max,
python::object ohist)
{
multi_array_ref<uint64_t, 1> hist = get_array<uint64_t, 1>(ohist);
int N = hist.shape()[0];
double dS = S_max - S_min;
auto dispatch = [&](auto& block_state)
{
typedef typename std::remove_reference<decltype(block_state)>::type
state_t;
exhaustive_block_state<state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
auto S = state._S;
int i = round((N - 1) * (S - S_min) / dS);
if (i >= 0 && i < N)
hist[i]++;
});
});
};
block_state::dispatch(oblock_state, dispatch);
}
void export_blockmodel_exhaustive()
{
using namespace boost::python;
def("exhaustive_sweep", &do_exhaustive_sweep);
def("exhaustive_sweep_iter", &do_exhaustive_sweep_iter);
def("exhaustive_dens", &do_exhaustive_dens);
}
// 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_BLOCKMODEL_EXHAUSTIVE_HH
#define GRAPH_BLOCKMODEL_EXHAUSTIVE_HH
#include "config.h"
#include <vector>
#include "graph_tool.hh"
#include "graph_state.hh"
#include "graph_blockmodel_util.hh"
#include <boost/mpl/vector.hpp>
namespace graph_tool
{
using namespace boost;
using namespace std;
typedef typename vprop_map_t<int32_t>::type vmap_t;
#define EXHAUSTIVE_BLOCK_STATE_params(State) \
((__class__,&, mpl::vector<python::object>, 1)) \
((state, &, State&, 0)) \
((S, , double, 0)) \
((vlist,&, std::vector<size_t>&, 0)) \
((multigraph,, bool, 0)) \
((dense,, bool, 0)) \
((partition_dl,, bool, 0)) \
((degree_dl,, bool, 0)) \
((edges_dl,, bool, 0)) \
((b_min,, vmap_t, 0)) \
((max_iter,, size_t, 0))
template <class State>
struct Exhaustive
{
GEN_STATE_BASE(ExhaustiveBlockStateBase,
EXHAUSTIVE_BLOCK_STATE_params(State))
template <class... Ts>
class ExhaustiveBlockState
: public ExhaustiveBlockStateBase<Ts...>
{
public:
GET_PARAMS_USING(ExhaustiveBlockStateBase<Ts...>,
EXHAUSTIVE_BLOCK_STATE_params(State))
GET_PARAMS_TYPEDEF(Ts, EXHAUSTIVE_BLOCK_STATE_params(State))
template <class... ATs,
typename std::enable_if_t<sizeof...(ATs) ==
sizeof...(Ts)>* = nullptr>
ExhaustiveBlockState(ATs&&... as)
: ExhaustiveBlockStateBase<Ts...>(as...),
_g(_state._g), _S_min(_S)
{
_state.init_mcmc(numeric_limits<double>::infinity(),
_partition_dl || _degree_dl || _edges_dl);
}
typename State::g_t& _g;
double _S_min;
size_t get_B()
{
return num_vertices(_state._bg);
}
size_t node_state(size_t v)
{
return _state._b[v];
}
double virtual_move_dS(size_t v, size_t nr)
{
return _state.virtual_move(v, nr, _dense, _multigraph,
_partition_dl, _degree_dl,
_edges_dl);
}
void perform_move(size_t v, size_t nr)
{
_state.move_vertex(v, nr);
}
};
};
} // graph_tool namespace
#endif //GRAPH_BLOCKMODEL_EXHAUSTIVE_HH
// 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_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_exhaustive.hh"
#include "exhaustive_loop.hh"
#include "numpy_bind.hh"
#ifdef HAVE_BOOST_COROUTINE
#include "graph_python_interface.hh"
#include <boost/coroutine/all.hpp>
#endif // HAVE_BOOST_COROUTINE
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(exhaustive_layered_block_state,
Exhaustive<State>::template ExhaustiveBlockState,
EXHAUSTIVE_BLOCK_STATE_params(State))
void do_exhaustive_layered_sweep(python::object oexhaustive_state,
python::object oblock_state,
python::object callback)
{
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
callback(state._S,
state._S_min);
});
});
});
};
block_state::dispatch(dispatch);
}
python::object do_exhaustive_layered_sweep_iter(python::object oexhaustive_state,
python::object oblock_state)
{
#ifdef HAVE_BOOST_COROUTINE
auto coro_dispatch = [&](auto& yield)
{
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep
(s,
[&](auto& state)
{
yield(python::make_tuple(state._S,
state._S_min));
});
});
});
};
block_state::dispatch(dispatch);
};
return python::object(CoroGenerator(coro_dispatch));
#else
throw GraphException("This functionality is not available because boost::coroutine was not found at compile-time");
#endif // HAVE_BOOST_COROUTINE
}
void do_exhaustive_layered_dens(python::object oexhaustive_state,
python::object oblock_state,
double S_min, double S_max,
python::object ohist)
{
multi_array_ref<uint64_t, 1> hist = get_array<uint64_t, 1>(ohist);
int N = hist.shape()[0];
double dS = S_max - S_min;
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
auto S = state._S;
int i = round((N - 1) * (S - S_min) / dS);
if (i >= 0 && i < N)
hist[i]++;
});
});
});
};
block_state::dispatch(dispatch);
}
void export_layered_blockmodel_exhaustive()
{
using namespace boost::python;
def("exhaustive_layered_sweep", &do_exhaustive_layered_sweep);
def("exhaustive_layered_sweep_iter", &do_exhaustive_layered_sweep_iter);
def("exhaustive_layered_dens", &do_exhaustive_layered_dens);
}
// 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_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_exhaustive.hh"
#include "exhaustive_loop.hh"
#include "numpy_bind.hh"
#ifdef HAVE_BOOST_COROUTINE
#include "graph_python_interface.hh"
#include <boost/coroutine/all.hpp>
#endif // HAVE_BOOST_COROUTINE
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(exhaustive_layered_block_state,
Exhaustive<State>::template ExhaustiveBlockState,
EXHAUSTIVE_BLOCK_STATE_params(State))
void do_exhaustive_layered_overlap_sweep(python::object oexhaustive_state,
python::object oblock_state,
python::object callback)
{
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
callback(state._S,
state._S_min);
});
});
});
};
overlap_block_state::dispatch(dispatch);
}
python::object do_exhaustive_layered_overlap_sweep_iter(python::object oexhaustive_state,
python::object oblock_state)
{
#ifdef HAVE_BOOST_COROUTINE
auto coro_dispatch = [&](auto& yield)
{
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep
(s,
[&](auto& state)
{
yield(python::make_tuple(state._S,
state._S_min));
});
});
});
};
overlap_block_state::dispatch(dispatch);
};
return python::object(CoroGenerator(coro_dispatch));
#else
throw GraphException("This functionality is not available because boost::coroutine was not found at compile-time");
#endif // HAVE_BOOST_COROUTINE
}
void do_exhaustive_layered_overlap_dens(python::object oexhaustive_state,
python::object oblock_state,
double S_min, double S_max,
python::object ohist)
{
multi_array_ref<uint64_t, 1> hist = get_array<uint64_t, 1>(ohist);
int N = hist.shape()[0];
double dS = S_max - S_min;
auto dispatch = [&](auto* block_state)
{
typedef typename std::remove_pointer<decltype(block_state)>::type
state_t;
layered_block_state<state_t>::dispatch
(oblock_state,
[&](auto& ls)
{
typedef typename std::remove_reference<decltype(ls)>::type
layered_state_t;
exhaustive_layered_block_state<layered_state_t>::make_dispatch
(oexhaustive_state,
[&](auto& s)
{
exhaustive_sweep(s,
[&](auto& state)
{
auto S = state._S;
int i = round((N - 1) * (S - S_min) / dS);
if (i >= 0 && i < N)
hist[i]++;
});
});
});
};
overlap_block_state::dispatch(dispatch);
}
void export_layered_overlap_blockmodel_exhaustive()
{
using namespace boost::python;
def("exhaustive_layered_overlap_sweep", &do_exhaustive_layered_overlap_sweep);
def("exhaustive_layered_overlap_sweep_iter", &do_exhaustive_layered_overlap_sweep_iter);
def("exhaustive_layered_overlap_dens", &do_exhaustive_layered_overlap_dens);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2016 Tiago de Paula Peixoto <tiago@skewed.de>
//
// This progr