Statistics
| Branch: | Revision:

iof-tools / networkxMiCe / networkx-master / networkx / tests / test_convert_numpy.py @ 5cef0f13

History | View | Annotate | Download (17.4 KB)

1
from nose import SkipTest
2
from nose.tools import assert_raises, assert_true, assert_equal
3

    
4
import networkx as nx
5
from networkx.generators.classic import barbell_graph, cycle_graph, path_graph
6
from networkx.testing.utils import assert_graphs_equal
7

    
8

    
9
class TestConvertNumpy(object):
10
    numpy = 1  # nosetests attribute, use nosetests -a 'not numpy' to skip test
11

    
12
    @classmethod
13
    def setupClass(cls):
14
        global np
15
        global np_assert_equal
16
        try:
17
            import numpy as np
18
            np_assert_equal = np.testing.assert_equal
19
        except ImportError:
20
            raise SkipTest('NumPy not available.')
21

    
22
    def __init__(self):
23
        self.G1 = barbell_graph(10, 3)
24
        self.G2 = cycle_graph(10, create_using=nx.DiGraph)
25

    
26
        self.G3 = self.create_weighted(nx.Graph())
27
        self.G4 = self.create_weighted(nx.DiGraph())
28

    
29
    def test_exceptions(self):
30
        G = np.array("a")
31
        assert_raises(nx.NetworkXError, nx.to_networkx_graph, G)
32

    
33
    def create_weighted(self, G):
34
        g = cycle_graph(4)
35
        G.add_nodes_from(g)
36
        G.add_weighted_edges_from((u, v, 10 + u) for u, v in g.edges())
37
        return G
38

    
39
    def assert_equal(self, G1, G2):
40
        assert_true(sorted(G1.nodes()) == sorted(G2.nodes()))
41
        assert_true(sorted(G1.edges()) == sorted(G2.edges()))
42

    
43
    def identity_conversion(self, G, A, create_using):
44
        assert(A.sum() > 0)
45
        GG = nx.from_numpy_matrix(A, create_using=create_using)
46
        self.assert_equal(G, GG)
47
        GW = nx.to_networkx_graph(A, create_using=create_using)
48
        self.assert_equal(G, GW)
49
        GI = nx.empty_graph(0, create_using).__class__(A)
50
        self.assert_equal(G, GI)
51

    
52
    def test_shape(self):
53
        "Conversion from non-square array."
54
        A = np.array([[1, 2, 3], [4, 5, 6]])
55
        assert_raises(nx.NetworkXError, nx.from_numpy_matrix, A)
56

    
57
    def test_identity_graph_matrix(self):
58
        "Conversion from graph to matrix to graph."
59
        A = nx.to_numpy_matrix(self.G1)
60
        self.identity_conversion(self.G1, A, nx.Graph())
61

    
62
    def test_identity_graph_array(self):
63
        "Conversion from graph to array to graph."
64
        A = nx.to_numpy_matrix(self.G1)
65
        A = np.asarray(A)
66
        self.identity_conversion(self.G1, A, nx.Graph())
67

    
68
    def test_identity_digraph_matrix(self):
69
        """Conversion from digraph to matrix to digraph."""
70
        A = nx.to_numpy_matrix(self.G2)
71
        self.identity_conversion(self.G2, A, nx.DiGraph())
72

    
73
    def test_identity_digraph_array(self):
74
        """Conversion from digraph to array to digraph."""
75
        A = nx.to_numpy_matrix(self.G2)
76
        A = np.asarray(A)
77
        self.identity_conversion(self.G2, A, nx.DiGraph())
78

    
79
    def test_identity_weighted_graph_matrix(self):
80
        """Conversion from weighted graph to matrix to weighted graph."""
81
        A = nx.to_numpy_matrix(self.G3)
82
        self.identity_conversion(self.G3, A, nx.Graph())
83

    
84
    def test_identity_weighted_graph_array(self):
85
        """Conversion from weighted graph to array to weighted graph."""
86
        A = nx.to_numpy_matrix(self.G3)
87
        A = np.asarray(A)
88
        self.identity_conversion(self.G3, A, nx.Graph())
89

    
90
    def test_identity_weighted_digraph_matrix(self):
91
        """Conversion from weighted digraph to matrix to weighted digraph."""
92
        A = nx.to_numpy_matrix(self.G4)
