Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/base/graph_backends.py
4048 views
1
"""
2
Implements various backends for Sage graphs.
3
4
"""
5
6
7
8
#*******************************************************************************
9
# Copyright (C) 2008 Robert L. Miller <[email protected]>
10
#
11
# Distributed under the terms of the GNU General Public License (GPL)
12
# http://www.gnu.org/licenses/
13
#*******************************************************************************
14
15
from sage.structure.sage_object import SageObject
16
17
class GenericGraphBackend(SageObject):
18
"""
19
A generic wrapper for the backend of a graph. Various graph classes use
20
extensions of this class. Note, this graph has a number of placeholder
21
functions, so the doctests are rather silly.
22
23
DOCTEST:
24
sage: import sage.graphs.base.graph_backends
25
26
"""
27
_loops = False
28
_multiple_edges = False
29
_name = ''
30
def add_edge(self, u, v, l, directed):
31
"""
32
Add an edge (u,v) to self, with label l. If directed is True, this is
33
interpreted as an arc from u to v.
34
35
INPUT:
36
u,v: vertices
37
l: edge label
38
directed: boolean
39
40
DOCTEST:
41
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
42
sage: G.add_edge(1,2,'a',True)
43
Traceback (most recent call last):
44
...
45
NotImplementedError
46
"""
47
raise NotImplementedError()
48
def add_edges(self, edges, directed):
49
"""
50
Add a sequence of edges to self. If directed is True, these are
51
interpreted as arcs.
52
53
INPUT:
54
edges: iterator
55
directed: boolean
56
57
DOCTEST:
58
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
59
sage: G.add_edges([],True)
60
Traceback (most recent call last):
61
...
62
NotImplementedError
63
"""
64
raise NotImplementedError()
65
def add_vertex(self, name):
66
"""
67
Add a labelled vertex to self.
68
69
INPUT:
70
71
- ``name`` -- vertex label
72
73
OUTPUT:
74
75
If ``name``=``None``, the new vertex name is returned, ``None`` otherwise.
76
77
DOCTEST:
78
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
79
sage: G.add_vertex(0)
80
Traceback (most recent call last):
81
...
82
NotImplementedError
83
"""
84
raise NotImplementedError()
85
def add_vertices(self, vertices):
86
"""
87
Add labelled vertices to self.
88
89
INPUT:
90
91
- ``vertices``: iterator of vertex labels. A new label is created, used and returned in
92
the output list for all ``None`` values in ``vertices``.
93
94
OUTPUT:
95
96
Generated names of new vertices if there is at least one ``None`` value
97
present in ``vertices``. ``None`` otherwise.
98
99
EXAMPLES::
100
101
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
102
sage: G.add_vertices([1,2,3])
103
Traceback (most recent call last):
104
...
105
NotImplementedError
106
"""
107
raise NotImplementedError()
108
def degree(self, v, directed):
109
"""
110
Returns the total number of vertices incident to v.
111
112
INPUT:
113
v: a vertex label
114
directed: boolean
115
OUTPUT:
116
degree of v
117
118
DOCTEST:
119
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
120
sage: G.degree(1, False)
121
Traceback (most recent call last):
122
...
123
NotImplementedError
124
"""
125
raise NotImplementedError()
126
def del_edge(self, u, v, l, directed):
127
"""
128
Deletes the edge (u,v) with label l.
129
130
INPUT:
131
u,v: vertices
132
l: edge label
133
directed: boolean
134
135
DOCTEST:
136
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
137
sage: G.del_edge(1,2,'a',True)
138
Traceback (most recent call last):
139
...
140
NotImplementedError
141
"""
142
raise NotImplementedError()
143
def del_vertex(self, v):
144
"""
145
Delete a labelled vertex in self.
146
147
INPUT:
148
v: vertex label
149
150
DOCTEST:
151
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
152
sage: G.del_vertex(0)
153
Traceback (most recent call last):
154
...
155
NotImplementedError
156
"""
157
raise NotImplementedError()
158
def del_vertices(self, vertices):
159
"""
160
Delete labelled vertices in self.
161
162
INPUT:
163
vertices: iterator of vertex labels
164
165
DOCTEST:
166
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
167
sage: G.del_vertices([1,2,3])
168
Traceback (most recent call last):
169
...
170
NotImplementedError
171
"""
172
raise NotImplementedError()
173
def get_edge_label(self, u, v):
174
"""
175
Returns the edge label of (u,v).
176
177
INPUT:
178
u,v: vertex labels
179
180
OUTPUT:
181
label of (u,v)
182
183
DOCTEST:
184
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
185
sage: G.get_edge_label(1,2)
186
Traceback (most recent call last):
187
...
188
NotImplementedError
189
"""
190
raise NotImplementedError()
191
def has_edge(self, u, v, l):
192
"""
193
True if self has an edge (u,v) with label l.
194
195
INPUT:
196
u,v: vertex labels
197
l: label
198
199
OUTPUT:
200
boolean
201
202
DOCTEST:
203
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
204
sage: G.has_edge(1,2,'a')
205
Traceback (most recent call last):
206
...
207
NotImplementedError
208
"""
209
raise NotImplementedError()
210
def has_vertex(self, v):
211
"""
212
True if self has a vertex with label v.
213
214
INPUT:
215
v: vertex label
216
217
OUTPUT:
218
boolean
219
220
DOCTEST:
221
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
222
sage: G.has_vertex(0)
223
Traceback (most recent call last):
224
...
225
NotImplementedError
226
"""
227
raise NotImplementedError()
228
def iterator_edges(self, vertices, labels):
229
"""
230
Iterate over the edges incident to a sequence of vertices. Edges are
231
assumed to be undirected.
232
233
INPUT:
234
vertices: a list of vertex labels
235
labels: boolean
236
237
OUTPUT:
238
a generator which yields edges, with or without labels
239
depending on the labels parameter.
240
241
DOCTEST:
242
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
243
sage: G.iterator_edges([],True)
244
Traceback (most recent call last):
245
...
246
NotImplementedError
247
"""
248
raise NotImplementedError()
249
def iterator_in_edges(self, vertices, labels):
250
"""
251
Iterate over the incoming edges incident to a sequence of vertices.
252
253
INPUT:
254
vertices: a list of vertex labels
255
labels: boolean
256
257
OUTPUT:
258
a generator which yields edges, with or without labels
259
depending on the labels parameter.
260
261
DOCTEST:
262
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
263
sage: G.iterator_in_edges([],True)
264
Traceback (most recent call last):
265
...
266
NotImplementedError
267
"""
268
raise NotImplementedError()
269
def iterator_out_edges(self, vertices, labels):
270
"""
271
Iterate over the outbound edges incident to a sequence of vertices.
272
273
INPUT:
274
vertices: a list of vertex labels
275
labels: boolean
276
277
OUTPUT:
278
a generator which yields edges, with or without labels
279
depending on the labels parameter.
280
281
DOCTEST:
282
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
283
sage: G.iterator_out_edges([],True)
284
Traceback (most recent call last):
285
...
286
NotImplementedError
287
"""
288
raise NotImplementedError()
289
def iterator_nbrs(self, v):
290
"""
291
Iterate over the vertices adjacent to v.
292
293
INPUT:
294
v: vertex label
295
296
OUTPUT:
297
a generator which yields vertex labels
298
299
DOCTEST:
300
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
301
sage: G.iterator_nbrs(0)
302
Traceback (most recent call last):
303
...
304
NotImplementedError
305
"""
306
raise NotImplementedError()
307
def iterator_in_nbrs(self, v):
308
"""
309
Iterate over the vertices u such that the edge (u,v) is in self
310
(that is, predecessors of v).
311
312
INPUT:
313
v: vertex label
314
315
OUTPUT:
316
a generator which yields vertex labels
317
318
DOCTEST:
319
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
320
sage: G.iterator_in_nbrs(0)
321
Traceback (most recent call last):
322
...
323
NotImplementedError
324
"""
325
raise NotImplementedError()
326
def iterator_out_nbrs(self, v):
327
"""
328
Iterate over the vertices u such that the edge (v,u) is in self
329
(that is, successors of v).
330
331
INPUT:
332
v: vertex label
333
334
OUTPUT:
335
a generator which yields vertex labels
336
337
DOCTEST:
338
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
339
sage: G.iterator_out_nbrs(0)
340
Traceback (most recent call last):
341
...
342
NotImplementedError
343
"""
344
raise NotImplementedError()
345
def iterator_verts(self, verts):
346
"""
347
Iterate over the vertices v with labels in verts.
348
349
INPUT:
350
vertex: vertex labels
351
352
OUTPUT:
353
a generator which yields vertices
354
355
DOCTEST:
356
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
357
sage: G.iterator_verts(0)
358
Traceback (most recent call last):
359
...
360
NotImplementedError
361
"""
362
raise NotImplementedError()
363
def loops(self, new):
364
"""
365
Get/set whether or not self allows loops.
366
367
INPUT:
368
new: boolean or None
369
370
DOCTEST:
371
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
372
sage: G.loops(True)
373
Traceback (most recent call last):
374
...
375
NotImplementedError
376
sage: G.loops(None)
377
Traceback (most recent call last):
378
...
379
NotImplementedError
380
"""
381
raise NotImplementedError()
382
def multiple_edges(self, new):
383
"""
384
Get/set whether or not self allows multiple edges.
385
386
INPUT:
387
new: boolean or None
388
389
DOCTEST:
390
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
391
sage: G.multiple_edges(True)
392
Traceback (most recent call last):
393
...
394
NotImplementedError
395
sage: G.multiple_edges(None)
396
Traceback (most recent call last):
397
...
398
NotImplementedError
399
"""
400
raise NotImplementedError()
401
def name(self, new):
402
"""
403
Get/set name of self.
404
405
INPUT:
406
new: string or None
407
408
DOCTEST:
409
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
410
sage: G.name("A Generic Graph")
411
Traceback (most recent call last):
412
...
413
NotImplementedError
414
sage: G.name(None)
415
Traceback (most recent call last):
416
...
417
NotImplementedError
418
"""
419
raise NotImplementedError()
420
def num_edges(self, directed):
421
"""
422
The number of edges in self
423
424
INPUT:
425
directed: boolean
426
427
DOCTEST:
428
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
429
sage: G.num_edges(True)
430
Traceback (most recent call last):
431
...
432
NotImplementedError
433
sage: G.num_edges(False)
434
Traceback (most recent call last):
435
...
436
NotImplementedError
437
"""
438
raise NotImplementedError()
439
def num_verts(self):
440
"""
441
The number of vertices in self
442
443
DOCTEST:
444
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
445
sage: G.num_verts()
446
Traceback (most recent call last):
447
...
448
NotImplementedError
449
"""
450
raise NotImplementedError()
451
def relabel(self, perm, directed):
452
"""
453
Relabel the vertices of self by a permutation.
454
INPUT:
455
perm: permutation
456
directed: boolean
457
458
DOCTEST:
459
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
460
sage: G.relabel([],False)
461
Traceback (most recent call last):
462
...
463
NotImplementedError
464
"""
465
raise NotImplementedError()
466
def set_edge_label(self, u, v, l, directed):
467
"""
468
Label the edge (u,v) by l.
469
470
INPUT:
471
u,v: vertices
472
l: edge label
473
directed: boolean
474
475
DOCTEST:
476
sage: G = sage.graphs.base.graph_backends.GenericGraphBackend()
477
sage: G.set_edge_label(1,2,'a',True)
478
Traceback (most recent call last):
479
...
480
NotImplementedError
481
"""
482
raise NotImplementedError()
483
484
class NetworkXGraphDeprecated(SageObject):
485
"""
486
Class for unpickling old networkx.XGraph formats
487
488
DOCTEST::
489
490
sage: from sage.graphs.base.graph_backends import NetworkXGraphDeprecated as NXGD
491
sage: X = NXGD()
492
doctest:...
493
494
"""
495
496
def __init__(self):
497
"""
498
Issue deprecation warnings for the old networkx XGraph formats
499
500
EXAMPLE::
501
502
sage: from sage.graphs.base.graph_backends import NetworkXGraphDeprecated
503
sage: NetworkXGraphDeprecated()
504
doctest:...
505
<class 'sage.graphs.base.graph_backends.NetworkXGraphDeprecated'>
506
"""
507
from sage.misc.misc import deprecation
508
deprecation("Your graph object is saved in an old format since networkx "+
509
"was updated to 1.0.1. You can re-save your graph by typing "+
510
"graph.save(filename) to make this warning go away.")
511
512
def mutate(self):
513
"""
514
Change the old networkx XGraph format into the new one.
515
516
OUTPUT:
517
518
- The networkx.Graph or networkx.MultiGraph corresponding to the
519
unpickled data.
520
521
EXAMPLES::
522
523
sage: from sage.graphs.base.graph_backends import NetworkXGraphDeprecated as NXGD
524
sage: X = NXGD()
525
doctest:...
526
sage: X.adj = {1:{2:7}, 2:{1:7}, 3:{2:[4,5,6,7]}, 2:{3:[4,5,6,7]}}
527
sage: X.multiedges = True
528
sage: G = X.mutate()
529
sage: G.edges()
530
[(1, 2), (2, 3)]
531
sage: G.edges(data=True)
532
[(1, 2, {'weight': 7}), (2, 3, {4: {}, 5: {}, 6: {}, 7: {}})]
533
534
"""
535
import networkx
536
new_adj = {}
537
538
for node1, edges in self.adj.iteritems():
539
new_adj[node1] = {}
540
for node2, weights in edges.iteritems():
541
new_adj[node1][node2] = {}
542
if weights is not None:
543
try:
544
for weight in weights:
545
new_adj[node1][node2][weight] = {}
546
except TypeError:
547
new_adj[node1][node2]['weight'] = weights
548
549
if self.multiedges:
550
G = networkx.MultiGraph(new_adj)
551
else:
552
G = networkx.Graph(new_adj)
553
554
return G
555
556
class NetworkXDiGraphDeprecated(SageObject):
557
"""
558
Class for unpickling old networkx.XDiGraph formats
559
560
DOCTEST:
561
sage: import sage.graphs.base.graph_backends
562
"""
563
564
def __init__(self):
565
"""
566
Issue deprecation warnings for the old networkx XDiGraph formats
567
568
EXAMPLE::
569
570
sage: from sage.graphs.base.graph_backends import NetworkXDiGraphDeprecated
571
sage: NetworkXDiGraphDeprecated()
572
doctest:...
573
<class 'sage.graphs.base.graph_backends.NetworkXDiGraphDeprecated'>
574
"""
575
from sage.misc.misc import deprecation
576
deprecation("Your digraph object is saved in an old format since networkx "+
577
"was updated to 1.0.1. You can re-save your digraph by typing "+
578
"digraph.save(filename) to make this warning go away.")
579
580
def mutate(self):
581
"""
582
Change the old networkx XDiGraph format into the new one.
583
584
OUTPUT:
585
586
- The networkx.DiGraph or networkx.MultiDiGraph corresponding to the
587
unpickled data.
588
589
EXAMPLES::
590
591
sage: from sage.graphs.base.graph_backends import NetworkXDiGraphDeprecated as NXDGD
592
sage: X = NXDGD()
593
doctest:...
594
sage: X.adj = {1:{2:7}, 2:{1:[7,8], 3:[4,5,6,7]}}
595
sage: X.multiedges = True
596
sage: G = X.mutate()
597
sage: G.edges()
598
[(1, 2), (2, 1), (2, 3)]
599
sage: G.edges(data=True)
600
[(1, 2, {'weight': 7}), (2, 1, {8: {}, 7: {}}), (2, 3, {4: {}, 5: {}, 6: {}, 7: {}})]
601
602
"""
603
import networkx
604
new_adj = {}
605
606
for node1, edges in self.adj.iteritems():
607
new_adj[node1] = {}
608
for node2, weights in edges.iteritems():
609
new_adj[node1][node2] = {}
610
if weights is not None:
611
try:
612
for weight in weights:
613
new_adj[node1][node2][weight] = {}
614
except TypeError:
615
new_adj[node1][node2]['weight'] = weights
616
617
if self.multiedges:
618
G = networkx.MultiDiGraph(new_adj)
619
else:
620
G = networkx.DiGraph(new_adj)
621
622
return G
623
624
from sage.structure.sage_object import register_unpickle_override
625
register_unpickle_override('networkx.xgraph','XGraph', NetworkXGraphDeprecated)
626
register_unpickle_override('networkx.xdigraph','XDiGraph', NetworkXDiGraphDeprecated)
627
628
class NetworkXGraphBackend(GenericGraphBackend):
629
"""
630
A wrapper for NetworkX as the backend of a graph.
631
632
DOCTEST:
633
sage: import sage.graphs.base.graph_backends
634
635
"""
636
637
_nxg = None
638
639
def __init__(self, N=None):
640
"""
641
Initialize the backend with NetworkX graph N.
642
643
DOCTEST:
644
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
645
sage: G.iterator_edges([],True)
646
<generator object iterator_edges at ...>
647
"""
648
if N is None:
649
import networkx
650
N = networkx.MultiGraph()
651
self._nxg = N
652
653
try:
654
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
655
except AssertionError:
656
self._nxg = self._nxg.mutate()
657
658
def add_edge(self, u, v, l, directed):
659
"""
660
Add an edge (u,v) to self, with label l. If directed is True, this is
661
interpreted as an arc from u to v.
662
663
INPUT:
664
u,v: vertices
665
l: edge label
666
directed: boolean
667
668
DOCTEST:
669
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
670
sage: G.add_edge(1,2,'a',True)
671
"""
672
673
try:
674
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
675
except AssertionError:
676
self._nxg = self._nxg.mutate()
677
678
if u is None: u = self.add_vertex(None)
679
if v is None: v = self.add_vertex(None)
680
681
if l:
682
self._nxg.add_edge(u, v, weight=l)
683
else:
684
self._nxg.add_edge(u, v)
685
686
def add_edges(self, edges, directed):
687
"""
688
Add a sequence of edges to self. If directed is True, these are
689
interpreted as arcs.
690
691
INPUT:
692
edges: iterator
693
directed: boolean
694
695
DOCTEST:
696
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
697
sage: G.add_edges([],True)
698
"""
699
for e in edges:
700
try:
701
u,v,l = e
702
except ValueError:
703
u,v = e
704
l = None
705
self.add_edge(u,v,l,directed)
706
707
def add_vertex(self, name):
708
"""
709
Add a labelled vertex to self.
710
711
INPUT:
712
713
- ``name``: vertex label
714
715
OUTPUT:
716
717
If ``name``=``None``, the new vertex name is returned. ``None`` otherwise.
718
719
DOCTEST:
720
721
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
722
sage: G.add_vertex(0)
723
"""
724
try:
725
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
726
except AssertionError:
727
self._nxg = self._nxg.mutate()
728
729
retval = None
730
if name is None: # then find an integer to use as a key
731
i = 0
732
while self.has_vertex(i):
733
i=i+1
734
name = i
735
retval = name
736
737
self._nxg.add_node(name)
738
739
return retval
740
741
def add_vertices(self, vertices):
742
"""
743
Add labelled vertices to self.
744
745
INPUT:
746
747
- ``vertices``: iterator of vertex labels. A new label is created, used and returned in
748
the output list for all ``None`` values in ``vertices``.
749
750
OUTPUT:
751
752
Generated names of new vertices if there is at least one ``None`` value
753
present in ``vertices``. ``None`` otherwise.
754
755
EXAMPLES::
756
757
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
758
sage: G.add_vertices([1,2,3])
759
sage: G.add_vertices([4,None,None,5])
760
[0, 6]
761
"""
762
try:
763
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
764
except AssertionError:
765
self._nxg = self._nxg.mutate()
766
767
vertices = list(vertices)
768
nones = vertices.count(None)
769
vertices = filter(lambda v: v is not None, vertices)
770
self._nxg.add_nodes_from(vertices)
771
772
new_names = []
773
i = 0
774
while nones > 0:
775
while self.has_vertex(i):
776
i += 1
777
self._nxg.add_node(i)
778
new_names.append(i)
779
780
nones -= 1
781
i += 1
782
783
return new_names if new_names != [] else None
784
785
def degree(self, v, directed):
786
"""
787
Returns the total number of vertices incident to v.
788
789
INPUT:
790
v: a vertex label
791
directed: boolean
792
OUTPUT:
793
degree of v
794
795
DOCTEST:
796
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
797
sage: G.add_vertices(range(3))
798
sage: G.degree(1, False)
799
0
800
"""
801
try:
802
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
803
except AssertionError:
804
self._nxg = self._nxg.mutate()
805
806
return self._nxg.degree(v)
807
808
def del_edge(self, u, v, l, directed):
809
"""
810
Deletes the edge (u,v) with label l.
811
812
INPUT:
813
u,v: vertices
814
l: edge label
815
directed: boolean
816
817
DOCTEST:
818
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
819
sage: G.del_edge(1,2,'a',True)
820
"""
821
try:
822
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
823
except AssertionError:
824
self._nxg = self._nxg.mutate()
825
826
import networkx
827
try:
828
if self._nxg.is_multigraph():
829
for k,d in self._nxg.edge[u][v].iteritems():
830
if d.get('weight',None) == l:
831
self._nxg.remove_edge(u,v,k)
832
break
833
else:
834
if l is None or self._nxg.edge[u][v].get('weight',None) == l:
835
self._nxg.remove_edge(u,v)
836
except (KeyError, networkx.NetworkXError):
837
pass
838
839
840
def del_vertex(self, v):
841
"""
842
Delete a labelled vertex in self.
843
844
INPUT:
845
v: vertex label
846
847
DOCTEST:
848
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
849
sage: G.del_vertex(0)
850
Traceback (most recent call last):
851
...
852
NetworkXError: The node 0 is not in the graph.
853
"""
854
try:
855
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
856
except AssertionError:
857
self._nxg = self._nxg.mutate()
858
859
self._nxg.remove_node(v)
860
861
def del_vertices(self, vertices):
862
"""
863
Delete labelled vertices in self.
864
865
INPUT:
866
vertices: iterator of vertex labels
867
868
DOCTEST:
869
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
870
sage: G.del_vertices([1,2,3])
871
Traceback (most recent call last):
872
...
873
NetworkXError: The node 1 is not in the graph.
874
"""
875
try:
876
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
877
except AssertionError:
878
self._nxg = self._nxg.mutate()
879
880
for v in vertices:
881
self._nxg.remove_node(v)
882
883
def get_edge_label(self, u, v):
884
"""
885
Returns the edge label of (u,v).
886
887
INPUT:
888
u,v: vertex labels
889
890
OUTPUT:
891
label of (u,v)
892
893
DOCTEST:
894
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
895
sage: G.get_edge_label(1,2)
896
Traceback (most recent call last):
897
...
898
NetworkXError: Edge (1,2) requested via get_edge_label does not exist.
899
"""
900
try:
901
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
902
except AssertionError:
903
self._nxg = self._nxg.mutate()
904
905
try:
906
E = self._nxg.edge[u][v]
907
except KeyError:
908
from networkx import NetworkXError
909
raise NetworkXError("Edge (%s,%s) requested via get_edge_label does not exist."%(u,v))
910
911
if self._nxg.is_multigraph():
912
return [ e.get('weight',None) for e in E.itervalues() ]
913
else:
914
return E.get('weight',None)
915
916
def has_edge(self, u, v, l):
917
"""
918
True if self has an edge (u,v) with label l.
919
920
INPUT:
921
u,v: vertex labels
922
l: label
923
924
OUTPUT:
925
boolean
926
927
DOCTEST:
928
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
929
sage: G.has_edge(1,2,'a')
930
False
931
"""
932
try:
933
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
934
except AssertionError:
935
self._nxg = self._nxg.mutate()
936
937
if not self._nxg.has_edge(u, v):
938
return False
939
if l is None:
940
return True
941
if self._nxg.is_multigraph():
942
return any( e.get('weight',None) == l for e in self._nxg.adj[u][v].itervalues() )
943
else:
944
return any( e == l for e in self._nxg.adj[u][v].itervalues() )
945
946
def has_vertex(self, v):
947
"""
948
True if self has a vertex with label v.
949
950
INPUT:
951
v: vertex label
952
953
OUTPUT:
954
boolean
955
956
DOCTEST:
957
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
958
sage: G.has_vertex(0)
959
False
960
"""
961
try:
962
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
963
except AssertionError:
964
self._nxg = self._nxg.mutate()
965
966
return self._nxg.has_node(v)
967
968
def iterator_edges(self, vertices, labels):
969
"""
970
Iterate over the edges incident to a sequence of vertices. Edges are
971
assumed to be undirected.
972
973
INPUT:
974
vertices: a list of vertex labels
975
labels: boolean
976
977
OUTPUT:
978
a generator which yields edges, with or without labels
979
depending on the labels parameter.
980
981
DOCTEST:
982
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
983
sage: G.iterator_edges([],True)
984
<generator object iterator_edges at ...>
985
"""
986
try:
987
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
988
except AssertionError:
989
self._nxg = self._nxg.mutate()
990
991
if labels:
992
for u,v,d in self._nxg.edges_iter(data=True):
993
if u in vertices or v in vertices:
994
yield (u,v,d.get('weight',None))
995
else:
996
for u,v in self._nxg.edges_iter():
997
if u in vertices or v in vertices:
998
yield (u,v)
999
1000
def _iterator_in_edges_with_labels(self, vertices):
1001
"""
1002
Iterate over the incoming edges incident to a sequence of vertices.
1003
Special case, only for internal use.
1004
1005
EXAMPLE::
1006
1007
sage: g = DiGraph(graphs.PetersenGraph(), implementation="networkx")._backend
1008
sage: sorted(list(g.iterator_in_edges([0,1], True)))
1009
[(0, 1, None), (1, 0, None), (2, 1, None), (4, 0, None), (5, 0, None), (6, 1, None)]
1010
"""
1011
try:
1012
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1013
except AssertionError:
1014
self._nxg = self._nxg.mutate()
1015
1016
for u,v,d in self._nxg.in_edges_iter(vertices,data=True):
1017
yield (u,v,d.get('weight',None))
1018
1019
def iterator_in_edges(self, vertices, labels):
1020
"""
1021
Iterate over the incoming edges incident to a sequence of vertices.
1022
1023
INPUT:
1024
vertices: a list of vertex labels
1025
labels: boolean
1026
1027
OUTPUT:
1028
a generator which yields edges, with or without labels
1029
depending on the labels parameter.
1030
1031
DOCTEST:
1032
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1033
sage: i = G.iterator_in_edges([],True)
1034
"""
1035
try:
1036
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1037
except AssertionError:
1038
self._nxg = self._nxg.mutate()
1039
1040
if self._nxg.is_directed():
1041
if labels:
1042
return self._iterator_in_edges_with_labels(vertices)
1043
else:
1044
return self._nxg.in_edges_iter(vertices)
1045
else:
1046
return self.iterator_edges(vertices,labels)
1047
1048
def _iterator_out_edges_with_labels(self, vertices):
1049
"""
1050
Iterate over the outbound edges incident to a sequence of vertices.
1051
Special case, only for internal use.
1052
1053
EXAMPLE::
1054
1055
sage: g = DiGraph(graphs.PetersenGraph(), implementation="networkx")._backend
1056
sage: sorted(list(g.iterator_out_edges([0,1], True)))
1057
[(0, 1, None), (0, 4, None), (0, 5, None), (1, 0, None), (1, 2, None), (1, 6, None)]
1058
"""
1059
try:
1060
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1061
except AssertionError:
1062
self._nxg = self._nxg.mutate()
1063
1064
for u,v,d in self._nxg.out_edges_iter(vertices,data=True):
1065
yield (u,v,d.get('weight',None))
1066
1067
def iterator_out_edges(self, vertices, labels):
1068
"""
1069
Iterate over the outbound edges incident to a sequence of vertices.
1070
1071
INPUT:
1072
vertices: a list of vertex labels
1073
labels: boolean
1074
1075
OUTPUT:
1076
a generator which yields edges, with or without labels
1077
depending on the labels parameter.
1078
1079
DOCTEST:
1080
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1081
sage: i = G.iterator_out_edges([],True)
1082
"""
1083
try:
1084
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1085
except AssertionError:
1086
self._nxg = self._nxg.mutate()
1087
1088
if self._nxg.is_directed():
1089
if labels:
1090
return self._iterator_out_edges_with_labels(vertices)
1091
else:
1092
return self._nxg.out_edges_iter(vertices)
1093
else:
1094
return self.iterator_edges(vertices,labels)
1095
1096
def iterator_nbrs(self, v):
1097
"""
1098
Iterate over the vertices adjacent to v.
1099
1100
INPUT:
1101
v: vertex label
1102
1103
OUTPUT:
1104
a generator which yields vertex labels
1105
1106
DOCTEST:
1107
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1108
sage: G.add_vertex(0)
1109
sage: G.iterator_nbrs(0)
1110
<dictionary-keyiterator object at ...>
1111
"""
1112
try:
1113
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1114
except AssertionError:
1115
self._nxg = self._nxg.mutate()
1116
1117
return self._nxg.neighbors_iter(v)
1118
1119
def iterator_in_nbrs(self, v):
1120
"""
1121
Iterate over the vertices u such that the edge (u,v) is in self
1122
(that is, predecessors of v).
1123
1124
INPUT:
1125
v: vertex label
1126
1127
OUTPUT:
1128
a generator which yields vertex labels
1129
1130
DOCTEST:
1131
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1132
sage: G.iterator_in_nbrs(0)
1133
Traceback (most recent call last):
1134
...
1135
AttributeError: 'MultiGraph' object has no attribute 'predecessors_iter'
1136
"""
1137
try:
1138
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1139
except AssertionError:
1140
self._nxg = self._nxg.mutate()
1141
1142
return self._nxg.predecessors_iter(v)
1143
1144
def iterator_out_nbrs(self, v):
1145
"""
1146
Iterate over the vertices u such that the edge (v,u) is in self
1147
(that is, successors of v).
1148
1149
INPUT:
1150
v: vertex label
1151
1152
OUTPUT:
1153
a generator which yields vertex labels
1154
1155
DOCTEST:
1156
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1157
sage: G.iterator_out_nbrs(0)
1158
Traceback (most recent call last):
1159
...
1160
AttributeError: 'MultiGraph' object has no attribute 'successors_iter'
1161
"""
1162
try:
1163
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1164
except AssertionError:
1165
self._nxg = self._nxg.mutate()
1166
1167
return self._nxg.successors_iter(v)
1168
1169
def iterator_verts(self, verts):
1170
"""
1171
Iterate over the vertices v with labels in verts.
1172
1173
INPUT:
1174
vertex: vertex labels
1175
1176
OUTPUT:
1177
a generator which yields vertices
1178
1179
DOCTEST:
1180
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1181
sage: G.iterator_verts(0)
1182
<generator object bunch_iter at ...>
1183
"""
1184
try:
1185
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1186
except AssertionError:
1187
self._nxg = self._nxg.mutate()
1188
1189
return self._nxg.nbunch_iter(verts)
1190
1191
def loops(self, new):
1192
"""
1193
Get/set whether or not self allows loops.
1194
1195
INPUT:
1196
new: boolean or None
1197
1198
DOCTEST:
1199
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1200
sage: G.loops(True)
1201
sage: G.loops(None)
1202
True
1203
"""
1204
if new is None:
1205
return self._loops
1206
if new:
1207
self._loops = True
1208
else:
1209
self._loops = False
1210
1211
def multiple_edges(self, new):
1212
"""
1213
Get/set whether or not self allows multiple edges.
1214
1215
INPUT:
1216
new: boolean or None
1217
1218
DOCTEST:
1219
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1220
sage: G.multiple_edges(True)
1221
sage: G.multiple_edges(None)
1222
True
1223
"""
1224
try:
1225
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1226
except AssertionError:
1227
self._nxg = self._nxg.mutate()
1228
1229
from networkx import Graph,MultiGraph,DiGraph,MultiDiGraph
1230
if new is None:
1231
return self._nxg.is_multigraph()
1232
if new == self._nxg.is_multigraph():
1233
return
1234
if new:
1235
if self._nxg.is_directed():
1236
self._nxg = MultiDiGraph(self._nxg)
1237
else:
1238
self._nxg = MultiGraph(self._nxg)
1239
else:
1240
if self._nxg.is_directed():
1241
self._nxg = DiGraph(self._nxg)
1242
else:
1243
self._nxg = Graph(self._nxg)
1244
1245
def name(self, new):
1246
"""
1247
Get/set name of self.
1248
1249
INPUT:
1250
new: string or None
1251
1252
DOCTEST:
1253
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1254
sage: G.name("A NetworkX Graph")
1255
sage: G.name(None)
1256
'A NetworkX Graph'
1257
"""
1258
try:
1259
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1260
except AssertionError:
1261
self._nxg = self._nxg.mutate()
1262
1263
if new is None:
1264
return self._nxg.name
1265
self._nxg.name = new
1266
1267
def num_edges(self, directed):
1268
"""
1269
The number of edges in self
1270
1271
INPUT:
1272
directed: boolean
1273
1274
DOCTEST:
1275
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1276
sage: G.num_edges(True)
1277
0
1278
sage: G.num_edges(False)
1279
0
1280
"""
1281
try:
1282
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1283
except AssertionError:
1284
self._nxg = self._nxg.mutate()
1285
1286
return self._nxg.size()
1287
1288
def num_verts(self):
1289
"""
1290
The number of vertices in self
1291
1292
DOCTEST:
1293
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1294
sage: G.num_verts()
1295
0
1296
"""
1297
try:
1298
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1299
except AssertionError:
1300
self._nxg = self._nxg.mutate()
1301
1302
return self._nxg.order()
1303
1304
def relabel(self, perm, directed):
1305
"""
1306
Relabel the vertices of self by a permutation.
1307
INPUT:
1308
perm: permutation
1309
directed: boolean
1310
1311
DOCTEST:
1312
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1313
sage: G.relabel([],False)
1314
"""
1315
try:
1316
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1317
except AssertionError:
1318
self._nxg = self._nxg.mutate()
1319
1320
from networkx import relabel_nodes
1321
name = self._nxg.name
1322
self._nxg = relabel_nodes(self._nxg,perm)
1323
self._nxg.name = name
1324
1325
# if directed:
1326
# oldsucc = self._nxg.succ
1327
# oldpred = self._nxg.pred
1328
# newsucc = {}
1329
# newpred = {}
1330
# for v in oldsucc.iterkeys():
1331
# oldtempsucc = oldsucc[v]
1332
# newtempsucc = {}
1333
# for w in oldtempsucc.iterkeys():
1334
# newtempsucc[perm[w]] = oldtempsucc[w]
1335
# newsucc[perm[v]] = newtempsucc
1336
# for v in oldpred.iterkeys():
1337
# oldtemppred = oldpred[v]
1338
# newtemppred = {}
1339
# for w in oldtemppred.iterkeys():
1340
# newtemppred[perm[w]] = oldtemppred[w]
1341
# newpred[perm[v]] = newtemppred
1342
# self._nxg.adj = newsucc
1343
# self._nxg.succ = self._nxg.adj
1344
# self._nxg.pred = newpred
1345
# else:
1346
# oldd = self._nxg.adj
1347
# newd = {}
1348
# for v in oldd.iterkeys():
1349
# oldtempd = oldd[v]
1350
# newtempd = {}
1351
# for w in oldtempd.iterkeys():
1352
# newtempd[perm[w]] = oldtempd[w]
1353
# newd[perm[v]] = newtempd
1354
# self._nxg.adj = newd
1355
1356
def set_edge_label(self, u, v, l, directed):
1357
"""
1358
Label the edge (u,v) by l.
1359
1360
INPUT:
1361
u,v: vertices
1362
l: edge label
1363
directed: boolean
1364
1365
DOCTEST:
1366
sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend()
1367
sage: G.set_edge_label(1,2,'a',True)
1368
"""
1369
try:
1370
assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated)))
1371
except AssertionError:
1372
self._nxg = self._nxg.mutate()
1373
1374
if not self.has_edge(u, v, None):
1375
return
1376
if self.multiple_edges(None):
1377
self._nxg[u][v].clear()
1378
self._nxg[u][v][0] = dict(weight=l)
1379
if directed is False:
1380
self._nxg[v][u].clear()
1381
self._nxg[v][u][0] = dict(weight=l)
1382
else:
1383
self._nxg[u][v]['weight'] = l
1384
if directed is False:
1385
self._nxg[v][u]['weight'] = l
1386
1387