comparison env/lib/python3.9/site-packages/networkx/algorithms/centrality/tests/test_trophic.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """Test trophic levels, trophic differences and trophic coherence
2 """
3 import pytest
4
5 np = pytest.importorskip("numpy")
6
7 import networkx as nx
8 from networkx.testing import almost_equal
9
10
11 def test_trophic_levels():
12 """Trivial example
13 """
14 G = nx.DiGraph()
15 G.add_edge("a", "b")
16 G.add_edge("b", "c")
17
18 d = nx.trophic_levels(G)
19 assert d == {"a": 1, "b": 2, "c": 3}
20
21
22 def test_trophic_levels_levine():
23 """Example from Figure 5 in Stephen Levine (1980) J. theor. Biol. 83,
24 195-207
25 """
26 S = nx.DiGraph()
27 S.add_edge(1, 2, weight=1.0)
28 S.add_edge(1, 3, weight=0.2)
29 S.add_edge(1, 4, weight=0.8)
30 S.add_edge(2, 3, weight=0.2)
31 S.add_edge(2, 5, weight=0.3)
32 S.add_edge(4, 3, weight=0.6)
33 S.add_edge(4, 5, weight=0.7)
34 S.add_edge(5, 4, weight=0.2)
35
36 # save copy for later, test intermediate implementation details first
37 S2 = S.copy()
38
39 # drop nodes of in-degree zero
40 z = [nid for nid, d in S.in_degree if d == 0]
41 for nid in z:
42 S.remove_node(nid)
43
44 # find adjacency matrix
45 q = nx.linalg.graphmatrix.adjacency_matrix(S).T
46
47 # fmt: off
48 expected_q = np.array([
49 [0, 0, 0., 0],
50 [0.2, 0, 0.6, 0],
51 [0, 0, 0, 0.2],
52 [0.3, 0, 0.7, 0]
53 ])
54 # fmt: on
55 assert np.array_equal(q.todense(), expected_q)
56
57 # must be square, size of number of nodes
58 assert len(q.shape) == 2
59 assert q.shape[0] == q.shape[1]
60 assert q.shape[0] == len(S)
61
62 nn = q.shape[0]
63
64 i = np.eye(nn)
65 n = np.linalg.inv(i - q)
66 y = np.dot(np.asarray(n), np.ones(nn))
67
68 expected_y = np.array([1, 2.07906977, 1.46511628, 2.3255814])
69 assert np.allclose(y, expected_y)
70
71 expected_d = {1: 1, 2: 2, 3: 3.07906977, 4: 2.46511628, 5: 3.3255814}
72
73 d = nx.trophic_levels(S2)
74
75 for nid, level in d.items():
76 expected_level = expected_d[nid]
77 assert almost_equal(expected_level, level)
78
79
80 def test_trophic_levels_simple():
81 matrix_a = np.array([[0, 0], [1, 0]])
82 G = nx.from_numpy_array(matrix_a, create_using=nx.DiGraph)
83 d = nx.trophic_levels(G)
84 assert almost_equal(d[0], 2)
85 assert almost_equal(d[1], 1)
86
87
88 def test_trophic_levels_more_complex():
89 # fmt: off
90 matrix = np.array([
91 [0, 1, 0, 0],
92 [0, 0, 1, 0],
93 [0, 0, 0, 1],
94 [0, 0, 0, 0]
95 ])
96 # fmt: on
97 G = nx.from_numpy_array(matrix, create_using=nx.DiGraph)
98 d = nx.trophic_levels(G)
99 expected_result = [1, 2, 3, 4]
100 for ind in range(4):
101 assert almost_equal(d[ind], expected_result[ind])
102
103 # fmt: off
104 matrix = np.array([
105 [0, 1, 1, 0],
106 [0, 0, 1, 1],
107 [0, 0, 0, 1],
108 [0, 0, 0, 0]
109 ])
110 # fmt: on
111 G = nx.from_numpy_array(matrix, create_using=nx.DiGraph)
112 d = nx.trophic_levels(G)
113
114 expected_result = [1, 2, 2.5, 3.25]
115 print("Calculated result: ", d)
116 print("Expected Result: ", expected_result)
117
118 for ind in range(4):
119 assert almost_equal(d[ind], expected_result[ind])
120
121
122 def test_trophic_levels_even_more_complex():
123 # fmt: off
124 # Another, bigger matrix
125 matrix = np.array([
126 [0, 0, 0, 0, 0],
127 [0, 1, 0, 1, 0],
128 [1, 0, 0, 0, 0],
129 [0, 1, 0, 0, 0],
130 [0, 0, 0, 1, 0]
131 ])
132 # Generated this linear system using pen and paper:
133 K = np.array([
134 [1, 0, -1, 0, 0],
135 [0, 0.5, 0, -0.5, 0],
136 [0, 0, 1, 0, 0],
137 [0, -0.5, 0, 1, -0.5],
138 [0, 0, 0, 0, 1],
139 ])
140 # fmt: on
141 result_1 = np.ravel(np.matmul(np.linalg.inv(K), np.ones(5)))
142 G = nx.from_numpy_array(matrix, create_using=nx.DiGraph)
143 result_2 = nx.trophic_levels(G)
144
145 for ind in range(5):
146 assert almost_equal(result_1[ind], result_2[ind])
147
148
149 def test_trophic_levels_singular_matrix():
150 """Should raise an error with graphs with only non-basal nodes
151 """
152 matrix = np.identity(4)
153 G = nx.from_numpy_array(matrix, create_using=nx.DiGraph)
154 with pytest.raises(nx.NetworkXError) as e:
155 nx.trophic_levels(G)
156 msg = (
157 "Trophic levels are only defined for graphs where every node "
158 + "has a path from a basal node (basal nodes are nodes with no "
159 + "incoming edges)."
160 )
161 assert msg in str(e.value)
162
163
164 def test_trophic_levels_singular_with_basal():
165 """Should fail to compute if there are any parts of the graph which are not
166 reachable from any basal node (with in-degree zero).
167 """
168 G = nx.DiGraph()
169 # a has in-degree zero
170 G.add_edge("a", "b")
171
172 # b is one level above a, c and d
173 G.add_edge("c", "b")
174 G.add_edge("d", "b")
175
176 # c and d form a loop, neither are reachable from a
177 G.add_edge("c", "d")
178 G.add_edge("d", "c")
179
180 with pytest.raises(nx.NetworkXError) as e:
181 nx.trophic_levels(G)
182 msg = (
183 "Trophic levels are only defined for graphs where every node "
184 + "has a path from a basal node (basal nodes are nodes with no "
185 + "incoming edges)."
186 )
187 assert msg in str(e.value)
188
189 # if self-loops are allowed, smaller example:
190 G = nx.DiGraph()
191 G.add_edge("a", "b") # a has in-degree zero
192 G.add_edge("c", "b") # b is one level above a and c
193 G.add_edge("c", "c") # c has a self-loop
194 with pytest.raises(nx.NetworkXError) as e:
195 nx.trophic_levels(G)
196 msg = (
197 "Trophic levels are only defined for graphs where every node "
198 + "has a path from a basal node (basal nodes are nodes with no "
199 + "incoming edges)."
200 )
201 assert msg in str(e.value)
202
203
204 def test_trophic_differences():
205 matrix_a = np.array([[0, 1], [0, 0]])
206 G = nx.from_numpy_array(matrix_a, create_using=nx.DiGraph)
207 diffs = nx.trophic_differences(G)
208 assert almost_equal(diffs[(0, 1)], 1)
209
210 # fmt: off
211 matrix_b = np.array([
212 [0, 1, 1, 0],
213 [0, 0, 1, 1],
214 [0, 0, 0, 1],
215 [0, 0, 0, 0]
216 ])
217 # fmt: on
218 G = nx.from_numpy_array(matrix_b, create_using=nx.DiGraph)
219 diffs = nx.trophic_differences(G)
220
221 assert almost_equal(diffs[(0, 1)], 1)
222 assert almost_equal(diffs[(0, 2)], 1.5)
223 assert almost_equal(diffs[(1, 2)], 0.5)
224 assert almost_equal(diffs[(1, 3)], 1.25)
225 assert almost_equal(diffs[(2, 3)], 0.75)
226
227
228 def test_trophic_incoherence_parameter_no_cannibalism():
229 matrix_a = np.array([[0, 1], [0, 0]])
230 G = nx.from_numpy_array(matrix_a, create_using=nx.DiGraph)
231 q = nx.trophic_incoherence_parameter(G, cannibalism=False)
232 assert almost_equal(q, 0)
233
234 # fmt: off
235 matrix_b = np.array([
236 [0, 1, 1, 0],
237 [0, 0, 1, 1],
238 [0, 0, 0, 1],
239 [0, 0, 0, 0]
240 ])
241 # fmt: on
242 G = nx.from_numpy_array(matrix_b, create_using=nx.DiGraph)
243 q = nx.trophic_incoherence_parameter(G, cannibalism=False)
244 assert almost_equal(q, np.std([1, 1.5, 0.5, 0.75, 1.25]))
245
246 # fmt: off
247 matrix_c = np.array([
248 [0, 1, 1, 0],
249 [0, 1, 1, 1],
250 [0, 0, 0, 1],
251 [0, 0, 0, 1]
252 ])
253 # fmt: on
254 G = nx.from_numpy_array(matrix_c, create_using=nx.DiGraph)
255 q = nx.trophic_incoherence_parameter(G, cannibalism=False)
256 # Ignore the -link
257 assert almost_equal(q, np.std([1, 1.5, 0.5, 0.75, 1.25]))
258
259 # no self-loops case
260 # fmt: off
261 matrix_d = np.array([
262 [0, 1, 1, 0],
263 [0, 0, 1, 1],
264 [0, 0, 0, 1],
265 [0, 0, 0, 0]
266 ])
267 # fmt: on
268 G = nx.from_numpy_array(matrix_d, create_using=nx.DiGraph)
269 q = nx.trophic_incoherence_parameter(G, cannibalism=False)
270 # Ignore the -link
271 assert almost_equal(q, np.std([1, 1.5, 0.5, 0.75, 1.25]))
272
273
274 def test_trophic_incoherence_parameter_cannibalism():
275 matrix_a = np.array([[0, 1], [0, 0]])
276 G = nx.from_numpy_array(matrix_a, create_using=nx.DiGraph)
277 q = nx.trophic_incoherence_parameter(G, cannibalism=True)
278 assert almost_equal(q, 0)
279
280 # fmt: off
281 matrix_b = np.array([
282 [0, 0, 0, 0, 0],
283 [0, 1, 0, 1, 0],
284 [1, 0, 0, 0, 0],
285 [0, 1, 0, 0, 0],
286 [0, 0, 0, 1, 0]
287 ])
288 # fmt: on
289 G = nx.from_numpy_array(matrix_b, create_using=nx.DiGraph)
290 q = nx.trophic_incoherence_parameter(G, cannibalism=True)
291 assert almost_equal(q, 2)
292
293 # fmt: off
294 matrix_c = np.array([
295 [0, 1, 1, 0],
296 [0, 0, 1, 1],
297 [0, 0, 0, 1],
298 [0, 0, 0, 0]
299 ])
300 # fmt: on
301 G = nx.from_numpy_array(matrix_c, create_using=nx.DiGraph)
302 q = nx.trophic_incoherence_parameter(G, cannibalism=True)
303 # Ignore the -link
304 assert almost_equal(q, np.std([1, 1.5, 0.5, 0.75, 1.25]))