93
        self.identity_conversion(self.G4, A, nx.DiGraph())
94

    
95
    def test_identity_weighted_digraph_array(self):
96
        """Conversion from weighted digraph to array to weighted digraph."""
97
        A = nx.to_numpy_matrix(self.G4)
98
        A = np.asarray(A)
99
        self.identity_conversion(self.G4, A, nx.DiGraph())
100

    
101
    def test_nodelist(self):
102
        """Conversion from graph to matrix to graph with nodelist."""
103
        P4 = path_graph(4)
104
        P3 = path_graph(3)
105
        nodelist = list(P3)
106
        A = nx.to_numpy_matrix(P4, nodelist=nodelist)
107
        GA = nx.Graph(A)
108
        self.assert_equal(GA, P3)
109

    
110
        # Make nodelist ambiguous by containing duplicates.
111
        nodelist += [nodelist[0]]
112
        assert_raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nodelist)
113

    
114
    def test_weight_keyword(self):
115
        WP4 = nx.Graph()
116
        WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
117
        P4 = path_graph(4)
118
        A = nx.to_numpy_matrix(P4)
119
        np_assert_equal(A, nx.to_numpy_matrix(WP4, weight=None))
120
        np_assert_equal(0.5 * A, nx.to_numpy_matrix(WP4))
121
        np_assert_equal(0.3 * A, nx.to_numpy_matrix(WP4, weight='other'))
122

    
123
    def test_from_numpy_matrix_type(self):
124
        A = np.matrix([[1]])
125
        G = nx.from_numpy_matrix(A)
126
        assert_equal(type(G[0][0]['weight']), int)
127

    
128
        A = np.matrix([[1]]).astype(np.float)
129
        G = nx.from_numpy_matrix(A)
130
        assert_equal(type(G[0][0]['weight']), float)
131

    
132
        A = np.matrix([[1]]).astype(np.str)
133
        G = nx.from_numpy_matrix(A)
134
        assert_equal(type(G[0][0]['weight']), str)
135

    
136
        A = np.matrix([[1]]).astype(np.bool)
137
        G = nx.from_numpy_matrix(A)
138
        assert_equal(type(G[0][0]['weight']), bool)
139

    
140
        A = np.matrix([[1]]).astype(np.complex)
141
        G = nx.from_numpy_matrix(A)
142
        assert_equal(type(G[0][0]['weight']), complex)
143

    
144
        A = np.matrix([[1]]).astype(np.object)
145
        assert_raises(TypeError, nx.from_numpy_matrix, A)
146

    
147
        G = nx.cycle_graph(3)
148
        A = nx.adj_matrix(G).todense()
149
        H = nx.from_numpy_matrix(A)
150
        assert_true(all(type(m) == int and type(n) == int for m, n in H.edges()))
151
        H = nx.from_numpy_array(A)
152
        assert_true(all(type(m) == int and type(n) == int for m, n in H.edges()))
153

    
154
    def test_from_numpy_matrix_dtype(self):
155
        dt = [('weight', float), ('cost', int)]
156
        A = np.matrix([[(1.0, 2)]], dtype=dt)
157
        G = nx.from_numpy_matrix(A)
158
        assert_equal(type(G[0][0]['weight']), float)
159
        assert_equal(type(G[0][0]['cost']), int)
160
        assert_equal(G[0][0]['cost'], 2)
161
        assert_equal(G[0][0]['weight'], 1.0)
162

    
163
    def test_to_numpy_recarray(self):
164
        G = nx.Graph()
165
        G.add_edge(1, 2, weight=7.0, cost=5)
166
        A = nx.to_numpy_recarray(G, dtype=[('weight', float), ('cost', int)])
167
        assert_equal(sorted(A.dtype.names), ['cost', 'weight'])
168
        assert_equal(A.weight[0, 1], 7.0)
169
        assert_equal(A.weight[0, 0], 0.0)
170
        assert_equal(A.cost[0, 1], 5)
171
        assert_equal(A.cost[0, 0], 0)
172

    
173
    def test_numpy_multigraph(self):
174
        G = nx.MultiGraph()
175
        G.add_edge(1, 2, weight=7)
176
        G.add_edge(1, 2, weight=70)
177
        A = nx.to_numpy_matrix(G)
178
        assert_equal(A[1, 0], 77)
179
        A = nx.to_numpy_matrix(G, multigraph_weight=min)
