Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/generators/random.py
8815 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Random Graphs
4
5
The methods defined here appear in :mod:`sage.graphs.graph_generators`.
6
"""
7
###########################################################################
8
#
9
# Copyright (C) 2006 Robert L. Miller <[email protected]>
10
# and Emily A. Kirkman
11
# Copyright (C) 2009 Michael C. Yurko <[email protected]>
12
#
13
# Distributed under the terms of the GNU General Public License (GPL)
14
# http://www.gnu.org/licenses/
15
###########################################################################
16
17
# import from Sage library
18
from sage.graphs.graph import Graph
19
from sage.misc.randstate import current_randstate
20
21
def RandomGNP(n, p, seed=None, fast=True, method='Sage'):
22
r"""
23
Returns a random graph on `n` nodes. Each edge is inserted independently
24
with probability `p`.
25
26
INPUTS:
27
28
- ``n`` -- number of nodes of the graph
29
30
- ``p`` -- probability of an edge
31
32
- ``seed`` -- integer seed for random number generator (default=None).
33
34
- ``fast`` -- boolean set to True (default) to use the algorithm with
35
time complexity in `O(n+m)` proposed in [BatBra2005]_. It is designed
36
for generating large sparse graphs. It is faster than other methods for
37
*LARGE* instances (try it to know whether it is useful for you).
38
39
- ``method`` -- By default (```method='Sage'``), this function uses the
40
method implemented in ```sage.graphs.graph_generators_pyx.pyx``. When
41
``method='networkx'``, this function calls the NetworkX function
42
``fast_gnp_random_graph``, unless ``fast=False``, then
43
``gnp_random_graph``. Try them to know which method is the best for
44
you. The ``fast`` parameter is not taken into account by the 'Sage'
45
method so far.
46
47
REFERENCES:
48
49
.. [ErdRen1959] P. Erdos and A. Renyi. On Random Graphs, Publ.
50
Math. 6, 290 (1959).
51
52
.. [Gilbert1959] E. N. Gilbert. Random Graphs, Ann. Math. Stat.,
53
30, 1141 (1959).
54
55
.. [BatBra2005] V. Batagelj and U. Brandes. Efficient generation of
56
large random networks. Phys. Rev. E, 71, 036113, 2005.
57
58
PLOTTING: When plotting, this graph will use the default spring-layout
59
algorithm, unless a position dictionary is specified.
60
61
EXAMPLES: We show the edge list of a random graph on 6 nodes with
62
probability `p = .4`::
63
64
sage: set_random_seed(0)
65
sage: graphs.RandomGNP(6, .4).edges(labels=False)
66
[(0, 1), (0, 5), (1, 2), (2, 4), (3, 4), (3, 5), (4, 5)]
67
68
We plot a random graph on 12 nodes with probability `p = .71`::
69
70
sage: gnp = graphs.RandomGNP(12,.71)
71
sage: gnp.show() # long time
72
73
We view many random graphs using a graphics array::
74
75
sage: g = []
76
sage: j = []
77
sage: for i in range(9):
78
....: k = graphs.RandomGNP(i+3,.43)
79
....: g.append(k)
80
sage: for i in range(3):
81
....: n = []
82
....: for m in range(3):
83
....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
84
....: j.append(n)
85
sage: G = sage.plot.graphics.GraphicsArray(j)
86
sage: G.show() # long time
87
sage: graphs.RandomGNP(4,1)
88
Complete graph: Graph on 4 vertices
89
90
TESTS::
91
92
sage: graphs.RandomGNP(50,.2,method=50)
93
Traceback (most recent call last):
94
...
95
ValueError: 'method' must be equal to 'networkx' or to 'Sage'.
96
sage: set_random_seed(0)
97
sage: graphs.RandomGNP(50,.2, method="Sage").size()
98
243
99
sage: graphs.RandomGNP(50,.2, method="networkx").size()
100
258
101
"""
102
if n < 0:
103
raise ValueError("The number of nodes must be positive or null.")
104
if 0.0 > p or 1.0 < p:
105
raise ValueError("The probability p must be in [0..1].")
106
107
if seed is None:
108
seed = current_randstate().long_seed()
109
if p == 1:
110
from sage.graphs.generators.basic import CompleteGraph
111
return CompleteGraph(n)
112
113
if method == 'networkx':
114
import networkx
115
if fast:
116
G = networkx.fast_gnp_random_graph(n, p, seed=seed)
117
else:
118
G = networkx.gnp_random_graph(n, p, seed=seed)
119
return Graph(G)
120
elif method in ['Sage', 'sage']:
121
# We use the Sage generator
122
from sage.graphs.graph_generators_pyx import RandomGNP as sageGNP
123
return sageGNP(n, p)
124
else:
125
raise ValueError("'method' must be equal to 'networkx' or to 'Sage'.")
126
127
def RandomBarabasiAlbert(n, m, seed=None):
128
u"""
129
Return a random graph created using the Barabasi-Albert preferential
130
attachment model.
131
132
A graph with m vertices and no edges is initialized, and a graph of n
133
vertices is grown by attaching new vertices each with m edges that are
134
attached to existing vertices, preferentially with high degree.
135
136
INPUT:
137
138
- ``n`` - number of vertices in the graph
139
140
- ``m`` - number of edges to attach from each new node
141
142
- ``seed`` - for random number generator
143
144
EXAMPLES:
145
146
We show the edge list of a random graph on 6 nodes with m = 2.
147
148
::
149
150
sage: graphs.RandomBarabasiAlbert(6,2).edges(labels=False)
151
[(0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (2, 4), (2, 5), (3, 5)]
152
153
We plot a random graph on 12 nodes with m = 3.
154
155
::
156
157
sage: ba = graphs.RandomBarabasiAlbert(12,3)
158
sage: ba.show() # long time
159
160
We view many random graphs using a graphics array::
161
162
sage: g = []
163
sage: j = []
164
sage: for i in range(1,10):
165
....: k = graphs.RandomBarabasiAlbert(i+3, 3)
166
....: g.append(k)
167
sage: for i in range(3):
168
....: n = []
169
....: for m in range(3):
170
....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
171
....: j.append(n)
172
sage: G = sage.plot.graphics.GraphicsArray(j)
173
sage: G.show() # long time
174
175
"""
176
if seed is None:
177
seed = current_randstate().long_seed()
178
import networkx
179
return Graph(networkx.barabasi_albert_graph(n,m,seed=seed))
180
181
def RandomBipartite(n1,n2, p):
182
r"""
183
Returns a bipartite graph with `n1+n2` vertices
184
such that any edge from `[n1]` to `[n2]` exists
185
with probability `p`.
186
187
INPUT:
188
189
- ``n1,n2`` : Cardinalities of the two sets
190
- ``p`` : Probability for an edge to exist
191
192
193
EXAMPLE::
194
195
sage: g=graphs.RandomBipartite(5,2,0.5)
196
sage: g.vertices()
197
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1)]
198
199
TESTS::
200
201
sage: g=graphs.RandomBipartite(5,-3,0.5)
202
Traceback (most recent call last):
203
...
204
ValueError: n1 and n2 should be integers strictly greater than 0
205
sage: g=graphs.RandomBipartite(5,3,1.5)
206
Traceback (most recent call last):
207
...
208
ValueError: Parameter p is a probability, and so should be a real value between 0 and 1
209
210
Trac ticket #12155::
211
212
sage: graphs.RandomBipartite(5,6,.2).complement()
213
complement(Random bipartite graph of size 5+6 with edge probability 0.200000000000000): Graph on 11 vertices
214
"""
215
if not (p>=0 and p<=1):
216
raise ValueError, "Parameter p is a probability, and so should be a real value between 0 and 1"
217
if not (n1>0 and n2>0):
218
raise ValueError, "n1 and n2 should be integers strictly greater than 0"
219
220
from numpy.random import uniform
221
222
g=Graph(name="Random bipartite graph of size "+str(n1) +"+"+str(n2)+" with edge probability "+str(p))
223
224
S1=[(0,i) for i in range(n1)]
225
S2=[(1,i) for i in range(n2)]
226
g.add_vertices(S1)
227
g.add_vertices(S2)
228
229
for w in range(n2):
230
for v in range(n1):
231
if uniform()<=p :
232
g.add_edge((0,v),(1,w))
233
234
pos = {}
235
for i in range(n1):
236
pos[(0,i)] = (0, i/(n1-1.0))
237
for i in range(n2):
238
pos[(1,i)] = (1, i/(n2-1.0))
239
240
g.set_pos(pos)
241
242
return g
243
244
def RandomBoundedToleranceGraph(n):
245
r"""
246
Returns a random bounded tolerance graph.
247
248
The random tolerance graph is built from a random bounded
249
tolerance representation by using the function
250
`ToleranceGraph`. This representation is a list
251
`((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))` where
252
`k = n-1` and `I_i = (l_i,r_i)` denotes a random interval and
253
`t_i` a random positive value less then or equal to the length
254
of the interval `I_i`. The width of the representation is
255
limited to n**2 * 2**n.
256
257
.. NOTE::
258
259
The tolerance representation used to create the graph can
260
be recovered using ``get_vertex()`` or ``get_vertices()``.
261
262
INPUT:
263
264
- ``n`` -- number of vertices of the random graph.
265
266
EXAMPLE:
267
268
Every (bounded) tolerance graph is perfect. Hence, the
269
chromatic number is equal to the clique number ::
270
271
sage: g = graphs.RandomBoundedToleranceGraph(8)
272
sage: g.clique_number() == g.chromatic_number()
273
True
274
"""
275
from sage.misc.prandom import randint
276
from sage.graphs.generators.intersection import ToleranceGraph
277
278
W = n**2 * 2**n
279
280
tolrep = map(lambda (l,r): (l,r,randint(0,r-l)),
281
[sorted((randint(0,W), randint(0,W))) for i in range(n)])
282
283
return ToleranceGraph(tolrep)
284
285
def RandomGNM(n, m, dense=False, seed=None):
286
"""
287
Returns a graph randomly picked out of all graphs on n vertices
288
with m edges.
289
290
INPUT:
291
292
- ``n`` - number of vertices.
293
294
- ``m`` - number of edges.
295
296
- ``dense`` - whether to use NetworkX's
297
dense_gnm_random_graph or gnm_random_graph
298
299
300
EXAMPLES: We show the edge list of a random graph on 5 nodes with
301
10 edges.
302
303
::
304
305
sage: graphs.RandomGNM(5, 10).edges(labels=False)
306
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
307
308
We plot a random graph on 12 nodes with m = 12.
309
310
::
311
312
sage: gnm = graphs.RandomGNM(12, 12)
313
sage: gnm.show() # long time
314
315
We view many random graphs using a graphics array::
316
317
sage: g = []
318
sage: j = []
319
sage: for i in range(9):
320
....: k = graphs.RandomGNM(i+3, i^2-i)
321
....: g.append(k)
322
sage: for i in range(3):
323
....: n = []
324
....: for m in range(3):
325
....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
326
....: j.append(n)
327
sage: G = sage.plot.graphics.GraphicsArray(j)
328
sage: G.show() # long time
329
"""
330
if seed is None:
331
seed = current_randstate().long_seed()
332
import networkx
333
if dense:
334
return Graph(networkx.dense_gnm_random_graph(n, m, seed=seed))
335
else:
336
return Graph(networkx.gnm_random_graph(n, m, seed=seed))
337
338
def RandomNewmanWattsStrogatz(n, k, p, seed=None):
339
"""
340
Returns a Newman-Watts-Strogatz small world random graph on n
341
vertices.
342
343
From the NetworkX documentation: First create a ring over n nodes.
344
Then each node in the ring is connected with its k nearest
345
neighbors. Then shortcuts are created by adding new edges as
346
follows: for each edge u-v in the underlying "n-ring with k nearest
347
neighbors"; with probability p add a new edge u-w with
348
randomly-chosen existing node w. In contrast with
349
watts_strogatz_graph(), no edges are removed.
350
351
INPUT:
352
353
- ``n`` - number of vertices.
354
355
- ``k`` - each vertex is connected to its k nearest
356
neighbors
357
358
- ``p`` - the probability of adding a new edge for
359
each edge
360
361
- ``seed`` - for the random number generator
362
363
364
EXAMPLE: We show the edge list of a random graph on 7 nodes with 2
365
"nearest neighbors" and probability `p = 0.2`::
366
367
sage: graphs.RandomNewmanWattsStrogatz(7, 2, 0.2).edges(labels=False)
368
[(0, 1), (0, 2), (0, 3), (0, 6), (1, 2), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)]
369
370
::
371
372
sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3)
373
sage: G.show() # long time
374
375
REFERENCE:
376
377
.. [NWS99] Newman, M.E.J., Watts, D.J. and Strogatz, S.H. Random
378
graph models of social networks. Proc. Nat. Acad. Sci. USA
379
99, 2566-2572.
380
"""
381
if seed is None:
382
seed = current_randstate().long_seed()
383
import networkx
384
return Graph(networkx.newman_watts_strogatz_graph(n, k, p, seed=seed))
385
386
def RandomHolmeKim(n, m, p, seed=None):
387
"""
388
Returns a random graph generated by the Holme and Kim algorithm for
389
graphs with power law degree distribution and approximate average
390
clustering.
391
392
INPUT:
393
394
- ``n`` - number of vertices.
395
396
- ``m`` - number of random edges to add for each new
397
node.
398
399
- ``p`` - probability of adding a triangle after
400
adding a random edge.
401
402
- ``seed`` - for the random number generator.
403
404
405
From the NetworkX documentation: The average clustering has a hard
406
time getting above a certain cutoff that depends on m. This cutoff
407
is often quite low. Note that the transitivity (fraction of
408
triangles to possible triangles) seems to go down with network
409
size. It is essentially the Barabasi-Albert growth model with an
410
extra step that each random edge is followed by a chance of making
411
an edge to one of its neighbors too (and thus a triangle). This
412
algorithm improves on B-A in the sense that it enables a higher
413
average clustering to be attained if desired. It seems possible to
414
have a disconnected graph with this algorithm since the initial m
415
nodes may not be all linked to a new node on the first iteration
416
like the BA model.
417
418
EXAMPLE: We show the edge list of a random graph on 8 nodes with 2
419
random edges per node and a probability `p = 0.5` of
420
forming triangles.
421
422
::
423
424
sage: graphs.RandomHolmeKim(8, 2, 0.5).edges(labels=False)
425
[(0, 2), (0, 5), (1, 2), (1, 3), (2, 3), (2, 4), (2, 6), (2, 7),
426
(3, 4), (3, 6), (3, 7), (4, 5)]
427
428
::
429
430
sage: G = graphs.RandomHolmeKim(12, 3, .3)
431
sage: G.show() # long time
432
433
REFERENCE:
434
435
.. [HolmeKim2002] Holme, P. and Kim, B.J. Growing scale-free networks
436
with tunable clustering, Phys. Rev. E (2002). vol 65, no 2, 026107.
437
"""
438
if seed is None:
439
seed = current_randstate().long_seed()
440
import networkx
441
return Graph(networkx.powerlaw_cluster_graph(n, m, p, seed=seed))
442
443
def RandomInterval(n):
444
"""
445
:meth:`RandomInterval` is deprecated. Use :meth:`RandomIntervalGraph` instead.
446
447
TEST::
448
449
sage: g = graphs.RandomInterval(8)
450
doctest:...: DeprecationWarning: RandomInterval() is deprecated. Use RandomIntervalGraph() instead.
451
See http://trac.sagemath.org/13283 for details.
452
"""
453
from sage.misc.superseded import deprecation
454
deprecation(13283, "RandomInterval() is deprecated. Use RandomIntervalGraph() instead.")
455
return RandomIntervalGraph(n)
456
457
def RandomIntervalGraph(n):
458
"""
459
Returns a random interval graph.
460
461
An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}`
462
of intervals : to each interval of the list is associated one
463
vertex, two vertices being adjacent if the two corresponding
464
intervals intersect.
465
466
A random interval graph of order `n` is generated by picking
467
random values for the `(a_i,b_j)`, each of the two coordinates
468
being generated from the uniform distribution on the interval
469
`[0,1]`.
470
471
This definitions follows [boucheron2001]_.
472
473
.. NOTE::
474
475
The vertices are named 0, 1, 2, and so on. The intervals
476
used to create the graph are saved with the graph and can
477
be recovered using ``get_vertex()`` or ``get_vertices()``.
478
479
INPUT:
480
481
- ``n`` (integer) -- the number of vertices in the random
482
graph.
483
484
EXAMPLE:
485
486
As for any interval graph, the chromatic number is equal to
487
the clique number ::
488
489
sage: g = graphs.RandomIntervalGraph(8)
490
sage: g.clique_number() == g.chromatic_number()
491
True
492
493
REFERENCE:
494
495
.. [boucheron2001] Boucheron, S. and FERNANDEZ de la VEGA, W.,
496
On the Independence Number of Random Interval Graphs,
497
Combinatorics, Probability and Computing v10, issue 05,
498
Pages 385--396,
499
Cambridge Univ Press, 2001
500
"""
501
502
from sage.misc.prandom import random
503
from sage.graphs.generators.intersection import IntervalGraph
504
505
intervals = [tuple(sorted((random(), random()))) for i in range(n)]
506
return IntervalGraph(intervals,True)
507
508
def RandomLobster(n, p, q, seed=None):
509
"""
510
Returns a random lobster.
511
512
A lobster is a tree that reduces to a caterpillar when pruning all
513
leaf vertices. A caterpillar is a tree that reduces to a path when
514
pruning all leaf vertices (q=0).
515
516
INPUT:
517
518
- ``n`` - expected number of vertices in the backbone
519
520
- ``p`` - probability of adding an edge to the
521
backbone
522
523
- ``q`` - probability of adding an edge (claw) to the
524
arms
525
526
- ``seed`` - for the random number generator
527
528
529
EXAMPLE: We show the edge list of a random graph with 3 backbone
530
nodes and probabilities `p = 0.7` and `q = 0.3`::
531
532
sage: graphs.RandomLobster(3, 0.7, 0.3).edges(labels=False)
533
[(0, 1), (1, 2)]
534
535
::
536
537
sage: G = graphs.RandomLobster(9, .6, .3)
538
sage: G.show() # long time
539
"""
540
if seed is None:
541
seed = current_randstate().long_seed()
542
import networkx
543
return Graph(networkx.random_lobster(n, p, q, seed=seed))
544
545
def RandomTree(n):
546
"""
547
Returns a random tree on `n` nodes numbered `0` through `n-1`.
548
549
By Cayley's theorem, there are `n^{n-2}` trees with vertex
550
set `\{0,1,...,n-1\}`. This constructor chooses one of these uniformly
551
at random.
552
553
ALGORITHM:
554
555
The algoritm works by generating an `(n-2)`-long
556
random sequence of numbers chosen independently and uniformly
557
from `\{0,1,\ldots,n-1\}` and then applies an inverse
558
Prufer transformation.
559
560
INPUT:
561
562
- ``n`` - number of vertices in the tree
563
564
EXAMPLE::
565
566
sage: G = graphs.RandomTree(10)
567
sage: G.is_tree()
568
True
569
sage: G.show() # long
570
571
TESTS:
572
573
Ensuring that we encounter no unexpected surprise ::
574
575
sage: all( graphs.RandomTree(10).is_tree()
576
....: for i in range(100) )
577
True
578
579
"""
580
from sage.misc.prandom import randint
581
g = Graph()
582
583
# create random Prufer code
584
code = [ randint(0,n-1) for i in xrange(n-2) ]
585
586
# We count the number of symbols of each type.
587
# count[k] is the no. of times k appears in code
588
#
589
# (count[k] is set to -1 when the corresponding vertex is not
590
# available anymore)
591
count = [ 0 for i in xrange(n) ]
592
for k in code:
593
count[k] += 1
594
595
g.add_vertices(range(n))
596
597
for s in code:
598
for x in range(n):
599
if count[x] == 0:
600
break
601
602
count[x] = -1
603
g.add_edge(x,s)
604
count[s] -= 1
605
606
# Adding as an edge the last two available vertices
607
last_edge = [ v for v in range(n) if count[v] != -1 ]
608
g.add_edge(last_edge)
609
610
return g
611
612
def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None):
613
"""
614
Returns a tree with a power law degree distribution. Returns False
615
on failure.
616
617
From the NetworkX documentation: A trial power law degree sequence
618
is chosen and then elements are swapped with new elements from a
619
power law distribution until the sequence makes a tree (size = order
620
- 1).
621
622
INPUT:
623
624
- ``n`` - number of vertices
625
626
- ``gamma`` - exponent of power law
627
628
- ``tries`` - number of attempts to adjust sequence to
629
make a tree
630
631
- ``seed`` - for the random number generator
632
633
634
EXAMPLE: We show the edge list of a random graph with 10 nodes and
635
a power law exponent of 2.
636
637
::
638
639
sage: graphs.RandomTreePowerlaw(10, 2).edges(labels=False)
640
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (6, 8), (6, 9)]
641
642
::
643
644
sage: G = graphs.RandomTreePowerlaw(15, 2)
645
sage: if G:
646
....: G.show() # random output, long time
647
"""
648
if seed is None:
649
seed = current_randstate().long_seed()
650
import networkx
651
try:
652
return Graph(networkx.random_powerlaw_tree(n, gamma, seed=seed, tries=tries))
653
except networkx.NetworkXError:
654
return False
655
656
def RandomRegular(d, n, seed=None):
657
"""
658
Returns a random d-regular graph on n vertices, or returns False on
659
failure.
660
661
Since every edge is incident to two vertices, n\*d must be even.
662
663
INPUT:
664
665
- ``n`` - number of vertices
666
667
- ``d`` - degree
668
669
- ``seed`` - for the random number generator
670
671
672
EXAMPLE: We show the edge list of a random graph with 8 nodes each
673
of degree 3.
674
675
::
676
677
sage: graphs.RandomRegular(3, 8).edges(labels=False)
678
[(0, 1), (0, 4), (0, 7), (1, 5), (1, 7), (2, 3), (2, 5), (2, 6), (3, 4), (3, 6), (4, 5), (6, 7)]
679
680
::
681
682
sage: G = graphs.RandomRegular(3, 20)
683
sage: if G:
684
....: G.show() # random output, long time
685
686
REFERENCES:
687
688
.. [KimVu2003] Kim, Jeong Han and Vu, Van H. Generating random regular
689
graphs. Proc. 35th ACM Symp. on Thy. of Comp. 2003, pp
690
213-222. ACM Press, San Diego, CA, USA.
691
http://doi.acm.org/10.1145/780542.780576
692
693
.. [StegerWormald1999] Steger, A. and Wormald, N. Generating random
694
regular graphs quickly. Prob. and Comp. 8 (1999), pp 377-396.
695
"""
696
if seed is None:
697
seed = current_randstate().long_seed()
698
import networkx
699
try:
700
N = networkx.random_regular_graph(d, n, seed=seed)
701
if N is False: return False
702
return Graph(N, sparse=True)
703
except Exception:
704
return False
705
706
def RandomShell(constructor, seed=None):
707
"""
708
Returns a random shell graph for the constructor given.
709
710
INPUT:
711
712
- ``constructor`` - a list of 3-tuples (n,m,d), each
713
representing a shell
714
715
- ``n`` - the number of vertices in the shell
716
717
- ``m`` - the number of edges in the shell
718
719
- ``d`` - the ratio of inter (next) shell edges to
720
intra shell edges
721
722
- ``seed`` - for the random number generator
723
724
725
EXAMPLE::
726
727
sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)])
728
sage: G.edges(labels=False)
729
[(0, 3), (0, 7), (0, 8), (1, 2), (1, 5), (1, 8), (1, 9), (3, 6), (3, 11), (4, 6), (4, 7), (4, 8), (4, 21), (5, 8), (5, 9), (6, 9), (6, 10), (7, 8), (7, 9), (8, 18), (10, 11), (10, 13), (10, 19), (10, 22), (10, 26), (11, 18), (11, 26), (11, 28), (12, 13), (12, 14), (12, 28), (12, 29), (13, 16), (13, 21), (13, 29), (14, 18), (16, 20), (17, 18), (17, 26), (17, 28), (18, 19), (18, 22), (18, 27), (18, 28), (19, 23), (19, 25), (19, 28), (20, 22), (24, 26), (24, 27), (25, 27), (25, 29)]
730
sage: G.show() # long time
731
"""
732
if seed is None:
733
seed = current_randstate().long_seed()
734
import networkx
735
return Graph(networkx.random_shell_graph(constructor, seed=seed))
736
737
def RandomToleranceGraph(n):
738
r"""
739
Returns a random tolerance graph.
740
741
The random tolerance graph is built from a random tolerance representation
742
by using the function `ToleranceGraph`. This representation is a list
743
`((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))` where `k = n-1` and
744
`I_i = (l_i,r_i)` denotes a random interval and `t_i` a random positive
745
value. The width of the representation is limited to n**2 * 2**n.
746
747
.. NOTE::
748
749
The vertices are named 0, 1, ..., n-1. The tolerance representation used
750
to create the graph is saved with the graph and can be recovered using
751
``get_vertex()`` or ``get_vertices()``.
752
753
INPUT:
754
755
- ``n`` -- number of vertices of the random graph.
756
757
EXAMPLE:
758
759
Every tolerance graph is perfect. Hence, the chromatic number is equal to
760
the clique number ::
761
762
sage: g = graphs.RandomToleranceGraph(8)
763
sage: g.clique_number() == g.chromatic_number()
764
True
765
766
TEST:
767
768
sage: g = graphs.RandomToleranceGraph(-2)
769
Traceback (most recent call last):
770
...
771
ValueError: The number `n` of vertices must be >= 0.
772
"""
773
from sage.misc.prandom import randint
774
from sage.graphs.generators.intersection import ToleranceGraph
775
776
if n<0:
777
raise ValueError('The number `n` of vertices must be >= 0.')
778
779
W = n**2 * 2**n
780
781
tolrep = [tuple(sorted((randint(0,W), randint(0,W)))) + (randint(0,W),) for i in range(n)]
782
783
return ToleranceGraph(tolrep)
784
785
786