Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/generators/smallgraphs.py
8815 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Small graphs
4
5
The methods defined here appear in :mod:`sage.graphs.graph_generators`.
6
"""
7
#*****************************************************************************
8
# Copyright (C) 2006 Robert L. Miller <[email protected]>
9
# and Emily A. Kirkman
10
# Copyright (C) 2009 Michael C. Yurko <[email protected]>
11
#
12
# Distributed under the terms of the GNU General Public License (GPL)
13
# as published by the Free Software Foundation; either version 2 of
14
# the License, or (at your option) any later version.
15
# http://www.gnu.org/licenses/
16
#*****************************************************************************
17
18
19
# import from Sage library
20
from sage.graphs.graph import Graph
21
from math import sin, cos, pi
22
from sage.graphs.graph_plot import _circle_embedding, _line_embedding
23
24
#######################################################################
25
# Named Graphs
26
#######################################################################
27
28
def HarriesGraph(embedding=1):
29
r"""
30
Returns the Harries Graph.
31
32
The Harries graph is a Hamiltonian 3-regular graph on 70
33
vertices. See the :wikipedia:`Wikipedia page on the Harries
34
graph <Harries_graph>`.
35
36
The default embedding here is to emphasize the graph's 4 orbits.
37
This graph actually has a funny construction. The following
38
procedure gives an idea of it, though not all the adjacencies
39
are being properly defined.
40
41
#. Take two disjoint copies of a :meth:`Petersen graph
42
<PetersenGraph>`. Their vertices will form an orbit of the
43
final graph.
44
45
#. Subdivide all the edges once, to create 15+15=30 new
46
vertices, which together form another orbit.
47
48
#. Create 15 vertices, each of them linked to 2 corresponding
49
vertices of the previous orbit, one in each of the two
50
subdivided Petersen graphs. At the end of this step all
51
vertices from the previous orbit have degree 3, and the only
52
vertices of degree 2 in the graph are those that were just
53
created.
54
55
#. Create 5 vertices connected only to the ones from the
56
previous orbit so that the graph becomes 3-regular.
57
58
INPUT:
59
60
- ``embedding`` -- two embeddings are available, and can be
61
selected by setting ``embedding`` to 1 or 2.
62
63
EXAMPLES::
64
65
sage: g = graphs.HarriesGraph()
66
sage: g.order()
67
70
68
sage: g.size()
69
105
70
sage: g.girth()
71
10
72
sage: g.diameter()
73
6
74
sage: g.show(figsize=[10, 10]) # long time
75
sage: graphs.HarriesGraph(embedding=2).show(figsize=[10, 10]) # long time
76
77
TESTS::
78
79
sage: graphs.HarriesGraph(embedding=3)
80
Traceback (most recent call last):
81
...
82
ValueError: The value of embedding must be 1 or 2.
83
84
"""
85
from sage.graphs.generators.families import LCFGraph
86
g = LCFGraph(70, [-29, -19, -13, 13, 21, -27, 27, 33, -13, 13,
87
19, -21, -33, 29], 5)
88
g.name("Harries Graph")
89
90
if embedding == 1:
91
gpos = g.get_pos()
92
ppos = PetersenGraph().get_pos()
93
94
# The graph's four orbits
95
o = [None]*4
96
o[0] = [0, 2, 6, 8, 14, 16, 20, 22, 28, 30, 34, 36, 42, 44, 48, 50,
97
56, 58, 62, 64]
98
o[1] = [1, 3, 5, 7, 9, 13, 15, 17, 19, 21, 23, 27, 29, 31, 33, 35,
99
37, 41, 43, 45, 47, 49, 51, 55, 57, 59, 61, 63, 65, 69]
100
o[2] = [60, 10, 12, 4, 24, 26, 18, 38, 40, 32, 52, 54, 46, 66, 68]
101
o[3] = [11, 25, 39, 53, 67]
102
103
# Correspondence between the vertices of one of the two Petersen
104
# graphs on o[0] and the vertices of a standard Petersen graph
105
# object
106
g_to_p = {0: 0, 2: 1, 42: 5, 44: 8, 14: 7, 16: 2, 56: 9, 58: 6,
107
28: 4, 30: 3}
108
109
# Correspondence between the vertices of the other Petersen graph
110
# on o[0] and the vertices of the first one
111
g_to_g = {64: 44, 34: 0, 36: 28, 6: 2, 8: 58, 48: 16, 50: 30,
112
20: 14, 22: 56, 62: 42}
113
114
# Position for the vertices from the first copy
115
for v, i in g_to_p.iteritems():
116
gpos[v] = ppos[i]
117
118
# Position for the vertices in the second copy. Moves the first,
119
# too.
120
offset = 3.5
121
for v, i in g_to_g.iteritems():
122
x, y = gpos[i]
123
gpos[v] = (x + offset*0.5, y)
124
gpos[i] = (x - offset*0.5, y)
125
126
# Vertices from o[1]. These are actually the "edges" of the
127
# copies of Petersen.
128
for v in o[1]:
129
p1, p2 = [gpos[x] for x in g.neighbors(v) if x in o[0]]
130
gpos[v] = ((p1[0] + p2[0])/2, (p1[1] + p2[1])/2)
131
132
# 15 vertices from o[2]
133
for i, v in enumerate(o[2]):
134
gpos[v] = (-1.75 + i*.25, 2)
135
136
# 5 vertices from o[3]
137
for i, v in enumerate(o[3]):
138
gpos[v] = (-1 + i*.5, 2.5)
139
140
return g
141
142
elif embedding == 2:
143
return g
144
else:
145
raise ValueError("The value of embedding must be 1 or 2.")
146
147
def HarriesWongGraph(embedding=1):
148
r"""
149
Returns the Harries-Wong Graph.
150
151
See the :wikipedia:`Wikipedia page on the Harries-Wong graph
152
<Harries-Wong_graph>`.
153
154
*About the default embedding:*
155
156
The default embedding is an attempt to emphasize the graph's
157
8 (!!!) different orbits. In order to understand this better,
158
one can picture the graph as being built in the following way:
159
160
#. One first creates a 3-dimensional cube (8 vertices, 12
161
edges), whose vertices define the first orbit of the
162
final graph.
163
164
#. The edges of this graph are subdivided once, to create 12
165
new vertices which define a second orbit.
166
167
#. The edges of the graph are subdivided once more, to
168
create 24 new vertices giving a third orbit.
169
170
#. 4 vertices are created and made adjacent to the vertices
171
of the second orbit so that they have degree
172
3. These 4 vertices also define a new orbit.
173
174
#. In order to make the vertices from the third orbit
175
3-regular (they all miss one edge), one creates a binary
176
tree on 1 + 3 + 6 + 12 vertices. The leaves of this new
177
tree are made adjacent to the 12 vertices of the third
178
orbit, and the graph is now 3-regular. This binary tree
179
contributes 4 new orbits to the Harries-Wong graph.
180
181
INPUT:
182
183
- ``embedding`` -- two embeddings are available, and can be
184
selected by setting ``embedding`` to 1 or 2.
185
186
EXAMPLES::
187
188
sage: g = graphs.HarriesWongGraph()
189
sage: g.order()
190
70
191
sage: g.size()
192
105
193
sage: g.girth()
194
10
195
sage: g.diameter()
196
6
197
sage: orbits = g.automorphism_group(orbits=True)[-1]
198
sage: g.show(figsize=[15, 15], partition=orbits) # long time
199
200
Alternative embedding::
201
202
sage: graphs.HarriesWongGraph(embedding=2).show()
203
204
TESTS::
205
206
sage: graphs.HarriesWongGraph(embedding=3)
207
Traceback (most recent call last):
208
...
209
ValueError: The value of embedding must be 1 or 2.
210
"""
211
212
L = [9, 25, 31, -17, 17, 33, 9, -29, -15, -9, 9, 25, -25, 29, 17, -9,
213
9, -27, 35, -9, 9, -17, 21, 27, -29, -9, -25, 13, 19, -9, -33,
214
-17, 19, -31, 27, 11, -25, 29, -33, 13, -13, 21, -29, -21, 25,
215
9, -11, -19, 29, 9, -27, -19, -13, -35, -9, 9, 17, 25, -9, 9, 27,
216
-27, -21, 15, -9, 29, -29, 33, -9, -25]
217
218
from sage.graphs.generators.families import LCFGraph
219
g = LCFGraph(70, L, 1)
220
g.name("Harries-Wong graph")
221
222
if embedding == 1:
223
d = g.get_pos()
224
225
# Binary tree (left side)
226
d[66] = (-9.5, 0)
227
_line_embedding(g, [37, 65, 67], first=(-8, 2.25),
228
last=(-8, -2.25))
229
_line_embedding(g, [36, 38, 64, 24, 68, 30], first=(-7, 3),
230
last=(-7, -3))
231
_line_embedding(g, [35, 39, 63, 25, 59, 29, 11, 5, 55, 23, 69, 31],
232
first=(-6, 3.5), last=(-6, -3.5))
233
234
# Cube, corners: [9, 15, 21, 27, 45, 51, 57, 61]
235
_circle_embedding(g, [61, 9], center=(0, -1.5), shift=.2,
236
radius=4)
237
_circle_embedding(g, [27, 15], center=(0, -1.5), shift=.7,
238
radius=4*.707)
239
_circle_embedding(g, [51, 21], center=(0, 2.5), shift=.2,
240
radius=4)
241
_circle_embedding(g, [45, 57], center=(0, 2.5), shift=.7,
242
radius=4*.707)
243
244
# Cube, subdivision
245
_line_embedding(g, [21, 22, 43, 44, 45], first=d[21], last=d[45])
246
_line_embedding(g, [21, 4, 3, 56, 57], first=d[21], last=d[57])
247
_line_embedding(g, [57, 12, 13, 14, 15], first=d[57], last=d[15])
248
_line_embedding(g, [15, 6, 7, 8, 9], first=d[15], last=d[9])
249
_line_embedding(g, [9, 10, 19, 20, 21], first=d[9], last=d[21])
250
_line_embedding(g, [45, 54, 53, 52, 51], first=d[45], last=d[51])
251
_line_embedding(g, [51, 50, 49, 58, 57], first=d[51], last=d[57])
252
_line_embedding(g, [51, 32, 33, 34, 61], first=d[51], last=d[61])
253
_line_embedding(g, [61, 62, 41, 40, 27], first=d[61], last=d[27])
254
_line_embedding(g, [9, 0, 1, 26, 27], first=d[9], last=d[27])
255
_line_embedding(g, [27, 28, 47, 46, 45], first=d[27], last=d[45])
256
_line_embedding(g, [15, 16, 17, 60, 61], first=d[15], last=d[61])
257
258
# Top vertices
259
_line_embedding(g, [2, 18, 42, 48], first=(-1, 7), last=(3, 7))
260
261
return g
262
263
elif embedding == 2:
264
return g
265
else:
266
raise ValueError("The value of embedding must be 1 or 2.")
267
268
def WellsGraph():
269
r"""
270
Returns the Wells graph.
271
272
For more information on the Wells graph (also called Armanios-Wells graph),
273
see `this page <http://www.win.tue.nl/~aeb/graphs/Wells.html>`_.
274
275
The implementation follows the construction given on page 266 of
276
[BCN89]_. This requires to create intermediate graphs and run a small
277
isomorphism test, while everything could be replaced by a pre-computed list
278
of edges : I believe that it is better to keep "the recipe" in the code,
279
however, as it is quite unlikely that this could become the most
280
time-consuming operation in any sensible algorithm, and .... "preserves
281
knowledge", which is what open-source software is meant to do.
282
283
EXAMPLES::
284
285
sage: g = graphs.WellsGraph(); g
286
Wells graph: Graph on 32 vertices
287
sage: g.order()
288
32
289
sage: g.size()
290
80
291
sage: g.girth()
292
5
293
sage: g.diameter()
294
4
295
sage: g.chromatic_number()
296
4
297
sage: g.is_regular(k=5)
298
True
299
300
REFERENCES:
301
302
.. [BCN89] A. E. Brouwer, A. M. Cohen, A. Neumaier,
303
Distance-Regular Graphs,
304
Springer, 1989.
305
"""
306
from platonic_solids import DodecahedralGraph
307
from basic import CompleteBipartiteGraph
308
309
# Following the construction from the book "Distance-regular graphs"
310
dodecahedron = DodecahedralGraph()
311
312
# Vertices at distance 3 in the Dodecahedron
313
distance3 = dodecahedron.distance_graph([3])
314
315
# Building the graph whose line graph is the dodecahedron.
316
b = CompleteBipartiteGraph(5,5)
317
b.delete_edges([(0,5), (1,6), (2,7), (3,8), (4,9)])
318
319
# Computing the isomorphism between the two
320
b = b.line_graph(labels = False)
321
_, labels = distance3.is_isomorphic(b, certify = True)
322
323
# The relabeling that the books claims to exist.
324
for v,new_name in labels.items():
325
x,y = new_name
326
labels[v] = (x%5,y%5)
327
328
dodecahedron.relabel(labels)
329
330
# Checking that the above computations indeed produces a good labeling.
331
for u in dodecahedron:
332
for v in dodecahedron:
333
if u == v:
334
continue
335
336
if (u[0] != v[0]) and (u[1] != v[1]):
337
continue
338
339
if dodecahedron.distance(u,v) != 3:
340
raise ValueError("There is something wrong going on !")
341
342
# The graph we will return, starting from the dodecahedron
343
g = dodecahedron
344
345
# Good ! Now adding 12 new vertices
346
for i in range(5):
347
g.add_edge((i,'+'),('inf','+'))
348
g.add_edge((i,'-'),('inf','-'))
349
for k in range(5):
350
if k == i:
351
continue
352
g.add_edge((i,'+'),(i,k))
353
g.add_edge((i,'-'),(k,i))
354
355
g.name("Wells graph")
356
357
# Giving our graph a "not-so-bad" layout
358
g.relabel({
359
(1, 3): 8, (3, 0): 18, (3, '+'): 22, (2, 1): 13,
360
(1, '+'): 10, (0, 3): 2, (2, '+'): 16, ('inf', '-'): 31,
361
(4, 0): 24, (1, 2): 7, (4, '+'): 28, (0, '-'): 5,
362
(0, 4): 3, (4, 1): 25, (2, '-'): 17, (3, 2): 20,
363
(3, '-'): 23, (1, '-'): 11, (1, 4): 9, (2, 3): 14,
364
('inf', '+'): 30, (4, 2): 26, (1, 0): 6, (0, 1): 0,
365
(3, 1): 19, (0, 2): 1, (2, 0): 12, (4, '-'): 29,
366
(0, '+'): 4, (4, 3): 27, (3, 4): 21, (2, 4): 15})
367
368
p = [(1, 29, 20, 13, 12, 28, 14, 7),
369
(2, 5, 30, 23, 18, 4, 31, 22),
370
(3, 17, 21, 9, 24, 16, 27, 25),
371
(6, 10, 8, 15, 0, 11, 19, 26)]
372
373
from sage.graphs.graph_plot import _circle_embedding
374
_circle_embedding(g, p[0], radius = 1)
375
_circle_embedding(g, p[1], radius = .9)
376
_circle_embedding(g, p[2], radius = .8)
377
_circle_embedding(g, p[3], radius = .7)
378
379
return g
380
381
382
def HallJankoGraph(from_string=True):
383
r"""
384
Returns the Hall-Janko graph.
385
386
For more information on the Hall-Janko graph, see its
387
:wikipedia:`Wikipedia page <Hall-Janko_graph>`.
388
389
The construction used to generate this graph in Sage is by
390
a 100-point permutation representation of the Janko group `J_2`,
391
as described in version 3 of the ATLAS of Finite Group
392
representations, in particular on the page `ATLAS: J2
393
-- Permutation representation on 100 points
394
<http://brauer.maths.qmul.ac.uk/Atlas/v3/permrep/J2G1-p100B0>`_.
395
396
INPUT:
397
398
- ``from_string`` (boolean) -- whether to build the graph from
399
its sparse6 string or through GAP. The two methods return the
400
same graph though doing it through GAP takes more time. It is
401
set to ``True`` by default.
402
403
EXAMPLES::
404
405
sage: g = graphs.HallJankoGraph()
406
sage: g.is_regular(36)
407
True
408
sage: g.is_vertex_transitive()
409
True
410
411
Is it really strongly regular with parameters 14, 12? ::
412
413
sage: nu = set(g.neighbors(0))
414
sage: for v in range(1, 100):
415
....: if v in nu:
416
....: expected = 14
417
....: else:
418
....: expected = 12
419
....: nv = set(g.neighbors(v))
420
....: nv.discard(0)
421
....: if len(nu & nv) != expected:
422
....: print "Something is wrong here!!!"
423
....: break
424
425
Some other properties that we know how to check::
426
427
sage: g.diameter()
428
2
429
sage: g.girth()
430
3
431
sage: factor(g.characteristic_polynomial())
432
(x - 36) * (x - 6)^36 * (x + 4)^63
433
434
TESTS::
435
436
sage: gg = graphs.HallJankoGraph(from_string=False) # long time
437
sage: g == gg # long time
438
True
439
"""
440
441
string = (":~?@c__E@?g?A?w?A@GCA_?CA`OWF`W?EAW?@?_OD@_[GAgcIaGGB@OcIA"
442
"wCE@o_K_?GB@?WGAouC@OsN_?GB@O[GB`A@@_e?@OgLB_{Q_?GC@O[GAOs"
443
"OCWGBA?kKBPA@?_[KB_{OCPKT`o_RD`]A?o[HBOwODW?DA?cIB?wRDP[X`"
444
"ogKB_{QD@]B@o_KBPWXE`mC@o_JB?{PDPq@?oWGA_{OCPKTDp_YEwCA@_c"
445
"IBOwOC`OX_OGB@?WPDPcYFg?C@_gKBp?SE@cYF`{_`?SGAOoOC`_\\FwCE"
446
"A?gKBO{QD@k[FqI??_OFA_oQE@k\\Fq?`GgCB@pGRD@_XFP{a_?SE@ocIA"
447
"ooNCPOUEqU@?oODA?cJB_{UEqYC@_kLC@CREPk]GAGbHgCA@?SMBpCSD`["
448
"YFq?`Ga]BA?gPC`KSD`_\\Fa?cHWGB@?[IAooPD`[WF@s^HASeIg?@@OcP"
449
"C`KYF@w^GQ[h`O[HAooMC@CQCpSVEPk\\GaSeIG?FA?kLB_{OC`OVE@cYG"
450
"QUA@?WLBp?PC`KVEqKgJg?DA?sMBpCSDP[WEQKfIay@?_KD@_[GC`SUE@k"
451
"[FaKdHa[k_?OLC@CRD@WVEpo^HAWfIAciIqoo_?CB@?kMCpOUE`o\\GAKg"
452
"IQgq_?GD@_[GB?{OCpWVE@cYFACaHAWhJR?q_?CC@_kKBpC\\GACdHa[kJ"
453
"a{o_?CA?oOFBpGRD@o\\GaKdIQonKrOt_?WHA`?PC`KTD`k]FqSeIaolJr"
454
"CqLWCA@OkKCPGRDpcYGAKdIAgjJAsmJr?t__OE@ogJB_{XEps`HA[gIQwn"
455
"KWKGAOoMBpGUE`k[Fa?aHqckJbSuLw?@?_SHA_kLC@OTFPw^GaOkLg?B@?"
456
"[HA_{PDP_XFaCbHa[gIqooKRWx_?CFBpOTE@cZFPw^GACcHQgoKrSvMwWG"
457
"BOwQCp_YFP{`HASfJAwnKRSx_OSSDP[WEq?aGqSfIQsoKR_zNWCE@o_HA_"
458
"sREPg^GAGcHQWfIAciKbOxNg?A@__IAooMC`KTD`g\\GAKcIasoKrOtLb["
459
"wMbyCA?cKBp?TD`[WE`s^GQGbHqcjJrK{NRw~_oODA?sNC@CQCpOZF@s]G"
460
"QOfIaolJrGsLbk}_?OFA_sRD@SVE`k[HQcjJa{qLb[xMb|?_OOFA?cIAos"
461
"RDP_ZFa?aGqOfIAsuMbk{Ns@@OsQAA_sPDPWXE`o\\FqKdIQkkJrCuLr_x"
462
"Mro}NsDAPG?@@OWFApKUE@o`IQolKRKsLrc|NsQC@OWGAOgJCpOWE`o_GQ"
463
"KiIqwnKr_~OcLCPS]A?oWHA_oMBpKSDP[\\FagjKBWxMbk{OSQ@@O_IAoo"
464
"LBpCSD`g\\FaGbHQWgIQgmKRKwMRl?PgGC@OWHB@KSE@c[FqCaGqSeIAkk"
465
"KBCqLBSuMBpGQWCA@?cKBOwRDPWVE@k^GqOfJr?pKbKtLrs}OSHDQwKIBO"
466
"wPD@WWEQ?`HQWfIQglKBOtLbo}Ns@@OsTE_?kLCpWWHA[gIqomKBGwMRgz"
467
"NBw~OSPDPc\\H_?CFAOoLCPSVE`o\\GAOeJAwpKbKtMrx?Qcq??OKFA?gJ"
468
"B`?QDpcYEpo]FqKfIAgjJB?qKr_{NS@A__SE@o_HBO{PC`OTD`{_HaciIq"
469
"{vMbt?OcPFQCeB@?SKBOwRD@SXE`k[FPw`HQ_lKRKxNRxBPC\\HQclK_?K"
470
"EB?sOC`OTDa?`GqWgJRCrNBw~OSHFQStMRtDQ_?KC@OoQE`k_GaOdHa[gI"
471
"q{tMBg|Nb|?OcPMSDDQSwCB@_cJB_{OCpOVFP{dHa[jJQwqKrk}NsHBQCd"
472
"MRtMA?oSEA_wPDp_YEpo]GAOeIq{pLBk}NsLEQCtNTDU??OKEA_oLC@[[G"
473
"aKnKBOtLbk~OCPFQStNSDLSTgGKC@GSD`[WEpw_GQGcIAciJAwpKb_xMbk"
474
"~QShJRc|R`_wNCPcZF@s^GAGbHA_hJR?qKrOvMRg|NsDEPsxTTgCB@?gJB"
475
"?sMC@CUDp_]FqCaHQcjJQwtLrhCPS\\IRCtQTw?B@?SHA_wPC`_aGqOiJa"
476
"{oKRKvMRpFQChKRtXVUTi??ocNC@KUE@cYFaGdHa_mJrKsLb[yMro|OcXI"
477
"RdPTTddZaOgJB@?UEPk[FQCfIaolJrSvMBczNR|AOsXFQCtOTtaB@?WGAP"
478
"?TEPo\\GAGdHqgmKBCqLR[xMb|?PC`HQs|TTt`XUtu@?o[HB?sNCPGXF@{"
479
"_GQKcIqolJb_yNCLDPs`MRtDRTTdYUwSEA?kLB`CWF@s]FqGgIqooLRgzN"
480
"RxFQSlMSDDQTDXVUTi@?_KDAOoLBpKUEQOfIa{oLB_xMrt?Os\\HQcpMST"
481
"HSTtl[VT}A@ocJBOwSD`_XEpo_Ha_mJrKtLbgzNSTGQspLRtDUUDp\\WG["
482
"HB`CQCp[WFQGgIQgkJQ{rLbc{Nc@APsdLRt@PSt\\WUtt_Wn")
483
484
if from_string:
485
g = Graph(string, loops = False, multiedges = False)
486
else:
487
488
# The following construction is due to version 3 of the ATLAS of
489
# Finite Group Representations, specifically the page at
490
# http://brauer.maths.qmul.ac.uk/Atlas/v3/permrep/J2G1-p100B0 .
491
492
from sage.interfaces.gap import gap
493
gap.eval("g1 := (1,84)(2,20)(3,48)(4,56)(5,82)(6,67)(7,55)(8,41)"
494
"(9,35)(10,40)(11,78)(12,100)(13,49)(14,37)(15,94)(16,76)"
495
"(17,19)(18,44)(21,34)(22,85)(23,92)(24,57)(25,75)(26,28)"
496
"(27,64)(29,90)(30,97)(31,38)(32,68)(33,69)(36,53)(39,61)"
497
"(42,73)(43,91)(45,86)(46,81)(47,89)(50,93)(51,96)(52,72)"
498
"(54,74)(58,99)(59,95)(60,63)(62,83)(65,70)(66,88)(71,87)"
499
"(77,98)(79,80);")
500
501
gap.eval("g2 := (1,80,22)(2,9,11)(3,53,87)(4,23,78)(5,51,18)"
502
"(6,37,24)(8,27,60)(10,62,47)(12,65,31)(13,64,19)"
503
"(14,61,52)(15,98,25)(16,73,32)(17,39,33)(20,97,58)"
504
"(21,96,67)(26,93,99)(28,57,35)(29,71,55)(30,69,45)"
505
"(34,86,82)(38,59,94)(40,43,91)(42,68,44)(46,85,89)"
506
"(48,76,90)(49,92,77)(50,66,88)(54,95,56)(63,74,72)"
507
"(70,81,75)(79,100,83);")
508
509
gap.eval("G := Group([g1,g2]);")
510
edges = gap('Orbit(G,[1,5],OnSets)').sage()
511
g = Graph([(int(u), int(v)) for u,v in edges])
512
g.relabel()
513
514
_circle_embedding(g, range(100))
515
g.name("Hall-Janko graph")
516
return g
517
518
def Balaban10Cage(embedding=1):
519
r"""
520
Returns the Balaban 10-cage.
521
522
The Balaban 10-cage is a 3-regular graph with 70 vertices and
523
105 edges. See its :wikipedia:`Wikipedia page
524
<Balaban_10-cage>`.
525
526
The default embedding gives a deeper understanding of the
527
graph's automorphism group. It is divided into 4 layers (each
528
layer being a set of points at equal distance from the drawing's
529
center). From outside to inside:
530
531
- L1: The outer layer (vertices which are the furthest from the
532
origin) is actually the disjoint union of two cycles of length
533
10.
534
535
- L2: The second layer is an independent set of 20 vertices.
536
537
- L3: The third layer is a matching on 10 vertices.
538
539
- L4: The inner layer (vertices which are the closest from the
540
origin) is also the disjoint union of two cycles of length 10.
541
542
This graph is not vertex-transitive, and its vertices are
543
partitioned into 3 orbits: L2, L3, and the union of L1 of L4
544
whose elements are equivalent.
545
546
INPUT:
547
548
- ``embedding`` -- two embeddings are available, and can be
549
selected by setting ``embedding`` to be either 1 or 2.
550
551
EXAMPLES::
552
553
sage: g = graphs.Balaban10Cage()
554
sage: g.girth()
555
10
556
sage: g.chromatic_number()
557
2
558
sage: g.diameter()
559
6
560
sage: g.is_hamiltonian()
561
True
562
sage: g.show(figsize=[10,10]) # long time
563
564
TESTS::
565
566
sage: graphs.Balaban10Cage(embedding='foo')
567
Traceback (most recent call last):
568
...
569
ValueError: The value of embedding must be 1 or 2.
570
"""
571
572
L = [-9, -25, -19, 29, 13, 35, -13, -29, 19, 25, 9, -29, 29, 17, 33,
573
21, 9,-13, -31, -9, 25, 17, 9, -31, 27, -9, 17, -19, -29, 27,
574
-17, -9, -29, 33, -25,25, -21, 17, -17, 29, 35, -29, 17, -17,
575
21, -25, 25, -33, 29, 9, 17, -27, 29, 19, -17, 9, -27, 31, -9,
576
-17, -25, 9, 31, 13, -9, -21, -33, -17, -29, 29]
577
578
from sage.graphs.generators.families import LCFGraph
579
g = LCFGraph(70, L, 1)
580
g.name("Balaban 10-cage")
581
582
if embedding == 2:
583
return g
584
elif embedding != 1:
585
raise ValueError("The value of embedding must be 1 or 2.")
586
587
L3 = [5, 24, 35, 46, 29, 40, 51, 34, 45, 56]
588
_circle_embedding(g, L3, center=(0,0), radius = 4.3)
589
590
L2 = [6, 4, 23, 25, 60, 36, 1, 47, 28, 30, 39, 41, 50, 52, 33, 9, 44,
591
20, 55, 57]
592
_circle_embedding(g, L2, center=(0,0), radius = 5, shift=-.5)
593
594
595
L1a = [69, 68, 67, 66, 65, 64, 63, 62, 61, 0]
596
L1b = [19, 18, 17, 16, 15, 14, 13, 12, 11, 10]
597
_circle_embedding(g, L1a, center=(0,0), radius = 6, shift = 3.25)
598
_circle_embedding(g, L1b, center=(0,0), radius = 6, shift = -1.25)
599
600
L4a = [37, 2, 31, 38, 53, 32, 21, 54, 3, 22]
601
_circle_embedding(g, L4a, center=(0,0), radius = 3, shift = 1.9)
602
603
L4b = [26, 59, 48, 27, 42, 49, 8, 43, 58, 7]
604
_circle_embedding(g, L4b, center=(0,0), radius = 3, shift = 1.1)
605
606
return g
607
608
def Balaban11Cage(embedding = 1):
609
r"""
610
Returns the Balaban 11-cage.
611
612
For more information, see this :wikipedia:`Wikipedia article on
613
the Balaban 11-cage <Balaban_11-cage>`.
614
615
INPUT:
616
617
- ``embedding`` -- three embeddings are available, and can be
618
selected by setting ``embedding`` to be 1, 2, or 3.
619
620
- The first embedding is the one appearing on page 9 of the
621
Fifth Annual Graph Drawing Contest report [FAGDC]_. It
622
separates vertices based on their eccentricity (see
623
:meth:`eccentricity()
624
<sage.graphs.generic_graph.GenericGraph.eccentricity>`).
625
626
- The second embedding has been produced just for Sage and is
627
meant to emphasize the automorphism group's 6 orbits.
628
629
- The last embedding is the default one produced by the
630
:meth:`LCFGraph` constructor.
631
632
.. NOTE::
633
634
The vertex labeling changes according to the value of
635
``embedding=1``.
636
637
EXAMPLES:
638
639
Basic properties::
640
641
sage: g = graphs.Balaban11Cage()
642
sage: g.order()
643
112
644
sage: g.size()
645
168
646
sage: g.girth()
647
11
648
sage: g.diameter()
649
8
650
sage: g.automorphism_group().cardinality()
651
64
652
653
Our many embeddings::
654
655
sage: g1 = graphs.Balaban11Cage(embedding=1)
656
sage: g2 = graphs.Balaban11Cage(embedding=2)
657
sage: g3 = graphs.Balaban11Cage(embedding=3)
658
sage: g1.show(figsize=[10,10]) # long time
659
sage: g2.show(figsize=[10,10]) # long time
660
sage: g3.show(figsize=[10,10]) # long time
661
662
Proof that the embeddings are the same graph::
663
664
sage: g1.is_isomorphic(g2) # g2 and g3 are obviously isomorphic
665
True
666
667
TESTS::
668
669
sage: graphs.Balaban11Cage(embedding='xyzzy')
670
Traceback (most recent call last):
671
...
672
ValueError: The value of embedding must be 1, 2, or 3.
673
674
REFERENCES:
675
676
.. [FAGDC] Fifth Annual Graph Drawing Contest
677
P. Eaded, J. Marks, P.Mutzel, S. North
678
http://www.merl.com/papers/docs/TR98-16.pdf
679
"""
680
if embedding == 1:
681
pos_dict = {}
682
for j in range(8):
683
for i in range(8):
684
pos_dict[str(j) + str(i)]= [
685
0.8 * float(cos(2*((8*j + i)*pi/64 + pi/128))),
686
0.8 * float(sin(2*((8*j + i)*pi/64 + pi/128)))
687
]
688
for i in range(4):
689
pos_dict['1' + str(j) + str(i)] = [
690
1.1 * float(cos(2*((4*j + i)*pi/32 + pi/64))),
691
1.1 * float(sin(2*((4*j + i)*pi/32 + pi/64)))
692
]
693
for i in range(2):
694
pos_dict['1' + str(j) + str(i + 4)] = [
695
1.4 * float(cos(2*((2*j + i)*pi/16 + pi/32))),
696
1.4 * float(sin(2*((2*j + i)*pi/16 + pi/32)))
697
]
698
699
edge_dict = {
700
"00": ["11"], "01": ["10"], "02": ["53"], "03": ["52"],
701
"11": ["20"], "10": ["21"], "53": ["22"], "52": ["23"],
702
"20": ["31"], "21": ["30"], "22": ["33"], "23": ["32"],
703
"31": ["40"], "30": ["41"], "33": ["43"], "32": ["42"],
704
"40": ["50"], "41": ["51"], "43": ["12"], "42": ["13"],
705
"50": ["61"], "51": ["60"], "12": ["63"], "13": ["62"],
706
"61": ["70"], "60": ["71"], "63": ["72"], "62": ["73"],
707
"70": ["01"], "71": ["00"], "72": ["03"], "73": ["02"],
708
709
"04": ["35"], "05": ["34"], "06": ["37"], "07": ["36"],
710
"35": ["64"], "34": ["65"], "37": ["66"], "36": ["67"],
711
"64": ["55"], "65": ["54"], "66": ["17"], "67": ["16"],
712
"55": ["45"], "54": ["44"], "17": ["46"], "16": ["47"],
713
"45": ["74"], "44": ["75"], "46": ["76"], "47": ["77"],
714
"74": ["25"], "75": ["24"], "76": ["27"], "77": ["26"],
715
"25": ["14"], "24": ["15"], "27": ["56"], "26": ["57"],
716
"14": ["05"], "15": ["04"], "56": ["07"], "57": ["06"],
717
718
"100": ["03", "04"], "110": ["10", "12"],
719
"101": ["01", "06"], "111": ["11", "13"],
720
"102": ["00", "07"], "112": ["14", "16"],
721
"103": ["02", "05"], "113": ["15", "17"],
722
723
"120": ["22", "24"], "130": ["33", "36"],
724
"121": ["20", "26"], "131": ["32", "37"],
725
"122": ["21", "27"], "132": ["31", "34"],
726
"123": ["23", "25"], "133": ["30", "35"],
727
728
"140": ["43", "45"], "150": ["50", "52"],
729
"141": ["40", "46"], "151": ["51", "53"],
730
"142": ["41", "47"], "152": ["54", "56"],
731
"143": ["42", "44"], "153": ["55", "57"],
732
733
"160": ["60", "66"], "170": ["73", "76"],
734
"161": ["63", "65"], "171": ["72", "77"],
735
"162": ["62", "64"], "172": ["71", "74"],
736
"163": ["61", "67"], "173": ["70", "75"],
737
738
"104": ["100", "102", "105"], "114": ["110", "111", "115"],
739
"105": ["101", "103", "104"], "115": ["112", "113", "114"],
740
741
"124": ["120", "121", "125"], "134": ["130", "131", "135"],
742
"125": ["122", "123", "124"], "135": ["132", "133", "134"],
743
744
"144": ["140", "141", "145"], "154": ["150", "151", "155"],
745
"145": ["142", "143", "144"], "155": ["152", "153", "154"],
746
747
"164": ["160", "161", "165"], "174": ["170", "171", "175"],
748
"165": ["162", "163", "164"], "175": ["172", "173", "174"]
749
}
750
751
return Graph(edge_dict, pos=pos_dict, name="Balaban 11-cage")
752
753
elif embedding == 2 or embedding == 3:
754
L = [44, 26, -47, -15, 35, -39, 11, -27, 38, -37, 43, 14, 28, 51,
755
-29, -16, 41, -11, -26, 15, 22, -51, -35, 36, 52, -14, -33,
756
-26, -46, 52, 26, 16, 43, 33, -15, 17, -53, 23, -42, -35, -28,
757
30, -22, 45, -44, 16, -38, -16, 50, -55, 20, 28, -17, -43,
758
47, 34, -26, -41, 11, -36, -23, -16, 41, 17, -51, 26, -33,
759
47, 17, -11, -20, -30, 21, 29, 36, -43, -52, 10, 39, -28, -17,
760
-52, 51, 26, 37, -17, 10, -10, -45, -34, 17, -26, 27, -21,
761
46, 53, -10, 29, -50, 35, 15, -47, -29, -41, 26, 33, 55, -17,
762
42, -26, -36, 16]
763
764
from sage.graphs.generators.families import LCFGraph
765
g = LCFGraph(112, L, 1)
766
g.name("Balaban 11-cage")
767
768
if embedding == 3:
769
return g
770
771
v1 = [34, 2, 54, 43, 66, 20, 89, 100, 72, 76, 6, 58, 16, 78, 74,
772
70, 36, 94, 27, 25, 10, 8, 45, 60, 14, 64, 80, 82, 109, 107,
773
49, 98]
774
v2 = [88, 3, 19, 55, 67, 42, 101, 33, 77, 5, 17, 57, 69, 71, 73,
775
75, 11, 61, 28, 9, 37, 26, 46, 95, 13, 63, 81, 83, 108, 106,
776
48, 97]
777
l1 = [35, 93, 1, 24, 53, 7, 44, 59, 15, 65, 79, 21, 110, 90, 50,
778
99]
779
l2 = [87, 4, 18, 56, 68, 41, 102, 32, 12, 62, 29, 84, 38, 105, 47,
780
96]
781
782
d = g.get_pos()
783
for i,v in enumerate(v1):
784
d[v] = (-2, 16.5-i)
785
786
for i,v in enumerate(l1):
787
d[v] = (-10, 8-i)
788
789
for i,v in enumerate(l2):
790
d[v] = (10, 8.5-i)
791
792
for i,v in enumerate(v2):
793
d[v] = (2, 16.5-i)
794
795
for i,v in enumerate([0, 111, 92, 91, 52, 51, 23, 22]):
796
d[v] = (-20, 14.5-4*i)
797
798
for i,v in enumerate([104, 103, 86, 85, 40, 39, 31, 30]):
799
d[v] = (20, 14.5-4*i)
800
801
return g
802
803
else:
804
raise ValueError("The value of embedding must be 1, 2, or 3.")
805
806
def BidiakisCube():
807
r"""
808
Returns the Bidiakis cube.
809
810
For more information, see this
811
`Wikipedia article on the Bidiakis cube <http://en.wikipedia.org/wiki/Bidiakis_cube>`_.
812
813
EXAMPLES:
814
815
The Bidiakis cube is a 3-regular graph having 12 vertices and 18
816
edges. This means that each vertex has a degree of 3. ::
817
818
sage: g = graphs.BidiakisCube(); g
819
Bidiakis cube: Graph on 12 vertices
820
sage: g.show() # long time
821
sage: g.order()
822
12
823
sage: g.size()
824
18
825
sage: g.is_regular(3)
826
True
827
828
It is a Hamiltonian graph with diameter 3 and girth 4::
829
830
sage: g.is_hamiltonian()
831
True
832
sage: g.diameter()
833
3
834
sage: g.girth()
835
4
836
837
It is a planar graph with characteristic polynomial
838
`(x - 3) (x - 2) (x^4) (x + 1) (x + 2) (x^2 + x - 4)^2` and
839
chromatic number 3::
840
841
sage: g.is_planar()
842
True
843
sage: bool(g.characteristic_polynomial() == expand((x - 3) * (x - 2) * (x^4) * (x + 1) * (x + 2) * (x^2 + x - 4)^2))
844
True
845
sage: g.chromatic_number()
846
3
847
"""
848
edge_dict = {
849
0:[1,6,11], 1:[2,5], 2:[3,10], 3:[4,9], 4:[5,8],
850
5:[6], 6:[7], 7:[8,11], 8:[9], 9:[10], 10:[11]}
851
pos_dict = {
852
0: [0, 1],
853
1: [0.5, 0.866025403784439],
854
2: [0.866025403784439, 0.500000000000000],
855
3: [1, 0],
856
4: [0.866025403784439, -0.5],
857
5: [0.5, -0.866025403784439],
858
6: [0, -1],
859
7: [-0.5, -0.866025403784439],
860
8: [-0.866025403784439, -0.5],
861
9: [-1, 0],
862
10: [-0.866025403784439, 0.5],
863
11: [-0.5, 0.866025403784439]}
864
return Graph(edge_dict, pos=pos_dict, name="Bidiakis cube")
865
866
def BiggsSmithGraph(embedding=1):
867
r"""
868
Returns the Biggs-Smith graph.
869
870
For more information, see this :wikipedia:`Wikipedia article on
871
the Biggs-Smith graph <Biggs-Smith_graph>`.
872
873
INPUT:
874
875
- ``embedding`` -- two embeddings are available, and can be
876
selected by setting ``embedding`` to be 1 or 2.
877
878
EXAMPLES:
879
880
Basic properties::
881
882
sage: g = graphs.BiggsSmithGraph()
883
sage: g.order()
884
102
885
sage: g.size()
886
153
887
sage: g.girth()
888
9
889
sage: g.diameter()
890
7
891
sage: g.automorphism_group().cardinality()
892
2448
893
sage: g.show(figsize=[10, 10]) # long time
894
895
The other embedding::
896
897
sage: graphs.BiggsSmithGraph(embedding=2).show()
898
899
TESTS::
900
901
sage: graphs.BiggsSmithGraph(embedding='xyzzy')
902
Traceback (most recent call last):
903
...
904
ValueError: The value of embedding must be 1 or 2.
905
906
"""
907
L = [16, 24, -38, 17, 34, 48, -19, 41, -35, 47, -20, 34, -36,
908
21, 14, 48, -16, -36, -43, 28, -17, 21, 29, -43, 46, -24,
909
28, -38, -14, -50, -45, 21, 8, 27, -21, 20, -37, 39, -34,
910
-44, -8, 38, -21, 25, 15, -34, 18, -28, -41, 36, 8, -29,
911
-21, -48, -28, -20, -47, 14, -8, -15, -27, 38, 24, -48, -18,
912
25, 38, 31, -25, 24, -46, -14, 28, 11, 21, 35, -39, 43, 36,
913
-38, 14, 50, 43, 36, -11, -36, -24, 45, 8, 19, -25, 38, 20,
914
-24, -14, -21, -8, 44, -31, -38, -28, 37]
915
916
from sage.graphs.generators.families import LCFGraph
917
g = LCFGraph(102, L, 1)
918
g.name("Biggs-Smith graph")
919
920
if embedding == 1:
921
922
orbs = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0],
923
[17, 101, 25, 66, 20, 38, 53, 89, 48, 75, 56, 92, 45, 78,
924
34, 28, 63],
925
[18, 36, 26, 65, 19, 37, 54, 90, 47, 76, 55, 91, 46, 77,
926
35, 27, 64],
927
[21, 39, 52, 88, 49, 74, 57, 93, 44, 79, 33, 29, 62, 83,
928
100, 24, 67],
929
[22, 97, 51, 96, 50, 95, 58, 94, 59, 80, 60, 81, 61, 82,
930
99, 23, 98],
931
[30, 86, 84, 72, 70, 68, 42, 40, 31, 87, 85, 73, 71, 69,
932
43, 41, 32]]
933
934
# central orbits
935
_circle_embedding(g, orbs[1], center=(-.4, 0), radius=.2)
936
_circle_embedding(g, orbs[3], center=(.4, 0), radius=.2, shift=4)
937
938
# lower orbits
939
_circle_embedding(g, orbs[0], center=(-.9, -.5), radius=.3,
940
shift=2)
941
_circle_embedding(g, orbs[2], center=(-.9, .5), radius=.3)
942
943
# upper orbits
944
_circle_embedding(g, orbs[4], center=(.9, -.5), radius=.3, shift=4)
945
_circle_embedding(g, orbs[5], center=(.9, .5), radius=.3, shift=-2)
946
947
elif embedding == 2:
948
pass
949
else:
950
raise ValueError("The value of embedding must be 1 or 2.")
951
952
return g
953
954
def BlanusaFirstSnarkGraph():
955
r"""
956
Returns the first Blanusa Snark Graph.
957
958
The Blanusa graphs are two snarks on 18 vertices and 27 edges. For more
959
information on them, see the :wikipedia:`Blanusa_snarks`.
960
961
.. SEEALSO::
962
963
* :meth:`~sage.graphs.graph_generators.GraphGenerators.BlanusaSecondSnarkGraph`.
964
965
EXAMPLES::
966
967
sage: g = graphs.BlanusaFirstSnarkGraph()
968
sage: g.order()
969
18
970
sage: g.size()
971
27
972
sage: g.diameter()
973
4
974
sage: g.girth()
975
5
976
sage: g.automorphism_group().cardinality()
977
8
978
"""
979
g = Graph({17:[4,7,1],0:[5],
980
3:[8],13:[9],12:[16],
981
10:[15],11:[6],14:[2]},
982
name="Blanusa First Snark Graph")
983
984
g.add_cycle(range(17))
985
_circle_embedding(g, range(17), shift=0.25)
986
g.get_pos()[17] = (0,0)
987
return g
988
989
def BlanusaSecondSnarkGraph():
990
r"""
991
Returns the second Blanusa Snark Graph.
992
993
The Blanusa graphs are two snarks on 18 vertices and 27 edges. For more
994
information on them, see the :wikipedia:`Blanusa_snarks`.
995
996
.. SEEALSO::
997
998
* :meth:`~sage.graphs.graph_generators.GraphGenerators.BlanusaFirstSnarkGraph`.
999
1000
EXAMPLES::
1001
1002
sage: g = graphs.BlanusaSecondSnarkGraph()
1003
sage: g.order()
1004
18
1005
sage: g.size()
1006
27
1007
sage: g.diameter()
1008
4
1009
sage: g.girth()
1010
5
1011
sage: g.automorphism_group().cardinality()
1012
4
1013
"""
1014
g = Graph({0:[(0,0),(1,4),1],1:[(0,3),(1,1)],(0,2):[(0,5)],
1015
(0,6):[(0,4)],(0,7):[(0,1)],(1,7):[(1,2)],
1016
(1,0):[(1,6)],(1,3):[(1,5)]},
1017
name="Blanusa Second Snark Graph")
1018
1019
g.add_cycle([(0,i) for i in range(5)])
1020
g.add_cycle([(1,i) for i in range(5)])
1021
g.add_cycle([(0,5),(0,6),(0,7),(1,5),(1,6),(1,7)])
1022
1023
_circle_embedding(g,
1024
[(0,(2*i)%5) for i in range(5)],
1025
center = (-1.5,0),
1026
shift = .5)
1027
_circle_embedding(g,
1028
[(1,(2*i)%5) for i in range(5)],
1029
center = (1.5,0))
1030
1031
_circle_embedding(g,
1032
[(0,i) for i in range(5,8)]+[0]*4,
1033
center = (-1.2,0),
1034
shift = 2.5,
1035
radius = 2.2)
1036
_circle_embedding(g,
1037
[(1,i) for i in range(5,8)]+[0]*4,
1038
center = (1.2,0),
1039
shift = -1,
1040
radius = 2.2)
1041
1042
_circle_embedding(g,[0,1], shift=.5)
1043
g.relabel()
1044
return g
1045
1046
def BrinkmannGraph():
1047
r"""
1048
Returns the Brinkmann graph.
1049
1050
For more information, see the
1051
`Wikipedia article on the Brinkmann graph <http://en.wikipedia.org/wiki/Brinkmann_graph>`_.
1052
1053
EXAMPLES:
1054
1055
The Brinkmann graph is a 4-regular graph having 21 vertices and 42
1056
edges. This means that each vertex has degree 4. ::
1057
1058
sage: G = graphs.BrinkmannGraph(); G
1059
Brinkmann graph: Graph on 21 vertices
1060
sage: G.show() # long time
1061
sage: G.order()
1062
21
1063
sage: G.size()
1064
42
1065
sage: G.is_regular(4)
1066
True
1067
1068
It is an Eulerian graph with radius 3, diameter 3, and girth 5. ::
1069
1070
sage: G.is_eulerian()
1071
True
1072
sage: G.radius()
1073
3
1074
sage: G.diameter()
1075
3
1076
sage: G.girth()
1077
5
1078
1079
The Brinkmann graph is also Hamiltonian with chromatic number 4::
1080
1081
sage: G.is_hamiltonian()
1082
True
1083
sage: G.chromatic_number()
1084
4
1085
1086
Its automorphism group is isomorphic to `D_7`::
1087
1088
sage: ag = G.automorphism_group()
1089
sage: ag.is_isomorphic(DihedralGroup(7))
1090
True
1091
"""
1092
edge_dict = {
1093
0: [2,5,7,13],
1094
1: [3,6,7,8],
1095
2: [4,8,9],
1096
3: [5,9,10],
1097
4: [6,10,11],
1098
5: [11,12],
1099
6: [12,13],
1100
7: [15,20],
1101
8: [14,16],
1102
9: [15,17],
1103
10: [16,18],
1104
11: [17,19],
1105
12: [18,20],
1106
13: [14,19],
1107
14: [17,18],
1108
15: [18,19],
1109
16: [19,20],
1110
17: [20]}
1111
pos_dict = {
1112
0: [0, 4],
1113
1: [3.12732592987212, 2.49395920743493],
1114
2: [3.89971164872729, -0.890083735825258],
1115
3: [1.73553495647023, -3.60387547160968],
1116
4: [-1.73553495647023, -3.60387547160968],
1117
5: [-3.89971164872729, -0.890083735825258],
1118
6: [-3.12732592987212, 2.49395920743493],
1119
7: [0.867767478235116, 1.80193773580484],
1120
8: [1.94985582436365, 0.445041867912629],
1121
9: [1.56366296493606, -1.24697960371747],
1122
10: [0, -2],
1123
11: [-1.56366296493606, -1.24697960371747],
1124
12: [-1.94985582436365, 0.445041867912629],
1125
13: [-0.867767478235116, 1.80193773580484],
1126
14: [0.433883739117558, 0.900968867902419],
1127
15: [0.974927912181824, 0.222520933956314],
1128
16: [0.781831482468030, -0.623489801858733],
1129
17: [0, -1],
1130
18: [-0.781831482468030, -0.623489801858733],
1131
19: [-0.974927912181824, 0.222520933956315],
1132
20: [-0.433883739117558, 0.900968867902419]}
1133
return Graph(edge_dict, pos=pos_dict, name="Brinkmann graph")
1134
1135
def BrouwerHaemersGraph():
1136
r"""
1137
Returns the Brouwer-Haemers Graph.
1138
1139
The Brouwer-Haemers is the only strongly regular graph of parameters
1140
`(81,20,1,6)`. It is build in Sage as the Affine Orthogonal graph
1141
`VO^-(6,3)`. For more information on this graph, see its `corresponding page
1142
on Andries Brouwer's website
1143
<http://www.win.tue.nl/~aeb/graphs/Brouwer-Haemers.html>`_.
1144
1145
EXAMPLE::
1146
1147
sage: g = graphs.BrouwerHaemersGraph()
1148
sage: g
1149
Brouwer-Haemers: Graph on 81 vertices
1150
1151
It is indeed strongly regular with parameters `(81,20,1,6)`::
1152
1153
sage: g.is_strongly_regular(parameters = True) # long time
1154
(81, 20, 1, 6)
1155
1156
Its has as eigenvalues `20,2` and `-7`::
1157
1158
sage: set(g.spectrum()) == {20,2,-7}
1159
True
1160
"""
1161
from sage.rings.finite_rings.constructor import FiniteField
1162
from sage.modules.free_module import VectorSpace
1163
from sage.matrix.constructor import Matrix
1164
from sage.matrix.constructor import identity_matrix
1165
1166
d = 4
1167
q = 3
1168
F = FiniteField(q,"x")
1169
V = VectorSpace(F,d)
1170
M = Matrix(F,identity_matrix(d))
1171
M[1,1]=-1
1172
G = Graph([map(tuple,V), lambda x,y:(V(x)-V(y))*(M*(V(x)-V(y))) == 0], loops = False)
1173
G.relabel()
1174
ordering = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
1175
18, 19, 20, 21, 22, 23, 24, 25, 26, 48, 49, 50, 51, 52, 53,
1176
45, 46, 47, 30, 31, 32, 33, 34, 35, 27, 28, 29, 39, 40, 41,
1177
42, 43, 44, 36, 37, 38, 69, 70, 71, 63, 64, 65, 66, 67, 68,
1178
78, 79, 80, 72, 73, 74, 75, 76, 77, 60, 61, 62, 54, 55, 56,
1179
57, 58, 59]
1180
_circle_embedding(G, ordering)
1181
G.name("Brouwer-Haemers")
1182
return G
1183
1184
def BuckyBall():
1185
r"""
1186
Create the Bucky Ball graph.
1187
1188
This graph is a 3-regular 60-vertex planar graph. Its vertices
1189
and edges correspond precisely to the carbon atoms and bonds
1190
in buckminsterfullerene. When embedded on a sphere, its 12
1191
pentagon and 20 hexagon faces are arranged exactly as the
1192
sections of a soccer ball.
1193
1194
EXAMPLES:
1195
1196
The Bucky Ball is planar. ::
1197
1198
sage: g = graphs.BuckyBall()
1199
sage: g.is_planar()
1200
True
1201
1202
The Bucky Ball can also be created by extracting the 1-skeleton
1203
of the Bucky Ball polyhedron, but this is much slower. ::
1204
1205
sage: g = polytopes.buckyball().vertex_graph()
1206
sage: g.remove_loops()
1207
sage: h = graphs.BuckyBall()
1208
sage: g.is_isomorphic(h)
1209
True
1210
1211
The graph is returned along with an attractive embedding. ::
1212
1213
sage: g = graphs.BuckyBall()
1214
sage: g.plot(vertex_labels=False, vertex_size=10).show() # long time
1215
"""
1216
edges = [(0, 2), (0, 48), (0, 59), (1, 3), (1, 9), (1, 58),
1217
(2, 3), (2, 36), (3, 17), (4, 6), (4, 8), (4, 12),
1218
(5, 7), (5, 9), (5, 16), (6, 7), (6, 20), (7, 21),
1219
(8, 9), (8, 56), (10, 11), (10, 12), (10, 20), (11, 27),
1220
(11, 47), (12, 13), (13, 46), (13, 54), (14, 15), (14, 16),
1221
(14, 21), (15, 25), (15, 41), (16, 17), (17, 40), (18, 19),
1222
(18, 20), (18, 26), (19, 21), (19, 24), (22, 23), (22, 31),
1223
(22, 34), (23, 25), (23, 38), (24, 25), (24, 30), (26, 27),
1224
(26, 30), (27, 29), (28, 29), (28, 31), (28, 35), (29, 44),
1225
(30, 31), (32, 34), (32, 39), (32, 50), (33, 35), (33, 45),
1226
(33, 51), (34, 35), (36, 37), (36, 40), (37, 39), (37, 52),
1227
(38, 39), (38, 41), (40, 41), (42, 43), (42, 46), (42, 55),
1228
(43, 45), (43, 53), (44, 45), (44, 47), (46, 47), (48, 49),
1229
(48, 52), (49, 53), (49, 57), (50, 51), (50, 52), (51, 53),
1230
(54, 55), (54, 56), (55, 57), (56, 58), (57, 59), (58, 59)
1231
]
1232
g = Graph()
1233
g.add_edges(edges)
1234
g.name("Bucky Ball")
1235
1236
pos = {
1237
0 : (1.00000000000000, 0.000000000000000),
1238
1 : (-1.00000000000000, 0.000000000000000),
1239
2 : (0.500000000000000, 0.866025403784439),
1240
3 : (-0.500000000000000, 0.866025403784439),
1241
4 : (-0.252886764483159, -0.146004241548845),
1242
5 : (-0.368953972399043, 0.0928336233191176),
1243
6 : (-0.217853192651371, -0.0480798425451855),
1244
7 : (-0.255589950938772, 0.0495517623332213),
1245
8 : (-0.390242139418333, -0.225306404242310),
1246
9 : (-0.586398703939125, -0.0441575936410641),
1247
10: (-0.113926229169631, -0.101751920396670),
1248
11: (-0.0461308635969359, -0.0928422349110366),
1249
12: (-0.150564961379772, -0.164626477859040),
1250
13: (-0.0848818904865275, -0.246123271631605),
1251
14: (-0.170708060452244, 0.196571509298384),
1252
15: (-0.0672882312715990, 0.212706320404226),
1253
16: (-0.264873262319233, 0.273106701265196),
1254
17: (-0.254957754106411, 0.529914971178085),
1255
18: (-0.103469165775548, 0.00647061768205703),
1256
19: (-0.113590051906687, 0.0655812470455896),
1257
20: (-0.145082862532183, -0.0477870484199328),
1258
21: (-0.179962687765901, 0.103901506225732),
1259
22: (0.0573383021786124, 0.0863716172289798),
1260
23: (0.0311566333625530, 0.149538968816603),
1261
24: (-0.0573383021786121, 0.0863716172289799),
1262
25: (-0.0311566333625527, 0.149538968816603),
1263
26: (-0.0517345828877740, 0.00161765442051429),
1264
27: (-0.0244663616211774, -0.0456122902452611),
1265
28: (0.0517345828877743, 0.00161765442051431),
1266
29: (0.0244663616211777, -0.0456122902452611),
1267
30: (-0.0272682212665964, 0.0439946358247470),
1268
31: (0.0272682212665968, 0.0439946358247470),
1269
32: (0.179962687765901, 0.103901506225732),
1270
33: (0.145082862532184, -0.0477870484199329),
1271
34: (0.113590051906687, 0.0655812470455895),
1272
35: (0.103469165775548, 0.00647061768205698),
1273
36: (0.254957754106411, 0.529914971178085),
1274
37: (0.264873262319233, 0.273106701265196),
1275
38: (0.0672882312715993, 0.212706320404226),
1276
39: (0.170708060452245, 0.196571509298384),
1277
40: (1.59594559789866e-16, 0.450612808484620),
1278
41: (2.01227923213310e-16, 0.292008483097691),
1279
42: (0.0848818904865278, -0.246123271631605),
1280
43: (0.150564961379773, -0.164626477859040),
1281
44: (0.0461308635969362, -0.0928422349110366),
1282
45: (0.113926229169631, -0.101751920396670),
1283
46: (1.66533453693773e-16, -0.207803012451463),
1284
47: (1.80411241501588e-16, -0.131162494091179),
1285
48: (0.586398703939126, -0.0441575936410641),
1286
49: (0.390242139418333, -0.225306404242310),
1287
50: (0.255589950938772, 0.0495517623332212),
1288
51: (0.217853192651372, -0.0480798425451855),
1289
52: (0.368953972399044, 0.0928336233191175),
1290
53: (0.252886764483159, -0.146004241548845),
1291
54: (-0.104080710079810, -0.365940324584313),
1292
55: (0.104080710079811, -0.365940324584313),
1293
56: (-0.331440949832714, -0.485757377537020),
1294
57: (0.331440949832715, -0.485757377537021),
1295
58: (-0.500000000000000, -0.866025403784438),
1296
59: (0.500000000000000, -0.866025403784439)
1297
}
1298
1299
g.set_pos(pos)
1300
1301
return g
1302
1303
def DoubleStarSnark():
1304
r"""
1305
Returns the double star snark.
1306
1307
The double star snark is a 3-regular graph on 30 vertices. See
1308
the :wikipedia:`Wikipedia page on the double star snark
1309
<Double-star_snark>`.
1310
1311
EXAMPLES::
1312
1313
sage: g = graphs.DoubleStarSnark()
1314
sage: g.order()
1315
30
1316
sage: g.size()
1317
45
1318
sage: g.chromatic_number()
1319
3
1320
sage: g.is_hamiltonian()
1321
False
1322
sage: g.automorphism_group().cardinality()
1323
80
1324
sage: g.show()
1325
"""
1326
1327
d = { 0: [1, 14, 15]
1328
, 1: [0, 2, 11]
1329
, 2: [1, 3, 7]
1330
, 3: [2, 4, 18]
1331
, 4: [3, 5, 14]
1332
, 5: [10, 4, 6]
1333
, 6: [5, 21, 7]
1334
, 7: [8, 2, 6]
1335
, 8: [9, 13, 7]
1336
, 9: [24, 8, 10]
1337
, 10: [9, 11, 5]
1338
, 11: [1, 10, 12]
1339
, 12: [11, 27, 13]
1340
, 13: [8, 12, 14]
1341
, 14: [0, 4, 13]
1342
, 15: [0, 16, 29]
1343
, 16: [15, 20, 23]
1344
, 17: [25, 18, 28]
1345
, 18: [3, 17, 19]
1346
, 19: [18, 26, 23]
1347
, 20: [16, 28, 21]
1348
, 21: [20, 6, 22]
1349
, 22: [26, 21, 29]
1350
, 23: [16, 24, 19]
1351
, 24: [25, 9, 23]
1352
, 25: [24, 17, 29]
1353
, 26: [27, 19, 22]
1354
, 27: [12, 26, 28]
1355
, 28: [17, 27, 20]
1356
, 29: [25, 22, 15]
1357
}
1358
1359
g = Graph(d, pos={}, name="Double star snark")
1360
_circle_embedding(g, range(15), radius=2)
1361
_circle_embedding(g, range(15, 30), radius=1.4)
1362
1363
return g
1364
1365
def MeredithGraph():
1366
r"""
1367
Returns the Meredith Graph
1368
1369
The Meredith Graph is a 4-regular 4-connected non-hamiltonian graph. For
1370
more information on the Meredith Graph, see the :wikipedia:`Meredith_graph`.
1371
1372
EXAMPLES::
1373
1374
sage: g = graphs.MeredithGraph()
1375
sage: g.is_regular(4)
1376
True
1377
sage: g.order()
1378
70
1379
sage: g.size()
1380
140
1381
sage: g.radius()
1382
7
1383
sage: g.diameter()
1384
8
1385
sage: g.girth()
1386
4
1387
sage: g.chromatic_number()
1388
3
1389
sage: g.is_hamiltonian() # long time
1390
False
1391
"""
1392
g = Graph(name="Meredith Graph")
1393
g.add_vertex(0)
1394
1395
# Edges between copies of K_{4,3}
1396
for i in range(5):
1397
g.add_edge(('outer',i,3),('outer',(i+1)%5,0))
1398
g.add_edge(('inner',i,3),('inner',(i+2)%5,0))
1399
g.add_edge(('outer',i,1),('inner',i ,1))
1400
g.add_edge(('outer',i,2),('inner',i ,2))
1401
1402
# Edges inside of the K_{4,3}s.
1403
for i in range(5):
1404
for j in range(4):
1405
for k in range(3):
1406
g.add_edge(('inner',i,j),('inner',i,k+4))
1407
g.add_edge(('outer',i,j),('outer',i,k+4))
1408
1409
_circle_embedding(g, sum([[('outer',i,j) for j in range(4)]+10*[0] for i in range(5)],[]), radius = 1, shift = 2)
1410
_circle_embedding(g, sum([[('outer',i,j) for j in range(4,7)]+10*[0] for i in range(5)],[]), radius = 1.2, shift = 2.2)
1411
_circle_embedding(g, sum([[('inner',i,j) for j in range(4)]+7*[0] for i in range(5)],[]), radius = .6, shift = 1.24)
1412
_circle_embedding(g, sum([[('inner',i,j) for j in range(4,7)]+5*[0] for i in range(5)],[]), radius = .4, shift = 1.05)
1413
1414
g.delete_vertex(0)
1415
g.relabel()
1416
return g
1417
1418
def KittellGraph():
1419
r"""
1420
Returns the Kittell Graph.
1421
1422
For more information, see the `Wolfram page about the Kittel Graph
1423
<http://mathworld.wolfram.com/KittellGraph.html>`_.
1424
1425
EXAMPLES::
1426
1427
sage: g = graphs.KittellGraph()
1428
sage: g.order()
1429
23
1430
sage: g.size()
1431
63
1432
sage: g.radius()
1433
3
1434
sage: g.diameter()
1435
4
1436
sage: g.girth()
1437
3
1438
sage: g.chromatic_number()
1439
4
1440
"""
1441
g = Graph({0: [1, 2, 4, 5, 6, 7], 1: [0, 2, 7, 10, 11, 13],
1442
2: [0, 1, 11, 4, 14], 3: [16, 12, 4, 5, 14], 4: [0, 2, 3, 5, 14],
1443
5: [0, 16, 3, 4, 6], 6: [0, 5, 7, 15, 16, 17, 18],
1444
7: [0, 1, 6, 8, 13, 18], 8: [9, 18, 19, 13, 7],
1445
9: [8, 10, 19, 20, 13], 10: [1, 9, 11, 13, 20, 21],
1446
11: [1, 2, 10, 12, 14, 15, 21], 12: [11, 16, 3, 14, 15],
1447
13: [8, 1, 10, 9, 7], 14: [11, 12, 2, 3, 4],
1448
15: [6, 11, 12, 16, 17, 21, 22],
1449
16: [3, 12, 5, 6, 15], 17: [18, 19, 22, 6, 15],
1450
18: [8, 17, 19, 6, 7], 19: [8, 9, 17, 18, 20, 22],
1451
20: [9, 10, 19, 21, 22], 21: [10, 11, 20, 22, 15],
1452
22: [17, 19, 20, 21, 15]},
1453
name = "Kittell Graph")
1454
1455
_circle_embedding(g, range(3), shift=.75)
1456
_circle_embedding(g, range(3,13), radius = .4)
1457
_circle_embedding(g, range(15,22), radius = .2, shift=-.15)
1458
pos = g.get_pos()
1459
pos[13] = (-.65,-.35)
1460
pos[14] = (.65,-.35)
1461
pos[22] = (0,0)
1462
1463
return g
1464
1465
def CameronGraph():
1466
r"""
1467
Returns the Cameron graph.
1468
1469
The Cameron graph is strongly regular with parameters `v = 231, k = 30,
1470
\lambda = 9, \mu = 3`.
1471
1472
For more information on the Cameron graph, see
1473
`<http://www.win.tue.nl/~aeb/graphs/Cameron.html>`_.
1474
1475
EXAMPLES::
1476
1477
sage: g = graphs.CameronGraph()
1478
sage: g.order()
1479
231
1480
sage: g.size()
1481
3465
1482
sage: g.is_strongly_regular(parameters = True) # long time
1483
(231, 30, 9, 3)
1484
1485
"""
1486
from sage.groups.perm_gps.permgroup_named import MathieuGroup
1487
from itertools import combinations
1488
g = Graph(name="Cameron Graph")
1489
sets = MathieuGroup(22).orbit((1,2,3,7,10,20), action = "OnSets")
1490
for s in sets:
1491
for a,b,c,d in combinations(set(s),4):
1492
g.add_edges([((a,b),(c,d)),((a,c),(b,d)), ((a,d),(b,c))])
1493
1494
g.relabel()
1495
ordering = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 18, 19, 20,
1496
21, 24, 25, 26, 27, 29, 31, 34, 35, 38, 39, 96, 97, 101, 105,
1497
51, 117, 198, 32, 196, 201, 131, 167, 199, 197, 86, 102, 195,
1498
200, 186, 144, 202, 177, 44, 53, 58, 45, 48, 54, 43, 57, 50,
1499
46, 59, 133, 169, 104, 188, 118, 208, 157, 52, 207, 209, 132,
1500
204, 13, 187, 33, 203, 70, 145, 103, 168, 178, 87, 124, 123,
1501
125, 111, 120, 116, 119, 112, 95, 114, 115, 137, 218, 213, 108,
1502
76, 77, 74, 62, 64, 67, 63, 68, 69, 61, 41, 75, 73, 66, 71, 72,
1503
60, 22, 230, 151, 184, 138, 193, 109, 228, 174, 214, 219, 93,
1504
126, 143, 150, 146, 224, 181, 16, 223, 171, 90, 135, 106, 205,
1505
211, 121, 148, 160, 216, 222, 190, 36, 55, 185, 175, 94, 139,
1506
110, 215, 152, 220, 229, 194, 40, 128, 99, 141, 173, 154, 82,
1507
156, 164, 159, 28, 127, 158, 65, 162, 163, 153, 161, 155, 140,
1508
98, 47, 113, 84, 180, 30, 129, 179, 183, 165, 176, 142, 100,
1509
49, 134, 210, 170, 147, 91, 37, 206, 182, 191, 56, 136, 225,
1510
221, 149, 227, 217, 17, 107, 172, 212, 122, 226, 23, 85, 42,
1511
80, 92, 81, 89, 78, 83, 88, 79, 130, 192, 189, 166]
1512
1513
_circle_embedding(g, ordering)
1514
return g
1515
1516
def ChvatalGraph():
1517
r"""
1518
Returns the Chvatal graph.
1519
1520
Chvatal graph is one of the few known graphs to satisfy Grunbaum's
1521
conjecture that for every m, n, there is an m-regular,
1522
m-chromatic graph of girth at least n. For more information, see this
1523
`Wikipedia article on the Chvatal graph <http://en.wikipedia.org/wiki/Chv%C3%A1tal_graph>`_.
1524
1525
EXAMPLES:
1526
1527
The Chvatal graph has 12 vertices and 24 edges. It is a 4-regular,
1528
4-chromatic graph with radius 2, diameter 2, and girth 4. ::
1529
1530
sage: G = graphs.ChvatalGraph(); G
1531
Chvatal graph: Graph on 12 vertices
1532
sage: G.order(); G.size()
1533
12
1534
24
1535
sage: G.degree()
1536
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
1537
sage: G.chromatic_number()
1538
4
1539
sage: G.radius(); G.diameter(); G.girth()
1540
2
1541
2
1542
4
1543
"""
1544
import networkx
1545
pos_dict = {}
1546
for i in range(5, 10):
1547
x = float(cos((pi / 2) + ((2 * pi) / 5) * i))
1548
y = float(sin((pi / 2) + ((2 * pi) / 5) * i))
1549
pos_dict[i] = (x, y)
1550
for i in range(5):
1551
x = float(2 * (cos((pi / 2) + ((2 * pi) / 5) * (i - 5))))
1552
y = float(2 * (sin((pi / 2) + ((2 * pi) / 5) * (i - 5))))
1553
pos_dict[i] = (x, y)
1554
pos_dict[10] = (0.5, 0)
1555
pos_dict[11] = (-0.5, 0)
1556
1557
return Graph(networkx.chvatal_graph(), pos=pos_dict, name="Chvatal graph")
1558
1559
def ClebschGraph():
1560
r"""
1561
Return the Clebsch graph.
1562
1563
EXAMPLES::
1564
1565
sage: g = graphs.ClebschGraph()
1566
sage: g.automorphism_group().cardinality()
1567
1920
1568
sage: g.girth()
1569
4
1570
sage: g.chromatic_number()
1571
4
1572
sage: g.diameter()
1573
2
1574
sage: g.show(figsize=[10, 10]) # long time
1575
"""
1576
g = Graph(pos={})
1577
x = 0
1578
for i in range(8):
1579
g.add_edge(x % 16, (x + 1) % 16)
1580
g.add_edge(x % 16, (x + 6) % 16)
1581
g.add_edge(x % 16, (x + 8) % 16)
1582
x += 1
1583
g.add_edge(x % 16, (x + 3) % 16)
1584
g.add_edge(x % 16, (x + 2) % 16)
1585
g.add_edge(x % 16, (x + 8) % 16)
1586
x += 1
1587
1588
_circle_embedding(g, range(16), shift=.5)
1589
g.name("Clebsch graph")
1590
1591
return g
1592
1593
def CoxeterGraph():
1594
r"""
1595
Return the Coxeter graph.
1596
1597
See the :wikipedia:`Wikipedia page on the Coxeter graph
1598
<Coxeter_graph>`.
1599
1600
EXAMPLES::
1601
1602
sage: g = graphs.CoxeterGraph()
1603
sage: g.automorphism_group().cardinality()
1604
336
1605
sage: g.girth()
1606
7
1607
sage: g.chromatic_number()
1608
3
1609
sage: g.diameter()
1610
4
1611
sage: g.show(figsize=[10, 10]) # long time
1612
"""
1613
g = Graph({
1614
27: [6, 22, 14],
1615
24: [0, 7, 18],
1616
25: [8, 15, 2],
1617
26: [10, 16, 23],
1618
}, pos={})
1619
1620
g.add_cycle(range(24))
1621
g.add_edges([(5, 11), (9, 20), (12, 1), (13, 19), (17, 4), (3, 21)])
1622
1623
_circle_embedding(g, range(24))
1624
_circle_embedding(g, [24, 25, 26], radius=.5)
1625
g.get_pos()[27] = (0, 0)
1626
1627
g.name("Coxeter Graph")
1628
1629
return g
1630
1631
def DesarguesGraph():
1632
"""
1633
Returns the Desargues graph.
1634
1635
PLOTTING: The layout chosen is the same as on the cover of [1].
1636
1637
EXAMPLE::
1638
1639
sage: D = graphs.DesarguesGraph()
1640
sage: L = graphs.LCFGraph(20,[5,-5,9,-9],5)
1641
sage: D.is_isomorphic(L)
1642
True
1643
sage: D.show() # long time
1644
1645
REFERENCE:
1646
1647
- [1] Harary, F. Graph Theory. Reading, MA: Addison-Wesley,
1648
1994.
1649
"""
1650
from sage.graphs.generators.families import GeneralizedPetersenGraph
1651
G = GeneralizedPetersenGraph(10,3)
1652
G.name("Desargues Graph")
1653
return G
1654
1655
def DurerGraph():
1656
r"""
1657
Returns the Dürer graph.
1658
1659
For more information, see this
1660
`Wikipedia article on the Dürer graph <http://en.wikipedia.org/wiki/D%C3%BCrer_graph>`_.
1661
1662
EXAMPLES:
1663
1664
The Dürer graph is named after Albrecht Dürer. It is a planar graph
1665
with 12 vertices and 18 edges. ::
1666
1667
sage: G = graphs.DurerGraph(); G
1668
Durer graph: Graph on 12 vertices
1669
sage: G.is_planar()
1670
True
1671
sage: G.order()
1672
12
1673
sage: G.size()
1674
18
1675
1676
The Dürer graph has chromatic number 3, diameter 4, and girth 3. ::
1677
1678
sage: G.chromatic_number()
1679
3
1680
sage: G.diameter()
1681
4
1682
sage: G.girth()
1683
3
1684
1685
Its automorphism group is isomorphic to `D_6`. ::
1686
1687
sage: ag = G.automorphism_group()
1688
sage: ag.is_isomorphic(DihedralGroup(6))
1689
True
1690
"""
1691
edge_dict = {
1692
0: [1,5,6],
1693
1: [2,7],
1694
2: [3,8],
1695
3: [4,9],
1696
4: [5,10],
1697
5: [11],
1698
6: [8,10],
1699
7: [9,11],
1700
8: [10],
1701
9: [11]}
1702
pos_dict = {
1703
0: [2, 0],
1704
1: [1, 1.73205080756888],
1705
2: [-1, 1.73205080756888],
1706
3: [-2, 0],
1707
4: [-1, -1.73205080756888],
1708
5: [1, -1.73205080756888],
1709
6: [1, 0],
1710
7: [0.5, 0.866025403784439],
1711
8: [-0.5, 0.866025403784439],
1712
9: [-1, 0],
1713
10: [-0.5, -0.866025403784439],
1714
11: [0.5, -0.866025403784439]}
1715
return Graph(edge_dict, pos=pos_dict, name="Durer graph")
1716
1717
def DyckGraph():
1718
"""
1719
Returns the Dyck graph.
1720
1721
For more information, see the `MathWorld article on the Dyck graph
1722
<http://mathworld.wolfram.com/DyckGraph.html>`_ or the `Wikipedia
1723
article on the Dyck graph <http://en.wikipedia.org/wiki/Dyck_graph>`_.
1724
1725
EXAMPLES:
1726
1727
The Dyck graph was defined by Walther von Dyck in 1881. It has `32`
1728
vertices and `48` edges, and is a cubic graph (regular of degree `3`)::
1729
1730
sage: G = graphs.DyckGraph(); G
1731
Dyck graph: Graph on 32 vertices
1732
sage: G.order()
1733
32
1734
sage: G.size()
1735
48
1736
sage: G.is_regular()
1737
True
1738
sage: G.is_regular(3)
1739
True
1740
1741
It is non-planar and Hamiltonian, as well as bipartite (making it a
1742
bicubic graph)::
1743
1744
sage: G.is_planar()
1745
False
1746
sage: G.is_hamiltonian()
1747
True
1748
sage: G.is_bipartite()
1749
True
1750
1751
It has radius `5`, diameter `5`, and girth `6`::
1752
1753
sage: G.radius()
1754
5
1755
sage: G.diameter()
1756
5
1757
sage: G.girth()
1758
6
1759
1760
Its chromatic number is `2` and its automorphism group is of order
1761
`192`::
1762
1763
sage: G.chromatic_number()
1764
2
1765
sage: G.automorphism_group().cardinality()
1766
192
1767
1768
It is a non-integral graph as it has irrational eigenvalues::
1769
1770
sage: G.characteristic_polynomial().factor()
1771
(x - 3) * (x + 3) * (x - 1)^9 * (x + 1)^9 * (x^2 - 5)^6
1772
1773
It is a toroidal graph, and its embedding on a torus is dual to an
1774
embedding of the Shrikhande graph (:meth:`ShrikhandeGraph
1775
<GraphGenerators.ShrikhandeGraph>`).
1776
"""
1777
pos_dict = {}
1778
for i in range(8):
1779
pos_dict[i] = [float(cos((2*i) * pi/8)),
1780
float(sin((2*i) * pi/8))]
1781
pos_dict[8 + i] = [0.75 * pos_dict[i][0],
1782
0.75 * pos_dict[i][1]]
1783
pos_dict[16 + i] = [0.50 * pos_dict[i][0],
1784
0.50 * pos_dict[i][1]]
1785
pos_dict[24 + i] = [0.25 * pos_dict[i][0],
1786
0.25 * pos_dict[i][1]]
1787
1788
edge_dict = {
1789
0O00: [0O07, 0O01, 0O10], 0O10: [0O00, 0O27, 0O21],
1790
0O01: [0O00, 0O02, 0O11], 0O11: [0O01, 0O20, 0O22],
1791
0O02: [0O01, 0O03, 0O12], 0O12: [0O02, 0O21, 0O23],
1792
0O03: [0O02, 0O04, 0O13], 0O13: [0O03, 0O22, 0O24],
1793
0O04: [0O03, 0O05, 0O14], 0O14: [0O04, 0O23, 0O25],
1794
0O05: [0O04, 0O06, 0O15], 0O15: [0O05, 0O24, 0O26],
1795
0O06: [0O05, 0O07, 0O16], 0O16: [0O06, 0O25, 0O27],
1796
0O07: [0O06, 0O00, 0O17], 0O17: [0O07, 0O26, 0O20],
1797
1798
0O20: [0O17, 0O11, 0O30], 0O30: [0O20, 0O35, 0O33],
1799
0O21: [0O10, 0O12, 0O31], 0O31: [0O21, 0O36, 0O34],
1800
0O22: [0O11, 0O13, 0O32], 0O32: [0O22, 0O37, 0O35],
1801
0O23: [0O12, 0O14, 0O33], 0O33: [0O23, 0O30, 0O36],
1802
0O24: [0O13, 0O15, 0O34], 0O34: [0O24, 0O31, 0O37],
1803
0O25: [0O14, 0O16, 0O35], 0O35: [0O25, 0O32, 0O30],
1804
0O26: [0O15, 0O17, 0O36], 0O36: [0O26, 0O33, 0O31],
1805
0O27: [0O16, 0O10, 0O37], 0O37: [0O27, 0O34, 0O32],
1806
}
1807
1808
return Graph(edge_dict, pos=pos_dict, name="Dyck graph")
1809
1810
def HortonGraph():
1811
r"""
1812
Returns the Horton Graph.
1813
1814
The Horton graph is a cubic 3-connected non-hamiltonian graph. For more
1815
information, see the :wikipedia:`Horton_graph`.
1816
1817
EXAMPLES::
1818
1819
sage: g = graphs.HortonGraph()
1820
sage: g.order()
1821
96
1822
sage: g.size()
1823
144
1824
sage: g.radius()
1825
10
1826
sage: g.diameter()
1827
10
1828
sage: g.girth()
1829
6
1830
sage: g.automorphism_group().cardinality()
1831
96
1832
sage: g.chromatic_number()
1833
2
1834
sage: g.is_hamiltonian() # not tested -- veeeery long
1835
False
1836
"""
1837
g = Graph(name = "Horton Graph")
1838
1839
# Each group of the 6 groups of vertices is based on the same 3-regular
1840
# graph.
1841
from sage.graphs.generators.families import LCFGraph
1842
lcf = LCFGraph(16,[5,-5],8)
1843
lcf.delete_edge(15,0)
1844
lcf.delete_edge(7,8)
1845
1846
for i in range(6):
1847
for u,v in lcf.edges(labels=False):
1848
g.add_edge((i,u),(i,v))
1849
1850
# Modifying the groups and linking them together
1851
for i in range(3):
1852
g.add_edge((2*i,0),(2*i+1,7))
1853
g.add_edge((2*i+1,8),(2*i,7))
1854
g.add_edge((2*i,15),(2*i+1,0))
1855
g.add_edge((2*i,8),1)
1856
g.add_edge((2*i+1,14),2)
1857
g.add_edge((2*i+1,10),0)
1858
1859
# Embedding
1860
for i in range(6):
1861
_circle_embedding(g, [(i,j) for j in range(16)], center=(cos(2*i*pi/6),sin(2*i*pi/6)), radius=.3)
1862
1863
for i in range(3):
1864
g.delete_vertex((2*i+1,15))
1865
1866
_circle_embedding(g, range(3), radius=.2, shift=-0.75)
1867
1868
g.relabel()
1869
1870
return g
1871
1872
def EllinghamHorton54Graph():
1873
r"""
1874
Returns the Ellingham-Horton 54-graph.
1875
1876
For more information, see the :wikipedia:`Wikipedia page on the
1877
Ellingham-Horton graphs <Ellingham-Horton_graph>`
1878
1879
EXAMPLE:
1880
1881
This graph is 3-regular::
1882
1883
sage: g = graphs.EllinghamHorton54Graph()
1884
sage: g.is_regular(k=3)
1885
True
1886
1887
It is 3-connected and bipartite::
1888
1889
sage: g.vertex_connectivity() # not tested - too long
1890
3
1891
sage: g.is_bipartite()
1892
True
1893
1894
It is not Hamiltonian::
1895
1896
sage: g.is_hamiltonian() # not tested - too long
1897
False
1898
1899
... and it has a nice drawing ::
1900
1901
sage: g.show(figsize=[10, 10]) # not tested - too long
1902
1903
TESTS::
1904
1905
sage: g.show() # long time
1906
"""
1907
from sage.graphs.generators.basic import CycleGraph
1908
up = CycleGraph(16)
1909
low = 2*CycleGraph(6)
1910
1911
for v in range(6):
1912
low.add_edge(v, v + 12)
1913
low.add_edge(v + 6, v + 12)
1914
low.add_edge(12, 15)
1915
low.delete_edge(1, 2)
1916
low.delete_edge(8, 7)
1917
low.add_edge(1, 8)
1918
low.add_edge(7, 2)
1919
1920
1921
# The set of vertices on top is 0..15
1922
# Bottom left is 16..33
1923
# Bottom right is 34..52
1924
# The two other vertices are 53, 54
1925
g = up + 2*low
1926
g.name("Ellingham-Horton 54-graph")
1927
g.set_pos({})
1928
1929
g.add_edges([(15, 4), (3, 8), (7, 12), (11, 0), (2, 13), (5, 10)])
1930
g.add_edges([(30, 6), (29, 9), (48, 14), (47, 1)])
1931
g.add_edge(32, 52)
1932
g.add_edge(50, 52)
1933
g.add_edge(33, 53)
1934
g.add_edge(51, 53)
1935
g.add_edge(52, 53)
1936
1937
# Top
1938
_circle_embedding(g, range(16), center=(0, .5), shift=.5, radius=.5)
1939
1940
# Bottom-left
1941
_circle_embedding(g, range(16, 22), center=(-1.5, -1))
1942
_circle_embedding(g, range(22, 28), center=(-1.5, -1), radius=.5)
1943
_circle_embedding(g, range(28, 34), center=(-1.5, -1), radius=.7)
1944
1945
# Bottom right
1946
_circle_embedding(g, range(34, 40), center=(1.5, -1))
1947
_circle_embedding(g, range(40, 46), center=(1.5, -1), radius=.5)
1948
_circle_embedding(g, range(46, 52), center=(1.5, -1), radius=.7)
1949
1950
d = g.get_pos()
1951
d[52] = (-.3, -2.5)
1952
d[53] = (.3, -2.5)
1953
d[31] = (-2.2, -.9)
1954
d[28] = (-.8, -.9)
1955
d[46] = (2.2, -.9)
1956
d[49] = (.8, -.9)
1957
1958
1959
return g
1960
1961
def EllinghamHorton78Graph():
1962
r"""
1963
Returns the Ellingham-Horton 78-graph.
1964
1965
For more information, see the :wikipedia:`Wikipedia page on the
1966
Ellingham-Horton graphs
1967
<http://en.wikipedia.org/wiki/Ellingham%E2%80%93Horton_graph>`
1968
1969
EXAMPLE:
1970
1971
This graph is 3-regular::
1972
1973
sage: g = graphs.EllinghamHorton78Graph()
1974
sage: g.is_regular(k=3)
1975
True
1976
1977
It is 3-connected and bipartite::
1978
1979
sage: g.vertex_connectivity() # not tested - too long
1980
3
1981
sage: g.is_bipartite()
1982
True
1983
1984
It is not Hamiltonian::
1985
1986
sage: g.is_hamiltonian() # not tested - too long
1987
False
1988
1989
... and it has a nice drawing ::
1990
1991
sage: g.show(figsize=[10,10]) # not tested - too long
1992
1993
TESTS::
1994
1995
sage: g.show(figsize=[10, 10]) # not tested - too long
1996
"""
1997
g = Graph({
1998
0: [1, 5, 60], 1: [2, 12], 2: [3, 7], 3: [4, 14], 4: [5, 9],
1999
5: [6], 6: [7, 11], 7: [15], 8: [9, 13, 22], 9: [10],
2000
10: [11, 72], 11: [12], 12: [13], 13: [14], 14: [72],
2001
15: [16, 20], 16: [17, 27], 17: [18, 22], 18: [19, 29],
2002
19: [20, 24], 20: [21], 21: [22, 26], 23: [24, 28, 72],
2003
24: [25], 25: [26, 71], 26: [27], 27: [28], 28: [29],
2004
29: [69], 30: [31, 35, 52], 31: [32, 42], 32: [33, 37],
2005
33: [34, 43], 34: [35, 39], 35: [36], 36: [41, 63],
2006
37: [65, 66], 38: [39, 59, 74], 39: [40], 40: [41, 44],
2007
41: [42], 42: [74], 43: [44, 74], 44: [45], 45: [46, 50],
2008
46: [47, 57], 47: [48, 52], 48: [49, 75], 49: [50, 54],
2009
50: [51], 51: [52, 56], 53: [54, 58, 73], 54: [55],
2010
55: [56, 59], 56: [57], 57: [58], 58: [75], 59: [75],
2011
60: [61, 64], 61: [62, 71], 62: [63, 77], 63: [67],
2012
64: [65, 69], 65: [77], 66: [70, 73], 67: [68, 73],
2013
68: [69, 76], 70: [71, 76], 76: [77]}, pos={})
2014
2015
_circle_embedding(g, range(15), center=(-2.5, 1.5))
2016
_circle_embedding(g, range(15, 30), center=(-2.5, -1.5))
2017
_circle_embedding(g, [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
2018
42, 74, 43, 44], center=(2.5, 1.5))
2019
_circle_embedding(g, [45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
2020
57, 58, 75, 59], center=(2.5, -1.5))
2021
2022
d = g.get_pos()
2023
2024
d[76] = (-.2, -.1)
2025
d[77] = (.2, .1)
2026
d[38] = (2.2, .1)
2027
d[52] = (2.3, -.1)
2028
d[15] = (-2.1, -.1)
2029
d[72] = (-2.1, .1)
2030
2031
_line_embedding(g, [60, 61, 62, 63], first=(-1, 2), last=(1, 2))
2032
_line_embedding(g, [64, 65, 37], first=(-.5, 1.5), last=(1.2, 1.5))
2033
_line_embedding(g, [66, 73, 67, 68, 69], first=(1.2, -2),
2034
last=(-.8, -2))
2035
_line_embedding(g, [66, 70, 71], first=(.7, -1.5), last=(-1, -1.5))
2036
2037
g.name("Ellingham-Horton 78-graph")
2038
2039
return g
2040
2041
def ErreraGraph():
2042
r"""
2043
Returns the Errera graph.
2044
2045
For more information, see this
2046
`Wikipedia article on the Errera graph <http://en.wikipedia.org/wiki/Errera_graph>`_.
2047
2048
EXAMPLES:
2049
2050
The Errera graph is named after Alfred Errera. It is a planar graph
2051
on 17 vertices and having 45 edges. ::
2052
2053
sage: G = graphs.ErreraGraph(); G
2054
Errera graph: Graph on 17 vertices
2055
sage: G.is_planar()
2056
True
2057
sage: G.order()
2058
17
2059
sage: G.size()
2060
45
2061
2062
The Errera graph is Hamiltonian with radius 3, diameter 4, girth 3,
2063
and chromatic number 4. ::
2064
2065
sage: G.is_hamiltonian()
2066
True
2067
sage: G.radius()
2068
3
2069
sage: G.diameter()
2070
4
2071
sage: G.girth()
2072
3
2073
sage: G.chromatic_number()
2074
4
2075
2076
Each vertex degree is either 5 or 6. That is, if `f` counts the
2077
number of vertices of degree 5 and `s` counts the number of vertices
2078
of degree 6, then `f + s` is equal to the order of the Errera
2079
graph. ::
2080
2081
sage: D = G.degree_sequence()
2082
sage: D.count(5) + D.count(6) == G.order()
2083
True
2084
2085
The automorphism group of the Errera graph is isomorphic to the
2086
dihedral group of order 20. ::
2087
2088
sage: ag = G.automorphism_group()
2089
sage: ag.is_isomorphic(DihedralGroup(10))
2090
True
2091
"""
2092
edge_dict = {
2093
0: [1,7,14,15,16],
2094
1: [2,9,14,15],
2095
2: [3,8,9,10,14],
2096
3: [4,9,10,11],
2097
4: [5,10,11,12],
2098
5: [6,11,12,13],
2099
6: [7,8,12,13,16],
2100
7: [13,15,16],
2101
8: [10,12,14,16],
2102
9: [11,13,15],
2103
10: [12],
2104
11: [13],
2105
13: [15],
2106
14: [16]}
2107
return Graph(edge_dict, name="Errera graph")
2108
2109
def FlowerSnark():
2110
"""
2111
Returns a Flower Snark.
2112
2113
A flower snark has 20 vertices. It is part of the class of
2114
biconnected cubic graphs with edge chromatic number = 4, known as
2115
snarks. (i.e.: the Petersen graph). All snarks are not Hamiltonian,
2116
non-planar and have Petersen graph graph minors.
2117
2118
PLOTTING: Upon construction, the position dictionary is filled to
2119
override the spring-layout algorithm. By convention, the nodes are
2120
drawn 0-14 on the outer circle, and 15-19 in an inner pentagon.
2121
2122
REFERENCES:
2123
2124
- [1] Weisstein, E. (1999). "Flower Snark - from Wolfram
2125
MathWorld". [Online] Available:
2126
http://mathworld.wolfram.com/FlowerSnark.html [2007, February 17]
2127
2128
EXAMPLES: Inspect a flower snark::
2129
2130
sage: F = graphs.FlowerSnark()
2131
sage: F
2132
Flower Snark: Graph on 20 vertices
2133
sage: F.graph6_string()
2134
'ShCGHC@?GGg@?@?Gp?K??C?CA?G?_G?Cc'
2135
2136
Now show it::
2137
2138
sage: F.show() # long time
2139
"""
2140
pos_dict = {}
2141
for i in range(15):
2142
x = float(2.5*(cos((pi/2) + ((2*pi)/15)*i)))
2143
y = float(2.5*(sin((pi/2) + ((2*pi)/15)*i)))
2144
pos_dict[i] = (x,y)
2145
for i in range(15,20):
2146
x = float(cos((pi/2) + ((2*pi)/5)*i))
2147
y = float(sin((pi/2) + ((2*pi)/5)*i))
2148
pos_dict[i] = (x,y)
2149
return Graph({0:[1,14,15],1:[2,11],2:[3,7],3:[2,4,16],4:[5,14], \
2150
5:[6,10],6:[5,7,17],8:[7,9,13],9:[10,18],11:[10,12], \
2151
12:[13,19],13:[14],15:[19],16:[15,17],18:[17,19]}, \
2152
pos=pos_dict, name="Flower Snark")
2153
2154
2155
def FolkmanGraph():
2156
"""
2157
Returns the Folkman graph.
2158
2159
See the :wikipedia:`Wikipedia page on the Folkman Graph
2160
<Folkman_graph>`.
2161
2162
EXAMPLE::
2163
2164
sage: g = graphs.FolkmanGraph()
2165
sage: g.order()
2166
20
2167
sage: g.size()
2168
40
2169
sage: g.diameter()
2170
4
2171
sage: g.girth()
2172
4
2173
sage: g.charpoly().factor()
2174
(x - 4) * (x + 4) * x^10 * (x^2 - 6)^4
2175
sage: g.chromatic_number()
2176
2
2177
sage: g.is_eulerian()
2178
True
2179
sage: g.is_hamiltonian()
2180
True
2181
sage: g.is_vertex_transitive()
2182
False
2183
sage: g.is_bipartite()
2184
True
2185
"""
2186
from sage.graphs.generators.families import LCFGraph
2187
g= LCFGraph(20, [5, -7, -7, 5], 5)
2188
g.name("Folkman Graph")
2189
return g
2190
2191
2192
def FosterGraph():
2193
"""
2194
Returns the Foster graph.
2195
2196
See the :wikipedia:`Wikipedia page on the Foster Graph
2197
<Foster_graph>`.
2198
2199
EXAMPLE::
2200
2201
sage: g = graphs.FosterGraph()
2202
sage: g.order()
2203
90
2204
sage: g.size()
2205
135
2206
sage: g.diameter()
2207
8
2208
sage: g.girth()
2209
10
2210
sage: g.automorphism_group().cardinality()
2211
4320
2212
sage: g.is_hamiltonian()
2213
True
2214
"""
2215
from sage.graphs.generators.families import LCFGraph
2216
g= LCFGraph(90, [17, -9, 37, -37, 9, -17], 15)
2217
g.name("Foster Graph")
2218
return g
2219
2220
2221
def FranklinGraph():
2222
r"""
2223
Returns the Franklin graph.
2224
2225
For more information, see this
2226
`Wikipedia article on the Franklin graph <http://en.wikipedia.org/wiki/Franklin_graph>`_.
2227
2228
EXAMPLES:
2229
2230
The Franklin graph is named after Philip Franklin. It is a
2231
3-regular graph on 12 vertices and having 18 edges. ::
2232
2233
sage: G = graphs.FranklinGraph(); G
2234
Franklin graph: Graph on 12 vertices
2235
sage: G.is_regular(3)
2236
True
2237
sage: G.order()
2238
12
2239
sage: G.size()
2240
18
2241
2242
The Franklin graph is a Hamiltonian, bipartite graph with radius 3,
2243
diameter 3, and girth 4. ::
2244
2245
sage: G.is_hamiltonian()
2246
True
2247
sage: G.is_bipartite()
2248
True
2249
sage: G.radius()
2250
3
2251
sage: G.diameter()
2252
3
2253
sage: G.girth()
2254
4
2255
2256
It is a perfect, triangle-free graph having chromatic number 2. ::
2257
2258
sage: G.is_perfect()
2259
True
2260
sage: G.is_triangle_free()
2261
True
2262
sage: G.chromatic_number()
2263
2
2264
"""
2265
edge_dict = {
2266
0: [1,5,6],
2267
1: [2,7],
2268
2: [3,8],
2269
3: [4,9],
2270
4: [5,10],
2271
5: [11],
2272
6: [7,9],
2273
7: [10],
2274
8: [9,11],
2275
10: [11]}
2276
pos_dict = {
2277
0: [2, 0],
2278
1: [1, 1.73205080756888],
2279
2: [-1, 1.73205080756888],
2280
3: [-2, 0],
2281
4: [-1, -1.73205080756888],
2282
5: [1, -1.73205080756888],
2283
6: [1, 0],
2284
7: [0.5, 0.866025403784439],
2285
8: [-0.5, 0.866025403784439],
2286
9: [-1, 0],
2287
10: [-0.5, -0.866025403784439],
2288
11: [0.5, -0.866025403784439]}
2289
return Graph(edge_dict, pos=pos_dict, name="Franklin graph")
2290
2291
def FruchtGraph():
2292
"""
2293
Returns a Frucht Graph.
2294
2295
A Frucht graph has 12 nodes and 18 edges. It is the smallest cubic
2296
identity graph. It is planar and it is Hamiltonian.
2297
2298
This constructor is dependent on NetworkX's numeric labeling.
2299
2300
PLOTTING: Upon construction, the position dictionary is filled to
2301
override the spring-layout algorithm. By convention, the first
2302
seven nodes are on the outer circle, with the next four on an inner
2303
circle and the last in the center.
2304
2305
REFERENCES:
2306
2307
- [1] Weisstein, E. (1999). "Frucht Graph - from Wolfram
2308
MathWorld". [Online] Available:
2309
http://mathworld.wolfram.com/FruchtGraph.html [2007, February 17]
2310
2311
EXAMPLES::
2312
2313
sage: FRUCHT = graphs.FruchtGraph()
2314
sage: FRUCHT
2315
Frucht graph: Graph on 12 vertices
2316
sage: FRUCHT.graph6_string()
2317
'KhCKM?_EGK?L'
2318
sage: (graphs.FruchtGraph()).show() # long time
2319
"""
2320
pos_dict = {}
2321
for i in range(7):
2322
x = float(2*(cos((pi/2) + ((2*pi)/7)*i)))
2323
y = float(2*(sin((pi/2) + ((2*pi)/7)*i)))
2324
pos_dict[i] = (x,y)
2325
pos_dict[7] = (0,1)
2326
pos_dict[8] = (-1,0)
2327
pos_dict[9] = (0,-1)
2328
pos_dict[10] = (1,0)
2329
pos_dict[11] = (0,0)
2330
import networkx
2331
G = networkx.frucht_graph()
2332
return Graph(G, pos=pos_dict, name="Frucht graph")
2333
2334
def GoldnerHararyGraph():
2335
r"""
2336
Return the Goldner-Harary graph.
2337
2338
For more information, see this
2339
`Wikipedia article on the Goldner-Harary graph <http://en.wikipedia.org/wiki/Goldner%E2%80%93Harary_graph>`_.
2340
2341
EXAMPLES:
2342
2343
The Goldner-Harary graph is named after A. Goldner and Frank Harary.
2344
It is a planar graph having 11 vertices and 27 edges. ::
2345
2346
sage: G = graphs.GoldnerHararyGraph(); G
2347
Goldner-Harary graph: Graph on 11 vertices
2348
sage: G.is_planar()
2349
True
2350
sage: G.order()
2351
11
2352
sage: G.size()
2353
27
2354
2355
The Goldner-Harary graph is chordal with radius 2, diameter 2, and
2356
girth 3. ::
2357
2358
sage: G.is_chordal()
2359
True
2360
sage: G.radius()
2361
2
2362
sage: G.diameter()
2363
2
2364
sage: G.girth()
2365
3
2366
2367
Its chromatic number is 4 and its automorphism group is isomorphic to
2368
the dihedral group `D_6`. ::
2369
2370
sage: G.chromatic_number()
2371
4
2372
sage: ag = G.automorphism_group()
2373
sage: ag.is_isomorphic(DihedralGroup(6))
2374
True
2375
"""
2376
edge_dict = {
2377
0: [1,3,4],
2378
1: [2,3,4,5,6,7,10],
2379
2: [3,7],
2380
3: [7,8,9,10],
2381
4: [3,5,9,10],
2382
5: [10],
2383
6: [7,10],
2384
7: [8,10],
2385
8: [10],
2386
9: [10]}
2387
2388
pos = {
2389
0: (-2, 0),
2390
1: (0, 1.5),
2391
2: (2, 0),
2392
3: (0, -1.5),
2393
4: (-1.5, 0),
2394
5: (-0.5, 0.5),
2395
6: (0.5, 0.5),
2396
7: (1.5, 0),
2397
8: (0.5, -0.5),
2398
9: (-0.5, -0.5),
2399
10: (0, 0)}
2400
2401
return Graph(edge_dict, pos = pos, name="Goldner-Harary graph")
2402
2403
def GrayGraph(embedding=1):
2404
r"""
2405
Returns the Gray graph.
2406
2407
See the :wikipedia:`Wikipedia page on the Gray Graph
2408
<Gray_graph>`.
2409
2410
INPUT:
2411
2412
- ``embedding`` -- two embeddings are available, and can be
2413
selected by setting ``embedding`` to 1 or 2.
2414
2415
EXAMPLES::
2416
2417
sage: g = graphs.GrayGraph()
2418
sage: g.order()
2419
54
2420
sage: g.size()
2421
81
2422
sage: g.girth()
2423
8
2424
sage: g.diameter()
2425
6
2426
sage: g.show(figsize=[10, 10]) # long time
2427
sage: graphs.GrayGraph(embedding = 2).show(figsize=[10, 10]) # long time
2428
2429
TESTS::
2430
2431
sage: graphs.GrayGraph(embedding = 3)
2432
Traceback (most recent call last):
2433
...
2434
ValueError: The value of embedding must be 1, 2, or 3.
2435
"""
2436
2437
from sage.graphs.generators.families import LCFGraph
2438
g = LCFGraph(54, [-25,7,-7,13,-13,25], 9)
2439
g.name("Gray graph")
2440
2441
if embedding == 1:
2442
o = g.automorphism_group(orbits=True)[-1]
2443
_circle_embedding(g, o[0], center=(0, 0), radius=1)
2444
_circle_embedding(g, o[1], center=(0, 0), radius=.6, shift=-.5)
2445
2446
elif embedding != 2:
2447
raise ValueError("The value of embedding must be 1, 2, or 3.")
2448
2449
return g
2450
2451
def GrotzschGraph():
2452
r"""
2453
Returns the Grötzsch graph.
2454
2455
The Grötzsch graph is an example of a triangle-free graph with
2456
chromatic number equal to 4. For more information, see this
2457
`Wikipedia article on Grötzsch graph <http://en.wikipedia.org/wiki/Gr%C3%B6tzsch_graph>`_.
2458
2459
REFERENCE:
2460
2461
- [1] Weisstein, Eric W. "Grotzsch Graph."
2462
From MathWorld--A Wolfram Web Resource.
2463
http://mathworld.wolfram.com/GroetzschGraph.html
2464
2465
EXAMPLES:
2466
2467
The Grötzsch graph is named after Herbert Grötzsch. It is a
2468
Hamiltonian graph with 11 vertices and 20 edges. ::
2469
2470
sage: G = graphs.GrotzschGraph(); G
2471
Grotzsch graph: Graph on 11 vertices
2472
sage: G.is_hamiltonian()
2473
True
2474
sage: G.order()
2475
11
2476
sage: G.size()
2477
20
2478
2479
The Grötzsch graph is triangle-free and having radius 2, diameter 2,
2480
and girth 4. ::
2481
2482
sage: G.is_triangle_free()
2483
True
2484
sage: G.radius()
2485
2
2486
sage: G.diameter()
2487
2
2488
sage: G.girth()
2489
4
2490
2491
Its chromatic number is 4 and its automorphism group is isomorphic
2492
to the dihedral group `D_5`. ::
2493
2494
sage: G.chromatic_number()
2495
4
2496
sage: ag = G.automorphism_group()
2497
sage: ag.is_isomorphic(DihedralGroup(5))
2498
True
2499
"""
2500
g = Graph()
2501
g.add_vertices(range(11))
2502
2503
edges = [];
2504
for u in range(1,6):
2505
edges.append( (0,u) )
2506
2507
edges.append( (10,6) )
2508
2509
for u in range(6,10):
2510
edges.append( (u,u+1) )
2511
edges.append( (u,u-4) )
2512
2513
edges.append( (10,1) )
2514
2515
for u in range(7,11):
2516
edges.append( (u,u-6) )
2517
2518
edges.append((6,5))
2519
2520
g.add_edges(edges)
2521
2522
pos = {}
2523
pos[0] = (0,0)
2524
for u in range(1,6):
2525
theta = (u-1)*2*pi/5
2526
pos[u] = (float(5*sin(theta)),float(5*cos(theta)))
2527
pos[u+5] = (2*pos[u][0], 2*pos[u][1])
2528
2529
g.set_pos(pos)
2530
g.name("Grotzsch graph")
2531
return g
2532
2533
def HeawoodGraph():
2534
"""
2535
Returns a Heawood graph.
2536
2537
The Heawood graph is a cage graph that has 14 nodes. It is a cubic
2538
symmetric graph. (See also the Moebius-Kantor graph). It is
2539
nonplanar and Hamiltonian. It has diameter = 3, radius = 3, girth =
2540
6, chromatic number = 2. It is 4-transitive but not 5-transitive.
2541
2542
This constructor is dependent on NetworkX's numeric labeling.
2543
2544
PLOTTING: Upon construction, the position dictionary is filled to
2545
override the spring-layout algorithm. By convention, the nodes are
2546
positioned in a circular layout with the first node appearing at
2547
the top, and then continuing counterclockwise.
2548
2549
REFERENCES:
2550
2551
- [1] Weisstein, E. (1999). "Heawood Graph - from Wolfram
2552
MathWorld". [Online] Available:
2553
http://mathworld.wolfram.com/HeawoodGraph.html [2007, February 17]
2554
2555
EXAMPLES::
2556
2557
sage: H = graphs.HeawoodGraph()
2558
sage: H
2559
Heawood graph: Graph on 14 vertices
2560
sage: H.graph6_string()
2561
'MhEGHC@AI?_PC@_G_'
2562
sage: (graphs.HeawoodGraph()).show() # long time
2563
"""
2564
pos_dict = {}
2565
for i in range(14):
2566
x = float(cos((pi/2) + (pi/7)*i))
2567
y = float(sin((pi/2) + (pi/7)*i))
2568
pos_dict[i] = (x,y)
2569
import networkx
2570
G = networkx.heawood_graph()
2571
return Graph(G, pos=pos_dict, name="Heawood graph")
2572
2573
def HerschelGraph():
2574
r"""
2575
Returns the Herschel graph.
2576
2577
For more information, see this
2578
`Wikipedia article on the Herschel graph <http://en.wikipedia.org/wiki/Herschel_graph>`_.
2579
2580
EXAMPLES:
2581
2582
The Herschel graph is named after Alexander Stewart Herschel. It is
2583
a planar, bipartite graph with 11 vertices and 18 edges. ::
2584
2585
sage: G = graphs.HerschelGraph(); G
2586
Herschel graph: Graph on 11 vertices
2587
sage: G.is_planar()
2588
True
2589
sage: G.is_bipartite()
2590
True
2591
sage: G.order()
2592
11
2593
sage: G.size()
2594
18
2595
2596
The Herschel graph is a perfect graph with radius 3, diameter 4, and
2597
girth 4. ::
2598
2599
sage: G.is_perfect()
2600
True
2601
sage: G.radius()
2602
3
2603
sage: G.diameter()
2604
4
2605
sage: G.girth()
2606
4
2607
2608
Its chromatic number is 2 and its automorphism group is
2609
isomorphic to the dihedral group `D_6`. ::
2610
2611
sage: G.chromatic_number()
2612
2
2613
sage: ag = G.automorphism_group()
2614
sage: ag.is_isomorphic(DihedralGroup(6))
2615
True
2616
"""
2617
edge_dict = {
2618
0: [1,3,4],
2619
1: [2,5,6],
2620
2: [3,7],
2621
3: [8,9],
2622
4: [5,9],
2623
5: [10],
2624
6: [7,10],
2625
7: [8],
2626
8: [10],
2627
9: [10]}
2628
pos_dict = {
2629
0: [2, 0],
2630
1: [0, 2],
2631
2: [-2, 0],
2632
3: [0, -2],
2633
4: [1, 0],
2634
5: [0.5, 0.866025403784439],
2635
6: [-0.5, 0.866025403784439],
2636
7: [-1, 0],
2637
8: [-0.5, -0.866025403784439],
2638
9: [0.5, -0.866025403784439],
2639
10: [0, 0]}
2640
return Graph(edge_dict, pos=pos_dict, name="Herschel graph")
2641
2642
def HigmanSimsGraph(relabel=True):
2643
r"""
2644
The Higman-Sims graph is a remarkable strongly regular
2645
graph of degree 22 on 100 vertices. For example, it can
2646
be split into two sets of 50 vertices each, so that each
2647
half induces a subgraph isomorphic to the
2648
Hoffman-Singleton graph
2649
(:meth:`~HoffmanSingletonGraph`).
2650
This can be done in 352 ways (see [BROUWER-HS-2009]_).
2651
2652
Its most famous property is that the automorphism
2653
group has an index 2 subgroup which is one of the
2654
26 sporadic groups. [HIGMAN1968]_
2655
2656
The construction used here follows [HAFNER2004]_.
2657
2658
INPUT:
2659
2660
- ``relabel`` - default: ``True``. If ``True`` the
2661
vertices will be labeled with consecutive integers.
2662
If ``False`` the labels are strings that are three
2663
digits long. "xyz" means the vertex is in group
2664
x (zero through three), pentagon or pentagram y
2665
(zero through four), and is vertex z (zero
2666
through four) of that pentagon or pentagram.
2667
See [HAFNER2004]_ for more.
2668
2669
OUTPUT:
2670
2671
The Higman-Sims graph.
2672
2673
EXAMPLES:
2674
2675
A split into the first 50 and last 50 vertices
2676
will induce two copies of the Hoffman-Singleton graph,
2677
and we illustrate another such split, which is obvious
2678
based on the construction used. ::
2679
2680
sage: H = graphs.HigmanSimsGraph()
2681
sage: A = H.subgraph(range(0,50))
2682
sage: B = H.subgraph(range(50,100))
2683
sage: K = graphs.HoffmanSingletonGraph()
2684
sage: K.is_isomorphic(A) and K.is_isomorphic(B)
2685
True
2686
sage: C = H.subgraph(range(25,75))
2687
sage: D = H.subgraph(range(0,25)+range(75,100))
2688
sage: K.is_isomorphic(C) and K.is_isomorphic(D)
2689
True
2690
2691
The automorphism group contains only one nontrivial
2692
proper normal subgroup, which is of index 2 and is
2693
simple. It is known as the Higman-Sims group. ::
2694
2695
sage: H = graphs.HigmanSimsGraph()
2696
sage: G = H.automorphism_group()
2697
sage: g=G.order(); g
2698
88704000
2699
sage: K = G.normal_subgroups()[1]
2700
sage: K.is_simple()
2701
True
2702
sage: g//K.order()
2703
2
2704
2705
REFERENCES:
2706
2707
.. [BROUWER-HS-2009] `Higman-Sims graph
2708
<http://www.win.tue.nl/~aeb/graphs/Higman-Sims.html>`_.
2709
Andries E. Brouwer, accessed 24 October 2009.
2710
.. [HIGMAN1968] A simple group of order 44,352,000,
2711
Math.Z. 105 (1968) 110-113. D.G. Higman & C. Sims.
2712
.. [HAFNER2004] `On the graphs of Hoffman-Singleton and
2713
Higman-Sims
2714
<http://www.combinatorics.org/Volume_11/PDF/v11i1r77.pdf>`_.
2715
The Electronic Journal of Combinatorics 11 (2004), #R77,
2716
Paul R. Hafner, accessed 24 October 2009.
2717
2718
AUTHOR:
2719
2720
- Rob Beezer (2009-10-24)
2721
"""
2722
HS = Graph()
2723
HS.name('Higman-Sims graph')
2724
2725
# Four groups of either five pentagons, or five pentagrams
2726
# 4 x 5 x 5 = 100 vertices
2727
# First digit is "group", second is "penta{gon|gram}", third is "vertex"
2728
vlist = ['%d%d%d'%(g,p,v)
2729
for g in range(4) for p in range(5) for v in range(5)]
2730
for avertex in vlist:
2731
HS.add_vertex(avertex)
2732
2733
# Edges: Within groups 0 and 2, joined as pentagons
2734
# Edges: Within groups 1 and 3, joined as pentagrams
2735
for g in range(4):
2736
shift = 1
2737
if g in [1,3]:
2738
shift += 1
2739
for p in range(5):
2740
for v in range(5):
2741
HS.add_edge(('%d%d%d'%(g,p,v), '%d%d%d'%(g,p,(v+shift)%5)))
2742
2743
# Edges: group 0 to group 1
2744
for x in range(5):
2745
for m in range(5):
2746
for c in range(5):
2747
y = (m*x+c)%5
2748
HS.add_edge(('0%d%d'%(x,y), '1%d%d'%(m,c)))
2749
2750
# Edges: group 1 to group 2
2751
for m in range(5):
2752
for A in range(5):
2753
for B in range(5):
2754
c = (2*(m-A)*(m-A)+B)%5
2755
HS.add_edge(('1%d%d'%(m,c), '2%d%d'%(A,B)))
2756
2757
# Edges: group 2 to group 3
2758
for A in range(5):
2759
for a in range(5):
2760
for b in range(5):
2761
B = (2*A*A+3*a*A-a*a+b)%5
2762
HS.add_edge(('2%d%d'%(A,B), '3%d%d'%(a,b)))
2763
2764
# Edges: group 3 to group 0
2765
for a in range(5):
2766
for b in range(5):
2767
for x in range(5):
2768
y = ((x-a)*(x-a)+b)%5
2769
HS.add_edge(('3%d%d'%(a,b), '0%d%d'%(x,y)))
2770
2771
# Edges: group 0 to group 2
2772
for x in range(5):
2773
for A in range(5):
2774
for B in range(5):
2775
y = (3*x*x+A*x+B+1)%5
2776
HS.add_edge(('0%d%d'%(x,y), '2%d%d'%(A,B)))
2777
y = (3*x*x+A*x+B-1)%5
2778
HS.add_edge(('0%d%d'%(x,y), '2%d%d'%(A,B)))
2779
2780
# Edges: group 1 to group 3
2781
for m in range(5):
2782
for a in range(5):
2783
for b in range(5):
2784
c = (m*(m-a)+b+2)%5
2785
HS.add_edge(('1%d%d'%(m,c), '3%d%d'%(a,b)))
2786
c = (m*(m-a)+b-2)%5
2787
HS.add_edge(('1%d%d'%(m,c), '3%d%d'%(a,b)))
2788
2789
# Rename to integer vertex labels, creating dictionary
2790
# Or not, and create identity mapping
2791
if relabel:
2792
vmap = HS.relabel(return_map=True)
2793
else:
2794
vmap={}
2795
for v in vlist:
2796
vmap[v] = v
2797
# Layout vertices in a circle
2798
# In the order given in vlist
2799
# Using labels from vmap
2800
pos_dict = {}
2801
for i in range(100):
2802
x = float(cos((pi/2) + ((2*pi)/100)*i))
2803
y = float(sin((pi/2) + ((2*pi)/100)*i))
2804
pos_dict[vmap[vlist[i]]] = (x,y)
2805
HS.set_pos(pos_dict)
2806
return HS
2807
2808
def HoffmanSingletonGraph():
2809
r"""
2810
Returns the Hoffman-Singleton graph.
2811
2812
The Hoffman-Singleton graph is the Moore graph of degree 7,
2813
diameter 2 and girth 5. The Hoffman-Singleton theorem states that
2814
any Moore graph with girth 5 must have degree 2, 3, 7 or 57. The
2815
first three respectively are the pentagon, the Petersen graph, and
2816
the Hoffman-Singleton graph. The existence of a Moore graph with
2817
girth 5 and degree 57 is still open.
2818
2819
A Moore graph is a graph with diameter `d` and girth
2820
`2d + 1`. This implies that the graph is regular, and
2821
distance regular.
2822
2823
PLOTTING: Upon construction, the position dictionary is filled to
2824
override the spring-layout algorithm. A novel algorithm written by
2825
Tom Boothby gives a random layout which is pleasing to the eye.
2826
2827
REFERENCES:
2828
2829
.. [GodsilRoyle] Godsil, C. and Royle, G. Algebraic Graph Theory.
2830
Springer, 2001.
2831
2832
EXAMPLES::
2833
2834
sage: HS = graphs.HoffmanSingletonGraph()
2835
sage: Set(HS.degree())
2836
{7}
2837
sage: HS.girth()
2838
5
2839
sage: HS.diameter()
2840
2
2841
sage: HS.num_verts()
2842
50
2843
2844
Note that you get a different layout each time you create the graph.
2845
::
2846
2847
sage: HS.layout()[1]
2848
(-0.844..., 0.535...)
2849
sage: graphs.HoffmanSingletonGraph().layout()[1]
2850
(-0.904..., 0.425...)
2851
2852
"""
2853
H = Graph({ \
2854
'q00':['q01'], 'q01':['q02'], 'q02':['q03'], 'q03':['q04'], 'q04':['q00'], \
2855
'q10':['q11'], 'q11':['q12'], 'q12':['q13'], 'q13':['q14'], 'q14':['q10'], \
2856
'q20':['q21'], 'q21':['q22'], 'q22':['q23'], 'q23':['q24'], 'q24':['q20'], \
2857
'q30':['q31'], 'q31':['q32'], 'q32':['q33'], 'q33':['q34'], 'q34':['q30'], \
2858
'q40':['q41'], 'q41':['q42'], 'q42':['q43'], 'q43':['q44'], 'q44':['q40'], \
2859
'p00':['p02'], 'p02':['p04'], 'p04':['p01'], 'p01':['p03'], 'p03':['p00'], \
2860
'p10':['p12'], 'p12':['p14'], 'p14':['p11'], 'p11':['p13'], 'p13':['p10'], \
2861
'p20':['p22'], 'p22':['p24'], 'p24':['p21'], 'p21':['p23'], 'p23':['p20'], \
2862
'p30':['p32'], 'p32':['p34'], 'p34':['p31'], 'p31':['p33'], 'p33':['p30'], \
2863
'p40':['p42'], 'p42':['p44'], 'p44':['p41'], 'p41':['p43'], 'p43':['p40']})
2864
for j in range(5):
2865
for i in range(5):
2866
for k in range(5):
2867
con = (i+j*k)%5
2868
H.add_edge(('q%d%d'%(k,con),'p%d%d'%(j,i)))
2869
H.name('Hoffman-Singleton graph')
2870
from sage.combinat.permutation import Permutations
2871
from sage.misc.prandom import randint
2872
P = Permutations([1,2,3,4])
2873
qpp = [0] + list(P[randint(0,23)])
2874
ppp = [0] + list(P[randint(0,23)])
2875
qcycle = lambda i,s : ['q%s%s'%(i,(j+s)%5) for j in qpp]
2876
pcycle = lambda i,s : ['p%s%s'%(i,(j+s)%5) for j in ppp]
2877
l = 0
2878
s = 0
2879
D = []
2880
while l < 5:
2881
for q in qcycle(l,s):
2882
D.append(q)
2883
vv = 'p%s'%q[1]
2884
s = int([v[-1] for v in H.neighbors(q) if v[:2] == vv][0])
2885
for p in pcycle(l,s):
2886
D.append(p)
2887
vv = 'q%s'%(int(p[1])+1)
2888
v = [v[-1] for v in H.neighbors(p) if v[:2] == vv]
2889
if len(v):
2890
s = int(v[0])
2891
l+=1
2892
map = H.relabel(return_map=True)
2893
pos_dict = {}
2894
for i in range(50):
2895
x = float(cos((pi/2) + ((2*pi)/50)*i))
2896
y = float(sin((pi/2) + ((2*pi)/50)*i))
2897
pos_dict[map[D[i]]] = (x,y)
2898
H.set_pos(pos_dict)
2899
return H
2900
2901
def HoffmanGraph():
2902
r"""
2903
Returns the Hoffman Graph.
2904
2905
See the :wikipedia:`Wikipedia page on the Hoffman graph
2906
<Hoffman_graph>`.
2907
2908
EXAMPLES::
2909
2910
sage: g = graphs.HoffmanGraph()
2911
sage: g.is_bipartite()
2912
True
2913
sage: g.is_hamiltonian() # long time
2914
True
2915
sage: g.radius()
2916
3
2917
sage: g.diameter()
2918
4
2919
sage: g.automorphism_group().cardinality()
2920
48
2921
"""
2922
g = Graph({
2923
0: [1, 7, 8, 13],
2924
1: [2, 9, 14],
2925
2: [3, 8, 10],
2926
3: [4, 9, 15],
2927
4: [5, 10, 11],
2928
5: [6, 12, 14],
2929
6: [7, 11, 13],
2930
7: [12, 15],
2931
8: [12, 14],
2932
9: [11, 13],
2933
10: [12, 15],
2934
11: [14],
2935
13: [15]})
2936
g.set_pos({})
2937
_circle_embedding(g, range(8))
2938
_circle_embedding(g, range(8, 14), radius=.7, shift=.5)
2939
_circle_embedding(g, [14, 15], radius=.1)
2940
2941
g.name("Hoffman Graph")
2942
2943
return g
2944
2945
def HoltGraph():
2946
r"""
2947
Returns the Holt graph (also called the Doyle graph)
2948
2949
See the :wikipedia:`Wikipedia page on the Holt graph
2950
<Holt_graph>`.
2951
2952
EXAMPLES::
2953
2954
sage: g = graphs.HoltGraph();g
2955
Holt graph: Graph on 27 vertices
2956
sage: g.is_regular()
2957
True
2958
sage: g.is_vertex_transitive()
2959
True
2960
sage: g.chromatic_number()
2961
3
2962
sage: g.is_hamiltonian() # long time
2963
True
2964
sage: g.radius()
2965
3
2966
sage: g.diameter()
2967
3
2968
sage: g.girth()
2969
5
2970
sage: g.automorphism_group().cardinality()
2971
54
2972
"""
2973
g = Graph(loops=False, name = "Holt graph", pos={})
2974
for x in range(9):
2975
for y in range(3):
2976
g.add_edge((x,y),((4*x+1)%9,(y-1)%3))
2977
g.add_edge((x,y),((4*x-1)%9,(y-1)%3))
2978
g.add_edge((x,y),((7*x+7)%9,(y+1)%3))
2979
g.add_edge((x,y),((7*x-7)%9,(y+1)%3))
2980
2981
for j in range(0,6,2):
2982
_line_embedding(g, [(x,j/2) for x in range(9)],
2983
first=(cos(2*j*pi/6),sin(2*j*pi/6)),
2984
last=(cos(2*(j+1)*pi/6),sin(2*(j+1)*pi/6)))
2985
2986
return g
2987
2988
def KrackhardtKiteGraph():
2989
"""
2990
Returns a Krackhardt kite graph with 10 nodes.
2991
2992
The Krackhardt kite graph was originally developed by David
2993
Krackhardt for the purpose of studying social networks. It is used
2994
to show the distinction between: degree centrality, betweeness
2995
centrality, and closeness centrality. For more information read the
2996
plotting section below in conjunction with the example.
2997
2998
REFERENCES:
2999
3000
- [1] Kreps, V. (2002). "Social Network Analysis". [Online] Available:
3001
http://www.orgnet.com/sna.html
3002
3003
This constructor depends on NetworkX numeric labeling.
3004
3005
PLOTTING: Upon construction, the position dictionary is filled to
3006
override the spring-layout algorithm. By convention, the graph is
3007
drawn left to right, in top to bottom row sequence of [2, 3, 2, 1,
3008
1, 1] nodes on each row. This places the fourth node (3) in the
3009
center of the kite, with the highest degree. But the fourth node
3010
only connects nodes that are otherwise connected, or those in its
3011
clique (i.e.: Degree Centrality). The eighth (7) node is where the
3012
kite meets the tail. It has degree = 3, less than the average, but
3013
is the only connection between the kite and tail (i.e.: Betweenness
3014
Centrality). The sixth and seventh nodes (5 and 6) are drawn in the
3015
third row and have degree = 5. These nodes have the shortest path
3016
to all other nodes in the graph (i.e.: Closeness Centrality).
3017
Please execute the example for visualization.
3018
3019
EXAMPLE: Construct and show a Krackhardt kite graph
3020
3021
::
3022
3023
sage: g = graphs.KrackhardtKiteGraph()
3024
sage: g.show() # long time
3025
"""
3026
pos_dict = {0:(-1,4),1:(1,4),2:(-2,3),3:(0,3),4:(2,3),5:(-1,2),6:(1,2),7:(0,1),8:(0,0),9:(0,-1)}
3027
import networkx
3028
G = networkx.krackhardt_kite_graph()
3029
return Graph(G, pos=pos_dict, name="Krackhardt Kite Graph")
3030
3031
def LjubljanaGraph(embedding=1):
3032
r"""
3033
Returns the Ljubljana Graph.
3034
3035
The Ljubljana graph is a bipartite 3-regular graph on 112
3036
vertices and 168 edges. It is not vertex-transitive as it has
3037
two orbits which are also independent sets of size 56. See the
3038
:wikipedia:`Wikipedia page on the Ljubljana Graph
3039
<Ljubljana_graph>`.
3040
3041
The default embedding is obtained from the Heawood graph.
3042
3043
INPUT:
3044
3045
- ``embedding`` -- two embeddings are available, and can be
3046
selected by setting ``embedding`` to 1 or 2.
3047
3048
EXAMPLES::
3049
3050
sage: g = graphs.LjubljanaGraph()
3051
sage: g.order()
3052
112
3053
sage: g.size()
3054
168
3055
sage: g.girth()
3056
10
3057
sage: g.diameter()
3058
8
3059
sage: g.show(figsize=[10, 10]) # long time
3060
sage: graphs.LjubljanaGraph(embedding=2).show(figsize=[10, 10]) # long time
3061
3062
TESTS::
3063
3064
sage: graphs.LjubljanaGraph(embedding=3)
3065
Traceback (most recent call last):
3066
...
3067
ValueError: The value of embedding must be 1 or 2.
3068
"""
3069
3070
L = [47, -23, -31, 39, 25, -21, -31, -41, 25, 15, 29, -41, -19, 15,
3071
-49, 33, 39, -35, -21, 17, -33, 49, 41, 31, -15, -29, 41, 31,
3072
-15, -25, 21, 31, -51, -25, 23, 9, -17, 51, 35, -29, 21, -51,
3073
-39, 33, -9, -51, 51, -47, -33, 19, 51, -21, 29, 21, -31, -39]
3074
3075
from sage.graphs.generators.families import LCFGraph
3076
g = LCFGraph(112, L, 2)
3077
g.name("Ljubljana graph")
3078
3079
if embedding == 1:
3080
dh = HeawoodGraph().get_pos()
3081
3082
# Correspondence between the vertices of the Heawood Graph and
3083
# 8-sets of the Ljubljana Graph.
3084
3085
d = {
3086
0: [1, 21, 39, 57, 51, 77, 95, 107],
3087
1: [2, 22, 38, 58, 50, 78, 94, 106],
3088
2: [3, 23, 37, 59, 49, 79, 93, 105],
3089
3: [4, 24, 36, 60, 48, 80, 92, 104],
3090
4: [5, 25, 35, 61, 15, 81, 91, 71],
3091
9: [6, 26, 44, 62, 16, 82, 100, 72],
3092
10: [7, 27, 45, 63, 17, 83, 101, 73],
3093
11: [8, 28, 46, 64, 18, 84, 102, 74],
3094
12: [9, 29, 47, 65, 19, 85, 103, 75],
3095
13: [10, 30, 0, 66, 20, 86, 56, 76],
3096
8: [11, 31, 111, 67, 99, 87, 55, 43],
3097
7: [12, 32, 110, 68, 98, 88, 54, 42],
3098
6: [13, 33, 109, 69, 97, 89, 53, 41],
3099
5: [14, 34, 108, 70, 96, 90, 52, 40]
3100
}
3101
3102
# The vertices of each 8-set are plotted on a circle, and the
3103
# circles are slowly shifted to obtain a symmetric drawing.
3104
3105
for i, (u, vertices) in enumerate(d.iteritems()):
3106
_circle_embedding(g, vertices, center=dh[u], radius=.1,
3107
shift=8.*i/14)
3108
3109
return g
3110
3111
elif embedding == 2:
3112
return g
3113
3114
else:
3115
raise ValueError("The value of embedding must be 1 or 2.")
3116
3117
def M22Graph():
3118
r"""
3119
Returns the M22 graph.
3120
3121
The `M_{22}` graph is the unique strongly regular graph with parameters
3122
`v = 77, k = 16, \lambda = 0, \mu = 4`.
3123
3124
For more information on the `M_{22}` graph, see
3125
`<http://www.win.tue.nl/~aeb/graphs/M22.html>`_.
3126
3127
EXAMPLES::
3128
3129
sage: g = graphs.M22Graph()
3130
sage: g.order()
3131
77
3132
sage: g.size()
3133
616
3134
sage: g.is_strongly_regular(parameters = True)
3135
(77, 16, 0, 4)
3136
"""
3137
from sage.groups.perm_gps.permgroup_named import MathieuGroup
3138
sets = map(tuple,MathieuGroup(22).orbit((1,2,3,7,10,20), action = "OnSets"))
3139
g = Graph([sets, lambda x,y : not any(xx in y for xx in x)], name="M22 Graph")
3140
g.relabel()
3141
ordering = [0, 1, 3, 4, 5, 6, 7, 10, 12, 19, 20, 31, 2, 24, 35, 34, 22, 32,
3142
36, 23, 27, 25, 40, 26, 16, 71, 61, 63, 50, 68, 39, 52, 48, 44,
3143
69, 28, 9, 64, 60, 17, 38, 49, 45, 65, 14, 70, 72, 21, 43, 56,
3144
33, 73, 58, 55, 41, 29, 66, 54, 76, 46, 67, 11, 51, 47, 62, 53,
3145
15, 8, 18, 13, 59, 37, 30, 57, 75, 74, 42]
3146
3147
_circle_embedding(g, ordering)
3148
3149
return g
3150
3151
def MarkstroemGraph():
3152
r"""
3153
Returns the Markström Graph.
3154
3155
The Markström Graph is a cubic planar graph with no cycles of length 4 nor
3156
8, but containing cycles of length 16. For more information, see the
3157
`Wolfram page about the Markström Graph
3158
<http://mathworld.wolfram.com/MarkstroemGraph.html>`_.
3159
3160
EXAMPLES::
3161
3162
sage: g = graphs.MarkstroemGraph()
3163
sage: g.order()
3164
24
3165
sage: g.size()
3166
36
3167
sage: g.is_planar()
3168
True
3169
sage: g.is_regular(3)
3170
True
3171
sage: g.subgraph_search(graphs.CycleGraph(4)) is None
3172
True
3173
sage: g.subgraph_search(graphs.CycleGraph(8)) is None
3174
True
3175
sage: g.subgraph_search(graphs.CycleGraph(16))
3176
Subgraph of (Markstroem Graph): Graph on 16 vertices
3177
"""
3178
g = Graph(name="Markstroem Graph")
3179
3180
g.add_cycle(range(9))
3181
g.add_path([0,9,10,11,2,1,11])
3182
g.add_path([3,12,13,14,5,4,14])
3183
g.add_path([6,15,16,17,8,7,17])
3184
g.add_cycle([10,9,18])
3185
g.add_cycle([12,13,19])
3186
g.add_cycle([15,16,20])
3187
g.add_cycle([21,22,23])
3188
g.add_edges([(19,22),(18,21),(20,23)])
3189
3190
_circle_embedding(g, sum([[9+3*i+j for j in range(3)]+[0]*2 for i in range(3)],[]), radius=.6, shift=.7)
3191
_circle_embedding(g, [18,19,20], radius=.35, shift=.25)
3192
_circle_embedding(g, [21,22,23], radius=.15, shift=.25)
3193
_circle_embedding(g, range(9))
3194
3195
return g
3196
3197
def McGeeGraph(embedding=2):
3198
r"""
3199
Returns the McGee Graph.
3200
3201
See the :wikipedia:`Wikipedia page on the McGee Graph
3202
<McGee_graph>`.
3203
3204
INPUT:
3205
3206
- ``embedding`` -- two embeddings are available, and can be
3207
selected by setting ``embedding`` to 1 or 2.
3208
3209
EXAMPLES::
3210
3211
sage: g = graphs.McGeeGraph()
3212
sage: g.order()
3213
24
3214
sage: g.size()
3215
36
3216
sage: g.girth()
3217
7
3218
sage: g.diameter()
3219
4
3220
sage: g.show()
3221
sage: graphs.McGeeGraph(embedding=1).show()
3222
3223
TESTS::
3224
3225
sage: graphs.McGeeGraph(embedding=3)
3226
Traceback (most recent call last):
3227
...
3228
ValueError: The value of embedding must be 1 or 2.
3229
"""
3230
3231
L = [47, -23, -31, 39, 25, -21, -31, -41, 25, 15, 29, -41, -19, 15,
3232
-49, 33, 39, -35, -21, 17, -33, 49, 41, 31, -15, -29, 41, 31,
3233
-15, -25, 21, 31, -51, -25, 23, 9, -17, 51, 35, -29, 21, -51,
3234
-39, 33, -9, -51, 51, -47, -33, 19, 51, -21, 29, 21, -31, -39]
3235
3236
from sage.graphs.generators.families import LCFGraph
3237
g = LCFGraph(24, [12, 7, -7], 8)
3238
g.name('McGee graph')
3239
3240
if embedding == 1:
3241
return g
3242
3243
elif embedding == 2:
3244
3245
o = [[7, 2, 13, 8, 19, 14, 1, 20],
3246
[5, 4, 11, 10, 17, 16, 23, 22],
3247
[3, 12, 9, 18, 15, 0, 21, 6]]
3248
3249
_circle_embedding(g, o[0], radius=1.5)
3250
_circle_embedding(g, o[1], radius=3, shift=-.5)
3251
_circle_embedding(g, o[2], radius=2.25, shift=.5)
3252
3253
return g
3254
3255
else:
3256
raise ValueError("The value of embedding must be 1 or 2.")
3257
3258
def McLaughlinGraph():
3259
r"""
3260
Returns the McLaughlin Graph.
3261
3262
The McLaughlin Graph is the unique strongly regular graph of parameters
3263
`(275, 112, 30, 56)`.
3264
3265
For more information on the McLaughlin Graph, see its web page on `Andries
3266
Brouwer's website <http://www.win.tue.nl/~aeb/graphs/McL.html>`_ which gives
3267
the definition that this method implements.
3268
3269
.. NOTE::
3270
3271
To create this graph you must have the gap_packages spkg installed.
3272
3273
EXAMPLES::
3274
3275
sage: g = graphs.McLaughlinGraph() # optional gap_packages
3276
sage: g.is_strongly_regular(parameters=True) # optional gap_packages
3277
(275, 112, 30, 56)
3278
sage: set(g.spectrum()) == {112, 2, -28} # optional gap_packages
3279
True
3280
"""
3281
from sage.combinat.designs.block_design import WittDesign
3282
from itertools import combinations
3283
from sage.sets.set import Set
3284
3285
blocks = WittDesign(23).blocks()
3286
blocks = map(Set, blocks)
3287
B = [b for b in blocks if 0 in b]
3288
C = [b for b in blocks if not 0 in b]
3289
g = graph.Graph()
3290
for b in B:
3291
for x in range(23):
3292
if not x in b:
3293
g.add_edge(b, x)
3294
3295
for b in C:
3296
for x in b:
3297
g.add_edge(b, x)
3298
3299
for b, bb in combinations(B, 2):
3300
if len(b & bb) == 1:
3301
g.add_edge(b, bb)
3302
3303
for c, cc in combinations(C, 2):
3304
if len(c & cc) == 1:
3305
g.add_edge(c, cc)
3306
3307
for b in B:
3308
for c in C:
3309
if len(b & c) == 3:
3310
g.add_edge(b, c)
3311
3312
g.relabel()
3313
g.name("McLaughlin")
3314
return g
3315
3316
def MoebiusKantorGraph():
3317
"""
3318
Returns a Moebius-Kantor Graph.
3319
3320
A Moebius-Kantor graph is a cubic symmetric graph. (See also the
3321
Heawood graph). It has 16 nodes and 24 edges. It is nonplanar and
3322
Hamiltonian. It has diameter = 4, girth = 6, and chromatic number =
3323
2. It is identical to the Generalized Petersen graph, P[8,3].
3324
3325
PLOTTING: See the plotting section for the generalized Petersen graphs.
3326
3327
REFERENCES:
3328
3329
- [1] Weisstein, E. (1999). "Moebius-Kantor Graph - from
3330
Wolfram MathWorld". [Online] Available:
3331
http://mathworld.wolfram.com/Moebius-KantorGraph.html [2007,
3332
February 17]
3333
3334
EXAMPLES::
3335
3336
sage: MK = graphs.MoebiusKantorGraph()
3337
sage: MK
3338
Moebius-Kantor Graph: Graph on 16 vertices
3339
sage: MK.graph6_string()
3340
'OhCGKE?O@?ACAC@I?Q_AS'
3341
sage: (graphs.MoebiusKantorGraph()).show() # long time
3342
"""
3343
from sage.graphs.generators.families import GeneralizedPetersenGraph
3344
G=GeneralizedPetersenGraph(8,3)
3345
G.name("Moebius-Kantor Graph")
3346
return G
3347
3348
def MoserSpindle():
3349
r"""
3350
Returns the Moser spindle.
3351
3352
For more information, see this
3353
`MathWorld article on the Moser spindle <http://mathworld.wolfram.com/MoserSpindle.html>`_.
3354
3355
EXAMPLES:
3356
3357
The Moser spindle is a planar graph having 7 vertices and 11 edges. ::
3358
3359
sage: G = graphs.MoserSpindle(); G
3360
Moser spindle: Graph on 7 vertices
3361
sage: G.is_planar()
3362
True
3363
sage: G.order()
3364
7
3365
sage: G.size()
3366
11
3367
3368
It is a Hamiltonian graph with radius 2, diameter 2, and girth 3. ::
3369
3370
sage: G.is_hamiltonian()
3371
True
3372
sage: G.radius()
3373
2
3374
sage: G.diameter()
3375
2
3376
sage: G.girth()
3377
3
3378
3379
The Moser spindle has chromatic number 4 and its automorphism
3380
group is isomorphic to the dihedral group `D_4`. ::
3381
3382
sage: G.chromatic_number()
3383
4
3384
sage: ag = G.automorphism_group()
3385
sage: ag.is_isomorphic(DihedralGroup(4))
3386
True
3387
"""
3388
edge_dict = {
3389
0: [1,4,5,6],
3390
1: [2,5],
3391
2: [3,5],
3392
3: [4,6],
3393
4: [6]}
3394
pos_dict = {
3395
0: [0, 2],
3396
1: [-1.90211303259031, 0.618033988749895],
3397
2: [-1.17557050458495, -1.61803398874989],
3398
3: [1.17557050458495, -1.61803398874989],
3399
4: [1.90211303259031, 0.618033988749895],
3400
5: [1, 0],
3401
6: [-1, 0]}
3402
return Graph(edge_dict, pos=pos_dict, name="Moser spindle")
3403
3404
3405
def NauruGraph(embedding=2):
3406
"""
3407
Returns the Nauru Graph.
3408
3409
See the :wikipedia:`Wikipedia page on the Nauru Graph
3410
<Nauru_graph>`.
3411
3412
INPUT:
3413
3414
- ``embedding`` -- two embeddings are available, and can be
3415
selected by setting ``embedding`` to 1 or 2.
3416
3417
EXAMPLES::
3418
3419
sage: g = graphs.NauruGraph()
3420
sage: g.order()
3421
24
3422
sage: g.size()
3423
36
3424
sage: g.girth()
3425
6
3426
sage: g.diameter()
3427
4
3428
sage: g.show()
3429
sage: graphs.NauruGraph(embedding=1).show()
3430
3431
TESTS::
3432
3433
sage: graphs.NauruGraph(embedding=3)
3434
Traceback (most recent call last):
3435
...
3436
ValueError: The value of embedding must be 1 or 2.
3437
sage: graphs.NauruGraph(embedding=1).is_isomorphic(g)
3438
True
3439
"""
3440
3441
if embedding == 1:
3442
from sage.graphs.generators.families import LCFGraph
3443
g = LCFGraph(24, [5, -9, 7, -7, 9, -5], 4)
3444
g.name('Nauru Graph')
3445
return g
3446
elif embedding == 2:
3447
from sage.graphs.generators.families import GeneralizedPetersenGraph
3448
g = GeneralizedPetersenGraph(12, 5)
3449
g.name("Nauru Graph")
3450
return g
3451
else:
3452
raise ValueError("The value of embedding must be 1 or 2.")
3453
3454
def PappusGraph():
3455
"""
3456
Returns the Pappus graph, a graph on 18 vertices.
3457
3458
The Pappus graph is cubic, symmetric, and distance-regular.
3459
3460
EXAMPLES::
3461
3462
sage: G = graphs.PappusGraph()
3463
sage: G.show() # long time
3464
sage: L = graphs.LCFGraph(18, [5,7,-7,7,-7,-5], 3)
3465
sage: L.show() # long time
3466
sage: G.is_isomorphic(L)
3467
True
3468
"""
3469
pos_dict = {}
3470
for i in range(6):
3471
pos_dict[i] = [float(cos(pi/2 + ((2*pi)/6)*i)),\
3472
float(sin(pi/2 + ((2*pi)/6)*i))]
3473
pos_dict[6 + i] = [(2/3.0)*float(cos(pi/2 + ((2*pi)/6)*i)),\
3474
(2/3.0)*float(sin(pi/2 + ((2*pi)/6)*i))]
3475
pos_dict[12 + i] = [(1/3.0)*float(cos(pi/2 + ((2*pi)/6)*i)),\
3476
(1/3.0)*float(sin(pi/2 + ((2*pi)/6)*i))]
3477
return Graph({0:[1,5,6],1:[2,7],2:[3,8],3:[4,9],4:[5,10],\
3478
5:[11],6:[13,17],7:[12,14],8:[13,15],9:[14,16],\
3479
10:[15,17],11:[12,16],12:[15],13:[16],14:[17]},\
3480
pos=pos_dict, name="Pappus Graph")
3481
3482
def PoussinGraph():
3483
r"""
3484
Returns the Poussin Graph.
3485
3486
For more information on the Poussin Graph, see its corresponding `Wolfram
3487
page <http://mathworld.wolfram.com/PoussinGraph.html>`_.
3488
3489
EXAMPLES::
3490
3491
sage: g = graphs.PoussinGraph()
3492
sage: g.order()
3493
15
3494
sage: g.is_planar()
3495
True
3496
"""
3497
g = Graph({2:[7,8,3,4],1:[7,6],0:[6,5,4],3:[5]},name="Poussin Graph")
3498
3499
g.add_cycle(range(3))
3500
g.add_cycle(range(3,9))
3501
g.add_cycle(range(9,14))
3502
g.add_path([8,12,7,11,6,10,5,9,3,13,8,12])
3503
g.add_edges([(14,i) for i in range(9,14)])
3504
_circle_embedding(g, range(3), shift=.75)
3505
_circle_embedding(g, range(3,9), radius=.4, shift=0)
3506
_circle_embedding(g, range(9,14), radius=.2, shift=.4)
3507
g.get_pos()[14] = (0,0)
3508
3509
return g
3510
3511
def PetersenGraph():
3512
"""
3513
The Petersen Graph is a named graph that consists of 10 vertices
3514
and 15 edges, usually drawn as a five-point star embedded in a
3515
pentagon.
3516
3517
The Petersen Graph is a common counterexample. For example, it is
3518
not Hamiltonian.
3519
3520
PLOTTING: See the plotting section for the generalized Petersen graphs.
3521
3522
EXAMPLES: We compare below the Petersen graph with the default
3523
spring-layout versus a planned position dictionary of [x,y]
3524
tuples::
3525
3526
sage: petersen_spring = Graph({0:[1,4,5], 1:[0,2,6], 2:[1,3,7], 3:[2,4,8], 4:[0,3,9], 5:[0,7,8], 6:[1,8,9], 7:[2,5,9], 8:[3,5,6], 9:[4,6,7]})
3527
sage: petersen_spring.show() # long time
3528
sage: petersen_database = graphs.PetersenGraph()
3529
sage: petersen_database.show() # long time
3530
"""
3531
from sage.graphs.generators.families import GeneralizedPetersenGraph
3532
P=GeneralizedPetersenGraph(5,2)
3533
P.name("Petersen graph")
3534
return P
3535
3536
3537
def RobertsonGraph():
3538
"""
3539
Returns the Robertson graph.
3540
3541
See the :wikipedia:`Wikipedia page on the Robertson Graph
3542
<Robertson_graph>`.
3543
3544
EXAMPLE::
3545
3546
sage: g = graphs.RobertsonGraph()
3547
sage: g.order()
3548
19
3549
sage: g.size()
3550
38
3551
sage: g.diameter()
3552
3
3553
sage: g.girth()
3554
5
3555
sage: g.charpoly().factor()
3556
(x - 4) * (x - 1)^2 * (x^2 + x - 5) * (x^2 + x - 1) * (x^2 - 3)^2 * (x^2 + x - 4)^2 * (x^2 + x - 3)^2
3557
sage: g.chromatic_number()
3558
3
3559
sage: g.is_hamiltonian()
3560
True
3561
sage: g.is_vertex_transitive()
3562
False
3563
"""
3564
from sage.graphs.generators.families import LCFGraph
3565
lcf = [8, 4, 7, 4, 8, 5, 7, 4, 7, 8, 4, 5, 7, 8, 4, 8, 4, 8, 4]
3566
g = LCFGraph(19, lcf, 1)
3567
g.name("Robertson Graph")
3568
return g
3569
3570
3571
def SchlaefliGraph():
3572
r"""
3573
Returns the Schläfli graph.
3574
3575
The Schläfli graph is the only strongly regular graphs of parameters
3576
`(27,16,10,8)` (see [GodsilRoyle]_).
3577
3578
For more information, see the :wikipedia:`Wikipedia article on the
3579
Schläfli graph <Schläfli_graph>`.
3580
3581
.. SEEALSO::
3582
3583
:meth:`Graph.is_strongly_regular` -- tests whether a graph is strongly
3584
regular and/or returns its parameters.
3585
3586
.. TODO::
3587
3588
Find a beautiful layout for this beautiful graph.
3589
3590
EXAMPLE:
3591
3592
Checking that the method actually returns the Schläfli graph::
3593
3594
sage: S = graphs.SchlaefliGraph()
3595
sage: S.is_strongly_regular(parameters = True)
3596
(27, 16, 10, 8)
3597
3598
The graph is vertex-transitive::
3599
3600
sage: S.is_vertex_transitive()
3601
True
3602
3603
The neighborhood of each vertex is isomorphic to the complement of the
3604
Clebsch graph::
3605
3606
sage: neighborhood = S.subgraph(vertices = S.neighbors(0))
3607
sage: graphs.ClebschGraph().complement().is_isomorphic(neighborhood)
3608
True
3609
"""
3610
from sage.graphs.graph import Graph
3611
G = Graph('ZBXzr|}^z~TTitjLth|dmkrmsl|if}TmbJMhrJX]YfFyTbmsseztKTvyhDvw')
3612
order = [1,8,5,10,2,6,11,15,17,13,18,12,9,24,25,3,26,7,16,20,23,0,21,14,22,4,19]
3613
_circle_embedding(G, order)
3614
G.name("Schläfli graph")
3615
return G
3616
3617
def ShrikhandeGraph():
3618
"""
3619
Returns the Shrikhande graph.
3620
3621
For more information, see the `MathWorld article on the Shrikhande graph
3622
<http://mathworld.wolfram.com/ShrikhandeGraph.html>`_ or the
3623
:wikipedia:`Wikipedia article on the Shrikhande graph <Shrikhande_graph>`.
3624
3625
.. SEEALSO::
3626
3627
:meth:`Graph.is_strongly_regular` -- tests whether a graph is strongly
3628
regular and/or returns its parameters.
3629
3630
EXAMPLES:
3631
3632
The Shrikhande graph was defined by S. S. Shrikhande in 1959. It has
3633
`16` vertices and `48` edges, and is strongly regular of degree `6` with
3634
parameters `(2,2)`::
3635
3636
sage: G = graphs.ShrikhandeGraph(); G
3637
Shrikhande graph: Graph on 16 vertices
3638
sage: G.order()
3639
16
3640
sage: G.size()
3641
48
3642
sage: G.is_regular(6)
3643
True
3644
sage: set([ len([x for x in G.neighbors(i) if x in G.neighbors(j)])
3645
....: for i in range(G.order())
3646
....: for j in range(i) ])
3647
set([2])
3648
3649
It is non-planar, and both Hamiltonian and Eulerian::
3650
3651
sage: G.is_planar()
3652
False
3653
sage: G.is_hamiltonian()
3654
True
3655
sage: G.is_eulerian()
3656
True
3657
3658
It has radius `2`, diameter `2`, and girth `3`::
3659
3660
sage: G.radius()
3661
2
3662
sage: G.diameter()
3663
2
3664
sage: G.girth()
3665
3
3666
3667
Its chromatic number is `4` and its automorphism group is of order
3668
`192`::
3669
3670
sage: G.chromatic_number()
3671
4
3672
sage: G.automorphism_group().cardinality()
3673
192
3674
3675
It is an integral graph since it has only integral eigenvalues::
3676
3677
sage: G.characteristic_polynomial().factor()
3678
(x - 6) * (x - 2)^6 * (x + 2)^9
3679
3680
It is a toroidal graph, and its embedding on a torus is dual to an
3681
embedding of the Dyck graph (:meth:`DyckGraph <GraphGenerators.DyckGraph>`).
3682
"""
3683
pos_dict = {}
3684
for i in range(8):
3685
pos_dict[i] = [float(cos((2*i) * pi/8)),
3686
float(sin((2*i) * pi/8))]
3687
pos_dict[8 + i] = [0.5 * pos_dict[i][0],
3688
0.5 * pos_dict[i][1]]
3689
edge_dict = {
3690
0O00: [0O06, 0O07, 0O01, 0O02, 0O11, 0O17],
3691
0O01: [0O07, 0O00, 0O02, 0O03, 0O12, 0O10],
3692
0O02: [0O00, 0O01, 0O03, 0O04, 0O13, 0O11],
3693
0O03: [0O01, 0O02, 0O04, 0O05, 0O14, 0O12],
3694
0O04: [0O02, 0O03, 0O05, 0O06, 0O15, 0O13],
3695
0O05: [0O03, 0O04, 0O06, 0O07, 0O16, 0O14],
3696
0O06: [0O04, 0O05, 0O07, 0O00, 0O17, 0O15],
3697
0O07: [0O05, 0O06, 0O00, 0O01, 0O10, 0O16],
3698
3699
0O10: [0O12, 0O13, 0O15, 0O16, 0O07, 0O01],
3700
0O11: [0O13, 0O14, 0O16, 0O17, 0O00, 0O02],
3701
0O12: [0O14, 0O15, 0O17, 0O10, 0O01, 0O03],
3702
0O13: [0O15, 0O16, 0O10, 0O11, 0O02, 0O04],
3703
0O14: [0O16, 0O17, 0O11, 0O12, 0O03, 0O05],
3704
0O15: [0O17, 0O10, 0O12, 0O13, 0O04, 0O06],
3705
0O16: [0O10, 0O11, 0O13, 0O14, 0O05, 0O07],
3706
0O17: [0O11, 0O12, 0O14, 0O15, 0O06, 0O00]
3707
}
3708
3709
return Graph(edge_dict, pos=pos_dict, name="Shrikhande graph")
3710
3711
def SylvesterGraph():
3712
"""
3713
Returns the Sylvester Graph.
3714
3715
This graph is obtained from the Hoffman Singleton graph by considering the
3716
graph induced by the vertices at distance two from the vertices of an (any)
3717
edge.
3718
3719
For more information on the Sylvester graph, see
3720
`<http://www.win.tue.nl/~aeb/graphs/Sylvester.html>`_.
3721
3722
.. SEEALSO::
3723
3724
* :meth:`~sage.graphs.graph_generators.GraphGenerators.HoffmanSingletonGraph`.
3725
3726
EXAMPLE::
3727
3728
sage: g = graphs.SylvesterGraph(); g
3729
Sylvester Graph: Graph on 36 vertices
3730
sage: g.order()
3731
36
3732
sage: g.size()
3733
90
3734
sage: g.is_regular(k=5)
3735
True
3736
"""
3737
g = HoffmanSingletonGraph()
3738
e = g.edge_iterator(labels = False).next()
3739
g.delete_vertices(g.neighbors(e[0]) + g.neighbors(e[1]))
3740
g.relabel()
3741
ordering = [0, 1, 2, 4, 5, 9, 16, 35, 15, 18, 20, 30, 22, 6, 33, 32, 14,
3742
10, 28, 29, 7, 24, 23, 26, 19, 12, 13, 21, 11, 31, 3, 27, 25,
3743
17, 8, 34]
3744
_circle_embedding(g,ordering, shift=.5)
3745
g.name("Sylvester Graph")
3746
return g
3747
3748
def SimsGewirtzGraph():
3749
"""
3750
Returns the Sims-Gewirtz Graph.
3751
3752
This graph is obtained from the Higman Sims graph by considering the graph
3753
induced by the vertices at distance two from the vertices of an (any)
3754
edge. It is the only strongly regular graph with parameters `v = 56, k = 10,
3755
\lambda = 0, \mu = 2`
3756
3757
For more information on the Sylvester graph, see
3758
`<http://www.win.tue.nl/~aeb/graphs/Sims-Gewirtz.html>`_ or its
3759
:wikipedia:`Wikipedia page <Gewirtz graph>`.
3760
3761
.. SEEALSO::
3762
3763
* :meth:`~sage.graphs.graph_generators.GraphGenerators.HigmanSimsGraph`.
3764
3765
EXAMPLE::
3766
3767
sage: g = graphs.SimsGewirtzGraph(); g
3768
Sims-Gewirtz Graph: Graph on 56 vertices
3769
sage: g.order()
3770
56
3771
sage: g.size()
3772
280
3773
sage: g.is_strongly_regular(parameters = True)
3774
(56, 10, 0, 2)
3775
3776
"""
3777
g = HigmanSimsGraph()
3778
e = g.edge_iterator(labels = False).next()
3779
g.delete_vertices(g.neighbors(e[0]) + g.neighbors(e[1]))
3780
g.relabel()
3781
ordering = [0, 2, 3, 4, 6, 7, 8, 17, 1, 41, 49, 5, 22, 26, 11, 27, 15, 47,
3782
53, 52, 38, 43, 44, 18, 20, 32, 19, 42, 54, 36, 51, 30, 33, 35,
3783
37, 28, 34, 12, 29, 23, 55, 25, 40, 24, 9, 14, 48, 39, 45, 16,
3784
13, 21, 31, 50, 10, 46]
3785
_circle_embedding(g,ordering)
3786
g.name("Sims-Gewirtz Graph")
3787
return g
3788
3789
def SousselierGraph():
3790
r"""
3791
Returns the Sousselier Graph.
3792
3793
The Sousselier graph is a hypohamiltonian graph on 16 vertices and 27
3794
edges. For more information, see the corresponding `Wikipedia page (in
3795
French) <http://fr.wikipedia.org/wiki/Graphe_de_Sousselier>`_.
3796
3797
EXAMPLES::
3798
3799
sage: g = graphs.SousselierGraph()
3800
sage: g.order()
3801
16
3802
sage: g.size()
3803
27
3804
sage: g.radius()
3805
2
3806
sage: g.diameter()
3807
3
3808
sage: g.automorphism_group().cardinality()
3809
2
3810
sage: g.is_hamiltonian()
3811
False
3812
sage: g.delete_vertex(g.random_vertex())
3813
sage: g.is_hamiltonian()
3814
True
3815
"""
3816
g = Graph(name="Sousselier Graph")
3817
3818
g.add_cycle(range(15))
3819
g.add_path([12,8,3,14])
3820
g.add_path([9,5,0,11])
3821
g.add_edge(6,2)
3822
g.add_edges([(15,i) for i in range(15) if i%3==1])
3823
3824
_circle_embedding(g, range(15), shift=-.25)
3825
g.get_pos()[15] = (0,0)
3826
3827
return g
3828
3829
def SzekeresSnarkGraph():
3830
r"""
3831
Returns the Szekeres Snark Graph.
3832
3833
The Szekeres graph is a snark with 50 vertices and 75 edges. For more
3834
information on this graph, see the :wikipedia:`Szekeres_snark`.
3835
3836
EXAMPLES::
3837
3838
sage: g = graphs.SzekeresSnarkGraph()
3839
sage: g.order()
3840
50
3841
sage: g.size()
3842
75
3843
sage: g.chromatic_number()
3844
3
3845
"""
3846
g = Graph(name="Szekeres Snark Graph")
3847
3848
for i in range(5):
3849
g.add_cycle([(i,j) for j in range(9)])
3850
g.delete_edge((i,0),(i,8))
3851
g.add_edge((i,1),i)
3852
g.add_edge((i,4),i)
3853
g.add_edge((i,7),i)
3854
g.add_edge((i,0),(i,5))
3855
g.add_edge((i,8),(i,3))
3856
3857
g.add_edge((i,0),((i+1)%5,8))
3858
g.add_edge((i,6),((i+2)%5,2))
3859
_circle_embedding(g, [(i,j) for j in range(9)],
3860
radius=.3,
3861
center=(cos(2*(i+.25)*pi/5),sin(2*(i+.25)*pi/5)),
3862
shift=5.45+1.8*i)
3863
3864
_circle_embedding(g, range(5), radius=1, shift=.25)
3865
3866
g.relabel()
3867
return g
3868
3869
3870
def ThomsenGraph():
3871
"""
3872
Returns the Thomsen Graph.
3873
3874
The Thomsen Graph is actually a complete bipartite graph with `(n1, n2) =
3875
(3, 3)`. It is also called the Utility graph.
3876
3877
PLOTTING: See CompleteBipartiteGraph.
3878
3879
EXAMPLES::
3880
3881
sage: T = graphs.ThomsenGraph()
3882
sage: T
3883
Thomsen graph: Graph on 6 vertices
3884
sage: T.graph6_string()
3885
'EFz_'
3886
sage: (graphs.ThomsenGraph()).show() # long time
3887
"""
3888
pos_dict = {0:(-1,1),1:(0,1),2:(1,1),3:(-1,0),4:(0,0),5:(1,0)}
3889
import networkx
3890
G = networkx.complete_bipartite_graph(3,3)
3891
return Graph(G, pos=pos_dict, name="Thomsen graph")
3892
3893
def TietzeGraph():
3894
r"""
3895
Returns the Tietze Graph.
3896
3897
For more information on the Tietze Graph, see the
3898
:wikipedia:`Tietze's_graph`.
3899
3900
EXAMPLES::
3901
3902
sage: g = graphs.TietzeGraph()
3903
sage: g.order()
3904
12
3905
sage: g.size()
3906
18
3907
sage: g.diameter()
3908
3
3909
sage: g.girth()
3910
3
3911
sage: g.automorphism_group().cardinality()
3912
12
3913
sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6))
3914
True
3915
"""
3916
g = Graph([(0,9),(3,10),(6,11),(1,5),(2,7),(4,8),(7,2)], name="Tietze Graph")
3917
g.add_cycle(range(9))
3918
g.add_cycle([9,10,11])
3919
_circle_embedding(g,range(9))
3920
_circle_embedding(g,[9,10,11],radius=.5)
3921
3922
return g
3923
3924
def Tutte12Cage():
3925
r"""
3926
Returns Tutte's 12-Cage.
3927
3928
See the :wikipedia:`Wikipedia page on the Tutte 12-Cage
3929
<Tutte_12-cage>`.
3930
3931
EXAMPLES::
3932
3933
sage: g = graphs.Tutte12Cage()
3934
sage: g.order()
3935
126
3936
sage: g.size()
3937
189
3938
sage: g.girth()
3939
12
3940
sage: g.diameter()
3941
6
3942
sage: g.show()
3943
"""
3944
L = [17, 27, -13, -59, -35, 35, -11, 13, -53, 53, -27, 21, 57, 11,
3945
-21, -57, 59, -17]
3946
3947
from sage.graphs.generators.families import LCFGraph
3948
g = LCFGraph(126, L, 7)
3949
g.name("Tutte 12-Cage")
3950
return g
3951
3952
def TutteCoxeterGraph(embedding=2):
3953
r"""
3954
Returns the Tutte-Coxeter graph.
3955
3956
See the :wikipedia:`Wikipedia page on the Tutte-Coxeter Graph
3957
<Tutte-Coxeter_graph>`.
3958
3959
INPUT:
3960
3961
- ``embedding`` -- two embeddings are available, and can be
3962
selected by setting ``embedding`` to 1 or 2.
3963
3964
EXAMPLES::
3965
3966
sage: g = graphs.TutteCoxeterGraph()
3967
sage: g.order()
3968
30
3969
sage: g.size()
3970
45
3971
sage: g.girth()
3972
8
3973
sage: g.diameter()
3974
4
3975
sage: g.show()
3976
sage: graphs.TutteCoxeterGraph(embedding=1).show()
3977
3978
TESTS::
3979
3980
sage: graphs.TutteCoxeterGraph(embedding=3)
3981
Traceback (most recent call last):
3982
...
3983
ValueError: The value of embedding must be 1 or 2.
3984
"""
3985
3986
from sage.graphs.generators.families import LCFGraph
3987
g = LCFGraph(30, [-13, -9, 7, -7, 9, 13], 5)
3988
g.name("Tutte-Coxeter graph")
3989
3990
if embedding == 1:
3991
d = {
3992
0: [1, 3, 5, 7, 29],
3993
1: [2, 4, 6, 28, 0],
3994
2: [8, 18, 26, 22, 12],
3995
3: [9, 13, 23, 27, 17],
3996
4: [11, 15, 21, 25, 19],
3997
5: [10, 14, 24, 20, 16]
3998
}
3999
4000
_circle_embedding(g, d[0], center=(-1, 1), radius=.25)
4001
_circle_embedding(g, d[1], center=(1, 1), radius=.25)
4002
_circle_embedding(g, d[2], center=(-.8, 0), radius=.25, shift=2.5)
4003
_circle_embedding(g, d[3], center=(1.2, 0), radius=.25)
4004
_circle_embedding(g, d[4], center=(-1, -1), radius=.25, shift=2)
4005
_circle_embedding(g, d[5], center=(1, -1), radius=.25)
4006
4007
return g
4008
4009
elif embedding == 2:
4010
return g
4011
4012
else:
4013
raise ValueError("The value of embedding must be 1 or 2.")
4014
4015
def TutteGraph():
4016
r"""
4017
Returns the Tutte Graph.
4018
4019
The Tutte graph is a 3-regular, 3-connected, and planar non-hamiltonian
4020
graph. For more information on the Tutte Graph, see the
4021
:wikipedia:`Tutte_graph`.
4022
4023
EXAMPLES::
4024
4025
sage: g = graphs.TutteGraph()
4026
sage: g.order()
4027
46
4028
sage: g.size()
4029
69
4030
sage: g.is_planar()
4031
True
4032
sage: g.vertex_connectivity() # long
4033
3
4034
sage: g.girth()
4035
4
4036
sage: g.automorphism_group().cardinality()
4037
3
4038
sage: g.is_hamiltonian()
4039
False
4040
"""
4041
g = Graph(name="Tutte Graph")
4042
from sage.graphs.graph_plot import _circle_embedding
4043
4044
g.add_cycle([(i,j) for i in range(3) for j in range(3) ])
4045
for i in range(3):
4046
g.add_cycle([(i,j) for j in range(9)])
4047
g.add_cycle([(i,j) for j in range(9,14)])
4048
g.add_edge((i,5),0)
4049
g.add_edge((i,13),(i,3))
4050
g.add_edge((i,12),(i,1))
4051
g.add_edge((i,11),(i,8))
4052
g.add_edge((i,10),(i,7))
4053
g.add_edge((i,6),(i,14))
4054
g.add_edge((i,4),(i,14))
4055
g.add_edge((i,9),(i,14))
4056
4057
_circle_embedding(g, [(i,j) for i in range(3) for j in range(6)], shift=.5)
4058
_circle_embedding(g, [(i,14) for i in range(3) ], radius=.3,shift=.25)
4059
4060
for i in range(3):
4061
_circle_embedding(g, [(i,j) for j in range(3,9)]+[0]*5,
4062
shift=3.7*(i-2)+.75,
4063
radius=.4,
4064
center=(.6*cos(2*(i+.25)*pi/3),.6*sin(2*(i+.25)*pi/3)))
4065
_circle_embedding(g, [(i,j) for j in range(9,14)],
4066
shift=1.7*(i-2)+1,
4067
radius=.2,
4068
center=(.6*cos(2*(i+.25)*pi/3),.6*sin(2*(i+.25)*pi/3)))
4069
4070
g.get_pos()[0] = (0,0)
4071
4072
return g
4073
4074
def WagnerGraph():
4075
"""
4076
Returns the Wagner Graph.
4077
4078
See the :wikipedia:`Wikipedia page on the Wagner Graph
4079
<Wagner_graph>`.
4080
4081
EXAMPLES::
4082
4083
sage: g = graphs.WagnerGraph()
4084
sage: g.order()
4085
8
4086
sage: g.size()
4087
12
4088
sage: g.girth()
4089
4
4090
sage: g.diameter()
4091
2
4092
sage: g.show()
4093
"""
4094
from sage.graphs.generators.families import LCFGraph
4095
g = LCFGraph(8, [4], 8)
4096
g.name("Wagner Graph")
4097
return g
4098
4099
def WatkinsSnarkGraph():
4100
r"""
4101
Returns the Watkins Snark Graph.
4102
4103
The Watkins Graph is a snark with 50 vertices and 75 edges. For more
4104
information, see the :wikipedia:`Watkins_snark`.
4105
4106
EXAMPLES::
4107
4108
sage: g = graphs.WatkinsSnarkGraph()
4109
sage: g.order()
4110
50
4111
sage: g.size()
4112
75
4113
sage: g.chromatic_number()
4114
3
4115
"""
4116
g = Graph(name="Watkins Snark Graph")
4117
4118
for i in range(5):
4119
g.add_cycle([(i,j) for j in range(9)])
4120
_circle_embedding(g,
4121
[(i,j) for j in range(4)]+[0]*2+[(i,4)]+[0]*2+[(i,j) for j in range(5,9)],
4122
radius=.3,
4123
center=(cos(2*(i+.25)*pi/5),sin(2*(i+.25)*pi/5)),
4124
shift=2.7*i+7.55)
4125
g.add_edge((i,5),((i+1)%5,0))
4126
g.add_edge((i,8),((i+2)%5,3))
4127
g.add_edge((i,1),i)
4128
g.add_edge((i,7),i)
4129
g.add_edge((i,4),i)
4130
g.add_edge((i,6),(i,2))
4131
4132
_circle_embedding(g, range(5), shift=.25, radius=1.1)
4133
return g
4134
4135
def WienerArayaGraph():
4136
r"""
4137
Returns the Wiener-Araya Graph.
4138
4139
The Wiener-Araya Graph is a planar hypohamiltonian graph on 42 vertices and
4140
67 edges. For more information, see the `Wolfram Page on the Wiener-Araya
4141
Graph <http://mathworld.wolfram.com/Wiener-ArayaGraph.html>`_ or its
4142
`(french) Wikipedia page
4143
<http://fr.wikipedia.org/wiki/Graphe_de_Wiener-Araya>`_.
4144
4145
EXAMPLES::
4146
4147
sage: g = graphs.WienerArayaGraph()
4148
sage: g.order()
4149
42
4150
sage: g.size()
4151
67
4152
sage: g.girth()
4153
4
4154
sage: g.is_planar()
4155
True
4156
sage: g.is_hamiltonian() # not tested -- around 30s long
4157
False
4158
sage: g.delete_vertex(g.random_vertex())
4159
sage: g.is_hamiltonian()
4160
True
4161
"""
4162
g = Graph(name="Wiener-Araya Graph")
4163
from sage.graphs.graph_plot import _circle_embedding
4164
4165
g.add_cycle([(0,i) for i in range(4)])
4166
g.add_cycle([(1,i) for i in range(12)])
4167
g.add_cycle([(2,i) for i in range(20)])
4168
g.add_cycle([(3,i) for i in range(6)])
4169
_circle_embedding(g, [(0,i) for i in range(4)], shift=.5)
4170
_circle_embedding(g,
4171
sum([[(1,3*i),(1,3*i+1)]+[0]*3+[(1,3*i+2)]+[0]*3 for i in range(4)],[]),
4172
shift=4,
4173
radius=.65)
4174
_circle_embedding(g, [(2,i) for i in range(20)], radius=.5)
4175
_circle_embedding(g, [(3,i) for i in range(6)], radius=.3, shift=.5)
4176
4177
for i in range(4):
4178
g.delete_edge((1,3*i),(1,3*i+1))
4179
g.add_edge((1,3*i),(0,i))
4180
g.add_edge((1,3*i+1),(0,i))
4181
g.add_edge((2,5*i+2),(1,3*i))
4182
g.add_edge((2,5*i+3),(1,3*i+1))
4183
g.add_edge((2,(5*i+5)%20),(1,3*i+2))
4184
g.add_edge((2,(5*i+1)%20),(3,i+(i>=1)+(i>=3)))
4185
g.add_edge((2,(5*i+4)%20),(3,i+(i>=1)+(i>=3)))
4186
4187
g.delete_edge((3,1),(3,0))
4188
g.add_edge((3,1),(2,4))
4189
g.delete_edge((3,4),(3,3))
4190
g.add_edge((3,4),(2,14))
4191
g.add_edge((3,1),(3,4))
4192
4193
g.get_pos().pop(0)
4194
g.relabel()
4195
return g
4196
4197