180
        assert_equal(A[1, 0], 7)
181
        A = nx.to_numpy_matrix(G, multigraph_weight=max)
182
        assert_equal(A[1, 0], 70)
183

    
184
    def test_from_numpy_matrix_parallel_edges(self):
185
        """Tests that the :func:`networkx.from_numpy_matrix` function
186
        interprets integer weights as the number of parallel edges when
187
        creating a multigraph.
188

189
        """
190
        A = np.matrix([[1, 1], [1, 2]])
191
        # First, with a simple graph, each integer entry in the adjacency
192
        # matrix is interpreted as the weight of a single edge in the graph.
193
        expected = nx.DiGraph()
194
        edges = [(0, 0), (0, 1), (1, 0)]
195
        expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
196
        expected.add_edge(1, 1, weight=2)
197
        actual = nx.from_numpy_matrix(A, parallel_edges=True,
198
                                      create_using=nx.DiGraph)
199
        assert_graphs_equal(actual, expected)
200
        actual = nx.from_numpy_matrix(A, parallel_edges=False,
201
                                      create_using=nx.DiGraph)
202
        assert_graphs_equal(actual, expected)
203
        # Now each integer entry in the adjacency matrix is interpreted as the
204
        # number of parallel edges in the graph if the appropriate keyword
205
        # argument is specified.
206
        edges = [(0, 0), (0, 1), (1, 0), (1, 1), (1, 1)]
207
        expected = nx.MultiDiGraph()
208
        expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
209
        actual = nx.from_numpy_matrix(A, parallel_edges=True,
210
                                      create_using=nx.MultiDiGraph)
211
        assert_graphs_equal(actual, expected)
212
        expected = nx.MultiDiGraph()
213
        expected.add_edges_from(set(edges), weight=1)
214
        # The sole self-loop (edge 0) on vertex 1 should have weight 2.
215
        expected[1][1][0]['weight'] = 2
216
        actual = nx.from_numpy_matrix(A, parallel_edges=False,
217
                                      create_using=nx.MultiDiGraph)
218
        assert_graphs_equal(actual, expected)
219

    
220
    def test_symmetric(self):
221
        """Tests that a symmetric matrix has edges added only once to an
222
        undirected multigraph when using :func:`networkx.from_numpy_matrix`.
223

224
        """
225
        A = np.matrix([[0, 1], [1, 0]])
226
        G = nx.from_numpy_matrix(A, create_using=nx.MultiGraph)
227
        expected = nx.MultiGraph()
228
        expected.add_edge(0, 1, weight=1)
229
        assert_graphs_equal(G, expected)
230

    
231
    def test_dtype_int_graph(self):
232
        """Test that setting dtype int actually gives an integer matrix.
233

234
        For more information, see GitHub pull request #1363.
235

236
        """
237
        G = nx.complete_graph(3)
238
        A = nx.to_numpy_matrix(G, dtype=int)
239
        assert_equal(A.dtype, int)
240

    
241
    def test_dtype_int_multigraph(self):
242
        """Test that setting dtype int actually gives an integer matrix.
243

244
        For more information, see GitHub pull request #1363.
245

246
        """
247
        G = nx.MultiGraph(nx.complete_graph(3))
248
        A = nx.to_numpy_matrix(G, dtype=int)
249
        assert_equal(A.dtype, int)
250

    
251

    
252
class TestConvertNumpyArray(object):
253
    numpy = 1  # nosetests attribute, use nosetests -a 'not numpy' to skip test
254

    
255
    @classmethod
256
    def setupClass(cls):
257
        global np
258
        global np_assert_equal
259
        try:
260
            import numpy as np
261
            np_assert_equal = np.testing.assert_equal
262
        except ImportError:
263
            raise SkipTest('NumPy not available.')
264

    
265
    def __init__(self):
266
        self.G1 = barbell_graph(10, 3)
267
        self.G2 = cycle_graph(10, create_using=nx.DiGraph)
268

    
269
        self.G3 = self.create_weighted(nx.Graph())
270
        self.G4 = self.create_weighted(nx.DiGraph())
271

    
272
    def create_weighted(self, G):
273
        g = cycle_graph(4)
274
        G.add_nodes_from(g)
275
        G.add_weighted_edges_from((u, v, 10 + u) for u, v in g.edges())
276
        return G
