Skip to content

Commit 8a777f0

Browse files
author
Release Manager
committed
sagemathgh-40740: add parameter immutable to distance regular graph generators (part 1) Following discussions in sagemath#39177, we add the option to return immutable graphs to some generators in `src/sage/graphs/generators/ditance_regular.pyx`. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40740 Reported by: David Coudert Reviewer(s): Chenxin Zhong
2 parents 5c8d9e9 + 27bbf71 commit 8a777f0

File tree

1 file changed

+124
-72
lines changed

1 file changed

+124
-72
lines changed

src/sage/graphs/generators/distance_regular.pyx

Lines changed: 124 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ import itertools
3838

3939
from cysignals.signals cimport sig_check
4040

41-
from sage.graphs.graph import Graph
42-
from sage.misc.lazy_import import LazyImport
41+
from sage.graphs.generators.platonic_solids import DodecahedralGraph
4342
from sage.graphs.generators.smallgraphs import (FosterGraph, BiggsSmithGraph,
4443
CoxeterGraph, LivingstoneGraph,
4544
WellsGraph, GossetGraph,
4645
HoffmanSingletonGraph,
4746
SimsGewirtzGraph,
4847
HigmanSimsGraph)
49-
from sage.graphs.generators.platonic_solids import DodecahedralGraph
48+
from sage.graphs.graph import Graph
5049
from sage.graphs.strongly_regular_db import strongly_regular_graph
50+
from sage.misc.lazy_import import LazyImport
5151

5252
codes = LazyImport('sage.coding', 'codes_catalog', as_name='codes')
5353
libgap = LazyImport('sage.libs.gap.libgap', 'libgap')
@@ -57,40 +57,60 @@ vector = LazyImport('sage.modules.free_module_element', 'vector')
5757
GF = LazyImport('sage.rings.finite_rings.finite_field_constructor', 'GF')
5858

5959

60-
def cocliques_HoffmannSingleton():
60+
def cocliques_HoffmannSingleton(immutable=False):
6161
r"""
6262
Return the graph obtained from the cocliques of the Hoffmann-Singleton graph.
6363
6464
This is a distance-regular graph with intersection array
6565
`[15, 14, 10, 3; 1, 5, 12, 15]`.
6666
67+
INPUT:
68+
69+
- ``immutable`` -- boolean (default: ``False``); whether to return an
70+
immutable or a mutable graph
71+
6772
EXAMPLES::
6873
6974
sage: G = graphs.cocliques_HoffmannSingleton()
7075
sage: G.is_distance_regular(True)
7176
([15, 14, 10, 3, None], [None, 1, 5, 12, 15])
7277
78+
TESTS:
79+
80+
Check the behavior of parameter `ìmmutable``::
81+
82+
sage: G = graphs.cocliques_HoffmannSingleton()
83+
sage: G.is_immutable()
84+
False
85+
sage: G.copy().is_immutable()
86+
False
87+
sage: G.copy(immutable=True).is_immutable()
88+
True
89+
sage: G = graphs.cocliques_HoffmannSingleton(immutable=True)
90+
sage: G.is_immutable()
91+
True
92+
sage: G.copy().is_immutable()
93+
True
94+
sage: G.copy(immutable=False).is_immutable()
95+
False
96+
7397
REFERENCES:
7498
7599
The construction of this graph can be found in [BCN1989]_ p. 392.
76100
"""
77-
from sage.graphs.graph_generators import GraphGenerators
78-
79-
D = GraphGenerators.HoffmanSingletonGraph()
101+
D = HoffmanSingletonGraph()
80102
DC = D.complement()
81103

82104
cocliques = [frozenset(c) for c in DC.cliques_maximum()] # 100 of this
83105

84-
edges = []
85-
for c1, c2 in itertools.combinations(cocliques, 2):
86-
if len(c1.intersection(c2)) == 8:
87-
edges.append((c1, c2))
106+
edges = ((c1, c2)
107+
for c1, c2 in itertools.combinations(cocliques, 2)
108+
if len(c1.intersection(c2)) == 8)
88109

89-
G = Graph(edges, format='list_of_edges')
90-
return G
110+
return Graph(edges, format='list_of_edges', immutable=immutable)
91111

92112

