From 1421e9458ecd489c05ad0341124f98ddb80b11db Mon Sep 17 00:00:00 2001 From: Etienne dg Date: Mon, 8 Nov 2021 15:40:18 +0100 Subject: [PATCH] [Port] New rich club metric (#29) added rich club metric with tests and support for directed graphs Co-authored-by: Victor Co-authored-by: vboussange --- docs/src/community.md | 1 + src/Graphs.jl | 3 ++- src/community/rich_club.jl | 27 +++++++++++++++++++++++++++ test/community/rich_club.jl | 17 +++++++++++++++++ test/runtests.jl | 5 +++-- 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/community/rich_club.jl create mode 100644 test/community/rich_club.jl diff --git a/docs/src/community.md b/docs/src/community.md index 359f33f9f..7a2ee5cf4 100644 --- a/docs/src/community.md +++ b/docs/src/community.md @@ -19,6 +19,7 @@ Pages = [ "community/label_propagation.jl", "community/modularity.jl", "community/assortativity.jl" + "community/rich_club.jl" ] Private = false ``` diff --git a/src/Graphs.jl b/src/Graphs.jl index ca07d57c0..e4febaca8 100644 --- a/src/Graphs.jl +++ b/src/Graphs.jl @@ -114,7 +114,7 @@ barabasi_albert!, static_fitness_model, static_scale_free, kronecker, dorogovtse #community modularity, core_periphery_deg, local_clustering,local_clustering_coefficient, global_clustering_coefficient, triangles, -label_propagation, maximal_cliques, clique_percolation, assortativity, +label_propagation, maximal_cliques, clique_percolation, assortativity,rich_club, #generators complete_graph, star_graph, path_graph, wheel_graph, cycle_graph, @@ -256,6 +256,7 @@ include("community/clustering.jl") include("community/cliques.jl") include("community/clique_percolation.jl") include("community/assortativity.jl") +include("community/rich_club.jl") include("spanningtrees/boruvka.jl") include("spanningtrees/kruskal.jl") include("spanningtrees/prim.jl") diff --git a/src/community/rich_club.jl b/src/community/rich_club.jl new file mode 100644 index 000000000..0c60c444f --- /dev/null +++ b/src/community/rich_club.jl @@ -0,0 +1,27 @@ +""" + rich_club(g, k) + +Return the non-normalised [rich-club coefficient](https://en.wikipedia.org/wiki/Rich-club_coefficient) of graph `g`, +with degree cut-off `k`. + +```jldoctest +julia> using LightGraphs +julia> g = star_graph(5) +julia> rich_club(g, 1) +0.4 +``` +""" +function rich_club(g::AbstractGraph{T}, k::Int) where T + E = zero(T) + for e in edges(g) + if (outdegree(g, src(e)) >= k) && (indegree(g, dst(e)) >= k ) + E +=1 + end + end + N = count(degree(g) .>= k) + if is_directed(g) + return E / (N*(N-1)) + else + return 2*E / (N*(N-1)) + end +end diff --git a/test/community/rich_club.jl b/test/community/rich_club.jl new file mode 100644 index 000000000..d15d3e4bf --- /dev/null +++ b/test/community/rich_club.jl @@ -0,0 +1,17 @@ + +@testset "Rich club coefficient" begin + @testset "Small graphs" for _n in 5:10 + @test @inferred rich_club(star_graph(_n), 1) ≈ 2 / _n + @test @inferred rich_club(DiGraph(star_graph(_n)), 1) ≈ 2 / _n + end + @testset "Directed ($seed)" for seed in [1, 2, 3], (n, ne) in [(14, 18), (10, 22), (7, 16)] + g = erdos_renyi(n, ne; is_directed=true, seed=seed) + _r = rich_club(g, 1) + @test @inferred rich_club(g, 1) > 0. + end + @testset "Undirected ($seed)" for seed in [1, 2, 3], (n, ne) in [(14, 18), (10, 22), (7, 16)] + g = erdos_renyi(n, ne; is_directed=false, seed=seed) + _r = rich_club(g, 1) + @test @inferred rich_club(g, 1) > 0. + end +end diff --git a/test/runtests.jl b/test/runtests.jl index 303ae1584..7972944e2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,13 +11,13 @@ using Statistics: mean const testdir = dirname(@__FILE__) -testgraphs(g) = is_directed(g) ? [g, DiGraph{UInt8}(g), DiGraph{Int16}(g)] : [g, Graph{UInt8}(g), Graph{Int16}(g)] +testgraphs(g) = is_directed(g) ? [g, DiGraph{UInt8}(g), DiGraph{Int16}(g)] : [g, Graph{UInt8}(g), Graph{Int16}(g)] testgraphs(gs...) = vcat((testgraphs(g) for g in gs)...) testdigraphs = testgraphs # some operations will create a large graph from two smaller graphs. We # might error out on very small eltypes. -testlargegraphs(g) = is_directed(g) ? [g, DiGraph{UInt16}(g), DiGraph{Int32}(g)] : [g, Graph{UInt16}(g), Graph{Int32}(g)] +testlargegraphs(g) = is_directed(g) ? [g, DiGraph{UInt16}(g), DiGraph{Int32}(g)] : [g, Graph{UInt16}(g), Graph{Int32}(g)] testlargegraphs(gs...) = vcat((testlargegraphs(g) for g in gs)...) tests = [ @@ -60,6 +60,7 @@ tests = [ "community/clustering", "community/clique_percolation", "community/assortativity", + "community/rich_club", "centrality/betweenness", "centrality/closeness", "centrality/degree",