277

    
278
    def assert_equal(self, G1, G2):
279
        assert_true(sorted(G1.nodes()) == sorted(G2.nodes()))
280
        assert_true(sorted(G1.edges()) == sorted(G2.edges()))
281

    
282
    def identity_conversion(self, G, A, create_using):
283
        assert(A.sum() > 0)
284
        GG = nx.from_numpy_array(A, create_using=create_using)
285
        self.assert_equal(G, GG)
286
        GW = nx.to_networkx_graph(A, create_using=create_using)
287
        self.assert_equal(G, GW)
288
        GI = nx.empty_graph(0, create_using).__class__(A)
289
        self.assert_equal(G, GI)
290

    
291
    def test_shape(self):
292
        "Conversion from non-square array."
293
        A = np.array([[1, 2, 3], [4, 5, 6]])
294
        assert_raises(nx.NetworkXError, nx.from_numpy_array, A)
295

    
296
    def test_identity_graph_array(self):
297
        "Conversion from graph to array to graph."
298
        A = nx.to_numpy_array(self.G1)
299
        self.identity_conversion(self.G1, A, nx.Graph())
300

    
301
    def test_identity_digraph_array(self):
302
        """Conversion from digraph to array to digraph."""
303
        A = nx.to_numpy_array(self.G2)
304
        self.identity_conversion(self.G2, A, nx.DiGraph())
305

    
306
    def test_identity_weighted_graph_array(self):
307
        """Conversion from weighted graph to array to weighted graph."""
308
        A = nx.to_numpy_array(self.G3)
309
        self.identity_conversion(self.G3, A, nx.Graph())
310

    
311
    def test_identity_weighted_digraph_array(self):
312
        """Conversion from weighted digraph to array to weighted digraph."""
313
        A = nx.to_numpy_array(self.G4)
314
        self.identity_conversion(self.G4, A, nx.DiGraph())
315

    
316
    def test_nodelist(self):
317
        """Conversion from graph to array to graph with nodelist."""
318
        P4 = path_graph(4)
319
        P3 = path_graph(3)
320
        nodelist = list(P3)
321
        A = nx.to_numpy_array(P4, nodelist=nodelist)
322
        GA = nx.Graph(A)
323
        self.assert_equal(GA, P3)
324

    
325
        # Make nodelist ambiguous by containing duplicates.
326
        nodelist += [nodelist[0]]
327
        assert_raises(nx.NetworkXError, nx.to_numpy_array, P3, nodelist=nodelist)
328

    
329
    def test_weight_keyword(self):
330
        WP4 = nx.Graph()
331
        WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
332
        P4 = path_graph(4)
333
        A = nx.to_numpy_array(P4)
334
        np_assert_equal(A, nx.to_numpy_array(WP4, weight=None))
335
        np_assert_equal(0.5 * A, nx.to_numpy_array(WP4))
336
        np_assert_equal(0.3 * A, nx.to_numpy_array(WP4, weight='other'))
337

    
338
    def test_from_numpy_array_type(self):
339
        A = np.array([[1]])
340
        G = nx.from_numpy_array(A)
341
        assert_equal(type(G[0][0]['weight']), int)
342

    
343
        A = np.array([[1]]).astype(np.float)
344
        G = nx.from_numpy_array(A)
345
        assert_equal(type(G[0][0]['weight']), float)
346

    
347
        A = np.array([[1]]).astype(np.str)
348
        G = nx.from_numpy_array(A)
349
        assert_equal(type(G[0][0]['weight']), str)
350

    
351
        A = np.array([[1]]).astype(np.bool)
352
        G = nx.from_numpy_array(A)
353
        assert_equal(type(G[0][0]['weight']), bool)
354

    
355
        A = np.array([[1]]).astype(np.complex)
356
        G = nx.from_numpy_array(A)
357
        assert_equal(type(G[0][0]['weight']), complex)
358

    
359
        A = np.array([[1]]).astype(np.object)
360
        assert_raises(TypeError, nx.from_numpy_array, A)
361

    
362
    def test_from_numpy_array_dtype(self):
363
        dt = [('weight', float), ('cost', int)]
364
        A = np.array([[(1.0, 2)]], dtype=dt)
365
        G = nx.from_numpy_array(A)
366
        assert_equal(type(G[0][0]['weight']), float)
367
        assert_equal(type(G[0][0]['cost']), int)
