From 0187e8930779b738d1e162a1e64be1c78058b371 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 8 Mar 2021 11:00:00 +0100 Subject: [PATCH 1/5] added rich club metric --- docs/src/community.md | 1 + src/LightGraphs.jl | 3 ++- src/community/rich_club.jl | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/community/rich_club.jl diff --git a/docs/src/community.md b/docs/src/community.md index 2654978ef..69dbce85a 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/LightGraphs.jl b/src/LightGraphs.jl index 221092db4..92a58e825 100644 --- a/src/LightGraphs.jl +++ b/src/LightGraphs.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..67e53c27c --- /dev/null +++ b/src/community/rich_club.jl @@ -0,0 +1,23 @@ +""" + 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 (degree(g,src(e)) >= k) && (degree(g,dst(e)) >= k ) + E +=1 + end + end + N = count(degree(g) .>= k) + return 2*E / (N*(N-1)) +end From ff35ee38c6f95ead631ad324fd63699f19da20ad Mon Sep 17 00:00:00 2001 From: vboussange Date: Thu, 11 Mar 2021 17:09:51 +0100 Subject: [PATCH 2/5] added some tests and modified method for directed graph --- src/community/rich_club.jl | 8 ++++++-- test/community/rich_club.jl | 17 +++++++++++++++++ test/runtests.jl | 5 +++-- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 test/community/rich_club.jl diff --git a/src/community/rich_club.jl b/src/community/rich_club.jl index 67e53c27c..549b9c5a6 100644 --- a/src/community/rich_club.jl +++ b/src/community/rich_club.jl @@ -14,10 +14,14 @@ julia> rich_club(g,1) function rich_club(g::AbstractGraph{T},k::Int) where T E = zero(T) for e in edges(g) - if (degree(g,src(e)) >= k) && (degree(g,dst(e)) >= k ) + if (outdegree(g,src(e)) >= k) && (indegree(g,dst(e)) >= k ) E +=1 end end N = count(degree(g) .>= k) - return 2*E / (N*(N-1)) + 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..2666deaf4 --- /dev/null +++ b/test/community/rich_club.jl @@ -0,0 +1,17 @@ + +@testset "Rich club coefficient" begin + @testset "Small graphs" for n = 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 295e400ef..9aa5cb196 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", + "rich_club", "centrality/betweenness", "centrality/closeness", "centrality/degree", From d8025dd5042e280d29d0a11f3769540145d6c857 Mon Sep 17 00:00:00 2001 From: vboussange Date: Thu, 11 Mar 2021 21:30:37 +0100 Subject: [PATCH 3/5] small fix --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 9aa5cb196..b7bf93886 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -60,7 +60,7 @@ tests = [ "community/clustering", "community/clique_percolation", "community/assortativity", - "rich_club", + "community/rich_club", "centrality/betweenness", "centrality/closeness", "centrality/degree", From 456565cd4027bb6aa1839635789352ee6006a8c7 Mon Sep 17 00:00:00 2001 From: vboussange Date: Thu, 11 Mar 2021 23:05:15 +0100 Subject: [PATCH 4/5] small fix --- test/community/rich_club.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/community/rich_club.jl b/test/community/rich_club.jl index 2666deaf4..a0ee87810 100644 --- a/test/community/rich_club.jl +++ b/test/community/rich_club.jl @@ -1,6 +1,6 @@ @testset "Rich club coefficient" begin - @testset "Small graphs" for n = 5:10 + @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 From 34ad732f522191bb7cee1461789c660010c5d714 Mon Sep 17 00:00:00 2001 From: vboussange Date: Tue, 30 Mar 2021 13:48:22 +0200 Subject: [PATCH 5/5] updated spaces --- src/community/rich_club.jl | 8 ++++---- test/community/rich_club.jl | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/community/rich_club.jl b/src/community/rich_club.jl index 549b9c5a6..0c60c444f 100644 --- a/src/community/rich_club.jl +++ b/src/community/rich_club.jl @@ -1,5 +1,5 @@ """ - rich_club(g,k) + 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`. @@ -7,14 +7,14 @@ with degree cut-off `k`. ```jldoctest julia> using LightGraphs julia> g = star_graph(5) -julia> rich_club(g,1) +julia> rich_club(g, 1) 0.4 ``` """ -function rich_club(g::AbstractGraph{T},k::Int) where T +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 ) + if (outdegree(g, src(e)) >= k) && (indegree(g, dst(e)) >= k ) E +=1 end end diff --git a/test/community/rich_club.jl b/test/community/rich_club.jl index a0ee87810..d15d3e4bf 100644 --- a/test/community/rich_club.jl +++ b/test/community/rich_club.jl @@ -1,17 +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 + @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. + _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. + _r = rich_club(g, 1) + @test @inferred rich_club(g, 1) > 0. end end