Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

New s_metric method #1548

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions docs/src/community.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Pages = [
"community/label_propagation.jl",
"community/modularity.jl",
"community/assortativity.jl"
"community/s_metric.jl"
]
Private = false
```
3 changes: 2 additions & 1 deletion src/LightGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,s_metric,

#generators
complete_graph, star_graph, path_graph, wheel_graph, cycle_graph,
Expand Down Expand Up @@ -256,6 +256,7 @@ include("community/clustering.jl")
include("community/cliques.jl")
include("community/clique_percolation.jl")
include("community/assortativity.jl")
include("community/s_metric.jl")
include("spanningtrees/boruvka.jl")
include("spanningtrees/kruskal.jl")
include("spanningtrees/prim.jl")
Expand Down
35 changes: 35 additions & 0 deletions src/community/s_metric.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
s_metric(g; norm=true)

Return the normalised s-metric of `g`.

The s-metric is defined as the sum of the product of degrees between pair of vertices
for every edge in `g`. [Ref](https://arxiv.org/abs/cond-mat/0501169)
In directed graphs, the paired values are the out-degree of source vertices
and the in-degree of destination vertices.
It is normalised by the maximum s_metric obtained from the family of graph
with similar degree distribution. s_max is computed from an approximation
formula as in https://journals.aps.org/pre/pdf/10.1103/PhysRevE.75.046102
If `norm=false`, no normalisation is performed.

# Examples
```jldoctest
julia> using LightGraphs

julia> s_metric(star_graph(4))
0.6
```
"""

function s_metric(g::AbstractGraph{T}; norm=true) where T
s = zero(T)
for e in edges(g)
s += outdegree(g, src(e)) * indegree(g, dst(e))
end
if norm
sm = sum(degree(g).^3)/2
return s/sm
else
return s
end
end
22 changes: 22 additions & 0 deletions test/community/s_metric.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Random, Statistics

@testset "S-metric" begin
@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)
sm = s_metric(g, norm=false)
sm2 = sum([outdegree(g, src(d)) * indegree(g, dst(d)) for d in edges(g)])
@test @inferred sm ≈ sm2
sm = s_metric(g, norm=true)
sm2 /= sum(degree(g).^3)/2
@test @inferred sm ≈ sm2
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)
sm = s_metric(g, norm=false)
sm2 = sum([degree(g, src(d)) * degree(g, dst(d)) for d in edges(g)])
@test @inferred sm ≈ sm2
sm = s_metric(g, norm=true)
sm2 /= sum(degree(g).^3)/2
@test @inferred sm ≈ sm2
end
end
5 changes: 3 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -60,6 +60,7 @@ tests = [
"community/clustering",
"community/clique_percolation",
"community/assortativity",
"community/s_metric",
"centrality/betweenness",
"centrality/closeness",
"centrality/degree",
Expand Down