Commit 8688be7a authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

blockmodel: Cleanup get_b(), beop(), etc.

parent 41d98f5c
...@@ -116,8 +116,7 @@ public: ...@@ -116,8 +116,7 @@ public:
_emat(_bg, rng), _emat(_bg, rng),
_neighbour_sampler(_g, _eweight), _neighbour_sampler(_g, _eweight),
_m_entries(num_vertices(_bg)), _m_entries(num_vertices(_bg)),
_coupled_state(nullptr), _coupled_state(nullptr)
_gstate(this)
{ {
_empty_blocks.clear(); _empty_blocks.clear();
_candidate_blocks.clear(); _candidate_blocks.clear();
...@@ -142,8 +141,7 @@ public: ...@@ -142,8 +141,7 @@ public:
_emat(other._emat), _emat(other._emat),
_neighbour_sampler(other._neighbour_sampler), _neighbour_sampler(other._neighbour_sampler),
_m_entries(num_vertices(_bg)), _m_entries(num_vertices(_bg)),
_coupled_state(nullptr), _coupled_state(nullptr)
_gstate(other._gstate == &other ? this : other._gstate)
{ {
if (other.is_partition_stats_enabled()) if (other.is_partition_stats_enabled())
enable_partition_stats(); enable_partition_stats();
...@@ -154,15 +152,13 @@ public: ...@@ -154,15 +152,13 @@ public:
// State modification // State modification
// ========================================================================= // =========================================================================
template <class MEntries, class EFilt, class GetB> template <class MEntries, class EFilt>
void get_move_entries(size_t v, size_t r, size_t nr, MEntries& m_entries, void get_move_entries(size_t v, size_t r, size_t nr, MEntries& m_entries,
EFilt&& efilt, GetB&& get_b) EFilt&& efilt)
{ {
auto& gs = *_gstate;
auto mv_entries = [&](auto&&... args) auto mv_entries = [&](auto&&... args)
{ {
move_entries(v, r, nr, std::forward<GetB>(get_b), gs._g, move_entries(v, r, nr, _b, _g, _eweight, m_entries,
gs._eweight, m_entries,
std::forward<EFilt>(efilt), is_loop_nop(), std::forward<EFilt>(efilt), is_loop_nop(),
std::forward<decltype(args)>(args)...); std::forward<decltype(args)>(args)...);
}; };
...@@ -173,10 +169,10 @@ public: ...@@ -173,10 +169,10 @@ public:
case weight_type::DISCRETE_GEOMETRIC: case weight_type::DISCRETE_GEOMETRIC:
case weight_type::DISCRETE_POISSON: case weight_type::DISCRETE_POISSON:
case weight_type::DELTA_T: case weight_type::DELTA_T:
mv_entries(gs._rec); mv_entries(_rec);
break; break;
case weight_type::SIGNED: // positive and negative weights case weight_type::SIGNED: // positive and negative weights
mv_entries(gs._rec, gs._drec); mv_entries(_rec, _drec);
break; break;
default: // no weights default: // no weights
mv_entries(); mv_entries();
...@@ -186,25 +182,20 @@ public: ...@@ -186,25 +182,20 @@ public:
template <class MEntries> template <class MEntries>
void get_move_entries(size_t v, size_t r, size_t nr, MEntries& m_entries) void get_move_entries(size_t v, size_t r, size_t nr, MEntries& m_entries)
{ {
get_move_entries(v, r, nr, m_entries, get_move_entries(v, r, nr, m_entries, [](auto) {return false;});
[](auto) { return false; },
[&](auto u) -> size_t { return this->_b[u]; });
} }
template <bool Add, class EFilt, class GetB, class BEop> template <bool Add, class EFilt>
void modify_vertex(size_t v, size_t r, EFilt&& efilt, GetB&& get_b, void modify_vertex(size_t v, size_t r, EFilt&& efilt)
BEop&& beop)
{ {
_m_entries.clear(); _m_entries.clear();
if (Add) if (Add)
get_move_entries(v, null_group, r, _m_entries, get_move_entries(v, null_group, r, _m_entries,
std::forward<EFilt>(efilt), std::forward<EFilt>(efilt));
std::forward<GetB>(get_b));
else else
get_move_entries(v, r, null_group, _m_entries, get_move_entries(v, r, null_group, _m_entries,
std::forward<EFilt>(efilt), std::forward<EFilt>(efilt));
std::forward<GetB>(get_b));
entries_op(_m_entries, _emat, entries_op(_m_entries, _emat,
[&](auto r, auto s, auto& me, auto& delta) [&](auto r, auto s, auto& me, auto& delta)
...@@ -212,8 +203,6 @@ public: ...@@ -212,8 +203,6 @@ public:
if (get<0>(delta) == 0) // can happen with zero-weight if (get<0>(delta) == 0) // can happen with zero-weight
return; // edges return; // edges
beop(false, me);
if (Add && me == this->_emat.get_null_edge()) if (Add && me == this->_emat.get_null_edge())
{ {
me = add_edge(r, s, this->_bg).first; me = add_edge(r, s, this->_bg).first;
...@@ -241,16 +230,13 @@ public: ...@@ -241,16 +230,13 @@ public:
case weight_type::DELTA_T: case weight_type::DELTA_T:
this->_brec[me] += get<1>(delta); this->_brec[me] += get<1>(delta);
} }
beop(true, me);
}); });
if (_rec_type == weight_type::DELTA_T) // waiting times if (_rec_type == weight_type::DELTA_T) // waiting times
{ {
auto& gs = *_gstate; if (_ignore_degrees[v] > 0)
if (gs._ignore_degrees[v] > 0)
{ {
double dt = out_degreeS()(v, gs._g, gs._rec); double dt = out_degreeS()(v, _g, _rec);
if (Add) if (Add)
_brecsum[r] += dt; _brecsum[r] += dt;
else else
...@@ -260,8 +246,7 @@ public: ...@@ -260,8 +246,7 @@ public:
if (Add) if (Add)
{ {
auto&& b_v = get_b(v); _b[v] = r;
b_v = r;
add_partition_node(v, r); add_partition_node(v, r);
} }
else else
...@@ -272,19 +257,17 @@ public: ...@@ -272,19 +257,17 @@ public:
void remove_partition_node(size_t v, size_t r) void remove_partition_node(size_t v, size_t r)
{ {
auto& gs = *_gstate; _wr[r] -= _vweight[v];
_wr[r] -= gs._vweight[v];
if (!_egroups.empty() && _gstate == this) if (!_egroups.empty())
_egroups.remove_vertex(v, _b, _g); _egroups.remove_vertex(v, _b, _g);
if (is_partition_stats_enabled()) if (is_partition_stats_enabled())
get_partition_stats(v).remove_vertex(v, r, _deg_corr, gs._g, get_partition_stats(v).remove_vertex(v, r, _deg_corr, _g,
gs._vweight, gs._eweight, _vweight, _eweight,
gs._degs); _degs);
if (gs._vweight[v] > 0 && _wr[r] == 0) if (_vweight[v] > 0 && _wr[r] == 0)
{ {
remove_element(_candidate_blocks, _candidate_pos, r); remove_element(_candidate_blocks, _candidate_pos, r);
add_element(_empty_blocks, _empty_pos, r); add_element(_empty_blocks, _empty_pos, r);
...@@ -293,38 +276,26 @@ public: ...@@ -293,38 +276,26 @@ public:
void add_partition_node(size_t v, size_t r) void add_partition_node(size_t v, size_t r)
{ {
auto& gs = *_gstate; _wr[r] += _vweight[v];
_wr[r] += gs._vweight[v]; if (!_egroups.empty())
if (!_egroups.empty() && _gstate == this)
_egroups.add_vertex(v, _b, _eweight, _g); _egroups.add_vertex(v, _b, _eweight, _g);
if (is_partition_stats_enabled()) if (is_partition_stats_enabled())
get_partition_stats(v).add_vertex(v, r, _deg_corr, gs._g, gs._vweight, get_partition_stats(v).add_vertex(v, r, _deg_corr, _g, _vweight,
gs._eweight, gs._degs); _eweight, _degs);
if (gs._vweight[v] > 0 && _wr[r] == gs._vweight[v]) if (_vweight[v] > 0 && _wr[r] == _vweight[v])
{ {
remove_element(_empty_blocks, _empty_pos, r); remove_element(_empty_blocks, _empty_pos, r);
add_element(_candidate_blocks, _candidate_pos, r); add_element(_candidate_blocks, _candidate_pos, r);
} }
} }
template <class EFilt, class GetB, class BEop>
void remove_vertex(size_t v, size_t r, EFilt&& efilt, GetB&& get_b,
BEop&& beop)
{
modify_vertex<false>(v, r, std::forward<EFilt>(efilt),
std::forward<GetB>(get_b), beop);
}
template <class EFilt> template <class EFilt>
void remove_vertex(size_t v, size_t r, EFilt&& efilt) void remove_vertex(size_t v, size_t r, EFilt&& efilt)
{ {
remove_vertex(v, r, std::forward<EFilt>(efilt), modify_vertex<false>(v, r, std::forward<EFilt>(efilt));
[&](auto u) -> auto& { return this->_b[u]; },
[](bool, const auto &){});
} }
void remove_vertex(size_t v, size_t r) void remove_vertex(size_t v, size_t r)
...@@ -396,21 +367,10 @@ public: ...@@ -396,21 +367,10 @@ public:
remove_vertices(vs); remove_vertices(vs);
} }
template <class EFilt, class GetB, class BEop>
void add_vertex(size_t v, size_t r, EFilt&& efilt, GetB&& get_b,
BEop&& beop)
{
modify_vertex<true>(v, r, std::forward<EFilt>(efilt),
std::forward<GetB>(get_b), std::forward<BEop>(beop));
//assert(size_t(get_b(v)) == r);
}
template <class EFilt> template <class EFilt>
void add_vertex(size_t v, size_t r, EFilt&& efilt) void add_vertex(size_t v, size_t r, EFilt&& efilt)
{ {
add_vertex(v, r, std::forward<EFilt>(efilt), modify_vertex<true>(v, r, std::forward<EFilt>(efilt));
[&](auto u) -> auto& { return this->_b[u]; },
[](bool, const auto&){});
} }
void add_vertex(size_t v, size_t r) void add_vertex(size_t v, size_t r)
...@@ -502,8 +462,7 @@ public: ...@@ -502,8 +462,7 @@ public:
} }
// move a vertex from its current block to block nr // move a vertex from its current block to block nr
template <class GetB, class BEop> void move_vertex(size_t v, size_t r, size_t nr)
void move_vertex(size_t v, size_t r, size_t nr, GetB&& get_b, BEop&& beop)
{ {
if (r == nr) if (r == nr)
return; return;
...@@ -511,10 +470,8 @@ public: ...@@ -511,10 +470,8 @@ public:
if (!allow_move(r, nr)) if (!allow_move(r, nr))
throw ValueException("cannot move vertex across clabel barriers"); throw ValueException("cannot move vertex across clabel barriers");
remove_vertex(v, r, [](auto&) {return false;}, std::forward<GetB>(get_b), remove_vertex(v, r, [](auto&) {return false;});
std::forward<BEop>(beop)); add_vertex(v, nr, [](auto&) {return false;});
add_vertex(v, nr, [](auto&) {return false;}, std::forward<GetB>(get_b),
std::forward<BEop>(beop));
if (_coupled_state != nullptr && _vweight[v] > 0) if (_coupled_state != nullptr && _vweight[v] > 0)
{ {
...@@ -532,22 +489,12 @@ public: ...@@ -532,22 +489,12 @@ public:
_bclabel[nr] = _bclabel[r]; _bclabel[nr] = _bclabel[r];
} }
} }
//assert(size_t(get_b(v)) == nr);
}
template <class GetB, class BEop>
void move_vertex(size_t v, size_t nr, GetB&& get_b, BEop&& beop)
{
size_t r = get_b(v);
move_vertex(v, r, nr, std::forward<GetB>(get_b),
std::forward<BEop>(beop));
} }
void move_vertex(size_t v, size_t nr) void move_vertex(size_t v, size_t nr)
{ {
move_vertex(v, nr, size_t r = _b[v];
[&](auto u) -> auto& { return this->_b[u]; }, move_vertex(v, r, nr);
[](bool, auto&){});
} }
void set_vertex_weight(size_t v, int w) void set_vertex_weight(size_t v, int w)
...@@ -566,25 +513,6 @@ public: ...@@ -566,25 +513,6 @@ public:
vweight[v] = w; vweight[v] = w;
} }
template <class Edge>
void set_edge_weight(Edge&& e, int w)
{
set_edge_weight(e, w, _eweight);
}
template <class Edge>
void set_edge_weight(Edge&&, int, ecmap_t&)
{
throw ValueException("Cannot set the weight of an unweighted state");
}
template <class Edge, class EMap>
void set_edge_weight(Edge&& e, int w, EMap&& eweight)
{
auto ew_c = eweight.get_checked();
ew_c[e] = w;
}
template <class Vec> template <class Vec>
void move_vertices(Vec& v, Vec& nr) void move_vertices(Vec& v, Vec& nr)
{ {
...@@ -806,13 +734,12 @@ public: ...@@ -806,13 +734,12 @@ public:
double dS = entries_dS<exact>(m_entries, _mrs, _emat, _bg); double dS = entries_dS<exact>(m_entries, _mrs, _emat, _bg);
auto& gs = *_gstate; size_t kout = out_degreeS()(v, _g, _eweight);
size_t kout = out_degreeS()(v, gs._g, gs._eweight);
size_t kin = kout; size_t kin = kout;
if (is_directed::apply<g_t>::type::value) if (is_directed::apply<g_t>::type::value)
kin = in_degreeS()(v, gs._g, gs._eweight); kin = in_degreeS()(v, _g, _eweight);
int dwr = gs._vweight[v]; int dwr = _vweight[v];
int dwnr = dwr; int dwnr = dwr;
if (r == null_group && dwnr == 0) if (r == null_group && dwnr == 0)
...@@ -848,9 +775,7 @@ public: ...@@ -848,9 +775,7 @@ public:
return virtual_move_sparse<exact>(v, r, nr); return virtual_move_sparse<exact>(v, r, nr);
} }
template <class GetB> double virtual_move_dense(size_t v, size_t r, size_t nr, bool multigraph)
double virtual_move_dense(size_t v, size_t r, size_t nr, bool multigraph,
GetB&& get_b)
{ {
if (_deg_corr) if (_deg_corr)
throw GraphException("Dense entropy for degree corrected model not implemented!"); throw GraphException("Dense entropy for degree corrected model not implemented!");
...@@ -860,38 +785,37 @@ public: ...@@ -860,38 +785,37 @@ public:
if (r == nr) if (r == nr)
return 0; return 0;
auto& gs = *_gstate;
int kin = 0, kout = 0; int kin = 0, kout = 0;
kout += out_degreeS()(v, gs._g, gs._eweight); kout += out_degreeS()(v, _g, _eweight);
if (is_directed::apply<g_t>::type::value) if (is_directed::apply<g_t>::type::value)
kin += in_degreeS()(v, gs._g, gs._eweight); kin += in_degreeS()(v, _g, _eweight);
vector<int> deltap(num_vertices(_bg), 0); vector<int> deltap(num_vertices(_bg), 0);
int deltal = 0; int deltal = 0;
for (auto e : out_edges_range(v, gs._g)) for (auto e : out_edges_range(v, _g))
{ {
vertex_t u = target(e, gs._g); vertex_t u = target(e, _g);
vertex_t s = get_b(u); vertex_t s = _b[u];
if (u == v) if (u == v)
deltal += gs._eweight[e]; deltal += _eweight[e];
else else
deltap[s] += gs._eweight[e]; deltap[s] += _eweight[e];
} }
if (!is_directed::apply<g_t>::type::value) if (!is_directed::apply<g_t>::type::value)
deltal /= 2; deltal /= 2;
vector<int> deltam(num_vertices(_bg), 0); vector<int> deltam(num_vertices(_bg), 0);
for (auto e : in_edges_range(v, gs._g)) for (auto e : in_edges_range(v, _g))
{ {
vertex_t u = source(e, gs._g); vertex_t u = source(e, _g);
if (u == v) if (u == v)
continue; continue;
vertex_t s = get_b(u); vertex_t s = _b[u];
deltam[s] += gs._eweight[e]; deltam[s] += _eweight[e];
} }
double dS = 0; double dS = 0;
int dwr = gs._vweight[v]; int dwr = _vweight[v];
int dwnr = dwr; int dwnr = dwr;
if (r == null_group && dwnr == 0) if (r == null_group && dwnr == 0)
...@@ -998,11 +922,11 @@ public: ...@@ -998,11 +922,11 @@ public:
return Sf - Si + dS; return Sf - Si + dS;
} }
template <class MEntries, class GetB> template <class MEntries>
double virtual_move(size_t v, size_t r, size_t nr, entropy_args_t ea, double virtual_move(size_t v, size_t r, size_t nr, entropy_args_t ea,
MEntries& m_entries, GetB&& get_b) MEntries& m_entries)
{ {
assert(size_t(get_b(v)) == r); assert(size_t(_b[v]) == r);
if (r == nr) if (r == nr)
return 0; return 0;
...@@ -1011,16 +935,14 @@ public: ...@@ -1011,16 +935,14 @@ public:
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
m_entries.clear(); m_entries.clear();
get_move_entries(v, r, nr, m_entries, [](auto) { return false; }, get_move_entries(v, r, nr, m_entries, [](auto) { return false; });
std::forward<GetB>(get_b));
double dS = 0; double dS = 0;
if (ea.adjacency) if (ea.adjacency)
{ {
if (ea.dense) if (ea.dense)
{ {
dS = virtual_move_dense(v, r, nr, ea.multigraph, dS = virtual_move_dense(v, r, nr, ea.multigraph);
std::forward<GetB>(get_b));
} }
else else
{ {
...@@ -1033,21 +955,20 @@ public: ...@@ -1033,21 +955,20 @@ public:
if (ea.partition_dl || ea.degree_dl || ea.edges_dl) if (ea.partition_dl || ea.degree_dl || ea.edges_dl)
{ {
auto& gs = *_gstate;
enable_partition_stats(); enable_partition_stats();
auto& ps = get_partition_stats(v); auto& ps = get_partition_stats(v);
if (ea.partition_dl) if (ea.partition_dl)
dS += ps.get_delta_partition_dl(v, r, nr, gs._vweight); dS += ps.get_delta_partition_dl(v, r, nr, _vweight);
if (_deg_corr && ea.degree_dl) if (_deg_corr && ea.degree_dl)
dS += ps.get_delta_deg_dl(v, r, nr, gs._vweight, gs._eweight, dS += ps.get_delta_deg_dl(v, r, nr, _vweight, _eweight,
gs._degs, gs._g, ea.degree_dl_kind); _degs, _g, ea.degree_dl_kind);
if (ea.edges_dl) if (ea.edges_dl)
{ {
size_t actual_B = 0; size_t actual_B = 0;
for (auto& ps : _partition_stats) for (auto& ps : _partition_stats)
actual_B += ps.get_actual_B(); actual_B += ps.get_actual_B();
dS += ps.get_delta_edges_dl(v, r, nr, gs._vweight, actual_B, dS += ps.get_delta_edges_dl(v, r, nr, _vweight, actual_B,
gs._g); _g);
} }
} }
...@@ -1121,11 +1042,10 @@ public: ...@@ -1121,11 +1042,10 @@ public:
}); });
break; break;
case weight_type::DELTA_T: // waiting times