Mercurial > repos > shellac > sam_consensus_v3
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])) |