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