Commit a9a2ba7f authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement graph_tool::is_directed()

parent 314bc212
......@@ -43,7 +43,7 @@ struct get_eigentrust
// Norm c values
InferredTrustMap c_sum(vertex_index);
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
{
TrustMap c_temp(edge_index, c.get_storage().size());
parallel_vertex_loop
......@@ -93,11 +93,11 @@ struct get_eigentrust
for (const auto& e : in_or_out_edges_range(v, g))
{
typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
s = source(e, g);
else
s = target(e, g);
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(g))
t_temp[v] += get(c, e) * t[s] / abs(c_sum[s]);
else
t_temp[v] += get(c, e) * t[s];
......
......@@ -68,7 +68,7 @@ struct get_eigenvector
for (const auto& e : in_or_out_edges_range(v, g))
{
typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
s = source(e, g);
else
s = target(e, g);
......
......@@ -79,7 +79,7 @@ struct get_hits
for (const auto& ie : in_or_out_edges_range(v, g))
{
typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
s = source(ie, g);
else
s = target(ie, g);
......
......@@ -65,7 +65,7 @@ struct get_katz
for (const auto& e : in_or_out_edges_range(v, g))
{
typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
s = source(e, g);
else
s = target(e, g);
......
......@@ -64,7 +64,7 @@ struct get_pagerank
for (const auto& e : in_or_out_edges_range(v, g))
{
typename graph_traits<Graph>::vertex_descriptor s;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
s = source(e, g);
else
s = target(e, g);
......
......@@ -75,7 +75,7 @@ get_triangles(typename graph_traits<Graph>::vertex_descriptor v, VProp& mark,
mark[n] = false;
size_t k = out_degree(v, g);
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return make_pair(triangles, (k * (k - 1)));
else
return make_pair(triangles / 2, (k * (k - 1)) / 2);
......
......@@ -212,7 +212,7 @@ void make_subgraph
auto viter = lower_bound(vlist.begin(), vlist.end(), ot);
size_t ot_index = viter - vlist.begin();
if (viter != vlist.end() && vlist[ot_index] == ot &&
(is_directed::apply<Graph>::type::value || ot < ov))
(graph_tool::is_directed(g) || ot < ov))
add_edge(nv, vertex(ot_index, sub), sub);
}
}
......@@ -283,12 +283,12 @@ void get_sig(Graph& g, std::vector<size_t>& sig)
sig.clear();
size_t N = num_vertices(g);
if (N > 0)
sig.resize(is_directed::apply<Graph>::type::value ? 2 * N : N);
sig.resize(graph_tool::is_directed(g) ? 2 * N : N);
for (size_t i = 0; i < N; ++i)
{
auto v = vertex(i, g);
sig[i] = out_degree(v, g);
if(is_directed::apply<Graph>::type::value)
if(graph_tool::is_directed(g))
sig[i + N] = in_degreeS()(v, g);
}
sort(sig.begin(), sig.end());
......
......@@ -92,7 +92,7 @@ struct get_assortativity_coefficient
// "jackknife" variance
double err = 0;
size_t one = (is_directed::apply<Graph>::type::value) ? 1 : 2;
size_t one = (graph_tool::is_directed(g)) ? 1 : 2;
#pragma omp parallel if (num_vertices(g) > OPENMP_MIN_THRESH) \
reduction(+:err)
parallel_vertex_loop_no_spawn
......@@ -114,7 +114,7 @@ struct get_assortativity_coefficient
err += (r - rl) * (r - rl);
}
});
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(g))
err /= 2;
#if (BOOST_VERSION >= 106000)
if (boost::math::relative_difference(1., t2) > 1e-8)
......@@ -194,7 +194,7 @@ struct get_scalar_assortativity_coefficient
r_err = 0.0;
double err = 0.0;
size_t one = (is_directed::apply<Graph>::type::value) ? 1 : 2;
size_t one = (graph_tool::is_directed(g)) ? 1 : 2;
#pragma omp parallel if (num_vertices(g) > OPENMP_MIN_THRESH) \
reduction(+:err)
parallel_vertex_loop_no_spawn
......@@ -219,7 +219,7 @@ struct get_scalar_assortativity_coefficient
err += (r - rl) * (r - rl);
}
});
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(g))
err /= 2;
if (stda*stdb > 0)
r_err = sqrt(err);
......
......@@ -140,7 +140,7 @@ struct get_community_network_edges
}
else
{
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(g))
{
iter = comm_edges[ct].find(cs);
if (iter != comm_edges[ct].end())
......@@ -296,7 +296,7 @@ struct get_edge_community_property_sum
continue; // self-loops not allowed
auto* ces = &comm_edges[make_pair(cs, ct)];
if (ces->empty() && !is_directed::apply<Graph>::type::value)
if (ces->empty() && !graph_tool::is_directed(g))
ces = &comm_edges[make_pair(ct, cs)];
if (ces->empty())
{
......
......@@ -574,7 +574,7 @@ struct gen_graph
typename graph_traits<Graph>::vertex_descriptor t =
vertex(vertices[t_i].index, g);
if ((s == t) && (!is_directed::apply<Graph>::type::value &&
if ((s == t) && (!graph_tool::is_directed(g) &&
s_deg.second < 2))
continue;
......
......@@ -47,7 +47,7 @@ struct get_line_graph
vertex_map[v] = edge_index[e];
}
if (boost::is_directed(g))
if (graph_tool::is_directed(g))
{
for (auto v : vertices_range(g))
{
......
......@@ -62,18 +62,18 @@ target(const pair<size_t, bool>& e,
template <class Nmap, class Graph>
void add_count(size_t s, size_t t, Nmap& nvmap, Graph&)
void add_count(size_t s, size_t t, Nmap& nvmap, Graph& g)
{
if (!is_directed::apply<Graph>::type::value && s > t)
if (!graph_tool::is_directed(g) && s > t)
std::swap(s, t);
auto& nmap = nvmap[s];
nmap[t]++;
}
template <class Nmap, class Graph>
void remove_count(size_t s, size_t t, Nmap& nvmap, Graph&)
void remove_count(size_t s, size_t t, Nmap& nvmap, Graph& g)
{
if (!is_directed::apply<Graph>::type::value && s > t)
if (!graph_tool::is_directed(g) && s > t)
std::swap(s, t);
auto& nmap = nvmap[s];
auto iter = nmap.find(t);
......@@ -83,9 +83,9 @@ void remove_count(size_t s, size_t t, Nmap& nvmap, Graph&)
}
template <class Nmap, class Graph>
size_t get_count(size_t s, size_t t, Nmap& nvmap, Graph&)
size_t get_count(size_t s, size_t t, Nmap& nvmap, Graph& g)
{
if (!is_directed::apply<Graph>::type::value && s > t)
if (!graph_tool::is_directed(g) && s > t)
std::swap(s, t);
auto& nmap = nvmap[s];
auto iter = nmap.find(t);
......@@ -157,12 +157,12 @@ struct swap_edge
remove_edge(edges[e.first], g);
remove_edge(edges[te.first], g);
if (is_directed::apply<Graph>::type::value || !e.second)
if (graph_tool::is_directed(g) || !e.second)
ne = add_edge(s_e, t_te, g).first;
else // keep invertedness (only for undirected graphs)
ne = add_edge(t_te, s_e, g).first;
edges[e.first] = ne;
if (is_directed::apply<Graph>::type::value || !te.second)
if (graph_tool::is_directed(g) || !te.second)
nte = add_edge(s_te, t_e, g).first;
else // keep invertedness (only for undirected graphs)
nte = add_edge(t_e, s_te, g).first;
......@@ -402,7 +402,7 @@ public:
size_t e_s = source(_edges[ei], _g);
size_t e_t = target(_edges[ei], _g);
if (!is_directed::apply<Graph>::type::value && e_s > e_t)
if (!graph_tool::is_directed(_g) && e_s > e_t)
std::swap(e_s, e_t);
//try randomly drawn pairs of vertices
......@@ -418,7 +418,7 @@ public:
continue;
}
else if (!is_directed::apply<Graph>::type::value && self_loops)
else if (!graph_tool::is_directed(_g) && self_loops)
{
// sample self-loops w/ correct probability for undirected
// graphs
......@@ -429,7 +429,7 @@ public:
break;
}
if (!is_directed::apply<Graph>::type::value && s > t)
if (!graph_tool::is_directed(_g) && s > t)
std::swap(s, t);
if (s == e_s && t == e_t)
......@@ -540,7 +540,7 @@ public:
double a = 0;
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
a -= log(2 + (s == t) + (ts == tt));
a += log(2 + (s == tt) + (ts == t));
......@@ -562,7 +562,7 @@ public:
int d = e_d.second;
size_t m = get_count(u, v, _nmap, _g);
a -= lgamma(m + 1) - lgamma((m + 1) + d);
if (!is_directed::apply<Graph>::type::value && u == v)
if (!graph_tool::is_directed(_g) && u == v)
a += d * log(2);
}
......@@ -644,7 +644,7 @@ public:
{
std::uniform_int_distribution<> sample(0, base_t::_edges.size() - 1);
pair<size_t, bool> et = make_pair(sample(base_t::_rng), false);
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
std::bernoulli_distribution coin(0.5);
et.second = coin(base_t::_rng);
......@@ -700,7 +700,7 @@ public:
deg_t tdeg = get_deg(t, _g);;
_edges_by_target[tdeg].push_back(make_pair(ei, false));
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
t = source(e, _g);
deg_t tdeg = get_deg(t, _g);
......@@ -711,7 +711,7 @@ public:
pair<size_t,bool> get_target_edge(pair<size_t, bool>& e, bool)
{
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
std::bernoulli_distribution coin(0.5);
e.second = coin(base_t::_rng);
......@@ -836,7 +836,7 @@ public:
pair<size_t, bool> get_target_edge(pair<size_t, bool>& e, bool)
{
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
std::bernoulli_distribution coin(0.5);
e.second = coin(base_t::_rng);
......@@ -848,7 +848,7 @@ public:
std::uniform_int_distribution<> sample(0, base_t::_edges.size() - 1);
size_t epi = sample(base_t::_rng);
pair<size_t, bool> ep = make_pair(epi, false);
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(_g))
{
// for undirected graphs we must select a random direction
std::bernoulli_distribution coin(0.5);
......@@ -1000,7 +1000,7 @@ public:
s = uniform_sample(svs, _rng);
t = uniform_sample(tvs, _rng);
if (!is_directed::apply<Graph>::type::value &&
if (!graph_tool::is_directed(_g) &&
deg.first == deg.second && s != t && self_loops)
{
// sample self-loops w/ correct probability for undirected
......
......@@ -42,7 +42,7 @@ template <bool micro_deg, class Graph, class VProp, class IVec, class FVec,
void gen_sbm(Graph& g, VProp b, IVec& rs, IVec& ss, FVec probs, VDProp in_deg,
VDProp out_deg, bool micro_ers, RNG& rng)
{
constexpr bool is_dir = is_directed::apply<Graph>::type::value;
constexpr bool is_dir = graph_tool::is_directed(g);
typedef typename std::conditional_t<micro_deg,size_t,double> dtype;
vector<vector<size_t>> rvs;
vector<vector<dtype>> v_in_probs, v_out_probs;
......
......@@ -61,7 +61,7 @@ struct do_edge_endpoint
{
auto s = v;
auto t = target(e, g);
if (!is_directed::apply<Graph>::type::value && s > t)
if (!graph_tool::is_directed(g) && s > t)
continue;
if (src)
eprop[e] = prop[s];
......
......@@ -233,7 +233,7 @@ struct get_edge_dispatch
bool all_edges, boost::python::list& es) const
{
auto gp = retrieve_graph_view<Graph>(gi, g);
size_t k_t = is_directed::apply<Graph>::type::value ?
size_t k_t = graph_tool::is_directed(g) ?
in_degreeS()(t, g) : out_degree(t, g);
if (out_degree(s, g) <= k_t)
{
......@@ -251,11 +251,11 @@ struct get_edge_dispatch
{
for (auto e : in_or_out_edges_range(vertex(t, g), g))
{
auto w = is_directed::apply<Graph>::type::value ?
auto w = graph_tool::is_directed(g) ?
source(e, g) : target(e, g);
if (w == vertex(s, g))
{
if (!is_directed::apply<Graph>::type::value && e.s != s)
if (!graph_tool::is_directed(g) && e.s != s)
std::swap(e.s, e.t);
es.append(PythonEdge<Graph>(gp, e));
if (!all_edges)
......
......@@ -68,6 +68,11 @@ struct is_directed
};
};
template <class Graph>
constexpr bool is_directed(const Graph&)
{
return is_directed::apply<std::remove_reference_t<Graph>>::type::value;
}
// This will count "by hand" the number of vertices on a graph. Always O(V).
struct HardNumVertices
......
......@@ -34,7 +34,7 @@ template <class Edge, class Graph>
inline typename graph_traits<Graph>::vertex_descriptor
get_source(const Edge& e, const Graph &g)
{
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return source(e, g);
return std::min(source(e, g), target(e, g));
}
......@@ -43,7 +43,7 @@ template <class Edge, class Graph>
inline typename graph_traits<Graph>::vertex_descriptor
get_target(const Edge& e, const Graph &g)
{
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return target(e, g);
return std::max(source(e, g), target(e, g));
}
......
......@@ -251,7 +251,6 @@ private:
vector<std::tuple<EVals...>> _delta;
vector<bedge_t> _mes;
size_t _dummy;
};
template <class Graph, class BGraph, class... EVals>
......@@ -274,7 +273,7 @@ void modify_entries(Vertex v, Vertex r, Vprop& _b, Graph& g, Eprop& eweights,
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
auto& self_weight = m_entries._self_weight;
if (!is_directed::apply<Graph>::type::value)
if (!graph_tool::is_directed(g))
{
tuple_apply([&](auto&&... vals)
{
......@@ -299,13 +298,13 @@ void modify_entries(Vertex v, Vertex r, Vprop& _b, Graph& g, Eprop& eweights,
m_entries.template insert_delta<Add>(r, s, ew,
make_vadapter(eprops, e)...);
if ((u == v || is_loop(v)) && !is_directed::apply<Graph>::type::value)
tuple_op(self_weight, [&](auto& r, auto& v){ r += v; },
if ((u == v || is_loop(v)) && !graph_tool::is_directed(g))
tuple_op(self_weight, [&](auto& x, auto& val){ x += val; },
ew, make_vadapter(eprops, e)...);
}
if (get<0>(self_weight) > 0 && get<0>(self_weight) % 2 == 0 &&
!is_directed::apply<Graph>::type::value)
!graph_tool::is_directed(g))
{
tuple_apply([&](auto&&... vals)
{
......@@ -315,18 +314,21 @@ void modify_entries(Vertex v, Vertex r, Vprop& _b, Graph& g, Eprop& eweights,
}, self_weight);
}
for (auto e : in_edges_range(v, g))
if (graph_tool::is_directed(g))
{
if (efilt(e))
continue;
vertex_t u = source(e, g);
if (u == v)
continue;
vertex_t s = _b[u];
int ew = eweights[e];
m_entries.template insert_delta<Add>(s, r, ew,
make_vadapter(eprops, e)...);
for (auto e : in_edges_range(v, g))
{
if (efilt(e))
continue;
vertex_t u = source(e, g);
if (u == v)
continue;
vertex_t s = _b[u];
int ew = eweights[e];
m_entries.template insert_delta<Add>(s, r, ew,
make_vadapter(eprops, e)...);
}
}
}
......
......@@ -53,11 +53,11 @@ struct entropy_args_t
// exact microcanonical deg-corr entropy
template <class Graph>
inline double eterm_exact(size_t r, size_t s, size_t mrs, const Graph&)
inline double eterm_exact(size_t r, size_t s, size_t mrs, const Graph& g)
{
double val = lgamma_fast(mrs + 1);
if (is_directed::apply<Graph>::type::value || r != s)
if (graph_tool::is_directed(g) || r != s)
{
return -val;
}
......@@ -74,18 +74,18 @@ inline double eterm_exact(size_t r, size_t s, size_t mrs, const Graph&)
template <class Graph>
inline double vterm_exact(size_t mrp, size_t mrm, size_t wr, bool deg_corr,
const Graph&)
const Graph& g)
{
if (deg_corr)
{
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return lgamma_fast(mrp + 1) + lgamma_fast(mrm + 1);
else
return lgamma_fast(mrp + 1);
}
else
{
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return (mrp + mrm) * safelog(wr);
else
return mrp * safelog(wr);
......@@ -94,14 +94,14 @@ inline double vterm_exact(size_t mrp, size_t mrm, size_t wr, bool deg_corr,
// "edge" term of the entropy
template <class Graph>
inline double eterm(size_t r, size_t s, size_t mrs, const Graph&)
inline double eterm(size_t r, size_t s, size_t mrs, const Graph& g)
{
if (!is_directed::apply<Graph>::type::value && r == s)
if (!graph_tool::is_directed(g) && r == s)
mrs *= 2;
double val = xlogx(mrs);
if (is_directed::apply<Graph>::type::value || r != s)
if (graph_tool::is_directed(g) || r != s)
return -val;
else
return -val / 2;
......@@ -110,11 +110,11 @@ inline double eterm(size_t r, size_t s, size_t mrs, const Graph&)
// "vertex" term of the entropy
template <class Graph>
inline double vterm(size_t mrp, size_t mrm, size_t wr, bool deg_corr,
Graph&)
Graph& g)
{
double one = 0.5;
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
one = 1;
if (deg_corr)
......@@ -131,7 +131,7 @@ inline double vterm(size_t mrp, size_t mrm, size_t wr, bool deg_corr,
// "edge" term of the entropy
template <class Graph>
inline double eterm_dense(size_t r, size_t s, int ers, double wr_r,
double wr_s, bool multigraph, const Graph&)
double wr_s, bool multigraph, const Graph& g)
{
// we should not use integers here, since they may overflow
double nrns;
......@@ -141,7 +141,7 @@ inline double eterm_dense(size_t r, size_t s, int ers, double wr_r,
assert(wr_r + wr_s > 0);
if (r != s || is_directed::apply<Graph>::type::value)
if (r != s || graph_tool::is_directed(g))
{
nrns = wr_r * wr_s;
}
......
......@@ -267,7 +267,7 @@ public:
template <class VProp, class Graph>
double get_delta_edges_dl(size_t v, size_t r, size_t nr, VProp& vweight,
size_t actual_B, Graph&)
size_t actual_B, Graph& g)
{
if (r == nr || _allow_empty)
return 0;
......@@ -297,9 +297,9 @@ public:
if (dB != 0)
{
auto get_x = [](size_t B)
auto get_x = [&g](size_t B)
{
if (is_directed::apply<Graph>::type::value)
if (graph_tool::is_directed(g))
return B * B;
else
return (B * (B + 1)) / 2;
......
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