Commit f466b829 authored by Tiago Peixoto's avatar Tiago Peixoto

uncertain_blockmodel: Implement latent_edges entropy argument

parent ea5052e7
......@@ -89,14 +89,14 @@ void export_measured_state()
.def("get_M", &state_t::get_M)
.def("get_edge_prob",
+[](state_t& state, size_t u, size_t v,
entropy_args_t ea, double epsilon)
uentropy_args_t ea, double epsilon)
{
return get_edge_prob(state, u, v, ea,
epsilon);
})
.def("get_edges_prob",
+[](state_t& state, python::object edges,
python::object probs, entropy_args_t ea,
python::object probs, uentropy_args_t ea,
double epsilon)
{
get_edges_prob(state, edges, probs, ea,
......
......@@ -24,7 +24,7 @@
#include "../support/graph_state.hh"
#include "../blockmodel/graph_blockmodel_util.hh"
#include "graph_blockmodel_sample_edge.hh"
#include "graph_blockmodel_uncertain.hh"
namespace graph_tool
{
......@@ -207,44 +207,50 @@ struct Measured
return -(Sf - Si);
}
double remove_edge_dS(size_t u, size_t v, entropy_args_t ea)
double remove_edge_dS(size_t u, size_t v, uentropy_args_t ea)
{
auto& e = get_u_edge(u, v);
double dS = _block_state.template modify_edge_dS<false>(source(e, _u),
target(e, _u),
e, _recs, ea);
if (_E_prior)
{
dS += _pe;
dS += lgamma_fast(_E) - lgamma_fast(_E + 1);
}
if (_eweight[e] == 1 && (_self_loops || u != v))
if (ea.latent_edges)
{
auto& m = get_edge<false>(u, v);
int dT = (m == _null_edge) ? _x_default : _x[m];
int dM = (m == _null_edge) ? _n_default : _n[m];
dS += get_dS(-dT, -dM);
if (_E_prior)
{
dS += _pe;
dS += lgamma_fast(_E) - lgamma_fast(_E + 1);
}
if (_eweight[e] == 1 && (_self_loops || u != v))
{
auto& m = get_edge<false>(u, v);
int dT = (m == _null_edge) ? _x_default : _x[m];
int dM = (m == _null_edge) ? _n_default : _n[m];
dS += get_dS(-dT, -dM);
}
}
return dS;
}
double add_edge_dS(size_t u, size_t v, entropy_args_t ea)
double add_edge_dS(size_t u, size_t v, uentropy_args_t ea)
{
auto& e = get_u_edge(u, v);
double dS = _block_state.template modify_edge_dS<true>(u, v, e,
_recs, ea);
if (_E_prior)
{
dS -= _pe;
dS += lgamma_fast(_E + 2) - lgamma_fast(_E + 1);
}
if ((e == _null_edge || _eweight[e] == 0) && (_self_loops || u != v))
if (ea.latent_edges)
{
auto& m = get_edge<false>(u, v);
int dT = (m == _null_edge) ? _x_default : _x[m];
int dM = (m == _null_edge) ? _n_default : _n[m];
dS += get_dS(dT, dM);
if (_E_prior)
{
dS -= _pe;
dS += lgamma_fast(_E + 2) - lgamma_fast(_E + 1);
}
if ((e == _null_edge || _eweight[e] == 0) && (_self_loops || u != v))
{
auto& m = get_edge<false>(u, v);
int dT = (m == _null_edge) ? _x_default : _x[m];
int dM = (m == _null_edge) ? _n_default : _n[m];
dS += get_dS(dT, dM);
}
}
return dS;
}
......
......@@ -61,6 +61,10 @@ void export_uncertain_state()
{
using namespace boost::python;
class_<uentropy_args_t, bases<entropy_args_t>>("uentropy_args",
init<entropy_args_t>())
.def_readwrite("latent_edges", &uentropy_args_t::latent_edges);
def("make_uncertain_state", &make_uncertain_state);
block_state::dispatch
......@@ -85,14 +89,14 @@ void export_uncertain_state()
.def("set_S_const", &state_t::set_S_const)
.def("get_edge_prob",
+[](state_t& state, size_t u, size_t v,
entropy_args_t ea, double epsilon)
uentropy_args_t ea, double epsilon)
{
return get_edge_prob(state, u, v, ea,
epsilon);
})
.def("get_edges_prob",
+[](state_t& state, python::object edges,
python::object probs, entropy_args_t ea,
python::object probs, uentropy_args_t ea,
double epsilon)
{
get_edges_prob(state, edges, probs, ea,
......
......@@ -31,6 +31,15 @@ namespace graph_tool
using namespace boost;
using namespace std;
struct uentropy_args_t:
public entropy_args_t
{
uentropy_args_t(const entropy_args_t& ea)
: entropy_args_t(ea){}
bool latent_edges;
};
#define UNCERTAIN_STATE_params \
((__class__,&, mpl::vector<python::object>, 1)) \
((g, &, all_graph_views, 1)) \
......@@ -166,42 +175,47 @@ struct Uncertain
return -S;
}
double remove_edge_dS(size_t u, size_t v, entropy_args_t ea)
double remove_edge_dS(size_t u, size_t v, uentropy_args_t ea)
{
auto& e = get_u_edge(u, v);
double dS = _block_state.template modify_edge_dS<false>(source(e, _u),
target(e, _u),
e, _recs, ea);
if (_E_prior)
if (ea.latent_edges)
{
dS += _pe;
dS += lgamma_fast(_E) - lgamma_fast(_E + 1);
if (_E_prior)
{
dS += _pe;
dS += lgamma_fast(_E) - lgamma_fast(_E + 1);
}
if (_eweight[e] == 1 && (_self_loops || u != v))
{
auto& m = get_edge<false>(u, v);
double q_e = (m == _null_edge) ? _q_default : _q[m];
dS += q_e;
}
}
if (_eweight[e] == 1 && (_self_loops || u != v))
{
auto& m = get_edge<false>(u, v);
double q_e = (m == _null_edge) ? _q_default : _q[m];
dS += q_e;
}
return dS;
}
double add_edge_dS(size_t u, size_t v, entropy_args_t ea)
double add_edge_dS(size_t u, size_t v, uentropy_args_t ea)
{
auto& e = get_u_edge(u, v);
double dS = _block_state.template modify_edge_dS<true>(u, v, e,
_recs, ea);
if (_E_prior)
{
dS -= _pe;
dS += lgamma_fast(_E + 2) - lgamma_fast(_E + 1);
}
if ((e == _null_edge || _eweight[e] == 0) && (_self_loops || u != v))
if (ea.latent_edges)
{
auto& m = get_edge<false>(u, v);
double q_e = (m == _null_edge) ? _q_default : _q[m];
dS -= q_e;
if (_E_prior)
{
dS -= _pe;
dS += lgamma_fast(_E + 2) - lgamma_fast(_E + 1);
}
if ((e == _null_edge || _eweight[e] == 0) && (_self_loops || u != v))
{
auto& m = get_edge<false>(u, v);
double q_e = (m == _null_edge) ? _q_default : _q[m];
dS -= q_e;
}
}
return dS;
}
......@@ -226,7 +240,7 @@ struct Uncertain
};
template <class State>
double get_edge_prob(State& state, size_t u, size_t v, entropy_args_t ea,
double get_edge_prob(State& state, size_t u, size_t v, uentropy_args_t ea,
double epsilon)
{
auto e = state.get_u_edge(u, v);
......@@ -264,7 +278,7 @@ double get_edge_prob(State& state, size_t u, size_t v, entropy_args_t ea,
template <class State>
void get_edges_prob(State& state, python::object edges, python::object probs,
entropy_args_t ea, double epsilon)
uentropy_args_t ea, double epsilon)
{
multi_array_ref<uint64_t,2> es = get_array<uint64_t,2>(edges);
multi_array_ref<double,1> eprobs = get_array<double,1>(probs);
......
......@@ -39,7 +39,7 @@ typedef std::vector<size_t> vlist_t;
((slist, &, vlist_t&, 0)) \
((tlist, &, vlist_t&, 0)) \
((beta,, double, 0)) \
((entropy_args,, entropy_args_t, 0)) \
((entropy_args,, uentropy_args_t, 0)) \
((verbose,, bool, 0)) \
((niter,, size_t, 0))
......
......@@ -122,7 +122,7 @@ def get_entropy_args(kargs, ignore=None):
kargs = kargs.copy()
if ignore is not None:
for a in ignore:
del kargs[a]
kargs.pop(a, None)
args = DictState(kargs)
deg_dl_kind = args.degree_dl_kind
del kargs["degree_dl_kind"]
......
......@@ -33,6 +33,12 @@ from . blockmodel import *
from . nested_blockmodel import *
from . blockmodel import _bm_test
def get_uentropy_args(kargs):
ea = get_entropy_args(kargs, ignore=["latent_edges"])
uea = libinference.uentropy_args(ea)
uea.latent_edges = kargs.get("latent_edges", True)
return uea
class UncertainBaseState(object):
def __init__(self, g, nested=True, state_args={}, bstate=None,
self_loops=False, init_empty=False):
......@@ -114,7 +120,7 @@ class UncertainBaseState(object):
tlist = self.tlist
dentropy_args = dict(self.bstate._entropy_args,
**kwargs.get("entropy_args", {}))
entropy_args = get_entropy_args(dentropy_args)
entropy_args = get_uentropy_args(dentropy_args)
state = self._state
mcmc_state = DictState(locals())
......@@ -169,14 +175,14 @@ class UncertainBaseState(object):
def get_edge_prob(self, u, v, entropy_args={}, epsilon=1e-8):
r"""Return conditional posterior probability of edge :math:`(u,v)`."""
entropy_args = dict(self.bstate._entropy_args, **entropy_args)
ea = get_entropy_args(entropy_args)
ea = get_uentropy_args(entropy_args)
return self._state.get_edge_prob(u, v, ea, epsilon)
def get_edges_prob(self, elist, entropy_args={}, epsilon=1e-8):
r"""Return conditional posterior probability of an edge list, with
shape :math:`(E,2)`."""
entropy_args = dict(self.bstate._entropy_args, **entropy_args)
ea = get_entropy_args(entropy_args)
ea = get_uentropy_args(entropy_args)
elist = numpy.asarray(elist, dtype="uint64")
probs = numpy.zeros(elist.shape[0])
self._state.get_edges_prob(elist, probs, ea, epsilon)
......
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