Commit 1df1da7b authored by Tiago Peixoto's avatar Tiago Peixoto

kcore_decomposition(): Fix behavior for directed graphs

parent 8237f35f
Pipeline #279 passed with stage
in 478 minutes and 15 seconds
......@@ -28,17 +28,15 @@ using namespace std;
using namespace boost;
using namespace graph_tool;
void do_kcore_decomposition(GraphInterface& gi, boost::any prop,
GraphInterface::deg_t deg)
void do_kcore_decomposition(GraphInterface& gi, boost::any prop)
([](auto& g, auto core, auto d)
([](auto& g, auto core)
kcore_decomposition(g, core, d);
kcore_decomposition(g, core);
all_graph_views(), writable_vertex_scalar_properties(),
degree_selectors())(gi.get_graph_view(), prop,
all_graph_views(), writable_vertex_scalar_properties())
(gi.get_graph_view(), prop);
void export_kcore()
......@@ -23,14 +23,12 @@ namespace graph_tool
using namespace std;
using namespace boost;
template <class Graph, class CoreMap, class DegSelector>
void kcore_decomposition(Graph& g, CoreMap core_map, DegSelector degS)
template <class Graph, class CoreMap>
void kcore_decomposition(Graph& g, CoreMap core_map)
typedef typename property_map<Graph, vertex_index_t>::type
vertex_index_map_t vertex_index = get(vertex_index_t(), g);
auto vertex_index = get(vertex_index_t(), g);
typedef unchecked_vector_property_map<size_t, vertex_index_map_t> vmap_t;
typedef typename vprop_map_t<size_t>::type::unchecked_t vmap_t;
vmap_t deg(vertex_index, num_vertices(g)); // Remaining degree
vmap_t pos(vertex_index, num_vertices(g)); // Position in bin (core)
......@@ -43,7 +41,7 @@ void kcore_decomposition(Graph& g, CoreMap core_map, DegSelector degS)
// Put each vertex to the bin corresponding to its degree
for (auto v : vertices_range(g))
size_t k = degS(v, g);
size_t k = degree(v, g);
deg[v] = k;
if (k >= bins.size())
bins.resize(k + 1);
......@@ -62,9 +60,8 @@ void kcore_decomposition(Graph& g, CoreMap core_map, DegSelector degS)
auto v = bins_k.back();
core_map[v] = k;
for (auto e : out_edges_range(v, g))
for (auto u : all_neighbours_range(v, g))
auto u = target(e, g);
auto& ku = deg[u];
if (ku > deg[v])
......@@ -73,10 +70,10 @@ void kcore_decomposition(Graph& g, CoreMap core_map, DegSelector degS)
auto pos_w = pos[w] = pos[u];
bins_ku[pos_w] = w;
auto& bins_ku_m = bins[ku - 1];
auto& bins_ku_m = bins[ku];
pos[u] = bins_ku_m.size() - 1;
......@@ -1422,17 +1422,13 @@ def edge_percolation(g, edges):
edges, max_size)
return max_size, tree
def kcore_decomposition(g, deg="out", vprop=None):
Perform a k-core decomposition of the given graph.
def kcore_decomposition(g, vprop=None):
"""Perform a k-core decomposition of the given graph.
g : :class:`~graph_tool.Graph`
Graph to be used.
deg : string
Degree to be used for the decomposition. It can be either "in", "out" or
"total", for in-, out-, or total degree of the vertices.
vprop : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
Vertex property to store the decomposition. If ``None`` is supplied,
one is created.
......@@ -1449,6 +1445,12 @@ def kcore_decomposition(g, deg="out", vprop=None):
The k-core is a maximal set of vertices such that its induced subgraph only
contains vertices with degree larger than or equal to k.
For directed graphs, the degree is assumed to be the total (in + out)
The algorithm accepts graphs with parallel edges and self loops, in which
case these edges contribute to the degree in the usual fashion.
This algorithm is described in [batagelk-algorithm]_ and runs in :math:`O(V + E)`
......@@ -1487,12 +1489,10 @@ def kcore_decomposition(g, deg="out", vprop=None):
_check_prop_writable(vprop, name="vprop")
_check_prop_scalar(vprop, name="vprop")
if deg not in ["in", "out", "total"]:
raise ValueError("invalid degree: " + str(deg))
kcore_decomposition(g._Graph__graph, _prop("v", g, vprop),
_degree(g, deg))
kcore_decomposition(g._Graph__graph, _prop("v", g, vprop))
return vprop
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