Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/base/dense_graph.pyx
8815 views
1
r"""
2
Fast dense graphs
3
4
Usage Introduction
5
------------------
6
7
::
8
9
sage: from sage.graphs.base.dense_graph import DenseGraph
10
11
Dense graphs are initialized as follows::
12
13
sage: D = DenseGraph(nverts = 10, extra_vertices = 10)
14
15
This example initializes a dense graph with room for twenty vertices, the first
16
ten of which are in the graph. In general, the first ``nverts`` are "active."
17
For example, see that 9 is already in the graph::
18
19
sage: D._num_verts()
20
10
21
sage: D.add_vertex(9)
22
9
23
sage: D._num_verts()
24
10
25
26
But 10 is not, until we add it::
27
28
sage: D._num_verts()
29
10
30
sage: D.add_vertex(10)
31
10
32
sage: D._num_verts()
33
11
34
35
You can begin working right away as follows::
36
37
sage: D.add_arc(0,1)
38
sage: D.add_arc(1,2)
39
sage: D.add_arc(1,0)
40
sage: D.has_arc(7,3)
41
False
42
sage: D.has_arc(0,1)
43
True
44
sage: D.in_neighbors(1)
45
[0]
46
sage: D.out_neighbors(1)
47
[0, 2]
48
sage: D.del_all_arcs(0,1)
49
sage: D.has_arc(0,1)
50
False
51
sage: D.has_arc(1,2)
52
True
53
sage: D.del_vertex(7)
54
sage: D.has_arc(7,3)
55
False
56
sage: D._num_verts()
57
10
58
sage: D._num_arcs()
59
2
60
61
Dense graphs do not support multiple or labeled edges.
62
63
::
64
65
sage: T = DenseGraph(nverts = 3, extra_vertices = 2)
66
sage: T.add_arc(0,1)
67
sage: T.add_arc(1,2)
68
sage: T.add_arc(2,0)
69
sage: T.has_arc(0,1)
70
True
71
72
::
73
74
sage: for _ in range(10): D.add_arc(5,4)
75
sage: D.has_arc(5,4)
76
True
77
78
Dense graphs are by their nature directed. As of this writing, you need to do
79
operations in pairs to treat the undirected case (or use a backend or a Sage
80
graph)::
81
82
sage: T.has_arc(1,0)
83
False
84
85
The curious developer is encouraged to check out the ``unsafe`` functions,
86
which do not check input but which run in pure C.
87
88
Underlying Data Structure
89
-------------------------
90
91
The class ``DenseGraph`` contains the following variables which are inherited
92
from ``CGraph`` (for explanation, refer to the documentation there)::
93
94
cdef int num_verts
95
cdef int num_arcs
96
cdef int *in_degrees
97
cdef int *out_degrees
98
cdef bitset_t active_vertices
99
100
It also contains the following variables::
101
102
cdef int radix_div_shift
103
cdef int radix_mod_mask
104
cdef int num_longs
105
cdef unsigned long *edges
106
107
The array ``edges`` is a series of bits which are turned on or off, and due to
108
this, dense graphs only support graphs without edge labels and with no multiple
109
edges. The ints ``radix_div_shift`` and ``radix_mod_mask`` are simply for doing
110
efficient division by powers of two, and ``num_longs`` stores the length of the
111
``edges`` array. Recall that this length reflects the number of available
112
vertices, not the number of "actual" vertices. For more details about this,
113
refer to the documentation for ``CGraph``.
114
"""
115
116
#*******************************************************************************
117
# Copyright (C) 2008-9 Robert L. Miller <[email protected]>
118
#
119
# Distributed under the terms of the GNU General Public License (GPL)
120
# http://www.gnu.org/licenses/
121
#*******************************************************************************
122
123
include 'sage/misc/bitset.pxi'
124
125
cdef class DenseGraph(CGraph):
126
"""
127
Compiled dense graphs.
128
129
::
130
131
sage: from sage.graphs.base.dense_graph import DenseGraph
132
133
Dense graphs are initialized as follows::
134
135
sage: D = DenseGraph(nverts = 10, extra_vertices = 10)
136
137
INPUT:
138
139
- ``nverts`` - non-negative integer, the number of vertices.
140
- ``extra_vertices`` - non-negative integer (default: 0), how many extra
141
vertices to allocate.
142
- ``verts`` - optional list of vertices to add
143
- ``arcs`` - optional list of arcs to add
144
145
The first ``nverts`` are created as vertices of the graph, and the next
146
``extra_vertices`` can be freely added without reallocation. See top level
147
documentation for more details. The input ``verts`` and ``arcs`` are mainly
148
for use in pickling.
149
150
"""
151
152
def __cinit__(self, int nverts, int extra_vertices = 10, verts = None, arcs = None):
153
"""
154
Allocation and initialization happen in one place.
155
156
Memory usage is
157
158
O( (nverts + extra_vertices)^2 ).
159
160
EXAMPLE::
161
162
sage: from sage.graphs.base.dense_graph import DenseGraph
163
sage: D = DenseGraph(nverts = 10, extra_vertices = 10)
164
"""
165
if nverts == 0 and extra_vertices == 0:
166
raise RuntimeError('Dense graphs must allocate space for vertices!')
167
cdef int radix = sizeof(unsigned long) << 3
168
self.radix_mod_mask = radix - 1
169
cdef int i = 0
170
while ((<unsigned long>1)<<i) & self.radix_mod_mask:
171
i += 1
172
self.radix_div_shift = i
173
self.num_verts = nverts
174
cdef int total_verts = nverts + extra_vertices
175
self.num_arcs = 0
176
177
i = total_verts >> self.radix_div_shift
178
if total_verts & self.radix_mod_mask:
179
i += 1
180
self.num_longs = i
181
182
self.edges = <unsigned long *> sage_malloc(total_verts * self.num_longs * sizeof(unsigned long))
183
self.in_degrees = <int *> sage_malloc(total_verts * sizeof(int))
184
self.out_degrees = <int *> sage_malloc(total_verts * sizeof(int))
185
186
if not self.edges or not self.in_degrees or not self.out_degrees:
187
if self.edges: sage_free(self.edges)
188
if self.in_degrees: sage_free(self.in_degrees)
189
if self.out_degrees: sage_free(self.out_degrees)
190
raise MemoryError
191
for i from 0 <= i < self.num_longs * total_verts:
192
self.edges[i] = 0
193
for i from 0 <= i < total_verts:
194
self.in_degrees[i] = 0
195
self.out_degrees[i] = 0
196
bitset_init(self.active_vertices, total_verts)
197
bitset_set_first_n(self.active_vertices, self.num_verts)
198
199
if verts is not None:
200
self.add_vertices(verts)
201
202
if arcs is not None:
203
for u,v in arcs:
204
self.add_arc(u,v)
205
206
def __dealloc__(self):
207
"""
208
New and dealloc are both tested at class level.
209
"""
210
sage_free(self.edges)
211
sage_free(self.in_degrees)
212
sage_free(self.out_degrees)
213
bitset_free(self.active_vertices)
214
215
def __reduce__(self):
216
"""
217
Return a tuple used for pickling this graph.
218
219
TESTS::
220
221
sage: from sage.graphs.base.dense_graph import DenseGraph
222
sage: D = DenseGraph(nverts = 10, extra_vertices = 10)
223
sage: D.add_arc(0,1)
224
sage: D.has_arc(0,1)
225
1
226
sage: D.has_arc(1,2)
227
0
228
sage: LD = loads(dumps(D))
229
sage: LD.has_arc(0,1)
230
1
231
sage: LD.has_arc(1,2)
232
0
233
234
"""
235
from sage.graphs.all import DiGraph
236
D = DiGraph(implementation='c_graph', sparse=False)
237
D._backend._cg = self
238
cdef int i
239
D._backend.vertex_labels = {}
240
for i from 0 <= i < self.active_vertices.size:
241
if bitset_in(self.active_vertices, i):
242
D._backend.vertex_labels[i] = i
243
D._backend.vertex_ints = D._backend.vertex_labels
244
return (DenseGraph, (0, self.active_vertices.size, self.verts(), D.edges(labels=False)))
245
246
cpdef realloc(self, int total_verts):
247
"""
248
Reallocate the number of vertices to use, without actually adding any.
249
250
INPUT:
251
252
- ``total`` - integer, the total size to make the array
253
254
Returns -1 and fails if reallocation would destroy any active vertices.
255
256
EXAMPLES::
257
258
sage: from sage.graphs.base.dense_graph import DenseGraph
259
sage: D = DenseGraph(nverts=4, extra_vertices=4)
260
sage: D.current_allocation()
261
8
262
sage: D.add_vertex(6)
263
6
264
sage: D.current_allocation()
265
8
266
sage: D.add_vertex(10)
267
10
268
sage: D.current_allocation()
269
16
270
sage: D.add_vertex(40)
271
Traceback (most recent call last):
272
...
273
RuntimeError: Requested vertex is past twice the allocated range: use realloc.
274
sage: D.realloc(50)
275
sage: D.add_vertex(40)
276
40
277
sage: D.current_allocation()
278
50
279
sage: D.realloc(30)
280
-1
281
sage: D.current_allocation()
282
50
283
sage: D.del_vertex(40)
284
sage: D.realloc(30)
285
sage: D.current_allocation()
286
30
287
288
"""
289
cdef int i, j
290
if total_verts == 0:
291
raise RuntimeError('Dense graphs must allocate space for vertices!')
292
cdef bitset_t bits
293
cdef int min_verts, min_longs, old_longs = self.num_longs
294
if total_verts < self.active_vertices.size:
295
min_verts = total_verts
296
min_longs = -1
297
bitset_init(bits, self.active_vertices.size)
298
bitset_set_first_n(bits, total_verts)
299
if not bitset_issubset(self.active_vertices, bits):
300
bitset_free(bits)
301
return -1
302
bitset_free(bits)
303
else:
304
min_verts = self.active_vertices.size
305
min_longs = self.num_longs
306
307
i = total_verts >> self.radix_div_shift
308
if total_verts & self.radix_mod_mask:
309
i += 1
310
self.num_longs = i
311
if min_longs == -1: min_longs = self.num_longs
312
313
cdef unsigned long *new_edges = <unsigned long *> sage_malloc(total_verts * self.num_longs * sizeof(unsigned long))
314
315
for i from 0 <= i < min_verts:
316
for j from 0 <= j < min_longs:
317
new_edges[i*self.num_longs + j] = self.edges[i*old_longs + j]
318
for j from min_longs <= j < self.num_longs:
319
new_edges[i*self.num_longs + j] = 0
320
for i from min_verts <= i < total_verts:
321
for j from 0 <= j < self.num_longs:
322
new_edges[i*self.num_longs + j] = 0
323
sage_free(self.edges)
324
self.edges = new_edges
325
326
self.in_degrees = <int *> sage_realloc(self.in_degrees, total_verts * sizeof(int))
327
self.out_degrees = <int *> sage_realloc(self.out_degrees, total_verts * sizeof(int))
328
329
cdef int first_limb
330
cdef unsigned long zero_gate
331
if total_verts > self.active_vertices.size:
332
first_limb = (self.active_vertices.size >> self.radix_div_shift)
333
zero_gate = (<unsigned long>1) << (self.active_vertices.size & self.radix_mod_mask)
334
zero_gate -= 1
335
for i from 0 <= i < total_verts:
336
self.edges[first_limb] &= zero_gate
337
for j from first_limb < j < self.num_longs:
338
self.edges[j] = 0
339
340
for i from self.active_vertices.size <= i < total_verts:
341
self.in_degrees[i] = 0
342
self.out_degrees[i] = 0
343
bitset_realloc(self.active_vertices, total_verts)
344
345
###################################
346
# Unlabeled arc functions
347
###################################
348
349
cdef int add_arc_unsafe(self, int u, int v):
350
"""
351
Adds arc (u, v) to the graph.
352
353
INPUT:
354
u, v -- non-negative integers
355
356
"""
357
cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)
358
cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)
359
if not self.edges[place] & word:
360
self.in_degrees[v] += 1
361
self.out_degrees[u] += 1
362
self.num_arcs += 1
363
self.edges[place] |= word
364
365
cpdef add_arc(self, int u, int v):
366
"""
367
Adds arc ``(u, v)`` to the graph.
368
369
INPUT:
370
371
- ``u, v`` -- non-negative integers, must be in self
372
373
EXAMPLE::
374
375
sage: from sage.graphs.base.dense_graph import DenseGraph
376
sage: G = DenseGraph(5)
377
sage: G.add_arc(0,1)
378
sage: G.add_arc(4,7)
379
Traceback (most recent call last):
380
...
381
LookupError: Vertex (7) is not a vertex of the graph.
382
sage: G.has_arc(1,0)
383
False
384
sage: G.has_arc(0,1)
385
True
386
387
"""
388
self.check_vertex(u)
389
self.check_vertex(v)
390
self.add_arc_unsafe(u,v)
391
392
cdef int has_arc_unsafe(self, int u, int v):
393
"""
394
Checks whether arc (u, v) is in the graph.
395
396
INPUT:
397
u, v -- non-negative integers, must be in self
398
399
OUTPUT:
400
0 -- False
401
1 -- True
402
403
"""
404
cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)
405
cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)
406
return (self.edges[place] & word) >> (v & self.radix_mod_mask)
407
408
cpdef bint has_arc(self, int u, int v):
409
"""
410
Checks whether arc ``(u, v)`` is in the graph.
411
412
INPUT:
413
u, v -- integers
414
415
EXAMPLE::
416
417
sage: from sage.graphs.base.dense_graph import DenseGraph
418
sage: G = DenseGraph(5)
419
sage: G.add_arc(0,1)
420
sage: G.has_arc(1,0)
421
False
422
sage: G.has_arc(0,1)
423
True
424
425
"""
426
if u < 0 or u >= self.active_vertices.size or not bitset_in(self.active_vertices, u):
427
return False
428
if v < 0 or v >= self.active_vertices.size or not bitset_in(self.active_vertices, v):
429
return False
430
return self.has_arc_unsafe(u,v) == 1
431
432
cdef int del_arc_unsafe(self, int u, int v):
433
"""
434
Deletes the arc from u to v, if it exists.
435
436
INPUT:
437
u, v -- non-negative integers, must be in self
438
439
"""
440
cdef int place = (u * self.num_longs) + (v >> self.radix_div_shift)
441
cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)
442
if self.edges[place] & word:
443
self.in_degrees[v] -= 1
444
self.out_degrees[u] -= 1
445
self.num_arcs -= 1
446
self.edges[place] &= ~word
447
448
cpdef del_all_arcs(self, int u, int v):
449
"""
450
Deletes the arc from ``u`` to ``v``.
451
452
INPUT:
453
- ``u, v`` - integers
454
455
NOTE:
456
The naming of this function is for consistency with ``SparseGraph``. Of
457
course, there can be at most one arc for a ``DenseGraph``.
458
459
EXAMPLE::
460
461
sage: from sage.graphs.base.dense_graph import DenseGraph
462
sage: G = DenseGraph(5)
463
sage: G.add_arc(0,1)
464
sage: G.has_arc(0,1)
465
True
466
sage: G.del_all_arcs(0,1)
467
sage: G.has_arc(0,1)
468
False
469
470
"""
471
self.check_vertex(u)
472
self.check_vertex(v)
473
self.del_arc_unsafe(u,v)
474
475
###################################
476
# Neighbor functions
477
###################################
478
479
cdef int out_neighbors_unsafe(self, int u, int *neighbors, int size):
480
"""
481
Gives all v such that (u, v) is an arc of the graph.
482
483
INPUT:
484
u -- non-negative integer, must be in self
485
neighbors -- must be a pointer to an (allocated) integer array
486
size -- the length of the array
487
488
OUTPUT:
489
nonnegative integer -- the number of v such that (u, v) is an arc
490
-1 -- indicates that the array has been filled with neighbors, but
491
there were more
492
493
"""
494
cdef int place = (u * self.num_longs), num_nbrs = 0
495
cdef int i, v = 0
496
cdef unsigned long word, data
497
for i from 0 <= i < self.num_longs:
498
data = self.edges[place + i]
499
word = 1
500
while word:
501
if word & data:
502
if num_nbrs == size:
503
return -1
504
neighbors[num_nbrs] = v
505
num_nbrs += 1
506
word = word << 1
507
v += 1
508
return num_nbrs
509
510
cpdef list out_neighbors(self, int u):
511
"""
512
Gives all ``v`` such that ``(u, v)`` is an arc of the graph.
513
514
INPUT:
515
- ``u`` - integer
516
517
EXAMPLES::
518
519
sage: from sage.graphs.base.dense_graph import DenseGraph
520
sage: G = DenseGraph(5)
521
sage: G.add_arc(0,1)
522
sage: G.add_arc(1,2)
523
sage: G.add_arc(1,3)
524
sage: G.out_neighbors(0)
525
[1]
526
sage: G.out_neighbors(1)
527
[2, 3]
528
529
"""
530
cdef int i, num_nbrs
531
self.check_vertex(u)
532
if self.out_degrees[u] == 0:
533
return []
534
cdef int size = self.out_degrees[u]
535
cdef int *neighbors = <int *> sage_malloc(size * sizeof(int))
536
if not neighbors:
537
raise MemoryError
538
num_nbrs = self.out_neighbors_unsafe(u, neighbors, size)
539
output = [neighbors[i] for i from 0 <= i < num_nbrs]
540
sage_free(neighbors)
541
return output
542
543
cdef int in_neighbors_unsafe(self, int v, int *neighbors, int size):
544
"""
545
Gives all u such that (u, v) is an arc of the graph.
546
547
INPUT:
548
v -- non-negative integer, must be in self
549
neighbors -- must be a pointer to an (allocated) integer array
550
size -- the length of the array
551
552
OUTPUT:
553
nonnegative integer -- the number of u such that (u, v) is an arc
554
-1 -- indicates that the array has been filled with neighbors, but
555
there were more
556
557
"""
558
cdef int place = v >> self.radix_div_shift
559
cdef unsigned long word = (<unsigned long>1) << (v & self.radix_mod_mask)
560
cdef int i, num_nbrs = 0
561
for i from 0 <= i < self.active_vertices.size:
562
if self.edges[place + i*self.num_longs] & word:
563
if num_nbrs == size:
564
return -1
565
neighbors[num_nbrs] = i
566
num_nbrs += 1
567
return num_nbrs
568
569
cpdef list in_neighbors(self, int v):
570
"""
571
Gives all ``u`` such that ``(u, v)`` is an arc of the graph.
572
573
INPUT:
574
- ``v`` - integer
575
576
EXAMPLES::
577
578
sage: from sage.graphs.base.dense_graph import DenseGraph
579
sage: G = DenseGraph(5)
580
sage: G.add_arc(0,1)
581
sage: G.add_arc(3,1)
582
sage: G.add_arc(1,3)
583
sage: G.in_neighbors(1)
584
[0, 3]
585
sage: G.in_neighbors(3)
586
[1]
587
588
"""
589
cdef int i, num_nbrs
590
self.check_vertex(v)
591
if self.in_degrees[v] == 0:
592
return []
593
cdef int size = self.in_degrees[v]
594
cdef int *neighbors = <int *> sage_malloc(size * sizeof(int))
595
if not neighbors:
596
raise MemoryError
597
num_nbrs = self.in_neighbors_unsafe(v, neighbors, size)
598
output = [neighbors[i] for i from 0 <= i < num_nbrs]
599
sage_free(neighbors)
600
return output
601
602
##############################
603
# Further tests. Unit tests for methods, functions, classes defined with cdef.
604
##############################
605
606
def random_stress():
607
"""
608
Randomly search for mistakes in the code.
609
610
DOCTEST (No output indicates that no errors were found)::
611
612
sage: from sage.graphs.base.dense_graph import random_stress
613
sage: for _ in xrange(400):
614
... random_stress()
615
616
"""
617
cdef int i, j, k, l, n
618
cdef DenseGraph Gnew
619
num_verts = 10
620
# This code deliberately uses random instead of sage.misc.prandom,
621
# so that every time it is run it does different tests, instead of
622
# doing the same random stress test every time. (Maybe it should
623
# use sage.misc.random_testing?)
624
from random import randint
625
from sage.graphs.all import DiGraph
626
from sage.misc.misc import uniq
627
Gnew = DenseGraph(num_verts)
628
Gold = DiGraph(num_verts, loops=True, implementation='networkx')
629
for n from 0 <= n < 100:
630
i = randint(0,num_verts-1)
631
j = randint(0,num_verts-1)
632
k = randint(0,num_verts-1)
633
if k != 0:
634
Gold.add_edge(i,j)
635
Gnew.add_arc_unsafe(i,j)
636
else:
637
Gold.delete_edge(i,j)
638
Gnew.del_arc_unsafe(i,j)
639
if Gnew.num_arcs != Gold.size():
640
raise RuntimeError( "NO" )
641
for i from 0 <= i < num_verts:
642
if Gnew.out_degrees[i] != Gold.out_degree(i):
643
raise RuntimeError( "NO" )
644
if Gnew.in_degrees[i] != Gold.in_degree(i):
645
raise RuntimeError( "NO" )
646
647
def _test_adjacency_sequence_out():
648
"""
649
Randomly test the method ``DenseGraph.adjacency_sequence_out()``. No output
650
indicates that no errors were found.
651
652
TESTS::
653
654
sage: from sage.graphs.base.dense_graph import _test_adjacency_sequence_out
655
sage: _test_adjacency_sequence_out() # long time
656
"""
657
from sage.graphs.digraph import DiGraph
658
from sage.graphs.graph_generators import GraphGenerators
659
from sage.misc.prandom import randint, random
660
low = 0
661
high = 500
662
randg = DiGraph(GraphGenerators().RandomGNP(randint(low, high), random()))
663
n = randg.order()
664
cdef DenseGraph g = DenseGraph(n,
665
verts=randg.vertices(),
666
arcs=randg.edges(labels=False))
667
assert g._num_verts() == randg.order(), (
668
"Graph order mismatch: %s vs. %s" % (g._num_verts(), randg.order()))
669
assert g._num_arcs() == randg.size(), (
670
"Graph size mismatch: %s vs. %s" % (g._num_arcs(), randg.size()))
671
M = randg.adjacency_matrix()
672
cdef int *V = <int *>sage_malloc(n * sizeof(int))
673
cdef int i = 0
674
for v in randg.vertex_iterator():
675
V[i] = v
676
i += 1
677
cdef int *seq = <int *> sage_malloc(n * sizeof(int))
678
for 0 <= i < randint(50, 101):
679
u = randint(low, n - 1)
680
g.adjacency_sequence_out(n, V, u, seq)
681
A = [seq[k] for k in range(n)]
682
try:
683
assert A == list(M[u])
684
except AssertionError:
685
sage_free(V)
686
sage_free(seq)
687
raise AssertionError("Graph adjacency mismatch")
688
sage_free(seq)
689
sage_free(V)
690
691
###########################################
692
# Dense Graph Backend
693
###########################################
694
695
from c_graph import CGraphBackend
696
from c_graph cimport check_vertex, vertex_label, get_vertex
697
698
class DenseGraphBackend(CGraphBackend):
699
"""
700
Backend for Sage graphs using DenseGraphs.
701
702
::
703
704
sage: from sage.graphs.base.dense_graph import DenseGraphBackend
705
706
This class is only intended for use by the Sage Graph and DiGraph class.
707
If you are interested in using a DenseGraph, you probably want to do
708
something like the following example, which creates a Sage Graph instance
709
which wraps a DenseGraph object::
710
711
sage: G = Graph(30, implementation="c_graph", sparse=False)
712
sage: G.add_edges([(0,1), (0,3), (4,5), (9, 23)])
713
sage: G.edges(labels=False)
714
[(0, 1), (0, 3), (4, 5), (9, 23)]
715
716
Note that Sage graphs using the backend are more flexible than DenseGraphs
717
themselves. This is because DenseGraphs (by design) do not deal with Python
718
objects::
719
720
sage: G.add_vertex((0,1,2))
721
sage: G.vertices()
722
[0,
723
...
724
29,
725
(0, 1, 2)]
726
sage: from sage.graphs.base.dense_graph import DenseGraph
727
sage: DG = DenseGraph(30)
728
sage: DG.add_vertex((0,1,2))
729
Traceback (most recent call last):
730
...
731
TypeError: an integer is required
732
733
"""
734
735
def __init__(self, n, directed=True):
736
"""
737
Initialize a dense graph with n vertices.
738
739
EXAMPLE::
740
741
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
742
sage: D.add_edge(0,1,None,False)
743
sage: list(D.iterator_edges(range(9), True))
744
[(0, 1, None)]
745
746
"""
747
self._cg = DenseGraph(n)
748
self._cg_rev = None
749
self._directed = directed
750
self.vertex_labels = {}
751
self.vertex_ints = {}
752
753
def add_edge(self, object u, object v, object l, bint directed):
754
"""
755
Adds the edge ``(u,v)`` to self.
756
757
INPUT:
758
759
- ``u,v`` - the vertices of the edge
760
- ``l`` - the edge label (ignored)
761
- ``directed`` - if False, also add ``(v,u)``
762
763
NOTE:
764
The input ``l`` is for consistency with other backends.
765
766
EXAMPLE::
767
768
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
769
sage: D.add_edge(0,1,None,False)
770
sage: list(D.iterator_edges(range(9), True))
771
[(0, 1, None)]
772
773
"""
774
if u is None: u = self.add_vertex(None)
775
if v is None: v = self.add_vertex(None)
776
777
cdef int u_int = check_vertex(u, self.vertex_ints, self.vertex_labels,
778
self._cg, None, 0)
779
cdef int v_int = check_vertex(v, self.vertex_ints, self.vertex_labels,
780
self._cg, None, 0)
781
782
if directed or u_int == v_int:
783
self._cg.add_arc(u_int, v_int)
784
else:
785
self._cg.add_arc(u_int, v_int)
786
self._cg.add_arc(v_int, u_int)
787
788
def add_edges(self, object edges, bint directed):
789
"""
790
Add edges from a list.
791
792
INPUT:
793
794
- ``edges`` - the edges to be added - can either be of the form
795
``(u,v)`` or ``(u,v,l)``
796
- ``directed`` - if False, add ``(v,u)`` as well as ``(u,v)``
797
798
EXAMPLE::
799
800
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
801
sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
802
sage: list(D.iterator_edges(range(9), True))
803
[(0, 1, None),
804
(2, 3, None),
805
(4, 5, None),
806
(5, 6, None)]
807
808
"""
809
for e in edges:
810
u,v = e[:2]
811
self.add_edge(u,v,None,directed)
812
813
def del_edge(self, object u, object v, object l, bint directed):
814
"""
815
Delete edge ``(u,v)``.
816
817
INPUT:
818
819
- ``u,v`` - the vertices of the edge
820
- ``l`` - the edge label (ignored)
821
- ``directed`` - if False, also delete ``(v,u,l)``
822
823
NOTE:
824
The input ``l`` is for consistency with other backends.
825
826
EXAMPLE::
827
828
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
829
sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
830
sage: list(D.iterator_edges(range(9), True))
831
[(0, 1, None),
832
(2, 3, None),
833
(4, 5, None),
834
(5, 6, None)]
835
sage: D.del_edge(0,1,None,True)
836
sage: list(D.iterator_out_edges(range(9), True))
837
[(1, 0, None),
838
(2, 3, None),
839
(3, 2, None),
840
(4, 5, None),
841
(5, 4, None),
842
(5, 6, None),
843
(6, 5, None)]
844
845
"""
846
if not ( self.has_vertex(u) and self.has_vertex(v) ):
847
return
848
cdef int u_int = check_vertex(u, self.vertex_ints, self.vertex_labels,
849
self._cg, None, 0)
850
cdef int v_int = check_vertex(v, self.vertex_ints, self.vertex_labels,
851
self._cg, None, 0)
852
if v is None:
853
u, v = u[:2]
854
if directed:
855
self._cg.del_all_arcs(u_int, v_int)
856
else:
857
self._cg.del_all_arcs(u_int, v_int)
858
self._cg.del_all_arcs(v_int, u_int)
859
860
def get_edge_label(self, object u, object v):
861
"""
862
Returns the edge label for ``(u,v)``. Always None, since dense graphs
863
do not support edge labels.
864
865
INPUT:
866
867
- ``u,v`` - the vertices of the edge
868
869
EXAMPLE::
870
871
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
872
sage: D.add_edges([(0,1), (2,3,7), (4,5), (5,6)], False)
873
sage: list(D.iterator_edges(range(9), True))
874
[(0, 1, None),
875
(2, 3, None),
876
(4, 5, None),
877
(5, 6, None)]
878
sage: D.del_edge(0,1,None,True)
879
sage: list(D.iterator_out_edges(range(9), True))
880
[(1, 0, None),
881
(2, 3, None),
882
(3, 2, None),
883
(4, 5, None),
884
(5, 4, None),
885
(5, 6, None),
886
(6, 5, None)]
887
sage: D.get_edge_label(2,3)
888
sage: D.get_edge_label(2,4)
889
Traceback (most recent call last):
890
...
891
LookupError: (2, 4) is not an edge of the graph.
892
893
"""
894
if not self.has_edge(u, v, None):
895
raise LookupError("({0}, {1}) is not an edge of the graph.".format(repr(u), repr(v)))
896
return None
897
898
def has_edge(self, object u, object v, object l):
899
"""
900
Returns whether this graph has edge ``(u,v)``.
901
902
NOTE:
903
The input ``l`` is for consistency with other backends.
904
905
INPUT:
906
907
- ``u,v`` - the vertices of the edge
908
- ``l`` - the edge label (ignored)
909
910
EXAMPLE::
911
912
sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
913
sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
914
sage: D.has_edge(0,1,None)
915
True
916
917
"""
918
if not ( self.has_vertex(u) and self.has_vertex(v) ):
919
return False
920
cdef int u_int = get_vertex(u, self.vertex_ints, self.vertex_labels,
921
self._cg)
922
cdef int v_int = get_vertex(v, self.vertex_ints, self.vertex_labels,
923
self._cg)
924
return self._cg.has_arc(u_int, v_int)
925
926
def iterator_edges(self, object vertices, bint labels):
927
"""
928
Iterate over the edges incident to a sequence of vertices. Edges are
929
assumed to be undirected.
930
931
INPUT:
932
- ``vertices`` - a list of vertex labels
933
- ``labels`` - boolean, whether to return labels as well
934
935
EXAMPLE::
936
937
sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)
938
sage: G.add_edge(1,2,None,False)
939
sage: list(G.iterator_edges(range(9), False))
940
[(1, 2)]
941
sage: list(G.iterator_edges(range(9), True))
942
[(1, 2, None)]
943
944
"""
945
cdef object v
946
vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,
947
self._cg) for v in vertices if self.has_vertex(v)]
948
cdef int u_int, v_int
949
if labels:
950
return iter([tuple(sorted(
951
(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),
952
vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg)
953
)))+(None,)
954
for v_int in vertices
955
for u_int in self._cg.out_neighbors(v_int)
956
if u_int >= v_int or u_int not in vertices])
957
else:
958
return iter([tuple(sorted(
959
(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),
960
vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg)
961
)))
962
for v_int in vertices
963
for u_int in self._cg.out_neighbors(v_int)
964
if u_int >= v_int or u_int not in vertices])
965
966
def iterator_in_edges(self, object vertices, bint labels):
967
"""
968
Iterate over the incoming edges incident to a sequence of vertices.
969
970
INPUT:
971
- ``vertices`` - a list of vertex labels
972
- ``labels`` - boolean, whether to return labels as well
973
974
EXAMPLE::
975
976
sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)
977
sage: G.add_edge(1,2,None,True)
978
sage: list(G.iterator_in_edges([1], False))
979
[]
980
sage: list(G.iterator_in_edges([2], False))
981
[(1, 2)]
982
sage: list(G.iterator_in_edges([2], True))
983
[(1, 2, None)]
984
985
"""
986
cdef object v
987
vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,
988
self._cg) for v in vertices if self.has_vertex(v)]
989
cdef int u_int, v_int
990
if labels:
991
return iter([
992
(vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),
993
vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),
994
None)
995
for v_int in vertices
996
for u_int in self._cg.in_neighbors(v_int)])
997
else:
998
return iter([
999
(vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),
1000
vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg))
1001
for v_int in vertices
1002
for u_int in self._cg.in_neighbors(v_int)])
1003
1004
def iterator_out_edges(self, object vertices, bint labels):
1005
"""
1006
Iterate over the outbound edges incident to a sequence of vertices.
1007
1008
INPUT:
1009
- ``vertices`` - a list of vertex labels
1010
- ``labels`` - boolean, whether to return labels as well
1011
1012
EXAMPLE::
1013
1014
sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)
1015
sage: G.add_edge(1,2,None,True)
1016
sage: list(G.iterator_out_edges([2], False))
1017
[]
1018
sage: list(G.iterator_out_edges([1], False))
1019
[(1, 2)]
1020
sage: list(G.iterator_out_edges([1], True))
1021
[(1, 2, None)]
1022
1023
"""
1024
cdef object u, v
1025
vertices = [get_vertex(v, self.vertex_ints, self.vertex_labels,
1026
self._cg) for v in vertices if self.has_vertex(v)]
1027
cdef int u_int, v_int
1028
if labels:
1029
return iter([
1030
(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),
1031
vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg),
1032
None)
1033
for v_int in vertices
1034
for u_int in self._cg.out_neighbors(v_int)])
1035
else:
1036
return iter([
1037
(vertex_label(v_int, self.vertex_ints, self.vertex_labels, self._cg),
1038
vertex_label(u_int, self.vertex_ints, self.vertex_labels, self._cg))
1039
for v_int in vertices
1040
for u_int in self._cg.out_neighbors(v_int)])
1041
1042
def multiple_edges(self, new):
1043
"""
1044
Get/set whether or not ``self`` allows multiple edges.
1045
1046
INPUT:
1047
1048
- ``new`` - boolean (to set) or ``None`` (to get)
1049
1050
EXAMPLES::
1051
1052
sage: import sage.graphs.base.dense_graph
1053
sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)
1054
sage: G.multiple_edges(True)
1055
Traceback (most recent call last):
1056
...
1057
NotImplementedError: Dense graphs do not support multiple edges.
1058
sage: G.multiple_edges(None)
1059
False
1060
1061
"""
1062
if new is None:
1063
return False
1064
if new:
1065
raise NotImplementedError("Dense graphs do not support multiple edges.")
1066
1067
def set_edge_label(self, object u, object v, object l, bint directed):
1068
"""
1069
Label the edge ``(u,v)`` by ``l``.
1070
1071
INPUT:
1072
1073
- ``u,v`` - the vertices of the edge
1074
- ``l`` - the edge label
1075
- ``directed`` - if False, also set ``(v,u)`` with label ``l``
1076
1077
EXAMPLE::
1078
1079
sage: import sage.graphs.base.dense_graph
1080
sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9)
1081
sage: G.set_edge_label(1,2,'a',True)
1082
Traceback (most recent call last):
1083
...
1084
NotImplementedError: Dense graphs do not support edge labels.
1085
"""
1086
raise NotImplementedError("Dense graphs do not support edge labels.")
1087
1088