This repository has been archived by the owner on Jun 23, 2023. It is now read-only.
/
conversions.jl
152 lines (131 loc) · 5.65 KB
/
conversions.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import Base.convert
"""
convert(::Type{UnipartiteNetwork}, N::T) where {T <: BipartiteNetwork}
Projects a deterministic bipartite network in its unipartite representation.
"""
function convert(::Type{UnipartiteNetwork}, N::T) where {T <: BipartiteNetwork}
itype = _interaction_type(N)
S = copy(species(N))
B = zeros(itype, (richness(N), richness(N)))
B[1:size(N)[1],size(N)[1]+1:richness(N)] = N.edges
return UnipartiteNetwork(sparse(B), S)
end
"""
convert(::Type{UnipartiteProbabilisticNetwork}, N::T) where {T <: BipartiteProbabilisticNetwork}
Projects a probabilistic bipartite network in its unipartite representation.
"""
function convert(::Type{UnipartiteProbabilisticNetwork}, N::T) where {T <: BipartiteProbabilisticNetwork}
itype = _interaction_type(N)
S = copy(species(N))
B = zeros(itype, (richness(N), richness(N)))
B[1:size(N)[1],size(N)[1]+1:richness(N)] = N.edges
return UnipartiteProbabilisticNetwork(sparse(B), S)
end
"""
convert(::Type{UnipartiteQuantitativeNetwork}, N::T) where {T <: BipartiteQuantitativeNetwork}
Projects a quantitative bipartite network in its unipartite representation.
"""
function convert(::Type{UnipartiteQuantitativeNetwork}, N::T) where {T <: BipartiteQuantitativeNetwork}
itype = _interaction_type(N)
S = copy(species(N))
B = zeros(itype, (richness(N), richness(N)))
B[1:size(N)[1],size(N)[1]+1:richness(N)] = N.edges
return UnipartiteQuantitativeNetwork(sparse(B), S)
end
"""
convert(::Type{UnipartiteNetwork}, N::T) where {T <: UnipartiteQuantitativeNetwork}
Convert a unipartite quantitative network to a unipartite binary network. This
amounts to *removing* the quantitative information.
"""
function convert(::Type{UnipartiteNetwork}, N::T) where {T <: UnipartiteQuantitativeNetwork}
S = copy(species(N))
B = dropzeros(N.edges)
return UnipartiteNetwork(B .!= zero(eltype(B)), S)
end
"""
convert(::Type{BipartiteNetwork}, N::T) where {T <: BipartiteQuantitativeNetwork}
Convert a bipartite quantitative network to a bipartite binary network. This
amounts to *removing* the quantitative information.
"""
function convert(::Type{BipartiteNetwork}, N::NT) where {NT <: BipartiteQuantitativeNetwork}
T = copy(species(N; dims=1))
B = copy(species(N; dims=2))
M = dropzeros(N.edges)
return BipartiteNetwork(M .!= zero(eltype(M)), T, B)
end
"""
convert(::Type{AbstractUnipartiteNetwork}, N::AbstractBipartiteNetwork)
Projects any bipartite network in its unipartite representation. This function
will call the correct type-to-type `convert` function depending on the type of
the input network.
The type to be converted to *must* be `AbstractUnipartiteNetwork` -- for
example, converting a bipartite probabilistic network to a probabilistic
unipartite network is not a meaningful operation.
"""
function convert(::Type{AbstractUnipartiteNetwork}, N::AbstractBipartiteNetwork)
if typeof(N) <: QuantitativeNetwork
return convert(UnipartiteQuantitativeNetwork, N)
end
if typeof(N) <: BinaryNetwork
return convert(UnipartiteNetwork, N)
end
if typeof(N) <: ProbabilisticNetwork
return convert(UnipartiteProbabilisticNetwork, N)
end
end
"""
convert(::Type{BinaryNetwork}, N::QuantitativeNetwork)
Projects any bipartite network in its unipartite representation. This function
will call the correct type-to-type `convert` function depending on the type of
the input network.
This function does *not* work for probabilistic networks. The operation of
generating a deterministic network from a probabilistic one is different from a
simple conversion: it can be done either through random draws, or by selecting
only interactions with a probability greater than 0 (`N>0.0` will do this).
"""
function convert(::Type{BinaryNetwork}, N::QuantitativeNetwork)
if typeof(N) <: BipartiteQuantitativeNetwork
return convert(BipartiteNetwork, N)
end
if typeof(N) <: UnipartiteQuantitativeNetwork
return convert(UnipartiteNetwork, N)
end
end
# Conversion to bipartite
type_pairs = [
(:BipartiteNetwork, :UnipartiteNetwork),
(:BipartiteProbabilisticNetwork, :UnipartiteProbabilisticNetwork),
(:BipartiteQuantitativeNetwork, :UnipartiteQuantitativeNetwork)
]
for comb in type_pairs
t1, t2 = comb
eval(
quote
"""
convert(::Type{$($t1)}, N::T) where {T <: $($t2)}
Projects a unipartite network (specifically, a `$($t1)`) to its bipartite
representation. The following checks are performed.
First, the network *cannot* be degenerate, since species with no interactions
cannot be assigned to a specific level. Second, the species cannot have both in
and out degree. If these conditions are met, the bipartite network will be
returned.
"""
function convert(::Type{$t1}, N::T) where {T <: $t2}
isdegenerate(N) && throw(ArgumentError("Impossible to convert a degenerate unipartite network into a bipartite one"))
d1 = degree(N; dims=1)
d2 = degree(N; dims=2)
for s in species(N)
(d1[s]*d2[s] == 0) || throw(ArgumentError("Species $s has both in and out degree"))
end
top_species = collect(keys(filter(p -> p.second == zero(eltype(N.edges)), d2)))
bot_species = collect(keys(filter(p -> p.second == zero(eltype(N.edges)), d1)))
A = zeros(_interaction_type(N), (length(top_species), length(bot_species)))
B = $t1(sparse(A), top_species, bot_species)
for s1 in species(B; dims=1), s2 in species(B; dims=2)
B[s1,s2] = N[s1, s2]
end
return B
end
end
)
end