93-
def locally_GQ42_distance_transitive_graph():
113+
def locally_GQ42_distance_transitive_graph(immutable=False):
94114
r"""
95115
Return the unique amply regular graph with `\mu = 6` which is locally
96116
a generalised quadrangle.
@@ -100,6 +120,11 @@ def locally_GQ42_distance_transitive_graph():
100120
101121
This graph is also distance-transitive.
102122
123+
INPUT:
124+
125+
- ``immutable`` -- boolean (default: ``False``); whether to return an
126+
immutable or a mutable graph
127+
103128
EXAMPLES::
104129
105130
sage: G = graphs.locally_GQ42_distance_transitive_graph() # optional - internet gap_package_atlasrep
@@ -117,18 +142,23 @@ def locally_GQ42_distance_transitive_graph():
117142
if len(N.GeneratorsSmallest()) == 7: # there is only one
118143
break
119144

120-
G = Graph(libgap.Orbit(N, [1, 9], libgap.OnSets), format='list_of_edges')
121-
G.name("locally GQ(4,2) distance transitive graph")
122-
return G
145+
return Graph(libgap.Orbit(N, [1, 9], libgap.OnSets), format='list_of_edges',
146+
name="locally GQ(4,2) distance transitive graph",
147+
immutable=immutable)
123148

124149

125-
def ConwaySmith_for_3S7():
150+
def ConwaySmith_for_3S7(immutable=False):
126151
r"""
127152
Return the Conway-Smith graph related to `3 Sym(7)`.
128153
129154
This is a distance-regular graph with intersection array
130155
`[10, 6, 4, 1; 1, 2, 6, 10]`.
131156
157+
INPUT:
158+
159+
- ``immutable`` -- boolean (default: ``False``); whether to return an
160+
immutable or a mutable graph
161+
132162
EXAMPLES::
133163
134164
sage: G = graphs.ConwaySmith_for_3S7() # needs sage.modules sage.rings.finite_rings sage.rings.number_field
@@ -195,16 +225,12 @@ def ConwaySmith_for_3S7():
195225
def has_edge(u, v):
196226
return sum(u[i].conjugate() * v[i] for i in range(6)) == 2
197227

198-
G = Graph()
199-
for Ki, Kj in itertools.combinations(K, 2):
200-
if has_edge(Ki, Kj):
201-
G.add_edge((Ki, Kj))
202-
203-
G.name("Conway-Smith graph for 3S7")
204-
return G
228+
edges = ((Ki, Kj) for Ki, Kj in itertools.combinations(K, 2) if has_edge(Ki, Kj))
229+
return Graph(edges, format='list_of_edges', immutable=immutable,
230+
name="Conway-Smith graph for 3S7")
205231

206232

207-
def graph_3O73():
233+
def graph_3O73(immutable=False):
208234
r"""
209235
Return the graph related to the group `3 O(7,3)`.
210236
@@ -214,6 +240,11 @@ def graph_3O73():
214240
The graph is also distance transitive with `3.O(7,3)` as automorphism
215241
group
216242
243+
INPUT:
244+
245+
- ``immutable`` -- boolean (default: ``False``); whether to return an
246+
immutable or a mutable graph
247+
217248
EXAMPLES::
218249
219250
sage: G = graphs.graph_3O73() # optional - internet gap_package_atlasrep
@@ -226,12 +257,12 @@ def graph_3O73():
226257
[BCN1989]_ p. 400.
227258
"""
228259
group = libgap.AtlasGroup("3.O7(3)", libgap.NrMovedPoints, 1134)
229-
G = Graph(libgap.Orbit(group, [1, 3], libgap.OnSets), format='list_of_edges')
230-
G.name("Distance transitive graph with automorphism group 3.O_7(3)")
231-
return G
260+
return Graph(libgap.Orbit(group, [1, 3], libgap.OnSets), format='list_of_edges',
261+
name="Distance transitive graph with automorphism group 3.O_7(3)",
262+
immutable=immutable)
232263

233264

