Skip to content
This repository has been archived by the owner on Jun 23, 2023. It is now read-only.

Resilience #139

Merged
merged 10 commits into from
Jun 25, 2019
16 changes: 8 additions & 8 deletions Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ uuid = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
version = "0.8.10"

[[BinaryProvider]]
deps = ["Libdl", "Pkg", "SHA", "Test"]
git-tree-sha1 = "055eb2690182ebc31087859c3dd8598371d3ef9e"
deps = ["Libdl", "SHA"]
git-tree-sha1 = "c7361ce8a2129f20b0e05a89f7070820cfed6648"
uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
version = "0.5.3"
version = "0.5.4"

[[Combinatorics]]
deps = ["LinearAlgebra", "Polynomials", "Test"]
Expand Down Expand Up @@ -79,10 +79,10 @@ deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[Missings]]
deps = ["Dates", "InteractiveUtils", "SparseArrays", "Test"]
git-tree-sha1 = "d1d2585677f2bd93a97cfeb8faa7a0de0f982042"
deps = ["SparseArrays", "Test"]
git-tree-sha1 = "f0719736664b4358aa9ec173077d4285775f8007"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "0.4.0"
version = "0.4.1"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
Expand All @@ -95,9 +95,9 @@ version = "1.1.0"

[[PDMats]]
deps = ["Arpack", "LinearAlgebra", "SparseArrays", "SuiteSparse", "Test"]
git-tree-sha1 = "b6c91fc0ab970c0563cbbe69af18d741a49ce551"
git-tree-sha1 = "8b68513175b2dc4023a564cb0e917ce90e74fd69"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.9.6"
version = "0.9.7"

[[Pkg]]
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
Expand Down
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

Expand Down
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ makedocs(
"Centrality and paths" => "properties/paths.md",
"Overlap and similarity" => "properties/overlap.md",
"Null models" => "properties/nullmodels.md",
"Beta-diversity" => "properties/betadiversity.md",
"Resilience" => "properties/resilience.md"
"Information theory" => "properties/information.md",
"Beta-diversity" => "properties/betadiversity.md"
]
]
)
Expand Down
49 changes: 49 additions & 0 deletions docs/src/properties/resilience.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Resilience

We provide the metrics proposed by Gao et al (2016) which summarize the global
behaviour of complex unipartite networks. The dynamics of a system of N components
(nodes/species) can follow the coupled nonlinear differential equation

$$
\frac{\text{d}x_i}{\text{d}t} = F(x_i) + \sum_{j=1}^N A_{ij}G(x_i, x_j)
$$

where the adjacency matrix $$A$$ captures the interaction between the components.

This system can be descibed in 1-D using an effective term

$$
\frac{\text{d}x_\text{eff}}{\text{d}t} = F(x_\text{eff}) + \beta_\text{eff}G(x_\text{eff}, x_\text{eff})
$$

with $$\beta_\text{eff}$$ a single resilience parameter which can capture
the effect of perturbating the system (node/link removal, weight change...).
This resience parameter can be computed from an `AbstractUnipartiteNetwork`
using the functions `βeff` or `resilience`.

It can be shown that

$$
\beta_\text{eff} = \langle s \rangle + \mathcal{S} \mathcal{H}\,,
$$

with

- $$\langle s \rangle$$ the average weighted degree (computed using `s_mean`),
- $$\mathcal{S}$$ the symmetry(computed using `symmetry`),
- $$\mathcal{H}$$ the heterogeneity (computed using `heterogeneity`).


> Goa, J., Barzael, B. and Barabási 2016. Universal resilience patterns in complex networks.
> Nature 530(7590), 307-312. doi:10.1038/nature16948

## Available functions

```@docs
s
σ_in
σ_out
symmetry
heterogeneity
resilience
```
7 changes: 7 additions & 0 deletions src/EcologicalNetworks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ include(joinpath(".", "community/overlap.jl"))
export overlap
export AJS, EAJS

# Overlap
include(joinpath(".", "community/resilience.jl"))
export resilience
export symmetry, heterogeneity
export s
export σ_in, σ_out

# Modularity
include(joinpath(".", "modularity/utilities.jl"))
export Q, Qr
Expand Down
103 changes: 103 additions & 0 deletions src/community/resilience.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#=
Some functions from *Universal resilience patterns in complex networks*
by Gao et al. (2016)
=#

using Statistics: mean, std

"""
s(N::AbstractUnipartiteNetwork; dims::Union{Nothing,Integer}=nothing)

Computes the average weighted degree. This is proportional to the (weighted)
density of interactions.

If dims is provided, the incoming (`dims=1`) or outgoing (`dims=2`) is computed.
"""
function s(N::AbstractUnipartiteNetwork; dims::Union{Nothing,Integer}=nothing)
dims == 1 && return sum(N.A, dims=2)
dims == 2 && return sum(N.A, dims=1)'
if dims == nothing
return sum(N.A) / size(N)[1]
end
end
#=
"""
s(N::AbstractUnipartiteNetwork; dims)

Computes the vector of incoming weighted degrees of an unipartite network.
"""
s_in(N::AbstractUnipartiteNetwork) = sum(N.A, dims=2)
MichielStock marked this conversation as resolved.
Show resolved Hide resolved