368
        assert_equal(G[0][0]['cost'], 2)
369
        assert_equal(G[0][0]['weight'], 1.0)
370

    
371
    def test_to_numpy_recarray(self):
372
        G = nx.Graph()
373
        G.add_edge(1, 2, weight=7.0, cost=5)
374
        A = nx.to_numpy_recarray(G, dtype=[('weight', float), ('cost', int)])
375
        assert_equal(sorted(A.dtype.names), ['cost', 'weight'])
376
        assert_equal(A.weight[0, 1], 7.0)
377
        assert_equal(A.weight[0, 0], 0.0)
378
        assert_equal(A.cost[0, 1], 5)
379
        assert_equal(A.cost[0, 0], 0)
380

    
381
    def test_numpy_multigraph(self):
382
        G = nx.MultiGraph()
383
        G.add_edge(1, 2, weight=7)
384
        G.add_edge(1, 2, weight=70)
385
        A = nx.to_numpy_array(G)
386
        assert_equal(A[1, 0], 77)
387
        A = nx.to_numpy_array(G, multigraph_weight=min)
388
        assert_equal(A[1, 0], 7)
389
        A = nx.to_numpy_array(G, multigraph_weight=max)
390
        assert_equal(A[1, 0], 70)
391

    
392
    def test_from_numpy_array_parallel_edges(self):
393
        """Tests that the :func:`networkx.from_numpy_array` function
394
        interprets integer weights as the number of parallel edges when
395
        creating a multigraph.
396

397
        """
398
        A = np.array([[1, 1], [1, 2]])
399
        # First, with a simple graph, each integer entry in the adjacency
400
        # matrix is interpreted as the weight of a single edge in the graph.
401
        expected = nx.DiGraph()
402
        edges = [(0, 0), (0, 1), (1, 0)]
403
        expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
404
        expected.add_edge(1, 1, weight=2)
405
        actual = nx.from_numpy_array(A, parallel_edges=True,
406
                                     create_using=nx.DiGraph)
407
        assert_graphs_equal(actual, expected)
408
        actual = nx.from_numpy_array(A, parallel_edges=False,
409
                                     create_using=nx.DiGraph)
410
        assert_graphs_equal(actual, expected)
411
        # Now each integer entry in the adjacency matrix is interpreted as the
412
        # number of parallel edges in the graph if the appropriate keyword
413
        # argument is specified.
414
        edges = [(0, 0), (0, 1), (1, 0), (1, 1), (1, 1)]
415
        expected = nx.MultiDiGraph()
416
        expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
417
        actual = nx.from_numpy_array(A, parallel_edges=True,
418
                                     create_using=nx.MultiDiGraph)
419
        assert_graphs_equal(actual, expected)
420
        expected = nx.MultiDiGraph()
421
        expected.add_edges_from(set(edges), weight=1)
422
        # The sole self-loop (edge 0) on vertex 1 should have weight 2.
423
        expected[1][1][0]['weight'] = 2
424
        actual = nx.from_numpy_array(A, parallel_edges=False,
425
                                     create_using=nx.MultiDiGraph)
426
        assert_graphs_equal(actual, expected)
427

    
428
    def test_symmetric(self):
429
        """Tests that a symmetric array has edges added only once to an
430
        undirected multigraph when using :func:`networkx.from_numpy_array`.
431

432
        """
433
        A = np.array([[0, 1], [1, 0]])
434
        G = nx.from_numpy_array(A, create_using=nx.MultiGraph)
435
        expected = nx.MultiGraph()
436
        expected.add_edge(0, 1, weight=1)
437
        assert_graphs_equal(G, expected)
438

    
439
    def test_dtype_int_graph(self):
440
        """Test that setting dtype int actually gives an integer array.
441

442
        For more information, see GitHub pull request #1363.
443

444
        """
445
        G = nx.complete_graph(3)
446
        A = nx.to_numpy_array(G, dtype=int)
447
        assert_equal(A.dtype, int)
448

    
449
    def test_dtype_int_multigraph(self):
450
        """Test that setting dtype int actually gives an integer array.
451

452
        For more information, see GitHub pull request #1363.
453

454
        """
455
        G = nx.MultiGraph(nx.complete_graph(3))
456
        A = nx.to_numpy_array(G, dtype=int)
457
        assert_equal(A.dtype, int)