234-
def FosterGraph3S6():
265+
def FosterGraph3S6(immutable=False):
235266
r"""
236267
Return the Foster graph for `3.Sym(6)`.
237268
@@ -240,6 +271,11 @@ def FosterGraph3S6():
240271
241272
The graph is also distance transitive.
242273
274+
INPUT:
275+
276+
- ``immutable`` -- boolean (default: ``False``); whether to return an
277+
immutable or a mutable graph
278+
243279
EXAMPLES::
244280
245281
sage: G = graphs.FosterGraph3S6() # needs sage.libs.gap
@@ -260,15 +296,20 @@ def FosterGraph3S6():
260296

261297
group = libgap.Group(a, b)
262298

263-
G = Graph(group.Orbit([1, 7], libgap.OnSets), format='list_of_edges')
264-
G.name("Foster graph for 3.Sym(6) graph")
265-
return G
299+
return Graph(group.Orbit([1, 7], libgap.OnSets), format='list_of_edges',
300+
name="Foster graph for 3.Sym(6) graph",
301+
immutable=immutable)
266302

267303

268-
def J2Graph():
304+
def J2Graph(immutable=False):
269305
r"""
270306
Return the distance-transitive graph with automorphism group `J_2`.
271307
308+
INPUT:
309+
310+
- ``immutable`` -- boolean (default: ``False``); whether to return an
311+
immutable or a mutable graph
312+
272313
EXAMPLES::
273314
274315
sage: G = graphs.J2Graph() # optional - internet gap_package_atlasrep
@@ -281,17 +322,21 @@ def J2Graph():
281322
[BCN1989]_ p. 408.
282323
"""
283324
group = libgap.AtlasGroup("J2", libgap.NrMovedPoints, 315)
284-
G = Graph(group.Orbit([1, 9], libgap.OnSets), format='list_of_edges')
285-
G.name("J_2 graph")
286-
return G
325+
return Graph(group.Orbit([1, 9], libgap.OnSets), format='list_of_edges',
326+
name="J_2 graph", immutable=immutable)
287327

288328

289-
def IvanovIvanovFaradjevGraph():
329+
def IvanovIvanovFaradjevGraph(immutable=False):
290330
r"""
291331
Return the IvanovIvanovFaradjev graph.
292332
293333
The graph is distance-transitive with automorphism group `3.M_{22}`.
294334
335+
INPUT:
336+
337+
- ``immutable`` -- boolean (default: ``False``); whether to return an
338+
immutable or a mutable graph
339+
295340
EXAMPLES::
296341
297342
sage: G = graphs.IvanovIvanovFaradjevGraph() # optional - internet gap_package_atlasrep
@@ -303,21 +348,24 @@ def IvanovIvanovFaradjevGraph():
303348
A description and construction of this graph can be found in
304349
[BCN1989]_ p. 369.
305350
"""
306-
307351
group = libgap.AtlasGroup("3.M22", libgap.NrMovedPoints, 990)
308-
graph = Graph(group.Orbit([1, 22], libgap.OnSets), format='list_of_edges')
352+
return Graph(group.Orbit([1, 22], libgap.OnSets), format='list_of_edges',
353+
name="Ivanov-Ivanov-Faradjev Graph",
354+
immutable=immutable)
309355

310-
graph.name("Ivanov-Ivanov-Faradjev Graph")
311-
return graph
312356

313-
314-
def LargeWittGraph():
357+
def LargeWittGraph(immutable=False):
315358
r"""
316359
Return the large Witt graph.
317360
318361
This is a distance-regular graph with intersection array
319362
`[30,28,24;1,3,15]`.
320363
364+
INPUT:
365+
366+
- ``immutable`` -- boolean (default: ``False``); whether to return an
367+
immutable or a mutable graph
368+
321369
EXAMPLES::
322370
323371
sage: g = graphs.LargeWittGraph() # needs sage.libs.pari sage.modules
@@ -331,22 +379,18 @@ def LargeWittGraph():
331379
This construction is taken from
332380
http://mathworld.wolfram.com/LargeWittGraph.html
333381
"""
334-
import itertools
335-
336382
C = codes.GolayCode(GF(2), extended=True)
337383
vertices = [c for c in C if c.hamming_weight() == 8]
338384

339-
edges = []
340-
for v, w in itertools.combinations(vertices, 2):
341-
if not set(v.support()).intersection(w.support()):
342-
edges.append((v, w))
385+
edges = ((v, w)
386+
for v, w in itertools.combinations(vertices, 2)
387+
if not set(v.support()).intersection(w.support()))
343388

344-
W = Graph(edges, format='list_of_edges')
345-
W.name("Large Witt graph")
346-
return W
389+
return Graph(edges, format='list_of_edges', immutable=immutable,
390+
name="Large Witt graph")
347391

348392

349-
def TruncatedWittGraph():
393+
def TruncatedWittGraph(immutable=False):
350394
r"""
351395
Return the truncated Witt graph.
352396
@@ -356,6 +400,11 @@ def TruncatedWittGraph():
356400
The graph is distance-regular with intersection array
357401
`[15,14,12;1,1,9]`.
358402
403+
INPUT:
404+
405+
- ``immutable`` -- boolean (default: ``False``); whether to return an
406+
immutable or a mutable graph
407+
359408
EXAMPLES::
360409
361410
sage: # long time, needs sage.libs.pari sage.modules
@@ -369,14 +418,13 @@ def TruncatedWittGraph():
369418
[BCN1989]_ p. 367.
370419
"""
371420
# get large witt graph and remove all vertices which start with a 1
372-
G = LargeWittGraph()
421+
G = LargeWittGraph(immutable=False)
373422
G.delete_vertices(filter(lambda x: x[0] == 1, G.vertices(sort=False)))
374-
375423
G.name("Truncated Witt graph")
376-
return G
424+
return G.copy(immutable=True) if immutable else G
377425

378426

379-
def DoublyTruncatedWittGraph():
427+
def DoublyTruncatedWittGraph(immutable=False):
380428
r"""
381429
Return the doubly truncated Witt graph.
382430
@@ -386,6 +434,11 @@ def DoublyTruncatedWittGraph():
386434
The graph is distance-regular with intersection array
387435
`[7,6,4,4;1,1,1,6]`.
388436
437+
INPUT:
438+
439+
- ``immutable`` -- boolean (default: ``False``); whether to return an
440+
immutable or a mutable graph
441+
389442
EXAMPLES::
390443
391444
sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.libs.pari sage.modules
@@ -397,11 +450,10 @@ def DoublyTruncatedWittGraph():
397450
A description and construction of this graph can be found in
398451
[BCN1989]_ p. 368.
399452
"""
400-
G = TruncatedWittGraph()
453+
G = TruncatedWittGraph(immutable=False)
401454
G.delete_vertices(filter(lambda x: x[1] == 1, G.vertices(sort=False)))
402-
403455
G.name("Doubly Truncated Witt graph")
404-
return G
456+
return G.copy(immutable=True) if immutable else G
405457

406458

407459
def distance_3_doubly_truncated_Golay_code_graph():
@@ -1180,17 +1232,17 @@ def DoubleGrassmannGraph(const int q, const int e):
11801232
11811233
TESTS::
11821234
1183-
sage: # needs sage.modules
1184-
sage: G = graphs.DoubleGrassmannGraph(5,1)
1185-
sage: G.order()
1186-
62
1187-
sage: G.is_distance_regular(True)
1188-
([6, 5, 5, None], [None, 1, 1, 6])
1189-
sage: G = graphs.DoubleGrassmannGraph(3, 2) # long time # needs sage.rings.finite_rings
1190-
sage: G.order() # long time # needs sage.rings.finite_rings
1191-
2420
1192-
sage: G.is_distance_regular(True) # long time # needs sage.rings.finite_rings
1193-
([13, 12, 12, 9, 9, None], [None, 1, 1, 4, 4, 13])
1235+
sage: # needs sage.modules
1236+
sage: G = graphs.DoubleGrassmannGraph(5,1)
1237+
sage: G.order()
1238+
62
1239+
sage: G.is_distance_regular(True)
1240+
([6, 5, 5, None], [None, 1, 1, 6])
1241+
sage: G = graphs.DoubleGrassmannGraph(3, 2) # long time # needs sage.rings.finite_rings
1242+
sage: G.order() # long time # needs sage.rings.finite_rings
1243+
2420
1244+
sage: G.is_distance_regular(True) # long time # needs sage.rings.finite_rings
1245+
([13, 12, 12, 9, 9, None], [None, 1, 1, 4, 4, 13])
11941246
"""
11951247
n = 2*e + 1
11961248
V = VectorSpace(GF(q), n)

0 commit comments

Comments
 (0)