"""
s_out(N::AbstractUnipartiteNetwork)

Computes the vector of outgoing weighted degrees of an unipartite network.
"""
s_out(N::AbstractUnipartiteNetwork) = sum(N.A, dims=1)'

=#

"""
σ_in(N::AbstractUnipartiteNetwork)

Computes the standard deviation of the ingoing weighted degree of an unipartite
network.
"""
σ_in(N::AbstractUnipartiteNetwork) = std(s(N, dims=1), corrected=false)

"""
σ_out(N::AbstractUnipartiteNetwork)

Computes the standard deviation of the outgoing weighted degree of an unipartite
network.
"""
σ_out(N::AbstractUnipartiteNetwork) = std(s(N, dims=2), corrected=false)

"""
symmetry(N::AbstractUnipartiteNetwork)

Computes the symmetry between s^in and s^out (the in- and outgoing weighted
degree of an unipartite network). This is computed as the Pearson correlation
between the s^in and s^out. It is hence a value between -1 and 1, where high
positive values indicate that species with many outgoing degrees tend to have
many ingoing degrees and negative values mean the opposite. An undirected network
is perfectly symmetric but, for example, a food web where predators are less likely
to be prey would have a negative symmetry.

> Goa, J., Barzael, B. and Barabási 2016. Universal resilience patterns in complex networks.
> Nature 530(7590), 307-312. doi:10.1038/nature16948

"""
symmetry(N::AbstractUnipartiteNetwork) = (mean(s(N, dims=1) .* s(N, dims=2)) - mean(s(N, dims=1)) * mean(s(N, dims=2))) / (σ_in(N) * σ_out(N))

"""
heterogeneity(N::AbstractUnipartiteNetwork)

Computes the heterogeneity for an unipartite network, a topological characteristic
which quantifies the difference in in- and outgoing degrees between species. It
is computed as σ_in * σ_out / s_mean. A value of 0 indicates that all species
have the same (weighted) in- and outdegrees.

> Goa, J., Barzael, B. and Barabási 2016. Universal resilience patterns in complex networks.
> Nature 530(7590), 307-312. doi:10.1038/nature16948

"""
heterogeneity(N::AbstractUnipartiteNetwork) = (σ_in(N) * σ_out(N)) / s(N)

"""
resilience(N::AbstractUnipartiteNetwork)
MichielStock marked this conversation as resolved.
Show resolved Hide resolved

A resilience parameters described by Gao et al. (2016). It is a global parameters
describing the dynamics of an unipartite network as an effective 1D equation of
the form

f(xeff) = F(xeff) + βeff G(xeff, xeff)

i.e. describing a second-order term representing the effect of the network on the
dynamics of the 'effective state' xeff of the system.

> Goa, J., Barzael, B. and Barabási 2016. Universal resilience patterns in complex networks.
> Nature 530(7590), 307-312. doi:10.1038/nature16948

"""
resilience(N::AbstractUnipartiteNetwork) = dot(s(N, dims=1), s(N, dims=2)) / sum(N)
42 changes: 42 additions & 0 deletions test/community/resilience.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module TestResilience
using Test, EcologicalNetworks

A = rand([0, 1, 0.5], 10, 10)
N = UnipartiteQuantitativeNetwork(A)

@assert s(N) ≈ sum(A) / 10
@assert s(N, dims=1) ≈ sum(A, dims=2)
@assert s(N, dims=2) ≈ sum(A, dims=1)'

@assert resilience(N) ≈ s(N) + symmetry(N) * heterogeneity(N)

# species only interact with themselves
Nid = UnipartiteNetwork([true false false false;
false true false false;
false false true false;
false false false true])

@assert heterogeneity(Nid) ≈ 0.0
# @assert symmetry(Nid) NAN

# symetric network
Nsym = UnipartiteNetwork([false true true true;
true false false false;
true false false false;
true false false false])
@assert symmetry(Nsym) ≈ 1.0 # in- and out degree is same
@assert heterogeneity(Nsym) ≈ 0.5


# asymetric network
Nasym = UnipartiteNetwork([false true true true;
false false false false;
false false false false;
false false false false])
@assert symmetry(Nasym) ≈ -1.0 # in- and out degree is same
@assert heterogeneity(Nasym) ≈ 0.75

v = ones(10) / 10
Nhomo = UnipartiteProbabilisticNetwork(v * v')
@assert isapprox(heterogeneity(Nhomo), 0.0, atol=1e-10)
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ my_tests = [
"community/centrality.jl",
"community/motifs.jl",
"community/foodwebs.jl",
"community/resilience.jl",
"betadiversity/operations.jl",
"betadiversity/partitions.jl",
"modularity/utilities.jl",
Expand Down