diff --git a/docs/src/macro_level/degeneracy.md b/docs/src/macro_level/degeneracy.md index cb94cf90..718efa8d 100644 --- a/docs/src/macro_level/degeneracy.md +++ b/docs/src/macro_level/degeneracy.md @@ -9,4 +9,10 @@ ```@docs isdisconnected isdegenerate -``` \ No newline at end of file +``` + +## Simplification of networks with disconnected species + +```@docs +simplify +``` diff --git a/src/SpeciesInteractionNetworks.jl b/src/SpeciesInteractionNetworks.jl index 45225a1e..444e7b36 100644 --- a/src/SpeciesInteractionNetworks.jl +++ b/src/SpeciesInteractionNetworks.jl @@ -90,6 +90,7 @@ export spectralradius include("macro_level/degeneracy.jl") export isdegenerate, isdisconnected +export simplify include("meta_level/set.jl") include("meta_level/partitions.jl") diff --git a/src/interfaces/abstractarray.jl b/src/interfaces/abstractarray.jl index 4d01c15d..13132cf8 100644 --- a/src/interfaces/abstractarray.jl +++ b/src/interfaces/abstractarray.jl @@ -15,6 +15,9 @@ Base.axes(N::SpeciesInteractionNetwork, i::Integer) = axes(N.edges, i) Base.size(E::Interactions) = size(E.edges) Base.size(E::Interactions, i::Integer) = size(E.edges, i) +Base.size(E::Bipartite) = (length(E.top), length(E.bottom)) +Base.size(E::Unipartite) = (length(E.margin), length(E.margin)) + Base.size(N::SpeciesInteractionNetwork) = size(N.edges) Base.size(N::SpeciesInteractionNetwork, i::Integer) = size(N.edges, i) diff --git a/src/macro_level/degeneracy.jl b/src/macro_level/degeneracy.jl index d004db84..58e250c4 100644 --- a/src/macro_level/degeneracy.jl +++ b/src/macro_level/degeneracy.jl @@ -81,4 +81,42 @@ end @test ~isdisconnected(N, :A, true) @test isdisconnected(N, :B, false) @test isdisconnected(N, :B, true) +end + +""" + simplify(N::SpeciesInteractionNetwork{<:Bipartite, <:Interactions}) + +Returns a *copy* of a network containing only the species with interactions. +Internally, this calls [`isdisconnected`](@ref). +""" +function simplify(N::SpeciesInteractionNetwork{<:Bipartite, <:Interactions}) + top_nodes = filter(sp -> !isdisconnected(N, sp), species(N, 1)) + bot_nodes = filter(sp -> !isdisconnected(N, sp), species(N, 2)) + return subgraph(N, top_nodes, bot_nodes) +end + +""" + simplify(N::SpeciesInteractionNetwork{<:Unipartite, <:Interactions}, allow_self_interactions::Bool=true) + +Returns a *copy* of a network containing only the species with interactions. +Internally, this calls [`isdisconnected`](@ref) -- see this documentation for +the consequences of `allow_self_interactions`. +""" +function simplify(N::SpeciesInteractionNetwork{<:Unipartite, <:Interactions}, allow_self_interactions::Bool=true) + nodes = filter(sp -> !isdisconnected(N, sp, allow_self_interactions), species(N)) + return subgraph(N, nodes) +end + +@testitem "We can simplify a bipartite network" begin + nodes = Bipartite([:A, :B, :C], [:a, :b]) + edges = Binary(zeros(Bool, size(nodes))) + N = SpeciesInteractionNetwork(nodes, edges) + N[:A, :a] = true + N[:A, :b] = true + N[:C, :a] = true + S = simplify(N) + @test richness(S) == 4 + S[:A, :a] = false + @test N[:A, :a] == true + @test S[:A, :a] == false end \ No newline at end of file